问题描述
我有一个模型A和一个模型B,关系是A has_many B(并且B属于A).我有一个模型,一个控制器和A的视图,而只有B的模型.我想在A(url/a/1/edit)的编辑视图上创建和编辑B的实例.
我知道我可以为B创建一个控制器并在A的视图中使用表单来调用这些方法,但是随后我需要重定向回A的视图,因为我不希望B的实际视图./p>
有推荐的方法吗?我想要的是不破坏任何Rails提供的帮助程序(例如,在转发后,我认为获得错误消息和类似的东西很痛苦).
提前谢谢!
在模型级别,您将使用 accepts_nested_attributes_for
.
A类<应用模型has_many:bsaccepts_nested_attributes_for:bsvalidates_associated:bs结尾B级应用模型当属:a结尾
这使A可以获取属性并通过将属性 bs_attributes
传递给属性数组来创建嵌套的 bs
. validates_associated
可以用来确保 bs
的A不能持续存在也是无效的.
要创建嵌套表格字段,请使用 fields_for
<%= form_for(@a)做| f |%>#A上的字段<%= f.text_input:foo%>#为与A关联的每个B创建一个字段.<%= f.fields_for(:bs)做| b |%><%= b.text_input:bar%><%结束%><%结束%>
要白名单嵌套属性,请使用带有允许数组的哈希键子记录的属性:
params.require(:a).permit(:foo,bs_attributes:[:id,:bar])
在创建新记录时,如果希望存在用于创建嵌套记录的输入,还必须填充"表单:
类AsController<应用程序控制器def新@a = A.newseed_form结尾def创建@a = A.new(a_params)如果@ a.saveredirect_to @a别的seed_form渲染:new结尾结尾def更新如果@ a.update(a_params)redirect_to @a别的渲染:edit结尾结尾私人的def seed_form5.times {@ a.bs.new}如果@ a.bs.none?结尾def a_paramsparams.require(:a).permit(:foo,bs_attributes:[:id,:bar])结尾结尾
修改:seed_form也可以只添加一个,然后每次都这样做.因此,您将始终要添加一个空"项.如果未填空,则需要确保将空的过滤掉,方法是将 accepts_nested_attributes_for
更改为:
accepts_nested_attributes_for:bs,reject_if:proc {| attr |attr ['bar'].blank?}
I have a model A und a model B and the relation is A has_many B (and B belongs_to A). I have a model, a controller and views for A and only a model for B.I want to create and edit the instances of B on the edit view of A ( url/a/1/edit).
I know I can create a controller for B and call those methods using a form in the view of A, but then I need to redirect back to the view of A, because I don't want actual views for B.
Is there a recommended way to do this? What I want is to not break any of the helpers rails provides (e.g. after a forward I think it's a pain to get error messages and stuff like that).
Thanks in advance!
On the model level you would use 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
This lets A take attributes and create nested bs
by passing the attribute bs_attributes
with an array of attributes. validates_associated
can be used to ensure that A cannot be persisted of the bs
are not also valid.
To create the 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 %>
To whitelist nested attributes use a hash key with an array of permitted attributes for the child records:
params.require(:a)
.permit(:foo, bs_attributes: [:id, :bar])
When creating new records you also have to "seed" the form if you want there to be inputs present for creating nested records:
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
Edit:seed_form can also just add one and do that every time. So you will always have one "empty" one to add. You need to make sure to filter out the empty one before saving if it was not filled by changing the accepts_nested_attributes_for
to:
accepts_nested_attributes_for :bs, reject_if: proc { |attr| attr['bar'].blank? }
这篇关于在其父模型的视图上创建嵌套的模型实例(has_many关系)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!