Models:
class Thread < ActiveRecord::Base
has_many :threaded, :through => :threaded, :foreign_key => :thread_id
class ThreadFeed < ActiveRecord::Base
belongs_to :threaded, :polymorphic => true
Model Fields
Thread (id)
ThreadFeed (id, thread_id, threaded_id, threaded_type)
Problem is with:
#thread.threaded
Rails is using (threaded_id, threaded_type) as the foreign key and I want thread_id to be the foreign key.
Take a look into this Railscast, Polymorphism
It will give you a better insight into how Polymorphism works.
First issue I notice is that it should be through :threadfeed, not :threaded
class Thread < ActiveRecord::Base
has_many :threadfeeds, :as => :threaded
In the Railscast, he has:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Article < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Photo < ActiveRecord::Base
has_many :comments, :as => :commentable
#...
end
class Event < ActiveRecord::Base
has_many :comments, :as => :commentable
end
The first problem is that Thread doesn't know what feed is:
class Thread < ActiveRecord::Base
has_many :feeds, :through => :thread_feeds, :as => :feeded
has_many :thread_feeds
class ThreadFeed < ActiveRecord::Base
belongs_to :feeded, :polymorphic => true
The second problem is the complexity of polymorphic. Here's a great article on it: http://blog.hasmanythrough.com/2006/4/3/polymorphic-through
Related
I've Googled and searched the forums but can't seem to find an answer that fits my scenario.
Let's say have the following models:
class TextProblem < ActiveRecord::Base
belongs_to :askable, :polymorphic => true
...
end
class MultipleChoice < ActiveRecord::Base
belongs_to :askable, :polymorphic => true
...
end
class WordMatch < ActiveRecord::Base
belongs_to :askable, :polymorphic => true
...
end
Now I have another model called question. It has a field named question_type_id that indicates what type of question it is and a field named question_id that is the foreign key to one of the askables.. I want to do something like this:
class Question < ActiveRecord::Base
has_one :askable, :foreign_key => 'question_id' ....
end
and give it the correct askable but I'm not sure how to write the association. Am I looking at this right or should I be trying to achieve this another way?
Any help is appreciated!
You should have your association the other way round
class Question < ActiveRecord::Base
belongs_to :askable, :polymorphic => true
end
class TextProblem < ActiveRecord::Base
has_many :questions, :as => :askable
...
end
class MultipleChoice < ActiveRecord::Base
has_many :questions, :as => :askable
...
end
class WordMatch < ActiveRecord::Base
has_many :questions, :as => :askable
...
end
Refer to this.
i have the following models
class Airplane < ActiveRecord::Base
has_many :airtags
has_many :pictures, :through => :airtags
end
class Airtag < ActiveRecord::Base
attr_accessible :airable_type, :airable_id, :airplane_id
belongs_to :airplane
belongs_to :airable, :polymorphic => true
end
class Picture < ActiveRecord::Base
belongs_to :picturable, :polymorphic => true
has_many :airtags, :as => :airable, :dependent => :destroy
has_many :airplanes, :through => :airtags
end
in my airplane show, i want to list all pictures, ordered by their name.
#airplane.pictures.order(:name)
Basically I want a Topic to have many Posts and Posts to have many Comments. If a Post gets destroyed I want it's Comments to be destroyed. If a Topic is deleted, I want it's Posts and Comments destroyed. Does the code below accomplish this? And is the has_one :topic line necessary?
topic.rb:
class Topic < ActiveRecord::Base
has_many :posts, :dependent => :destroy
end
post.rb:
class Post < ActiveRecord::Base
belongs_to :topic, :dependent => :destroy, :touch => true
has_one :topic
has_many :comments, :dependent => :destroy
end
comment.rb:
class Comment < ActiveRecord::Base
belongs_to :post, :dependent => :destroy, :touch => true
end
Should I be using the Ancestry gem for this? Would that make this even more simple? Thanks for reading my questions. Any assistance would be greatly appreciated.
1) has_one :topic is unnecessary, with the belongs_to you already declare the association.
2) :dependent => :destroy goes on the has_many side for your requirements. If you place them on the belongs_to side you will destroy a Topic once destroying one of his posts, leaving orphan a lot of other posts.
This is the code you're looking for:
topic.rb:
class Topic < ActiveRecord::Base
has_many :posts, :dependent => :destroy
end
post.rb:
class Post < ActiveRecord::Base
belongs_to :topic, :touch => true
has_many :comments, :dependent => :destroy
end
comment.rb:
class Comment < ActiveRecord::Base
belongs_to :post, :touch => true
end
Right now I have a rich many-to-many association with VideoVote as the independent record.
class VideoVote < ActiveRecord::Base
belongs_to :user
belongs_to :video
end
class User < ActiveRecord::Base
has_many :video_votes
has_many :voted_videos,
:through => :video_votes,
:source => :video
end
class Video < ActiveRecord::Base
has_many :video_votes
has_many :voted_users,
:through => :video_votes,
:source => :user
end
However, I want to trasform this into a polymorphic association where comments can also have many VideoVotes (I realize this is confusing, so I should probably change it to Votes). (also, a video will have many comments.) How should I do this?
You first want to add voteable_id:integer and voteable_type:string to your video_votes table.
Then your models will look like:
class VideoVote < ActiveRecord::Base
belongs_to :voteable, :polymorphic => true
end
class Comment < ActiveRecord::Base
has_many :video_votes, :as => :voteable
#code
end
class Video < ActiveRecord::Base
has_many :video_votes, :as => :voteable
#code
end
Then you can access them just like any other has_many:
#video.video_votes
#comment.video_votes
#etc.
I'm using has_many_polymorphs to create a "Favorites" feature on a site where multiple users can post stories and make comments. I want users to be able to "favorite" stories and comments.
class User < ActiveRecord::Base
has_many :stories
has_many :comments
has_many_polymorphs :favorites, :from => [:stories, :comments]
end
class Story < ActiveRecord::Base
belongs_to :user, :counter_cache => true
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :story, :counter_cache => true
end
class FavoritesUser < ActiveRecord::Base
belongs_to :user
belongs_to :favorite, :polymorphic => true
end
Now say #user writes a story. Now #user.stories.size = 1. Then #user favorites a different story. Now #user.stories... wait a minute. #user has_many :stories and :has_many :stories through :favorites.
The issue arises when I attempt to call #user.stories or #user.comments. I want to call #user.stories for stories they own and #user.favorites.stories for stories they favorite.
So I tried this:
class User < ActiveRecord::Base
has_many :stories
has_many :comments
has_many_polymorphs :favorites, :from => [:favorite_stories, :favorite_comments]
end
and then subclassed Story and Comment like so:
class FavoriteStory < Story
end
class FavoriteComment < Comment
end
That fixed the problem because now I can call #user.stories and #user.favorite_stories.
BUT when I get this error in reference to comments:
ActiveRecord::Associations::PolymorphicError in UsersController#show
Could not find a valid class for :favorite_comments (tried FavoriteComment). If it's namespaced, be sure to specify it as :"module/favorite_comments" instead.
I found discussion of this error in a similar context, but it doesn't answer my question.
What's going on here? How can I do this better?
What about something like this?
class UserFavorite < ActiveRecord::Base
belongs_to :user
belongs_to :favorite, :polymorphic => true
end
class User < ActiveRecord::Base
has_many :favourite_story_items, :class_name => "UserFavourite", :conditions => "type = 'Story'"
has_many :favourite_stories, :through => :favourite_story_items, :as => :favourite
has_many :favourite_comment_items, :class_name => "UserFavourite", :conditions => "type = 'Comment'"
has_many :favourite_comments, :through => :favourite_comment_items, :as => :favourite
end