Creating forms for polymorphic associations in Rails
I have a couple classes that can each have comments:
class Movie < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Actor < Activ开发者_如何学运维eRecord::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.)
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.
精彩评论