views:

19

answers:

1

i have a form_for code

<%form_for :a,:url=>{:controller=>"biz/a",:action=>"save"},:html =>{:multipart => true} do |f| %>
.....
<%f.fields_for :b do |b|%>
.....
<%b.fields_for :apples  do |apple|%>
...
<%end%>
....
<%end%>

it outputs the html code without fields_for function

<textarea cols="40" id="a_b_apples_content" name="a[b][apples][content]" rows="20" style="width:500px;height:100px;border:1px #889BAA solid;color:#999;font-size:12px;padding:6px;"></textarea>

when i change the form_for to :

<%form_for @a,:url=>{:controller=>"biz/a",:action=>"save"},:html =>{:multipart => true} do |f| %>

it just work fine. And it outputs:

<textarea cols="40" id="a_b_apples_content" name="a[b_attributes][apples_attributes][0][content]" rows="20" style="width:500px;height:100px;border:1px #889BAA solid;color:#999;font-size:12px;padding:6px;"></textarea>

as i want. why dont the symbol in form_for work fine?what's difference between :a and @a in form_for. Thanks. I use rails 2.3.8 , ruby 1.8.7,chrome web browser.

A: 

This is a common source of frustration. form_for actually behaves differently based on whether you pass it a symbol or an object. If you pass it a symbol, like so:

<% form_for :person do |f| %>
  <% f.text_field :name %>
<% end %>

Then the form builder will work, but it will only setup the param values, and load the default values if @person exists. Your parmas hash will look like it should:

params = {
  :person => {
    :name => 'bob'
  }
}

But it won't setup your route properly. It'll assume you want to submit to the same page you're already on. Now if you give it an object, form_for will do much more for you. It will check to see if this object is new, or being updated, and it will set the form tag's parameters accordingly, along with some other benefits.

Honestly, I can't tell you why they behave differently. The symbol version obviously still has access to the instance variable (@person in the example above) because the fields will be populated with their existing values. The easy solution is that passing an instance variable is always the way to go, and will work correctly.

Jaime Bellmyer