我查看了有关Stack Overflow的相关问题,但我不知道该尝试解决这个问题。
要阐明,
User
,A
和B
。A
包含3条记录,每条记录包含p1_name
,p1_score
,p2_name
和p2_score
字段。所以,A
看起来像 -----------------------------------------------------------
id
|
p1_name
|
p1_score
|
p2_name
|
p2_score
id
|
p1_name
|
p1_score
|
p2_name
|
p2_score
id
|
p1_name
|
p1_score
|
p2_name
|
p2_score
-----------------------------------------------------------
B
是User
提交p1_name
和p2_name
来自A
评分的猜测的模型。所以,B
看起来像: ---------------------------------------------------------------------------------
id
|
user
|
a_id
|
p1_name
|
p1_score_guess
|
p2_name
|
p2_score_guess
id
|
user
|
a_id
|
p1_name
|
p1_score_guess
|
p2_name
|
p2_score_guess
id
|
user
|
a_id
|
p1_name
|
p1_score_guess
|
p2_name
|
p2_score_guess
---------------------------------------------------------------------------------
B
belongs_to
A
,B
中的每条记录都由user
和a_id
唯一标识。我需要使用视图B
为模型new
创建一个表单,由其控制器的views/B/new.html.erb
操作处理。
这需要是一个单独的表单,显示3行,每行包含:
p1_name
的A
(作为文字)p1_score_guess
的B
(作为数字字段)p2_name
的B
(作为文字)p2_score_guess
的B
(作为数字字段)使用一个提交按钮提交后,需要将3条记录中的每条记录的上述数据提交给控制器,并创建多条B
条记录。
我之前没有在Rails 4.2.5中遇到过这种要求,也不知道如何去做。我一直试图这样做两天,首先使用simple_form,它似乎不支持这个(或者我不能支持),然后是Rails表单。
这对我来说变得棘手,因为我必须在形式的视图中显示模型p1_name
中的p2_name
和A
以及使用它另外,填充模型B
。 B
的控制器需要同时接纳p1_name
,p2_name
和p1_score_guess
,p2_score_guess
。由于a_id
对于每一行都不同,因此也需要考虑(进一步使我无法想出这一行)。
答案 0 :(得分:1)
怎么样:
<%= form_for :bs, url: bs_path do |f| %>
<% @as.each do |a| %>
<%= f.fields_for "[#{a.id}]", B.new do |afields| %>
<%= a.p1_name %>
<%= afields.text_field :p1_score_guess %>
<%= a.p2_name %>
<%= afields.text_field :p2_score_guess %>
<% end -%>
<% end -%>
<%= f.submit 'save' %>
<% end -%>
在Controller中,你遍历params [:a_s]
def create
bs_params.each do |a_id, b_attributes|
B.create b_attributes.merge(a_id: a_id, user: current_user)
end
end
与
def bs_params
params.require(:bs).permit(allowed_a_s)
end
def allowed_a_s
Hash[a_ids.map {|id| [id.to_s, [:p1_score_guess, :p2_score_guess]]}]
end
def a_ids
A.pluck(:id)
end
只是为了向您展示我的测试用例 - 我已经分配了@as:
@as = [A.new(id: 1, p1_name: 'p11', p2_name: 'p12'), A.new(id: 2, p1_name: 'p21', p2_name: 'p22'), A.new(id: 3, p1_name: 'p31', p2_name: 'p32')]
并设置为a_ids static:
def a_ids
%w[1 2 3]
end
并为bs_params启用了一个调试器,输入1,2,3,4,5,6用于猜测:
=> {
"1"=>{"p1_score_guess"=>"1", "p2_score_guess"=>"2"},
"2"=>{"p1_score_guess"=>"3", "p2_score_guess"=>"4"},
"3"=>{"p1_score_guess"=>"5", "p2_score_guess"=>"6"}
}
更新:由于上面的代码没有检查验证,我再试一次(这次没有测试 - 抱歉):
<%= form_for :bs, url: bs_path do |f| %>
<% @bs.each do |a, b| %>
<%= f.fields_for "[#{a.id}]", b do |afields| %>
<%= a.p1_name %>
<%= afields.text_field :p1_score_guess %>
<%= a.p2_name %>
<%= afields.text_field :p2_score_guess %>
<% end -%>
<% end -%>
<%= f.submit 'save' %>
<% end -%>
在控制器中执行:
def new
@bs = Hash[a_ids.map { |a_id| [a_id, B.new] }]
end
def create
@bs = {}
bs_params.each do |a_id, b_attributes|
@bs[a_id] = B.new b_attributes.merge(a_id: a_id, user: current_user)
end
@bs.values.each(&:valid?) # to ensure, all errors are assigned - and not finding one will stop to check for any other
if @bs.values.all?(&:valid?)
@bs.values.each &:save
redirect_to root_path
else
render :new
end
end
和bs_params,allowod_a_s和a_ids如上