[英]Saving multiple records with a single form in Rails 4
I have a model called Family
, which belongs_to :user
I want to enable the user to add multiple family members in a single form, which is in /views/families/new.html.erb
我有一个名为模型
Family
,其中belongs_to :user
我想使用户能够在一个单一的形式,这是添加多个家庭成员/views/families/new.html.erb
EDIT: Sorry, I should've provided more detailed code earlier after slight modification in code编辑:对不起,我应该在代码稍作修改后更早地提供更详细的代码
# config/routes.rb
resources :families
#app/models/user.rb
class User < ActiveRecord::Base
has_many :families
end
#app/models/family.rb
class Family < ActiveRecord::Base
belongs_to :user
end
#app/controllers/families_controller.rb
class FamiliesController < ActiveRecord::Controller
def new
end
def create
@family = Family.new(family_params)
a = params[:family][:"0"]
@family.user_id = current_user.id
if @family.save
flash[:notice] = params[:family][:"0"]
redirect_to dummy_path
else
flash[:notice] = "didnt happen"
end
end
private
def family_params
params.require(:family).permit(:all)
end
end
#app/views/families/_form.html.erb
<%= form_tag(controller: "families") do %>
<% i = 0 %>
<% 3.times do %>
<br>
<h2>Family Member # <%= i+1 %> : </h2>
<br>
<%= fields_for("family[#{i}]") do |f| %>
<%= f.text_field :name, class: "form-control" , placeholder: "Name"%> <br>
<%= f.text_field :relationship, class: "form-control" , placeholder: "Relationship" %> <br>
<%= f.date_field :dob, class: "form-control" %> <br>
<%= f.text_field :blood_group, class: "form-control", placeholder: "Blood group" %> <br>
<%= f.text_field :email, class: "form-control", placeholder: "Email" %> <br>
<%= f.number_field :phone, class: "form-control", placeholder: "Phone number" %> <br>
<%= f.text_area :hobbies, class: "form-control", placeholder: "Hobbies" %> <br>
<% i=i+1 %>
<% end %>
<hr>
<% end %><br>
<%= submit_tag "Submit", class: "btn btn-primary" %> <br>
<% end %>
You want to use nested forms
.您想使用
nested forms
。 You should be able to copy and paste the following code to get going:您应该能够复制并粘贴以下代码以开始使用:
app/models/family.rb应用程序/模型/family.rb
class Family < ActiveRecord::Base
has_many :users
accepts_nested_attributes_for :users
end
app/models/user.rb应用程序/模型/user.rb
class User < ActiveRecord::Base
belongs_to :family
end
app/views/families/new.html.erb应用程序/视图/家庭/new.html.erb
<%= form_for(@family) do |f| %>
<%= f.fields_for :users do |user| %>
<p>
<%= user.text_field :name %><br>
<%= user.text_field :email %>
</p>
<% end %>
<%= f.submit %>
<% end %>
app/controllers/families_controller.rb应用程序/控制器/families_controller.rb
[...]
def new
@family = Family.new
3.times { @family.users.build }
end
[...]
private
# Use callbacks to share common setup or constraints between actions.
def set_family
@family = Family.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def family_params
params.require(:family).permit(:name, users_attributes: [ :name, :email ])
end
The way that i always do this is to make a new action update_multiple
.我总是这样做的方式是做一个新的行动
update_multiple
。 This expects params with the following structure (using your Family example, and updating two records, with ids 123 and 456)这需要具有以下结构的参数(使用您的家庭示例,并更新两个记录,ID 为 123 和 456)
params = {:families => {123 => {:name => "foo", :address => "bar"}, 456 => {:name => "baz", :address => "qux"} }}
and the action works like so:动作如下:
@families = []
params[:families].each do |id, attributes|
if family = Family.find_by_id(id)
family.update_attributes(attributes)
@families << family
end
end
In order to set up the params with the required structure, your form would be set up like so:为了设置具有所需结构的参数,您的表单将设置如下:
<% @families.each do |family| %>
<div class="family">
<label>Name: <%= text_field_tag "families[#{family_id}][name]", family.name %></label>
<label>Address: <%= text_field_tag "families[#{family_id}][address]", family.address %></label>
</div>
<% end %>
You could, instead of making a new action, change the structure of your update
action to do the standard code if it gets params[:family] and the above code if it gets params[:families].你可以,而不是做一个新的动作,改变你的
update
动作的结构,如果它得到 params[:family] 和上面的代码,如果它得到 params[:families] 来执行标准代码。
You need to tweak your code like this.Assuming you have the attribute name
in users table.您需要像这样调整您的代码。假设您在用户表中有属性
name
。
In your User model在您的用户模型中
class User < ActiveRecord::Base
has_many :families, :dependent => :destroy
accepts_nested_attributes_for :families, :allow_destroy => true
end
In your users_controller在您的 users_controller 中
def new
@user = User.new
@family = 3.times { @user.families.build } #here
end
Your strong parametrs should look like this你的强参数应该是这样的
def user_params
params.require(:user).permit(:name, families_attributes: [:name,:email])
end
# users/new.html.erb
<%= form_for(@user) do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<%= f.fields_for :familes do |builder| %>
<%= render 'family_fields', :f => builder %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
# users/_family_fields.html.erb
<div>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<br>
<%= f.label :email, "Email" %>
<%= f.text_field :email %>
</div>
I prefer gems Slim
, Simple form
and Cocoon
for form operations.我更喜欢 gems
Slim
、 Simple form
和Cocoon
进行表单操作。 Using cocoon you can add/remove
as many sub-records you want.使用 cocoon,您可以
add/remove
任意数量的子记录。
User model用户模型
class User < ActiveRecord::Base
has_many :families, dependent: :destroy
accepts_nested_attributes_for :families, reject_if: :all_blank, allow_destroy: true
end
Controller控制器
class UsersController < ApplicationController
def new
@user = User.new
@user.families.build # This builds default nested form in cocoon
end
def create
@user = User.new(user_params)
@user.save
end
private
def user_params
params.require(:user).permit(
:name, :email,
families_attributes: [:id, :name, :relationship, :_destroy])
end
end
Form形式
.form
= simple_form_for(@user) do |f|
= f.input :name, label: false, input_html: { placeholder: 'Name' }
= f.input :email, label: false, input_html: { placeholder: 'Email' }
.cocoon-form
= f.simple_fields_for :families do |family|
= render 'family_fields', f: family
.links
= link_to_add_association 'Add a member', f, :families
.form-actions
= f.submit
Cocoon partial _family_fields.html.slim
茧部分
_family_fields.html.slim
.nested-fields
.form-inputs
= f.input :name, label: false, input_html: { placeholder: 'Name' }
= f.input :relationship, label: false, input_html: { placeholder: 'Relationship' }
.remove-instance
= link_to_remove_association " X ", f
Happy coding !快乐编码! :-)
:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.