Multiple non-nested model creation on same page
Create multiple records in one form with one model
Here's users_controller.rb
def new
end
def create_multiple
params[:users].each do |user|
user = User.create(user)
end
redirect_to users_url
end
Here's new.html.erb
<%= form_tag '/users/create_multiple' do %>
<%= render 'user_fields' %>
<div class="actions">
<%= submit_tag %>
</div>
<% end %>
Here's _user_fields.html.erb
<script type="text/javascript">
$(function() {
var scntDiv = $('#addusers');
var i = $('#addusers div').size() + 1;
$('#addfields').on('click', function() {
$('<div class="field"><h2>User ' + i +'</h2><input id="users__firstname' + i +'" name="users[][firstname]" placeholder="first name" type="text" /><input id="users__lastname' + i +'" name="users[][lastname]" placeholder="last name" type="text" /></div>').appendTo(scntDiv);
i++;
return false;
});
});
</script>
<div id="addusers">
<div class="field">
<h2>User 1</h2>
<%= text_field_tag "users[][firstname]", nil, :placeholder => "first name" %>
<%= text_field_tag "users[][lastname]", nil, :placeholder => "last name" %>
</div>
</div>
<a href="#" id="addfields">Add a New User</a><br/>
Result on Log
Started POST "/users/create_multiple" for 127.0.0.1 at 2013-06-05 00:40:07 +0700
Processing by UsersController#create_multiple as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"xOPM6PB1h6DMUEGS7fX9/eWs/e6dg
XKRj231ReviKFo=", "users"=>[{"firstname"=>"test1", "lastname"=>"last1"}, {"first
name"=>"test2", "lastname"=>"last2"}], "commit"=>"Save changes"}
←[1m←[36m (78.0ms)←[0m ←[1mbegin transaction←[0m
←[1m←[35mSQL (49.0ms)←[0m INSERT INTO "users" ("created_at", "firstname", "la
stname", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Tue, 04 Jun 2013 17:
40:08 UTC +00:00], ["firstname", "test1"], ["lastname", "last1"], ["updated_at",
Tue, 04 Jun 2013 17:40:08 UTC +00:00]]
←[1m←[36m (7.0ms)←[0m ←[1mcommit transaction←[0m
←[1m←[35m (0.0ms)←[0m begin transaction
←[1m←[36mSQL (3.0ms)←[0m ←[1mINSERT INTO "users" ("created_at", "firstname",
"lastname", "updated_at") VALUES (?, ?, ?, ?)←[0m [["created_at", Tue, 04 Jun 2
013 17:40:08 UTC +00:00], ["firstname", "test2"], ["lastname", "last2"], ["updat
ed_at", Tue, 04 Jun 2013 17:40:08 UTC +00:00]]
←[1m←[35m (5.0ms)←[0m commit transaction
Redirected to http://localhost:3000/users
Completed 302 Found in 156ms (ActiveRecord: 142.0ms)
You can add validation code as per your wishes, here's how to pass form params for multiple records basic-structures
Adding fields and keep only one form, one submit button:
= form_tag(url: create_user_path, remote: true) do
%table
%tr
%td= text_field_tag 'user[][first_name]'
%td= text_field_tag 'user[][last_name]'
%tr.actions
%td= submit_tag 'Save'
%td= button_tag 'Add new user form', id: 'add_user_form'
%tr.new_user_row.hidden # hidden class matches the css rule: {display:none;}
%td= text_field_tag "user[][first_name]"
%td= text_field_tag "user[][last_name]"
:javascript # jQuery
$('#add_user_form').bind('click', function(e) {
var row = $('tr.new_user_row').clone().removeClass('hidden new_user_row');
$('tr.actions').before(row); # will append the <tr> before the actions
});
In UsersController:
def create
params[:user].each do |attr|
User.create(attr)
end
end
The row tr.new_user_row.hidden
serves the purpose of template for a new line: by clicking on the button #add_user_form
, the JS code will select the template row, clone
it and add this new row with empty inputs as the last visible row of the table.