January 5, 2015 by Daniel P. Clark

Dealing with Rails 4 forms and params

In the learning stage of Rails developments one will come across different scenarios of handling parameters from Rails forms that are submitted.  Also since Rails 4 introduced Strong Parameters there are some additional things to keep in mind.

Form Params 101

Submitted forms return a JSON response with data in it.  You can access it from your controller with the params Hash.  To access the first name here from params you would have to do params[‘profile’][‘first_name’] and you would get back “Daniel”.  With the introduction of Strong Parameters in Rails 4 you are asked to no longer directly use params for security reasons.  You will use a middle man method usually named after your model name such as profile_params.

The Strong Params method will look a lot like:

Consider this strong params method as a read-only parameter access used to help protect you.  Also note that this will step into the parameters one level into the params Hash it calls.  In this example it returns the “profile” subset of the Hash.  So profile_params returns the same results as params[‘profile’] unless additional fields exist that are not within the :permit method.  It will drop any items not in :permit.

If you want to modify any of the parameters before your controller saves or updates the Object then you need to perform your work on the params Hash before the save/update methods are invoked.  Note: I said to work directly on params for modification or changes.  Again; that’s because profile_params is a read-only method and it will be updated accordingly with any changes you commit to params.

Form to params

The form_for method will create the nested params before being submitted.  What I mean by that is the Object you give form_for will be the name of the Hash subset that the Strong Params method will have in require().  For example form_for(:profile). will have a params[‘profile’] Hash in the results.  In this example case :profile is assigned to an existing Profile Object.  Each of the standard input fields will be nested within params[‘profile’].  For example:

Will submit a result that you can access first_name through params[‘profile’][‘first_name’] or through the read only strong params method profile_params[‘first_name’].  If you wanted to change the value before it gets saved you need to change it directly on params.  For example params[‘profile’][‘first_name’] = params[‘profile’][‘first_name’].reverse will work.  But trying the same with profile_params will do nothing in the end.

With form_for you assign it to an object like |f| and each item within it must then be called on f … such as f.text_field.  But there are times when you won’t want to do things in this way.  When dealing with custom situations in forms there are alternative methods with their counterpart postfixed _tag  method.

Dealing with _tag methods

One thing I’ve found when using _tag methods is that they don’t usually follow the same order of method parameters as their non _tag method counterparts.  So when using a _tag method it’s best to look up the online method usage reference.  My favorite online reference for these methods are apidock.com.  Beyond the documentation there are tips and comments on how these methods may be used.

The first thing you should know about _tag methods is that they aren’t nested for Strong Params on their own.  In other words you need to nest it yourself.  If I replace the f.text_field from the earlier example with text_field_tag I need to use the nested name representation of the parameter I’m setting.  For example:

This will be true for any _tag method that you want to pass the Strong Parameters requirement.  Also notice my use of f.object.first_name.  Any time you want to access the values from the Object you’ve piped into the form through |f| you can simply use f.objectf.object is basically the same as accessing @profile directly.  There are times when this may come in handy for you.

Another thing to keep in mind with _tag methods is they don’t understand how to get the value for the string ‘profile[first_name]’ to show in the page’s input field.  This is why you need to specifically declare the value for it.

Nested Attributes

In the parameter example I gave at the beginning of this you may have noticed:

When you have items of something belonging to another you use nested attributes.  In the example above this is a Social Network that belongs to the Profile.  So Profile has_many Social Networks and Social Networks belongs_to Profile.  Here are the models:

You’ll notice the word polymorphicWhenever you create an Object model that can belong to more than one other kind of Object model you will want to use polymorphic.  If you didn’t use it you would have to reference profile via a profile_id field in your Social model.  With polymorphic it keeps to pieces of information for you: the type and the id.  In this case the sociable_type will be “Profile” and the id will reference whatever the owners Profile id is for this “Social Network” Object.

The form that would submit these parameters would look as follows:

The one_by_kind is my own method.  I’ve replicated first_or_create with a first or build syntax.  You can see my code for this method in a previous article Manual Polymorphic Creation in Rails.

You’ll notice nested attributes are generally given through the fields_for method.  fields_for is for all of your belongs_to/has child Objects.   You can also replicate the nested fields by using _tag methods.  I won’t be covering that at this time though.

