我正在尝试构建一个允许用户更新某些记录的表单。但是,它们无法更新每个字段,因此我将进行一些显式处理(现在在控制器中)以相对于表单更新模型。以下是我试图这样做的方法:
家庭模特:
class Family < ActiveRecord::Base
has_many :people, dependent: :destroy
accepts_nested_attributes_for :people, allow_destroy: true, reject_if: ->(p){p[:name].blank?}
end
在控制器中
def check
edited_family = Family.new(params[:family])
#compare to the one we have in the db
#update each person as needed/allowed
#save it
end
形式:
= form_for current_family, url: check_rsvp_path, method: :post do |f|
= f.fields_for :people do |person_fields|
- if person_fields.object.user_editable
= person_fields.text_field :name, class: "person-label"
- else
%p.person-label= person_fields.object.name
问题是,我想,Family.new(params[:family])
试图将人们拉出数据库,我明白了:
ActiveRecord::RecordNotFound in RsvpsController#check
Couldn't find Person with ID=7 for Family with ID=
那是,我想,因为我没有在嵌套表单中添加一个家庭id的字段,我想我可以这样做,但实际上我并不需要从数据库加载任何东西,所以我宁愿不。我也可以通过自己挖掘params哈希来获取我需要的数据,但这并不是一件容易的事。从params散列中创建一个对象然后再使用它似乎是最好的。
有更好的方法吗?我怎样才能创建嵌套对象?
答案 0 :(得分:1)
我不建议使用这些参数实例化一个新的Family对象,而是建议使用creating a member route来检查rsvp动作。路线将采取以下形式:
resources :families do
member do
post 'check_rsvp'
end
end
然后form_for将自动传递current_family的id,以便检查操作如下所示:
def check
edited_family = Family.find(params[:id])
# ...
end
虽然这看起来在功能上可能等同于自己添加family id参数,但我认为它优于基于其他params实例化或基于其他params实例化的新Family对象,因为:
答案 1 :(得分:0)
我最终接受了@ 244an的建议:
class Person < ActiveRecord::Base
belongs_to :family
def temp_id
@temp_id || self.id
end
def temp_id=(new_id)
@temp_id = new_id
end
end
表格形式:
= form_for current_family, url: check_rsvp_path, method: :post, html: {class: "form-inline"} do |f|
#people-list
= f.fields_for :people, include_id: false do |person_fields|
= person_fields.hidden_field :temp_id
#rest of the form here
然后在我的控制器中:
def check
@edited_family = Family.new(params[:family])
current_people = Hash[current_family.people.map{|p| [p.id, p]}]
@edited_family.people.each do |person|
current_person = current_people[person.temp_id.to_i]
next unless current_person
current_person.name = person.name if current_person.user_editable
current_person.attending = person.attending
current_person.save!
end
current_family.responded = true
current_family.save!
end
我将该字段添加到模型的原因是我无法想出使用hidden_field
重命名字段的好方法。
无论如何,它感觉超级苛刻,但它的确有效。我真正想要的只是一种告诉new
不要尝试将子对象与数据库匹配的方法,即使它们有ID。