Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 < 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.)

like image 976
grautur Avatar asked Sep 20 '10 03:09

grautur


People also ask

How is polymorphic association set up in Rails?

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.

What is polymorphic association in Rails?

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.

What is single table inheritance in rails?

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.


2 Answers

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.
like image 180
Rohit Avatar answered Nov 09 '22 03:11

Rohit


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.

like image 40
Eric Avatar answered Nov 09 '22 04:11

Eric