I have 3 classes:
1. Article
class Article < ActiveRecord::Base
has_many :categories_articles
has_many :subcategories_articles
has_many :categories, :through => :categories_articles
has_many :subcategories, :through => :subcategories_articles
end
2.Category
class Category < ActiveRecord::Base
has_many :articles
has_many :categories_articles
has_many :categories_subcategories
has_many :subcategories, :through => :categories_subcategories
has_many :articles, :through => :categories_articles
end
3.The third class is the union of the first two, category_article
class CategoryArticle < ActiveRecord::Base
belongs_to :category
belongs_to :article
end
so, when i called in the view
<% f.collection_select(:category_ids, Category.all, :id, :name, {include_blank:"selects"},{class:'form-control select2 multi', :required=>true, multiple: true}) %>
I get this error:
uninitialized constant Article::CategoriesArticle
The same goes for the class Subcategory and subcategory_article
Try
has_many :category_articles
And
has_many :subcategory_articles
You'll also have to change these:
has_many :categories, :through => :categories_articles
has_many :subcategories, :through => :subcategories_articles
To something like:
has_many :categories, :through => :category_articles
has_many :subcategories, :through => :subcategory_articles
Rails doesn't pluralize both components of the composite table names. Just the last component.
Related
I am trying to transform my HABTM to has_many through relations. Sometimes I have to connect the same models in different ways. For example to specify different roles for authors.
With a HABTM I would do this through the declaration of a class_name option. Just like:-
class Project < ActiveRecord::Base
has_and_belongs_to_many :curators, :class_name => :author, :through => :projects_curators
end
class ProjectsCurator < ActiveRecord::Base
attr_accessible :project_id, :author_id
belongs_to :project
belongs_to :author
end
class Author < ActiveRecord::Base
has_and_belongs_to_many :projects, :through => :projects_curators
end
But when I transform everything into a has_many through:
class Project < ActiveRecord::Base
has_many :project_curators
has_many :curators, :class_name => :author, :through => :project_curators
end
class ProjectCurator < ActiveRecord::Base
attr_accessible :project_id, :author_id
belongs_to :project
belongs_to :author
end
class Author < ActiveRecord::Base
has_many :project_curators
has_many :projects, :through => :project_curators
end
I get: Could not find the source association(s) :curator or :curators in model ProjectCurator. Try 'has_many :curators, :through => :project_curators, :source => <name>'. Is it one of :author or :project?
When I add :source
has_many :curators, :class_name => :author, :through => :project_curators, :source => :author
I get:
uninitialized constant Project::author
How can I get this working? Thank you very much in advance!
Understanding :source option of has_one/has_many through of Rails should help you out
When you declare the source you're not declaring the class of the has_many relationship, but the name of the relationship you're using as the middle man. In your case, try:
has_many :curators, :through => :project_curators, :source => :author
As someone in the above post states:
Most simple answer - the name of the relationship in the middle
In my app I have 3 models: Item, Category and Categorization defined as below:
class Item < ActiveRecord::Base
attr_accessible :name, :description
has_many :categorizations
has_many :categories, :through => :categorizations
end
class Category < ActiveRecord::Base
attr_accessible :name, :description, :parent, :children, :items, :parent_id
has_many :children, :class_name => "Category", :foreign_key => "parent_id", :dependent => :nullify
belongs_to :parent, :class_name => "Category"
has_many :categorizations
has_many :items, :through => :categorizations
end
class Categorization < ActiveRecord::Base
attr_accessible :category, :item
belongs_to :category
belongs_to :item
end
However, doing this:
Category.where(:parent_id => self.id).includes(:items)
won't return me the items associated to the category. What am I missing here?
Try this:
Category.where(parent_id: id).joins(:items)
Try this:
Category.where(:parent_id => id).collect(&:items)
It will return the items of all categories matching the where clause.
I have two tables for tagging so that I can attach tags to any models, it works likes so…
There's a tagged item join table which has a tag_id column and then two other columns for polymorphism: taggable_type and taggable_id…
class TaggedItem < ActiveRecord::Base
attr_accessible :taggable_id, :taggable_type, :tag_id
belongs_to :taggable, :polymorphic => true
belongs_to :tag
end
There's also all of the things that can have tags, for example here's a product and image model with tags attached:
class Product < ActiveRecord::Base
has_many :tagged_items, :as => :taggable, :dependent => :destroy
has_many :tags, :through => :tagged_items
end
class Image < ActiveRecord::Base
has_many :tagged_items, :as => :taggable, :dependent => :destroy
has_many :tags, :through => :tagged_items
end
The problem is with the tag model, I can seem to get the reverse work, on the tag modle I want to have a has_many images and has_many products like so:
class Tag < ActiveRecord::Base
has_many :tagged_items, :dependent => :destroy
has_many :products, :through => :tagged_items
has_many :images, :through => :tagged_items
end
This is causing an error, I was wondering how I can fix this. So the tag table works through the polymorphic tagged items table.
Any help would be much appreciated. Thanks!
Edit:
Could not find the source association(s) :product or :products in model TaggedItem. Try 'has_many :products, :through => :tagged_items, :source => <name>'. Is it one of :taggable or :tag?
The has_many :through associations in your Tag model are not able to get the source association for Product and Image from the TaggedItem Model. e.g. has_many :products, :through => :tagged_items will look for a direct association belongs_to :product in TaggedItem which in case of polymorphic association is written as belongs_to :taggable, :polymorphic => true. So for the Tag model to understand exact source of the association we need to add an option :source and its type as :source_type
So change your Tag model associations to look like
class Tag < ActiveRecord::Base
has_many :tagged_items, :dependent => :destroy
has_many :products, :through => :tagged_items, :source => :taggable, :source_type => 'Product'
has_many :images, :through => :tagged_items, :source => :taggable, :source_type => 'Image'
end
This should fix your problem. :)
you do not need the as option when you set up the Tag association to TaggedItem. :as => :taggable would mean that tag on tagged item is polymorphic which it is not. Instead the other side is, ie., the items that are taggable as your name cleverly suggests :).
class Tag < ActiveRecord::Base
has_many :tagged_items, :dependent => :destroy
has_many :products, :through => :tagged_items
has_many :images, :through => :tagged_items
end
The following examples differ only in the Book and Movie models.
Example 1: Book has_many :taggings, :as => :taggable
Example 2: Book has_many :taggings, :through => :taggable
What does this difference mean?
Example 1:
class Book < ActiveRecord::Base
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings
end
class Movie < ActiveRecord::Base
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings
end
class Tag < ActiveRecord::Base
has_many :taggings
has_many :books, :through => :taggings, :source => :taggable, :source_type => "Book"
has_many :movies, :through => :taggings, :source => :taggable, :source_type => "Movie"
end
class Tagging < ActiveRecord::Base
belongs_to :taggable, :polymorphic => true
belongs_to :tag
end
Example 2:
class Book < ActiveRecord::Base
has_many :taggings, :through => :taggable
has_many :tags, :through => :taggings
end
class Movie < ActiveRecord::Base
has_many :taggings, :through => :taggable
has_many :tags, :through => :taggings
end
class Tag < ActiveRecord::Base
has_many :taggings
has_many :books, :through => :taggings, :source => :taggable, :source_type => "Book"
has_many :movies, :through => :taggings, :source => :taggable, :source_type => "Movie"
end
class Tagging < ActiveRecord::Base
belongs_to :taggable, :polymorphic => true
belongs_to :tag
end
Are you sure the 2nd example works? I don't have an rails environment in windows.
For my understanding about your question,
case1.
has_many :taggings, :as => :taggable
here the "taggable" is not an exact Model name, it's just an alias. (there's no Taggable class)
case2.
has_many :taggings, :through => :taggable
here the "taggable" must be an real (exsting) model, I mean there must be an Taggable class somewhere.
refer: http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
Assuming the examples worked .. and taggable was a real model .. which as Siwei suggests probably doesn't actually work ...
:as defines a polymorphic association
and
:through says that
if A has many B's
and B has many C's
then A has many C's through B
I have a User Model(:name, :password, :email), and Event model(:name, :etc) and Interest model (:name) [>all singular<]
Then I created two join tables -> UsersInterests and EventsInterests; each not containing a primary key and only comprised of the user_id/interest_id and event_id/interest_id respectively. [>plural<]
My Models Use the Nested Has Many Through Plugin
user.rb => has_many :users_interests
has_many :interests, :through => :users_interests
has_many :events_interests, :through => :interests
has_many :events, :through => :events_interests
event.rb => has_many :events_interests
has_many :interests, :through => :events_interests
has_many :users_interests, :through => :interests
has_many :users, :through => :users_interests
interest.rb => has_and_belongs_to_many :users
has_and_belongs_to_many :events
events_interests.rb => belongs_to :interests
belongs_to :events
users_interests.rb => belongs_to :users
belongs_to :interests
Whew..ok So I wanted to created a named_scope of that find all the events that share interest with a particular user. Here is some code someone helped me with.
named_scope :shares_interest_with_users, lambda {|user|
{ :joins => :users_interests,
:conditions => {:users_interests => {:user_id => user}}
}}
When i run from the controller =>
#user = User.find(1)
#events = Event.shares_interest_with_user(#user)
I get the error :
uninitialized constant Event::EventsInterest
Can anyone see what i messed up?
You must have named something wrong along the way. At a glance I'd say you have a file or class named incorrectly. Remember model names MUST always be singular, both in file and class names or else Rails won't make the connection. Another source of your problem is that arguments to belongs_to must also be singular. Even if you had got things right, the HABTM relationship in interests with users would have thrown an error when you ran the named scope.
I was able to solve your error with the following models.
user.rb
class User < ActiveRecord::Base
has_many :users_interests
has_many :interests, :through => :users_interests
has_many :events_interests, :through => :interests
has_many :events, :through => :events_interests
end
users_interest.rb
class UsersInterest < ActiveRecord::Base
belongs_to :user
belongs_to :interest
end
interest.rb
class Interest < ActiveRecord::Base
has_many :users,:through => :users_interests
has_many :users_interests
has_many :events_interests
has_many :events, :through => :events_interests
end
**events_interest.rb
class EventsInterest <ActiveRecord::Base
belongs_to :interest
belongs_to :event
end
event.rb
class Event <ActiveRecord::Base
has_many :events_interests
has_many :interests, :through => :events_interests
has_many :users_interests, :through => :interests
has_many :users, :through => :users_interests
named_scope :shares_interest_with_users, lambda {|user|
{ :joins => :users_interests,
:conditions => {:users_interests => {:user_id => user}}
}
}
end