在其父模型的视图上创建嵌套模型实例(has_many 关系)
Creating a nested model instance (has_many relation) on the view of its parent model
我有一个模型 A 和一个模型 B,关系是 A has_many B(和 B belongs_to A)。我有 A 的模型、控制器和视图,只有 B 的模型。
我想在 A 的编辑视图中创建和编辑 B 的实例 (url/a/1/edit)。
我知道我可以为 B 创建一个控制器并在 A 的视图中使用表单调用这些方法,但是我需要重定向回 A 的视图,因为我不想要 B 的实际视图.
有推荐的方法吗?我想要的是不破坏 rails 提供的任何助手(例如,在转发之后,我认为收到错误消息和类似的东西很痛苦)。
提前致谢!
在模型级别,您将使用 accepts_nested_attributes_for
。
class A < ApplicationModel
has_many :bs
accepts_nested_attributes_for :bs
validates_associated :bs
end
class B < ApplicationModel
belongs_to :a
end
这让 A 获取属性并通过将属性 bs_attributes
与属性数组一起传递来创建嵌套的 bs
。 validates_associated
可用于确保 A 无法持久化 bs
也无效。
创建 nested form fields use fields_for
<%= form_for(@a) do |f| %>
# field on A
<%= f.text_input :foo %>
# creates a fields for each B associated with A.
<%= f.fields_for(:bs) do |b| %>
<%= b.text_input :bar %>
<% end %>
<% end %>
要 whitelist nested attributes 使用带有子记录允许属性数组的散列键:
params.require(:a)
.permit(:foo, bs_attributes: [:id, :bar])
创建新记录时,如果您希望存在用于创建嵌套记录的输入,还必须 "seed" 表单:
class AsController < ApplicationController
def new
@a = A.new
seed_form
end
def create
@a = A.new(a_params)
if @a.save
redirect_to @a
else
seed_form
render :new
end
end
def update
if @a.update(a_params)
redirect_to @a
else
render :edit
end
end
private
def seed_form
5.times { @a.bs.new } if @a.bs.none?
end
def a_params
params.require(:a)
.permit(:foo, bs_attributes: [:id, :bar])
end
end
编辑:
seed_form 也可以只加一个,每次都这样做。因此,您将始终有一个 "empty" 要添加。如果未通过将 accepts_nested_attributes_for
更改为:
来填充,则需要确保在保存之前过滤掉空的
accepts_nested_attributes_for :bs, reject_if: proc { |attr| attr['bar'].blank? }
我有一个模型 A 和一个模型 B,关系是 A has_many B(和 B belongs_to A)。我有 A 的模型、控制器和视图,只有 B 的模型。 我想在 A 的编辑视图中创建和编辑 B 的实例 (url/a/1/edit)。
我知道我可以为 B 创建一个控制器并在 A 的视图中使用表单调用这些方法,但是我需要重定向回 A 的视图,因为我不想要 B 的实际视图.
有推荐的方法吗?我想要的是不破坏 rails 提供的任何助手(例如,在转发之后,我认为收到错误消息和类似的东西很痛苦)。
提前致谢!
在模型级别,您将使用 accepts_nested_attributes_for
。
class A < ApplicationModel
has_many :bs
accepts_nested_attributes_for :bs
validates_associated :bs
end
class B < ApplicationModel
belongs_to :a
end
这让 A 获取属性并通过将属性 bs_attributes
与属性数组一起传递来创建嵌套的 bs
。 validates_associated
可用于确保 A 无法持久化 bs
也无效。
创建 nested form fields use fields_for
<%= form_for(@a) do |f| %>
# field on A
<%= f.text_input :foo %>
# creates a fields for each B associated with A.
<%= f.fields_for(:bs) do |b| %>
<%= b.text_input :bar %>
<% end %>
<% end %>
要 whitelist nested attributes 使用带有子记录允许属性数组的散列键:
params.require(:a)
.permit(:foo, bs_attributes: [:id, :bar])
创建新记录时,如果您希望存在用于创建嵌套记录的输入,还必须 "seed" 表单:
class AsController < ApplicationController
def new
@a = A.new
seed_form
end
def create
@a = A.new(a_params)
if @a.save
redirect_to @a
else
seed_form
render :new
end
end
def update
if @a.update(a_params)
redirect_to @a
else
render :edit
end
end
private
def seed_form
5.times { @a.bs.new } if @a.bs.none?
end
def a_params
params.require(:a)
.permit(:foo, bs_attributes: [:id, :bar])
end
end
编辑:
seed_form 也可以只加一个,每次都这样做。因此,您将始终有一个 "empty" 要添加。如果未通过将 accepts_nested_attributes_for
更改为:
accepts_nested_attributes_for :bs, reject_if: proc { |attr| attr['bar'].blank? }