Things to Keep in Mind

  1. Be careful about saving user_id from parameters.  Think that they may be compromised.  Before the save/update commands are committed assign them to the current_user in the controller.  Example:
  2. _tag methods are done differently then their counterpart methods.  For example:
  3. The Strong Params method is read only.  Do any necessary modification on params and please still use the strong_params method to save with.
  4. Strong Parameters requires you to declare any field you want to allow in to be saved.  Sometimes this will slip your mind.
  5. If you’re using form_for or form_tag and the form is closing itself off prematurely (before your inputs) then you can put a tag for a submit button right before the <% end %>.  If you don’t want a submit button for the form simply make it invisible.

There are still many things I haven’t covered here.  I’ve addressed what I’ve seen as some of the biggest issues when first learning to implement forms in Rails.  Things only get more technical when you delve into JavaScript submitted forms via AJAX.  It’s not hard, just a bit more to learn.  As always I hope what I’ve written has been both helpful to you, and enjoyable to read!

Please comment, share, subscribe to my RSS Feed, and follow me on twitter @6ftdan!

God Bless!
-Daniel P. Clark

#_tag#101#article#attributes#blog#field#fields#fields_for#form#form_for#forms#hidden_field#hidden_field_tag#input#nested#parameters#params#post#rails#rails 4#strong#Strong Parameters

Leave a Reply

4 Comment threads
4 Thread replies
Most reacted comment
Hottest comment thread
5 Comment authors
MSCAULarry LawalavadhDaniel P. ClarkDan Shultz Recent comment authors
newest oldest most voted
Notify of
Dan Shultz
Dan Shultz

Good blog post, it covers and details strong parameters well. I wanted to add one critique because I think it affects the whole mental model of how forms and rails works. You mentioned that, “Submitted forms return a JSON response with data in it…” What happens in the case of forms, they are submitted normally via the browser with a content type usually of `application/x-www-form-urlencoded` and there is a rails middleware called `ActionDispatch::ParamsParser` which reads this content type and takes the appropriate action to populate the `params` for your controller. In the case of a content type of `application/json`, the… Read more »

Daniel P. Clark

Thanks for your input! I also believe the params Object that is generated is an instance of ActiveSupport::HashWithIndifferentAccess thereby allowing you to access each params key by either a Symbol or a String. So there is quite a bit being done with the data that is returned.

=> [ActionController::Parameters,


Hi Daniel,

Great to find your blogpost. I am having issues with an API only app where I can not use form_for in this case how should I test the API, Postman seems not to work with the Key Wrapping.

Any thoughts suggestion would be helpful.

Daniel P. Clark

You haven’t given me enough information to understand what you’re working with. What test suite? And postman is email server related. When testing any server via GET/POST requests there is a command line tool called curl. In Ruby one of the best tools like curl is typhoeus. Although in Rails itself there are plenty of ways to test with a simple get/post command in your integration/controller tests… you just need to inherit or include the right class/module.

Larry Lawal
Larry Lawal

how do i find a record in rails using a value sent in a nested parameter request?

Daniel P. Clark

Can you give an example? In my JSON code at the top of this post accessing the Twitter username can be done in two ways. Ruby [crayon-5cbb30f114eac612264331 class="ruby"] params["profile"]["socials_attributes"]["0"]["username"] # and strong params (the right way) profile_params["socials_attributes"]["0"]["username"] 123456  [crayon-5cbb30f114eac612264331   class="ruby"]params["profile"]["socials_attributes"]["0"]["username"] # and strong params (the right way)profile_params["socials_attributes"]["0"]["username"] [/crayon] It is recommended to handle multiple nested attributes with an each loop. Ruby [crayon-5cbb30f114eb1621508239 class="ruby"] profile_params["socials_attributes"].each do |_, value| # here the underscore takes the "0" key and value gets the kind & username hash value["username"] end 123456  [crayon-5cbb30f114eb1621508239   class="ruby"]profile_params["socials_attributes"].each do |_, value|  # here the underscore takes the "0" key and value gets… Read more »


Outstanding! You have saved my day. The official Rails docs don’t explain this well at all so where did you learn this from?

Daniel P. Clark

Mostly trial and error and by picking through subtle hints in looking up online how methods worked. Also examining the console log from `rails server` will give you insight into which parameters are having issues.