views:

116

answers:

6

I am creating a very simple book review site and it needs the ability to allow the user to add little comments about a book. Now I have my two tables, one for the book and one for the comments and now need a way to transfer data between the two because i find the way rails handles things quite puzzling.

So my book model contains "has_many :comments" and me comment model has: "belongs_to :book"

the view i am using to both view and add comments is "/views/book/viewbook.html.erb" this shows the book and all its details, at the bottom is a section where the user can add their own comments, it looks like this:

     <%= form.text_field :title %>
    <%= form.text_area :body %>
    <%= submit_tag "Add Comment", :class => "submit" %>

now i know this cannot work because that above ":title" and ":body" would be in the book model but i need them to be send to the comment model because these are in the comment DB. How do i pass this data to the comment database. I've tried ":comment.title" and other various things but still cannot workout how to pass this data.

Any thoughts would be greatly appreciated.

(I apologize if this question is very stupid or has not been explained to well, my lecturer set this assignment and rails is not a language i have ever used.)

A: 

It sounds like you need to use nested object forms. This is a new feature in Rails 2.3:

http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

+2  A: 

You define what the form is for in the opening form tag:

<% form_for :comment do |form| %>

  <%= form.text_field :title %>
  <%= form.text_area  :body %>

  <%= submit_tag "Add Comment", :class => "submit" %>

<%= end %>

The idea is that the form is an empty comment object. Controllers communicate between models and views, so your controller should have an action to process the form that knows to save the comment object into the comment model. You'll also want to specify which book the comment is for. There are a lot of ways to handle this (hidden fields, nested RESTful resources, etc.).

Maybe start here: http://guides.rubyonrails.org/action_controller_overview.html

Jarrod
A: 

So i have modified it using your great suggestions and now only one problem has come-up. Whilst i can now successfully store the comments title, body, time and the person who left the comment to the DB i still cant work out how to use store the book.id. Here is the view:

<% form_for :comment, :url => { :action => "addcomment" } do |form| %>
  <%= form.hidden_field :user_id, :value => session[:user_id] %>
  <%= form.hidden_field :book_id, :value => @book.id %> <!-- WONT WORK -->
  <%= form.label "Title" %><%= form.text_field :title %><br />
  <%= form.label "Comment" %><%= form.text_area :comment %>
    <%= submit_tag "addComment", :class => "submit" %>
<% end %>

Here is my controller that can now successfully store the details, apart from the book.id

def addcomment
  @newcomment = Comment.new(params[:comment])
  if @newcomment.save
    flash[:notice] = "Comment Was Added To The System."
    redirect_to :action => "index"
  end
end

i though that "@book.id" would work because in that view i am also showing the books details using things like "@book.title" and "@book.authour" and that seems to work, but not for the ID field though.

Looks like that should work. Are your associations set up correctly in your models (has_many and belongs_to)? Maybe it's saving the correct info, but without the correct associations it isn't finding what it should.
Jarrod
Don't accept the posting user_id via the form. Read it from the session as you save the comment to the DB. Otherwise anyone can submit a comment as anyone else. In other words, you shouldn't trust data sent from the client.
James
A: 

So can now successfully post comments and store them with the correct details, now im on to displaying a list of comments of that particular book using the "book_id" value. Here is what i thought would work, i also have code like this in the search part of my app so i thought it would well:

def view
  @book = Book.find(params[:id])
  @reviews = Comment.find_by_book_id(@book.id)
end

With the corresponding view:

<% if @reviews %>
  <% for review in @reviews %>
    <%= form.label "Title: " %><%h review.title %> <br />
    <%= form.label "Review:" %><%h review.comment %>
  <% end %>
<% end %>

Now that should get the comments that have the "book_id" of the book i am viewing and the display each one using the for loop. Doesnt quite work though, it spits out an error message saying the following:

#undefined method `each' for #<Comment:0xb682c2f4>
#Extracted source (around line #27)

And line 27 is

 <% for review in @reviews %>
A: 

To find the comments for a book it's just:

@book = Book.find(params[:id])

like you've already done, then:

@book.comments

for that books comments. So:

<% for review in @book.comments %
  <%= form.label "Title: " %><%h review.title %> <br />
  <%= form.label "Review:" %><%h review.comment %>
<% end %>

You don't have to find the comments in the controller.

Jarrod
A: 

Wonderful, You've all saved my life! (And my grade)

Thank you for everything, Been most helpful.

Working well now, Apart from it wont display the user_id field from the comments table, but oh well, i'll just leave that feature.

Thanks again.