我正在使用nested_form
gem来表示AddressBook
关系。当用户清空现有Addr
的值时,我想删除Addr
,而不是使用空白value
保存
class Person < ActiveRecord::Base
has_many :addrs, dependent: :destroy
attr_accessible :name, :addrs_attributes
accepts_nested_attributes_for :addrs, reject_if: :addr_blank, allow_destroy: true
def addr_blank(a)
valid? && a[:id].blank? && a[:value].blank?
end
class Addr < ActiveRecord::Base
belongs_to :person
attr_accessible :kind, :label, :value, :person_id
我的:reject_if
方法效果很好,但它并没有给我所需的一切
valid?
通过验证保留我的空白地址a[:id].blank?
在用户空白和现有记录时避免拒绝现在,当用户空白Addr
时,我需要删除(而不是保存)现有的value
。另外,我通过RESTful API公开了Persons和Addrs。我看到两种可能的选择:
params
哈希以添加神奇的_destroy=1
参数。 IOW,模拟按下删除按钮的用户活动。Addr
模型中,以便将带有空白value
的更新实际视为删除。基于这里的建议是我如何实现它:
people_controller.rb
def update
@person = Person.find(params[:id])
@person.destroy_blank_addrs(params[:person])
respond_to do |format|
...
person.rb
def destroy_blank_addrs(person_params)
if valid? && person_params[:addrs_attributes]
person_params[:addrs_attributes].each do |addr_params_array|
addr_params= addr_params_array[1]
addr_params[:_destroy] = '1' if !addr_params[:id].blank? && addr_params[:value].blank?
end
end
end
答案 0 :(得分:15)
accepts_nested_attributes_for :addrs,
allow_destroy: true,
:reject_if => proc { |att| att[:name].blank? && attr[:description].blank? }
答案 1 :(得分:8)
accepts_nested_attributes_for :addrs,
allow_destroy: true,
reject_if: -> { |attr| [name, description].any? &:blank? }
答案 2 :(得分:5)
第三种方法是在Person上添加before_save
回调,删除所有空白的地址。这个想法有一些优点,但我可能不会接受它。
在你提出的两个选项中,我不会对params进行后期处理。它会成功,但这是太多的工作。此外,控制器代码将变得有点混乱,我坚信一个非常苗条的控制器。
在我的脑海中,最简单的选择是保存后删除空白地址。您可以添加Person#remove_blank_addresses()
,然后在成功保存时调用它。您不需要传递参数 - 它可以迭代地址并删除空白地址。它的缺点是创建空地址然后销毁它们,但无论如何你都需要它来更新人。
如果我们谈论最干净的解决方案(在我看来),我会介绍第三个类,它将处理所有逻辑并让控制器委托给它。控制器很容易单独测试,然后你可以编写一个模型规范来检查所有细节。这是一个更多的工作,我现在想不出一个好名字(PersonUpdater
?),但这可能是一个值得思考的想法。
答案 3 :(得分:2)
accepts_nested_attributes_for :addrs,
allow_destroy: true,
reject_if: :all_blank