rails: self-referential association - ruby-on-rails

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

Related

Rails table join with extra details doesn't work

I have these 2 models, and I'm trying to add an association between them so I can add some extra details later:
class Ticket < ActiveRecord::Base
belongs_to :user
has_many :event_tickets
has_many :events, :through => :event_tickets
end
class Event < ActiveRecord::Base
has_many :event_tickets
has_many :tickets, :through => :event_tickets
end
class EventTicket < ActiveRecord::Base
belongs_to :event
belongs_to :ticket
end
I've tried adding an association like this, just to see it's working:
event_ticket = EventTicket.new(:ticket => ticket, :event => Event.all[0])
event_ticket.save!
This gives me:
can't write unknown attribute `ticket_id`
The ticket and event exist and are working fine, but can't get the event_ticket object working.
What am I doing wrong?
It sounds like you don't have an event_tickets table, or at least it doesn't have a ticket_id column. Are you sure you wrote the migration and ran it?

Rails model association

I am trying to design model associations in rails
that consist of the following 3 types:
Commentator, Blogpost and Comment
--> it's "Commentator" and not "User" what means
that they are not the users who create blogposts...
instead they create comments only.
While the basic relationship between Commentator
and Comment is obvious:
class Commentator < ActiveRecord::Base
has_many :comments
class Comment < ActiveRecord::Base
belongs_to: comments
I am not sure how to relate "Blogpost" to this...
--> I would like go be able to ask for all the Blogposts
a Commentator has left as well as all the Commentators
of a specific Blogpost.
Since this is a many-to-many relationship I
would use:
class Commentator < ActiveRecord::Base
has_many :comments
has_many :blogposts, :through => :comments
class Blogpost < ActiveRecord::Base
"has_many :commentators, :through => :comments
When a commentator creates a blogpost, do I have to
write the commenentator_id and blogpost_id in comments
by myself into the corresponding fields of the comment table?
I think it would be better to have Blogposts as the
going through element since the relationship could be
automatically be build when a commentator creates a comment.
(apart from the fact that commentators cannot create comments
to Blogposts that do not exist...)
But then, Commentator to Comment would NOT be a many-to-many
relationship and I cannot use "has_many ... through" anymore.
What is a good way to relate this 3 types of models?
Solution to the stated problem
class Commentator < ActiveRecord::Base
has_many :comments
has_many :blogposts, :through => :comments
end
class Comment < ActiveRecord::Base
belongs_to :commentator
belongs_to :blogpost
end
class Blogpost < ActiveRecord::Base
has_many :comments
has_many :commentators, :through => :comments
belongs_to :user
class User
has_many :blogposts
end
To add a comment to an existing blog post (assuming we have a blog and commentator variables)
blog.comments.create(:commentator => commentator, :comment => "foo bar")
OR
commentator.comments.create(:blog => blog, :comment => "foo bar")
Note
Instead of using two models for users(i.e. User and Commenter), I would use one model and assign privileges
to distinguish between a commentor and a blog post writer.
class User
has_many :blogs
has_many :comments
has_many :commented_blogs, :through => :comments, :source => :blog
end
class Blog
has_many :comments
belongs_to :user
has_many :commenters, :through => :comments, :source => :user
end
class Comment
belongs_to :user
belongs_to :blog
end
Creating a blog entry:
if current_user.has_role?(:blog_writer)
current_user.blogs.create(params[:blog])
end
Adding a comment:
current_user.comments.create(:blog => blog, :content => "foor bar")
OR
blog.comments.create(:user => current_user, :content => "foor bar")

Nested associates the rails way

I'm fairly new to Rails and I'm trying to gain a better understanding of how to be leverage the Rails framework for my associations.
While it's not specific for my app, the structure is similar -- for my example, I'll use the standard blog associates.
Example Models:
class Author < ActiveRecord::Base
has_many :posts, :through => :posts
end
class Post < ActiveRecord::Base
belongs_to :author
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
end
My challenge is that I want to select all comments that belong to a specific author. I understand how to reference post and author elements that are associated with a specific post:
comment_author = Comment.first
puts comment_author.post.author.name
But as I stated I'm trying to select all comments that belong to a specific author. I could accomplish this by doing a find_by_sql, but I want to ensure db independence and I want to do this the "Rails way."
Thanks!
You can use the has_many :through assocication:
class Author < ActiveRecord::Base
has_many :posts
has_many :comments, :through => :posts
end
#Femaref provided the exact answer to your question and you should accept it. Mine is merely a complement.
If an author can leave comments on posts, here is what you might want to do:
class Author
has_many :posts
has_many :comments
has_many :responses, through: :posts, source: :comments
end
class Post
belongs_to :author
has_many :comments
end
class Comment
belongs_to :author
belongs_to :post
end
To get all the comments left by sophia: sophia.comments
To get all the comments left on sophia's posts: sophia.responses
See the options for has_many (especially through and source)

Comment belongs_to one of several models

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.

Rails: Implementing a reuseable Comment model

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.

Resources