views:

224

answers:

2

This may seem basic but I can't figure it out.

I have a "Write Review" link which looks as follows:

<%= link_to 'Write', new_review_path(@new, :vendor_id => @vendor.id) %>

This creates the URL:

reviews/new?vendor_id=10

All I want is to create a new Review object based on three inputs:

  1. vendor_id (above)
  2. user_id (which is working currently)
  3. @review hash from the form (which is working)

But I cannot get it to store the vendor_id:

  def new
    @review = Review.new
    @vendor = Vendor.find(params[:vendor_id])
    @vendor.reviews.create

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @review }
    end
  end

 def create
    @review = Review.new(params[:review])
    #@vendor = Vendor.find(params[:vendor_id]) #error

    #@review = @vendor.reviews.build #error

    @review = @current_user.reviews.build #build a review with the current_user id

    respond_to do |format|
      if @review.save
        flash[:notice] = 'Review was successfully created.'
        format.html { redirect_to(@review) }
        format.xml  { render :xml => @review, :status => :created, :location => @review }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @review.errors, :status => :unprocessable_entity }
      end
    end
  end

I am thinking I need to change the url in the form_for, but I'm not clear how. Here is what I have currently:

<% form_for(@review) do |f| %>
 ......

Can I have some help, please? Thanks!

Here is the view code for new (note: I also created a has_many route so that vendors/1/reviews/new has meaning, although I am not invoking it anymore):

My code in routes.rb:

map.resources :vendors, :has_many => :reviews

My code for views/reviews/new.html.erb:

<h1>New review for <%= @vendor.name%></h1>

Current User ID: <%= @current_user.id %>
Vendor ID: <%= @vendor.id %> <%= @review.vendor.id %>
Current Review ID: <%= @review.id %>

<% form_for @review do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :summary %><br />
    <%= f.text_field :summary %><br />

    <%= f.label :pro_review %><br />
    <%= f.text_field :pro_review %><br />

    <%= f.label :con_review %><br />
    <%= f.text_field :con_review %><br />

    <%= f.label :detail_review %><br />
    <%= f.text_field :detail_review %>  <br />

  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', reviews_path %>

Here is the source view:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>Reviews: new</title>
  <link href="/stylesheets/scaffold.css?1238999620" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>

<p style="color: green"></p>

<h1>New review for Fiberlink</h1>

Current User ID: 2
Vendor ID: 16 16
Current Review ID: 

<form action="/reviews" class="new_review" id="new_review" method="post"><div style="margin:0;padding:0"><input name="authenticity_token" type="hidden" value="XDknE1mvQT4zwem1z/gCYm8I2ODhqHLKKgd8y12zzzo=" /></div>


  <p>
    <label for="review_summary">Summary</label><br />
    <input id="review_summary" name="review[summary]" size="30" type="text" /><br />

    <label for="review_pro_review">Pro review</label><br />
    <input id="review_pro_review" name="review[pro_review]" size="30" type="text" /><br />

    <label for="review_con_review">Con review</label><br />
    <input id="review_con_review" name="review[con_review]" size="30" type="text" /><br />

    <label for="review_detail_review">Detail review</label><br />
    <input id="review_detail_review" name="review[detail_review]" size="30" type="text" />  <br />

  </p>
  <p>
    <input id="review_submit" name="commit" type="submit" value="Create" />
  </p>
</form>

<a href="/reviews">Back</a>

</body>
</html>
+1  A: 

You're almost there. You need a slight change to your new method.

  def new
    @review = Review.new
    @vendor = Vendor.find(params[:vendor_id])
    @review.vendor = @vendor # this will insert the vendor_id into the form
                             # when you do form_for

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @review }
    end
  end

EDIT: Try also adding a hidden field to your view code to hold the vendor_id.

<% form_for @review do |f| %>
  <%= f.hidden_field vendor_id %>
  # ...

EDIT 2: Actually, looking at the HTML the code generates, I think you need a slightly differnt form_for. The UI side of Rails is not my forte, as you can tell. :)

<% form_for :review, @review, :url => { :action => "create" } do |f| %>
  <%= f.hidden_field vendor_id %>
  # ...
Sarah Mei
Hi -- thanks -- do I need to make changes to the create as well? I must've done something that tweaked it it's not quite working....thanks
AFG
ugh, nothing is passed from the form, nor is the value which does display in the view/new.erb.html for @review.vendor so that is working...I'm assuming it is going to the :create action just because it is using POST thorugh the form but I cannot figure out why nothing is getting inserted into the database....
AFG
Can you post your view code and the HTML it's generating?
Sarah Mei
sure...let me add above
AFG
okay was thinking about that...is there a reason it is not passing the rest of the params[:review]) anymore? Would changing the route.rb have affected that?
AFG
I'm not sure if/how the routing works into it, but if you don't specify the :url in form_for, it seems to default to list. (In your generated HTML, the form submits to /reviews, which is the list.)
Sarah Mei
A: 

I would normally do:

<% form_for Review.new, :url => new_review_path do |f| %>
  <%= f.hidden_field :vendor_id, :value => @vendor.id %>
Matt Darby