My scenario is that there are several different models which can have comments. Trying to figure out the relationships:
Post
has_many :comments
Update
has_many :comments
Comment
belongs_to EITHER :post OR :update (but not both)????
Whats the proper way to set up the comment relationships? I want to be able to call Post.comments and Update.comments
Smells like a polymorphic association:
With polymorphic associations, a model can belong to more than one other model, on a single association. For example, you might have a picture model that belongs to either an employee model or a product model.
So you'd want something like this:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Post < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Update < ActiveRecord::Base
has_many :comments, :as => :commentable
end
You'd have to set up a few things in the database for this to work as well. See the Polymorphic Associations section of the Active Record Associations Guide for details on the columns you'll need.
Related
I'm new to Rails and have some doubts about the kind of relationship do I need to use. Here is the case.
I have two models Offer and User, a user could belong to to many offers and offers can have many user. Also the users create the offers.
I think I have to use a has_many :through ralationship. For example I've created another model "Applicant". Applicant belongs_to user and belongs_to offer. But how is the relationship from the user and offer model? For example:
User Model
has_many :offer, :through => :applicant
Offer Model
has_many :user, :through => :applicant
My doubt is because I already have this two relationship
User Model
has_many :offers, :dependent => :destroy
Offer Model
belongs_to :user
After solve this, I guest I have to save the record in the applicant model from the applicanst_controller, right?
Thanks in advance
What you have described is a many-to-many relationship using a join table. You're actually pretty close but you just need to remove the has_many :offers, :dependent => :destroy from your user model and the blongs_to :user in your offer model. It should look something like this:
class User < ActiveRecord::Base
has_many :offers, :through => :applicants
end
class Applicant < ActiveRecord::Base
belongs_to :users
belongs_to :offers
end
class Offer < ActiveRecord::Base
has_many :users, :through => :applicants
end
You don't have to worry about the dependent destroy part as associations are automatically removed as the corresponding objects are removed. With a many to many association it doesn't really matter how you go about building the relationship. Either of the following will work:
#user.offers << #offer
#offers.users << #user
If you don't need to store any information specific to your applicant join table (e.g., time stamps, descriptions) you might instead want to look at a has_and_belongs_to_many relationship. Check out choosing between has_many_through and has_and_belongs_to_many for reference.
Edit
Heres the code for a HABTM relationship:
class User < ActiveRecord::Base
has_and_belongs_to_many :offers
end
class Offer < ActiveRecord::Base
has_and_belongs_to_many :users
end
I have a Comments model, and I also have a Video, and Photo model. Now, I want for my Video and Photo models to have_many comments, but that means my Comment model will have to have a belongs to :video and a belongs_to :model (as well as foreign keys for each model in the database). Now say I create a Post model in that same application and I want it to have many comments, that would mean I would have to add belongs_to :post to my Comment class. In rails is there a better way to implement a Comment model when there are many other models that are going to have an association with it, or is this just how it is done? Any advice would be much appreciated.
You're looking for polymorphic associations.
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Photo < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Video < ActiveRecord::Base
has_many :comments, :as => :commentable
end
You also have to make some changes to your migrations, see the linked documentation for more information.
My needs are very simple: I have a Tip table to receive comments and have comments to receive comments, too.
To retrieve each comment that is stored in the same table (comments), I created another key for the comments on comments: "inverse_comments".
I tried to use one comments table by using self-referntial association. Some resources seem to bring more than one table into the piture which are diffent from my needs. So I came up whth the following modeling for comments:
class Comment < ActiveRecord::Base
belongs_to :tip
belongs_to :user
has_many :mycomments,
:through => :inverse_comments,
:source => :comment
end
Apparently something is missing here but I cannot figure it out.
Could some one enlighten me on this:
what changes I need to do to make the model work?
thanks.
I believe you should use a polymorphic association.
For that you'll need to add a commentable_id and a commentable_type on your comments table. And your models should look like:
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :commentable, :polymorphic => true
has_many :comments, :as => :commentable
end
class Tip < ActiveRecord::Base
has_many :comments, :as => :commentable
end
This way you can use
#tip.comments
#comment.comments
Say I'm writing a blog app with models for posts, pages and photos. I've got a category model, that may be linked to any of these models. So, a category may contain various kinds of items. Every item only has ONE category.
I could implement this using a generic tagging pattern with a join table, but I want to make sure every subject can have only category.
What would be the best way to implement this in Rails?
Okay, I think I've got it:
class Post < ActiveRecord::Base
has_one :categorization, :as => :categorizable
has_one :category, :through => :categorization
end
class Category < ActiveRecord::Base
has_many :categorizations, :dependent => :destroy
end
class Categorization < ActiveRecord::Base
belongs_to :category
belongs_to :categorizable, :polymorphic => true
end
Now various models can have a category, but each instance can have only one category… I guess.
In my Rails application, I have two models, Articles and Projects, which are both associated with a user. I want to add comments to each of these models. What's the best way to structure this?
Here's my current setup:
class Comment < ActiveRecord::Base
belongs_to :article
belongs_to :project
end
class Article < ActiveRecord::Base
belongs_to :user
has_many :comments
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :comments
end
class User < ActiveRecord::Base
has_many :articles
has_many :projects
has_many :comments, :through => :articles
has_many :comments, :through => :projects
end
Is this the right way to handle the structure? If so, how do I manage the CommentsController to have an article_id if it was created through an Article, and a project_id if it was created through a Project? Are there special routes I should set up?
One final comment: Comments don't always have to have a user. Since this if for my website, I want anonymous viewers to be able to leave comments. Is this a trivial task to handle?
Make Comment a polymorphic model. Then create a polymorphic association.
Here's an example of polymorphic relationship from the Rails wiki and here's a Railscast from the screencast-men Ryan Bates.
You can check out - acts_as_commentable plugin http://github.com/jackdempsey/acts_as_commentable/tree/master
Or you can proceed with polymorphic relation
You could have ArticleComments and ProjectComments with similar structure but stored separately, then create a method that returns both types of comments.