Jan 27 2010

Using form_tag in Ruby on Rails

Published by at 10:41 am under Coding

I had some trouble finding a less than simplistic example of using the form_tag in Rails yesterday and, after griping on twitter about it was called out and told to do it myself.  Good advice.  Here we go.

In Rails you’ve got two ways to create a form:  form_for and form_tag.  You see examples for form_for everywhere, because that’s what you use to directly interact with the models you created in your database.  But a lot of times you need to create a form that has no interaction with your database and that isn’t mapped to any data model.  Enter form_tag.

There are two syntatic differences between forms created with form_for and those with form_tag.  First, you typically declare form_for like this:

<% form_for(@person) do |f| %>

And from then on you add fields using the f variable you just defined, like f.text_field or f.select.  The other difference is that the way you declare the fields themselves changes.  text_field becomes text_field_tag, select becomes select_tag and so on.  The reason is that text_field is meant, just like form_for, to interact with a defined object model.  All those ones ending in _tag are for unbound forms.

<% form_tag(create_ticket_path, :method=>'post', :multipart => true) do %>

In the example, you see a couple of things.  First, when defining a form_tag you can’t just pass it an object and let rails figure out what needs to happen.  You need to tell it, first, what URL to point at and, second, what HTTP call to make (typically post or put).  Those are the first two parameters. In my case, I have a path defined in my routes.rb for create_ticket, so I can call create_ticket_path to get it. And I’m creating a support ticket, so I’m going to use the ‘post’ method.

The third parameter is where you pass your options, which are roughly the same as the options you can pass form_for.  You’ll see in mine I passed it :multipart => true.  I do that to define a multipart form so that I can let people upload a file on submission.

The other thing to note is when defining the input fields.  When using form_for, you can just pass, say, text_field the symbol for the field you want it bound to. So, if you were creating a field for the subject of a support ticket request, you’d do:

<%= f.text_field :subject %>

Rails figures out the rest.  Without the model, we need to do it ourselves and define the field’s id.  (If you wanted to have a default value, you’d put it in the second parameter, but for this example it doesn’t really make sense).

<%= text_field_tag "subject" %>

Pretty simple, I know.  But sometimes you just need to see how the syntax works, and it felt like every tutorial assumed every form would either use Rails’ models and form_for, or your form_tag usage would be hilariously simple.  The full example of the form is below.  Just like when you use form_for, if you’re catching this with a rails controller, everything will be available through the params[] array.  So, to catch that text_field_tag “subject” all you have to do in your controller is grab for params[:subject] .

File uploads are their own story, but to get you started, it’ll be in params just like everything else. Just be sure to use :multipart => true or your form will quietly ignore that an attachment was chosen.

Easy, right?

<% form_tag(create_ticket_path, :method=>'post', :multipart => true) do %>
 <p>
   Subject:<br />
   <%= text_field_tag "subject" %>
 </p>
 <p>
   Priority: <br />
   <%= select_tag("priority", options_for_select([['Critical', '1'],
                 ['Important', '2'],['Standard','3']], '3')) %>
 </p>
 <p>
   Describe your problem:<br />
   <%= text_area_tag "description", "", :size=>"50x20" %>
 </p>
 <p>
   Add an attachment:<br />
   <%= file_field_tag "attachment" %>
 </p>
 <p>
   <%= submit_tag 'Submit' %>
 </p>
<% end %>

18 responses so far

18 Responses to “Using form_tag in Ruby on Rails”

  1. my_elfon 12 Mar 2010 at 3:16 pm

    Great article :)

  2. gullomon 24 Mar 2010 at 8:55 pm

    Simple and effective article…Was looking for similar info and basic example of form_tag so thanks!

  3. Horace Hoon 28 Mar 2010 at 7:01 pm

    How can I group params in form_tag?

    For example, what if I want the params[:subject] and params[:description] to be grouped into

    params[:ticket][:subject], and
    params[:ticket][:description] ?

    such that the form_tag variables are not ‘mixed’ with other params (e.g. params[:action], params[:controller]. …, etc.)

    thx, and great article!

  4. BSiseon 05 May 2010 at 8:57 pm

    This really helped me in in designing a submission form for my language learning site iLearnWords (http://www.ilearnwords.com) — thank you!

    BSise

  5. Hal Helmson 31 Jul 2010 at 3:07 pm

    Thanks very much! Great, focused tutorial.

  6. Navinon 29 Sep 2010 at 7:34 pm

    Good work – helped this newbie! Have you considered doing an article on fields_for as well?

  7. Asif Sheikhon 04 Oct 2010 at 12:05 pm

    This article was very helpful. Thank you :)

  8. Richard Smithon 26 Oct 2010 at 12:32 pm

    Hi,

    Nice article, just what I needed, sometimes the Rails API docs really are sparse.

    A note for new users like me, the code to do something with the data you get form the user goes in the same controller method as the one that called the page in the first place, typically this is your index method.

    Richard.
    IT Contractor Mortgages

  9. arivarasanon 12 Dec 2010 at 10:51 pm

    nice work! It will help the newbie(me too) for rails…

  10. Artemon 26 Feb 2011 at 6:10 am

    very good and clear information

  11. RORailson 25 Mar 2011 at 11:53 pm

    Thanks a ton for this.

  12. Spyroson 28 Mar 2011 at 8:46 pm

    I’m having some trouble on getting that to work. I want to pass a work_hours param. My route is :

    post ‘start/:work_hours’ => :start, :as => ‘start’

    My code is :

    :post do %>

    But i get a “No route matches {:controller=>”labor”, :action=>”start”}” when rendering the form. Any idea on what i’m doing wrong ? :/

  13. saalonon 03 Apr 2011 at 8:26 am

    Spyros,

    Is the comment system cutting off part of your code? What you posted looks a little incomplete. I don’t think WordPress does a great job handling code in comments.

    I suggest posting your question on http://stackoverflow.com and, if you’d like, leaving the link to the question here. I’d be happy to answer it (and if I can’t, someone else there probably can).

    Eric

  14. bhaveshon 19 Apr 2011 at 9:05 pm

    fine explanation

  15. supriyaon 15 Jun 2011 at 4:41 am

    thanks a lot.. great work

  16. Daveon 13 Jul 2011 at 1:53 pm

    Awesome article, just what I needed when I was about ready to throw my laptop out the window because form_tag was breaking my code. Thanks!

  17. Whoever You Were: Love | Saalon Muyoon 20 Oct 2011 at 11:47 pm

    [...] been there. I hope my post helped. Truly and [...]

  18. Ed Castanoon 10 Nov 2011 at 4:44 pm

    Very helpful, thanks! The Rails documentation doesn’t really lend a hand here.

Trackback URI | Comments RSS

Leave a Reply