感谢Ruby on Rails: How to gather values for child tables from a form?和“Agile Web Dev”,我知道如何使用fields_for
在表单中包含多个模型。但是我在这个上面撕裂我的头发。
假设我有一个模型Person
。 Person
具有name
属性和has_many :foos
。反过来,Foo
模型具有colour
属性。
此外,我知道每个Person
都有正好三个 Foos
。我的模型,new
中的create
和PersonController
操作以及new
视图应该是什么样子才能呈现三个标记精美的文本输入框,一个用于每个Foo并且能够报告验证错误,允许我的“新人”表单一次创建整个四个对象集合?
另外,我可以在没有accepts_nested_attributes_for
的情况下执行此操作吗?
答案 0 :(得分:3)
在玩了一些方形括号和不同的循环的不同位置之后,我想我已经解决了这个问题。以下是我的代码现在的样子(根据脚手架设置路线,以便从/new
发布create
}。
模型/ person.rb
class Person < ActiveRecord::Base
has_many :foos
validates_presence_of :name
end
模型/ foo.rb
class Foo < ActiveRecord::Base
belongs_to :person
validates_presence_of :colour
validates_uniqueness_of :colour, :scope => "person_id"
end
控制器/ people_controller.rb
def new
# Set up a Person with 3 defaulted Foos
@person = Person.new
(1..3).each { |i| @person.foos.build }
end
def create
# Create (but don't save) a Person as specified
@person = Person.new(params[:person])
# Create (but don't save) a Foo for each set of Foo details
@foos = []
params[:foo].each do |foo_param|
@foos << Foo.new(foo_param)
end
# Save everything in a transaction
Person.transaction do
@person.save!
@foos.each do |foo|
foo.person = @person
foo.save!
end
end
redirect_to :action => 'show', :id => @person
rescue ActiveRecord::RecordInvalid => e
@foos.each do |foo|
foo.valid?
end
render :action => 'new'
end
视图/人/ new.html.erb
<% form_for :person do |f| %>
<%= error_messages_for :object => [@person] + @person.foos %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<table>
<% @person.foos.each_with_index do |foo, index| @foo = foo%>
<tr>
<td><%= label :colour, "Foo colour #{index + 1}: " %></td>
<td><%= text_field("foo[]", "colour" %></td>
</tr>
<% end %>
</table>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
这似乎可以解决问题。