I have a couple classes that can each have comments:
class Movie < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Actor < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
How do I create a form for a new movie-comment? I added
resources :movies do
resources :comments
end
to my routes.rb, and tried new_movie_comment_path(@movie), but this gives me a form containing commentable_id and commentable_type [which I want to be populated automatically, not entered by the user directly]. I also tried creating the form myself:
form_for [@movie, Comment.new] do |f|
f.text_field :text
f.submit
end
(where "text" is a field in the Comment table) but this doesn't work either.
I'm not actually sure how to associate a comment with a movie at all. For example,
c = Comment.create(:text => "This is a comment.", :commentable_id => 1, :commentable_type => "movie")
doesn't seem to create a comment associated to the movie with id 1. (Movie.find(1).comments returns an empty array.)
In Ruby on Rails, a polymorphic association is an Active Record association that can connect a model to multiple other models. For example, we can use a single association to connect the Review model with the Event and Restaurant models, allowing us to connect a review with either an event or a restaurant.
Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.
Single-table inheritance (STI) is the practice of storing multiple types of values in the same table, where each record includes a field indicating its type, and the table includes a column for every field of all the types it stores.
As you have created the polymorphic association in your model, you need not worry about that anymore in the view. You just need to do this in your Comments controller.
@movie = Movie.find(id) # Find the movie with which you want to associate the comment
@comment = @movie.comments.create(:text => "This is a comment") # you can also use build
# instead of create like @comment = @movie.comments.create(:text => "This is a comment")
# and then @comment.save
# The above line will build your new comment through the movie which you will be having in
# @movie.
# Also this line will automatically save fill the commentable_id as the id of movie and
# the commentable_type as Movie.
You're going to have to be more descriptive than "...but this doesn't work either," but the general idea is:
@movie.comments.create( :text => params[:movie][:comment][:text] )
More typically:
@movie.comments.create( params[:comment] ) # or params[:movie][:comment]
The important thing is that you find @movie
first and create your associated objects through it. That way you won't have to worry about Commentable
or types or anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With