A Video, a Song and an Article can have many Tags. And each Tag also can have many Video, Songs or Articles. So I have 5 models: Video, Song, Article, Tag and Taggings.
Here are these models:
class Video < ActiveRecord::Base
has_many :tags, :through => :taggings
end
class Song < ActiveRecord::Base
has_many :tags, :through => :taggings
end
class Article < ActiveRecord::Base
has_many :tags, :through => :taggings
end
class Tag < ActiveRecord::Base
has_many :articles
has_many :videos
has_many :songs
belong_to :taggings, :polymorphic => true #is this correct?
end
The database definition of Taggings
create_table "taggings", :force => true do |t|
t.integer "tag_id"
t.string "taggable_type"
t.integer "taggable_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
Taggings model:
class Taggings < ActiveRecord::Base
belongs_to :tag #is this correct?
belong_to :taggable, :polymorphic => true #is this correct?
end
The issue I'm worried by is, do I have right definitions of model (belongs_to, has_many?) ? My gut tells me that I missed something. I've seen many articles and I'm quite confused by them.
You need these changes:
class Video < ActiveRecord::Base # or Song, or Article
has_many :taggings, :as => :taggable # add this
has_many :tags, :through => :taggings # ok
class Tag < ActiveRecord::Base
# WRONG! Tag has no tagging_id
# belong_to :taggings, :polymorphic => true
has_many :taggings # make it this way
# WRONG! Articles are available through taggings
# has_many :articles
# make it this way
with_options :through => :taggings, :source => :taggable do |tag|
tag.has_many :articles, :source_type => 'Article'
# same for videos
# and for songs
end
About with_options.
Your class Taggings seems ok except its name. It has to be singular, Tagging:
class Tagging < ActiveRecord::Base # no 's'!
belongs_to :tag
belong_to :taggable, :polymorphic => true
end
Related
I'm in front of a little problem, I try to have a polymophic has many through association :
post.rb
has_many :categories, as: :categorizable, through: :categorizations
category.rb
has_many :categorizables, through: :categorizations, dependent: :destroy
event.rb
has_many :categories, as: :categorizable, through: :categorizations
categorization.rb
belongs_to :categorizable, :polymorphic => true
belongs_to :category
My migration :
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
create_table :categorizations do |t|
t.references :category
t.integer :categorizable_id, :polymorphic => true
t.string :categorizable_type, :polymorphic => true
t.datetime :created_at
end
add_index :categorizations, :category_id
end
the problem :
I got this error :
Could not find the association :categorizations in model Post
Or when I try in category
Could not find the association :categorizations in model Category
Does anyone know where is the problem?
You need to specify :categorizations association also, in Category, Post and Event. Also, your as option should go to categorizations association, since this is where you have polymorphism.
Post class:
class Post < ActiveRecord::Base
has_many :categorizations, as: :categorizable
has_many :categories, through: :categorizations
# ...
end
You should modify Event class in similar manner.
Category class:
class Category < ActiveRecord::Base
has_many :categorizations
has_many :categorizables, through: :categorizations, dependent: :destroy
# ...
end
I have read this isnt possible, and then someone else told me it is. They gave me this code but then had to go, now now my app is broken until I get this working :/
I have a Tag model, and each tag has_many resources :through => resource tags. Each resource also has_many tags.
I need to know the number of resource each tag has (I dont care about the other way around).
The problem is it says unkown key cache_counter
This is my model
Tag.rb
has_many :resource_tags, :dependent => :destroy, :counter_cache => :resource_count
has_many :resources, :through => :resource_tags
Resource.rb
has_many :resource_tags, :dependent => :destroy
has_many :tags, :through => :resource_tags
My migration:
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :name
t.integer :resource_count, :default => 0
t.timestamps
end
end
end
:counter_cache option is for belongs_to method
in resorce_tag model
belongs_to :tag, :counter_cache => :resource_count
and i think it is better to name column resources_count (plural)
I am trying to add a "following" like functionality to my site but I am having trouble finding the right way to use a polymorphic association. A user needs to be able to follow 3 different classes, these 3 classes do not follow the user back. I have created a user following user in the past but this is proving to be more difficult.
My Migration was
class CreateRelationships < ActiveRecord::Migration
def change
create_table :relationships do |t|
t.integer :follower_id
t.integer :relations_id
t.string :relations_type
t.timestamps
end
end
end
My Relationship model is
class Relationship < ActiveRecord::Base
attr_accessible :relations_id
belongs_to :relations, :polymorphic => true
has_many :followers, :class_name => "User"
end
In my User model
has_many :relationships, :foreign_key => "supporter_id", :dependent => :destroy
and in the other 3 models
has_many :relationships, :as => :relations
Am I missing something with setting up this association?
You basically have it right, except for a few minor errors:
attr_accessible :relations_id is redundant. Remove it from your Relationship model.
Both Relationship and User models call has_many to associate with each other. Relationship should call belongs_to because it contains the foreign key.
In your User model, set :foreign_key => "follower_id".
Here is how I would do it.
Have a Follow middle class with polymorphic association on the followable content side and has_many on the follower user side (user has many follows).
First, create a follows table:
class CreateFollows < ActiveRecord::Migration
def change
create_table :follows do |t|
t.integer :follower_id
t.references :followable, :polymorphic => true
t.timestamps
end
end
end
Replace Relationship model with a Follow model:
class Follow < ActiveRecord::Base
belongs_to :followable, :polymorphic => true
belongs_to :followers, :class_name => "User"
end
Include in User model:
has_many :follows, :foreign_key => :follower_id
Include in your three followable classes:
has_many :follows, :as => :followable
You can now do this:
TheContent.follows # => [Follow,...] # Useful for counting "N followers"
User.follows # => [Follow,...]
Follow.follower # => User
Follow.followable # => TheContent
I have a User model and a Tag model. The User has Skills and Interests.
A Skill is a Tag, and an Interest is a Tag.
I have a table for Users, Tags, UsersSkills, UsersInterests. The last two being the intermediate table. How do I associate all this. The following is what I have but is not working. Thanks ahead of time.
#User model
class User < ActiveRecord::Base
has_and_belongs_to_many :skills
has_and_belongs_to_many :interests
end
#Tag model
class Tag < ActiveRecord::Base
has_and_belongs_to_many :users
end
#Migrations
create_table :users_interests, :id => false do |t|
t.references :user
t.references :tag
end
create_table :users_skills, :id => false do |t|
t.references :user
t.references :tag
end
SO here is the answer for anyone else experiencing this problem. The intermediate table had to have its name be alphabetically in order, even if that means readability goes down the tube. A join_table was then used. If this is not the right answer (it works but might not be good coding), please let me know.
class User < ActiveRecord::Base
has_and_belongs_to_many :skills, :class_name => "Tag", :join_table => "skills_users"
has_and_belongs_to_many :interests, :class_name => "Tag", :join_table => "interests_users"
end
class Tag < ActiveRecord::Base
has_and_belongs_to_many :users
end
create_table :skills_users, :id => false do |t|
t.references :user
t.references :tag
end
create_table :interests_users, :id => false do |t|
t.references :user
t.references :tag
end
It's expecting your join tables to have skill_id and interest_id FK's rather than tag_id.
I believe you're looking for (don't have a terminal handy):
class User < ActiveRecord::Base
has_and_belongs_to_many :skills, :association_foreign_key => :tag_id
has_and_belongs_to_many :interests, :association_foreign_key => :tag_id
end
Given the fact that I have models like this:
class Person
has_many :owned_groups, :class_name => "Group", :foreign_key => :owner_id
has_many :owned_group_memberships, :through => :owned_groups,
:source => :group_memberships
has_many :group_memberships, :foreign_key => "member_id"
has_many :groups, :through => :group_memberships
end
class GroupMembership
belongs_to :member, :class_name => 'Person'
belongs_to :group
end
class Group
belongs_to :owner, :class_name => "Person"
has_many :group_memberships
has_many :members, :through => :group_memberships
end
How can I access the members a group has? Always I do #group.members or things like that, gives me an error saying that the relation can't be found in the model.
Thanks in advance.
##EDIT##
The error I'm getting is: Could not find the association "group_memberships" in model Group
I do a similar thing on a site I'm working on but the associations are a little different to how you're doing it but maybe it'll help. I think you need to use the has_and_belongs_to_many association to join up your many-to-many's.
In my database I have Users, Members and UsersMembers
You don't need to create a UsersMembers model (GroupMembership in your case) but you do need a database table to link the two.
#Migration
create_table :bands_users, :id => false, :force => true do |t|
t.integer :band_id, :null => false
t.integer :user_id, :null => false
end
#Models
class Band < ActiveRecord::Base
has_and_belongs_to_many :members, :class_name => 'User'
end
class User < ActiveRecord::Base
has_and_belongs_to_many :bands
end
From this I can now call #band.members or #user.bands
You may need to specify :class_name => 'Person' in your has_many :members statement.