DEV Community

Ayush Newatia
Ayush Newatia

Posted on

How to submit an array using a Rails form

This article was originally posted on my blog.

Sometimes an array of data needs to be submitted in an HTML form. A form to send invites to a bunch of users for example. That'd just be a series of email fields; and in the controller; we'd want an array of the emails to iterate over and send invites.

Rails form helpers are set up to have a key and value for each field, so it's not immediately obvious how to send an array of data. But in Rails, there's always a way!

If we append [] to the name of a field, it'll be parsed as an array! So for an array of emails to send invites; setting name as invites[] on all the email fields and gives us an array in the controller.

To generate the form, we can use the following code:

<%= form_with(scope: :invites, url: invite_path) do |form| %>
  <% 3.times do %> 
    <!-- id has to be nil to prevent clashes as all fields would have the same id -->
    <%= form.email_field nil, id: nil, placeholder: "Email Address" %> 
  <% end %>
  <%= form.submit %>
<% end %>
Enter fullscreen mode Exit fullscreen mode

Passing nil as the first argument to email_field instead of a name gives us the [] we need for an array. The generated markup looks like:

<form action="/invite" accept-charset="UTF-8" data-remote="true" method="post">
  <input type="hidden" name="authenticity_token" value="....">    
  <input placeholder="Email Address" type="email" name="invites[]">
  <input placeholder="Email Address" type="email" name="invites[]"> 
  <input placeholder="Email Address" type="email" name="invites[]"> 
  <input type="submit" name="commit" value="Save Invites" data-disable-with="Save Invites">
</form>
Enter fullscreen mode Exit fullscreen mode

On the controller, we can use the submitted data as:

def create 
  invited_users = params.require(:invites) 

  p invited_users 
  # => ["a@example.com", "b@example.com", "c@example.com"]
end
Enter fullscreen mode Exit fullscreen mode

To permit an array parameter in a nested form field, we can use the following pattern:

params.require(:product).permit(tags: [])
Enter fullscreen mode Exit fullscreen mode

It's a little unintuitive but submitting arrays from a form can be a useful tool in your toolbox!

Top comments (2)

Collapse
 
pargara_ profile image
Sebastian G

what is the difference of your approach and using "multiple: true" ?

<%= form.email_field :email, multiple:true, placeholder: "Email Address" %>

Collapse
 
ayushn21 profile image
Ayush Newatia • Edited

The multiple option relies on the user knowing that they have to provide a comma separated list of email addresses. That's not user friendly in my book. Also, if you do that, Rails parses it into an Array with a single string of the comma separated emails:

"email"=>["a@example.com, b@example.com"]

This means you'd need to do some processing on the server before updating the record. You couldn't just pass the parameters through to Active Record.

Do that make sense?