Types of forms

Pål Bergström wrote:

I'm I right that there are two kinds of forms in an edit page? One is:

<%= start_form_tag :action => 'update', :id => @content %>
  <%= render :partial => 'form' %>

This will simply output the columns in the database.

No. There is no automatic form system in Rails. With the code above,
you still need to create a partial template called _form.rhtml, and in
that you need to write view code that specifies which fields you want
to appear and how you want them laid out.

The other is:

<% form_for :content, :url => { :action => "update" } do |f| %>

Here you are more free to select what to display from the db than the
first.

No. As described above, with either method you have equal freedom in
terms of layouts and which fields you include, because with both
methods you have to write the view code manually.

But can you use the first and tell RoR not to render/output a particular
field?

Yes, as described above.

And can the second be written in another way? Does it need :url?
Why not just the :action?

Yes, it does need :url. The start_form_tag method call actually looks
like this:

start_form_tag({:action => 'update', :id => @content})

it's just that Ruby puts in those {curly braces} for you automatically
because it sees that you're giving it a hash. So that hash in there is
actually just the first parameter to the start_form_tag. There is an
optional second parameter to the start_form_tag method that lets you
specify HTML options, such as :multipart => true. If you wanted to
specify some HTML options, you'd have to write out the hashes
explicitly:

start_form_tag({:action => 'update', :id => @content}, {:multipart =>
true})

This won't work:

start_form_tag(:action => 'update', :id => @content, :multipart =>
true)

because you're mixing up HTML options with a URL specification.

With this in mind, we can look at the form_for method call:

form_for(:content, :url => {:action => 'update'})

As with start_form_tag, you can specify HTML options too:

form_for(:content, :url => {:action => 'update}, :html => {:multipart
=> true})

The difference is just a difference in style. Recently in Rails,
methods have tended to look more like form_for than start_form_tag, for
two reasons: 1. It makes it very clear that there are two separate bits
and you need to specify them separately; 2. It makes it very clear what
each bit is relating to (this here is the URL stuff, and this here is
the HTML stuff).

The upshot of all of this is that, yes, you do need to use :url when
you're calling form_for.

The real difference between form_for (beyond the style difference) is
that form_for reduces repetition if you're writing a lot of fields for
the same object. And it lets you easily create a form for the
attributes of (say) a local variable 'person', rather than the instance
variable '@person' that start_form_tag and its helpers expect.

To create a form for the 'person' variable using start_form_tag, you'd
have something like:

<%= start_form_tag(:action => 'update', :id => person) %>
<%= text_field(:person, :name, :object => person) %>
<%= text_field(:person, :job, :object => person) %>
<%= end_form_tag %>

Very repetitive. Using form_for, it would look like this:

<% form_for(:person, person, :url => {:action => 'update', :id =>
person} do |f| -%>
<%= f.text_field(:name) %>
<%= f.text_field(:job) %>
<% end -%>

Much nicer.

Chris