Skip to content

Instantly share code, notes, and snippets.

@FaisalAl-Tameemi
Forked from rob0t7/form_helpers.md
Last active March 2, 2016 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FaisalAl-Tameemi/bbc288633fdc7e6ee6b1 to your computer and use it in GitHub Desktop.
Save FaisalAl-Tameemi/bbc288633fdc7e6ee6b1 to your computer and use it in GitHub Desktop.

Rails and Form Helpers

The reference materials used for this lecture can be found at http://api.rubyonrails.org and http://guides.rubyonrails.org.

We also have to take a quick look at rails's flash object.

Rails Flash

The flash object allows you to set temporary messages that will automatically be removed when the next action is called. They are closely related to session and cookies and behave in a similar fashion. They behave just like a hash

flash[:notice] = 'Success' # to set value
flash[:notice] # to retrieve value

The big difference however is that they values that are stored are removed when the next rails controller action is called. If you want to use the flash right away you will need to instead call flash.now[:key].

form_tag

If you are just creating a regular form that is not bound to a model in the database then you should use the form_tag() helper. They main reason is that rails expects a csrf value with all forms because of its builtin security feature.

<!-- This creates a simple login form -->
<%= form_tag(sessions_path) %>
  <%= text_field_tag :email %>
  <%= password_field_tag :password %>
<% end %>

As you can see we also use different form helpers to create the individual html tags. In this example we used 3 helpers:

  • the form_tag helper itself that creates the tag and 2 hidden fields for security
  • text_field_tag that creates a text tag
  • password_field_tag that creates a password tag

This only provides you with a few extras over creating the tags manually in html but the main thing it gives you is a sane way of create the name attribues for all the input tags and you are reassured that it will be parsed properly by the rack middleware. The only tag that you need is the form_tag.

form_for

As you can see above, making forms is hard. Many times with rails we actually want to store the data that is entered in those fields into a model on the DB. When this is the case we should use form_for.

Lets assume we have a user object. We could create a form this way.

<%= form_for @user do |f| %>
  <%= f.text_field :name %>
  <%= f.email_field :email %>
  <%= f.password_field :password %>
  <%= f.submit %>
<% end %>

When you use form_for, a formbuild object is returned that allows you to create form html tags based off of a specific type and it binds the value to the method of the object that is passed it. For example, f.text_field :name creates a text input tag that is attached to the name method on the @user object. Internally the form builder calls the proper corresponding _field_tag method.

Forms with multiple models

Yes, it's possible. Use the fields_for helper to do it. This is pretty useful for models with relationships. fields_for works similar to form_for but does not create a tag.

<%= form_for @person, url: {action: "create"} do |person_form| %>
  <%= person_form.text_field :name %>
  <%= fields_for @person.contact_detail do |contact_details_form| %>
    <%= contact_details_form.text_field :phone_number %>
  <% end %>
<% end %>

Strong params

Something you may have noticed is that rails does not allow us to pass in a params hash into an activerecord object creation call. This is a security feature. To do mass assignment we first need to whitelist valid params. You can do this in the following:

def user_params
  params.require(:user).permit(:name, :email, password)
end

In the the example above, if your params don't have a value for params[:user] and exception is thrown. If they do, only the values in the permit() are passed throught, the rest are filtered out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment