I have the following model classes...
class Image < ActiveRecord::Base
attr_accessible :description, :title
has_many :imageTags
has_many :tags, :through => :imageTags
end
class Tag < ActiveRecord::Base
attr_accessible :name
has_many :imageTags
has_many :images, :through => :imageTags
end
class ImageTag < ActiveRecord::Base
attr_accessible :position
belongs_to :image
belongs_to :tag
end
And when I use find for getting the Tag with the id 1
t = Tag.find(1);
#images = t.images;
But when I do the same with where, I get a NoMethodError, with the description undefined method 'images':
t = Tag.where(:name => "foo");
#images = t.images;
I also tried adding .includes(:images) before the .where statement, but that doesn't work too. So, how can I get all Images that belong to a Tag?
.where returns an ActiveRecord::Relation instance, not a single object. Tack on a .first to grab (presumably) the only record returned:
t = Tag.where(name: "foo").first
#images = t.images
Related
I have following three models
class Rating < ActiveRecord::Base
belongs_to :user
belongs_to :book
end
class User < ActiveRecord::Base
attr_accessible :name, :dob, :mobile
has_many :books, :through => 'ratings'
end
class Book < ActiveRecord::Base
attr_accessible :book_name, :author, :pages
has_many :users, :through => 'ratings'
end
Now I have to find all the "book_name"s of each book which is related the respective user and store it in the array.
Here is code
#book_names = []
#books = Rating.find(:all, 'user_id = ?', current_user.id)
#books.each do |book|
book_info = Book.find(book.id)
#book_names << book_info.book_name
end
Is there any other way for the same or join method.
Yes, there is simple way to do it. Try
#book_names= current_user.books.map(&:book_name)
I have three models
Tag => :id, :name
Tagging => :id, :tag_id, :post_id
Post => :id, :summary
I know the id of the tag. I would like to query for all of the posts that have a specific tag_id, through the Taggings model.
Something like
#post = Post.joins(:taggings).where(:tag_id => 17)
but this doesn't work because it is looking for the tag_id in the Post model and not the Tagging model.
I'm not sure how to do this.
I don't like to use string in ActiveRecord queries, so, I prefer this sintax:
#post = Post.joins(:taggings).where(taggings: {tag_id: 17})
First of all :
class Post < ActiveRecord::Base
has_many :taggings
has_many :tags, :through => :taggings
end
class Taggins < ActiveRecord::Base
belongs_to :post
belongs_to :tag
end
class Tag < ActiveRecord::Base
has_many :taggings
has_many :posts, :through => :taggings
end
If you have the tag object you can do
#posts = #tag.posts
or
class Post < ....
....
def self.find_by_tag_id(tag_id)
Post.joins(:taggings).where('taggings.tag_id = ?', tag_id)
end
end
Using the .where format you can pass a string like .where("taggings.tag_id = ?", 17) to qualify the joined taggings table.
As #tharrison mentioned. A solution is:
#post = Post.joins(:taggings).where("taggings.tag_id = ?", 17)
I'm currently working on a small project using Ruby On Rails 3.2 to create a database that contains several unique Models. Each Model has many Elements and each Element has the potential to belong to many Models. I have been able to set up the models in the following manner:
class Model < ActiveRecord::Base
has_many :model_elements
has_many :elements, :through => :model_elements
attr_accessible :elements, :name, :notes, :ref
end
class Element < ActiveRecord::Base
has_many :model_elements
has_many :models, :through => :model_elements
attr_accessible :elementType, :name, :notes, :ref
validates_presence_of :name
end
class ModelElement < ActiveRecord::Base
belongs_to :Model
belongs_to :element
attr_accessible :model_id, :created_at, :element_id
end
My question is how do I add multiple Elements to a single Model? I've tried to find some documentation but I can't find anything. Currently I'm trying to do the following:
#model.elements = #element
Where #element is a predefined element however it's throwing the following error:
undefined method `each' for #<Element:0x007ff803066500>
Any help would be greatly appreciated.
Try
#model.elements << #element
collection.create(attributes = {})
Returns a new object of the collection type that has been instantiated with attributes, linked to this object through the join table, and that has already been saved.
#model.elements.create(:name => "example")
Amar's answer is correct. If you wanted you can simplify your models further by using the has_and_belongs_to_many association.
class Model < ActiveRecord::Base
has_and_belongs_to_many :elements, :join_table => :model_elements
end
class Element < ActiveRecord::Base
has_and_belongs_to_many :models, :join_table => :model_elements
end
#model.elements << #element
I have 3 associated models:
class Brand < ActiveRecord::Base
has_many :car_models
end
class CarModel < ActiveRecord::Base
has_many :production_years
belongs_to :brand
end
class ProductionYear < ActiveRecord::Base
belongs_to :car_model
end
So, how i can make custom filter in ActiveAdmin production_year section, if i want make filtering by Brand? Default filters there: car_model select and year value
Did you try something like this?
ActiveAdmin.register ProductionYear do
filter :brand, :as => :check_boxes, :collection => proc { Brand.all }
end
EDIT oops I didn't notice the complexity of your association, I think if you add this to your ProductionYear class things should work better:
class ProductionYear < ActiveRecord::Base
belongs_to :car_model
has_one :brand, :through => :car_model
end
i've written the following classes:
class Occupation < ActiveRecord::Base
has_many :pref_labels
has_many :cv_occupations
has_many :cvs, :through => :cv_occupations
validates_uniqueness_of :uri
# This function will return the specified label for the given language.
def label(language = Language.find_or_create_by_code(:en))
self.pref_labels.where("language_id = #{language.id}")
end
end
class PrefLabel < ActiveRecord::Base
belongs_to :language
belongs_to :concept
belongs_to :skill
belongs_to :occupation
validates_uniqueness_of :value, :scope => [:language_id, :value]
validates_uniqueness_of :language_id, :scope => [:language_id, :value]
end
In my view, I call the following: %td= occupation.label(#language)
but this returns as error :
undefined method `value' for #<ActiveRecord::Relation:0x80c8368>
How can I get the actuall object returned instead of the relation? I know this has something to do with the lazy loading....
Change
self.pref_labels.where("language_id = #{language.id}")
To
self.pref_labels.where("language_id = #{language.id}").all #or .first if you only one the first one