views:

50

answers:

2

Hello, I'm working to install the acts_as_commentable plugin on my Rails 3 app.

After adding "acts_as_commentable" to my book model, I then added a comment form on my book show view:

<% form_for(@comment) do|f| %> 
  <%= f.hidden_field :book_id %> 
  <%= f.label :comment %><br /> 
  <%= f.text_area :comment %> 
  <%= f.submit "Post Comment" %> 
<% end %> 

Then in the controller (comments_controller.rb),

  def create 
    @comment = Comment.new(params[:comment]) 
    Book.comments.create(:title => "First comment.", :comment => "This 
is the first comment.") 
  end 

Then when submitting a comment, it returns the error: "unknown attribute: book_id" From the log:

  Processing by CommentsController#create as HTML 
  Parameters: {"comment"=>{"comment"=>"WOOOW", "book_id"=>"32"}, 
"commit"=>"Post Comment", 
"authenticity_token"=>"5YbtEMpoQL1e9coAIJBOm0WD55vB2XRZMJa4MMAR1YI=", 
"utf8"=>"✓"} 
Completed   in 11ms 
ActiveRecord::UnknownAttributeError (unknown attribute: book_id): 
  app/controllers/comments_controller.rb:3:in `new' 
  app/controllers/comments_controller.rb:3:in `create' 

Suggestions?

+1  A: 
<%= f.hidden_field :book_id %> 

It means your Comment model has no book_id field. Also, it's not a very good idea to call a field as the model name (comment). Use body (or message) instead of comment for the field which should contains the message body.

Simone Carletti
Thanks but I don't think that's an option with the Acts As Commentable plugin for Rails 3
AnApprentice
+1  A: 

I think you have to options:

Option 1) The view:

<% form_for(@comment) do|f| %> 
  <%= f.hidden_field :commentable_id, :value => @book.id %>
  <%= f.hidden_field :commentable_type, :value => 'Book' %> 
  <%= f.label :comment %><br /> 
  <%= f.text_area :comment %> 
  <%= f.submit "Post Comment" %> 
<% end %> 

The controller:

def create
  @comment = Comment.create(params[:comment])
end

Option 2)

In the controller:

def create
  @book = Book.find(params[:comment][:book_id])
  @comment = @book.comments.create(params[:comment].except([:comment][:book_id]))
end

I haven't tested the code, but the idea should be correct

Update, given you want to comment on various models (i'm writting my code without testing it...). So let's say you have Book and Magazine, and you want to comment on them. I guess I would define nested routes for them.

map.resources :books, :has_many => :comments
map.resources :magazines, :has_many => :comments

And then in your controller you could do:

before_filter :find_commentable

def find_commentable
  @commentable = Book.find(params[:book_id]) if params[:book_id]
  @commentable = Magazine.find(params[:magazine_id]) if params[:magazine_id]
end

And in the new view:

<% form_for :comment, [@commentable, @comment] do |f| %>
  <%= f.label :comment %>
  <%= f.text_area :comment %>
  <%= f.submit %>
<% end %>

So the create action could look something like:

def create
  @user.comments.create(params[:comment].merge(:commentable_id => @commentable.id, :commentable_type => @commentable.class.name))
  redirect_to @commentable
end

Maybe there are even better ways to do it...

jordinl
@Jordinl thanks for this... Is this the normal way acts as commentable works? My concern with this is I want comment on various models and the above code is customer per model which isn't DRY. Does that make sense? Also to get the user_id set in the comments table, I updated it to "@comment = current_user.comments.create(params[:comment])" Is there a way where I can get this commenting to work for books and then be able to apply it to any model with about repeating everything or customizing the hidden fields, etc.. ?
AnApprentice
i'll edit my answer
jordinl
@jordinl very nice. I'm going to try that out and report back tonight. Thanks!
AnApprentice