如何避免在嵌套的 rails 表单上保存空记录 [英] how to avoid saving empty records on a nested rails form
问题描述
我将 nested_form
gem 用于我的 AddressBook
关系.当用户清空现有 Addr
的值时,我想删除该 Addr
而不是用空白的 value
I'm using the nested_form
gem for my AddressBook
relation. When the user blanks out the value of an existing Addr
, I want to delete that Addr
rather than saving with a blank 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
方法运行良好,但它没有提供我需要的一切
My :reject_if
method works well but it doesn't give me everything I need
valid?
通过验证保持我的空白地址a[:id].blank?
避免在用户空白和现有记录时被拒绝
valid?
keeps my blank Addrs around through validationa[:id].blank?
avoids rejections when the user blanks out and existing record
现在,当用户将 value
设为空白时,我需要删除(而不是保存)现有的 Addr
.此外,我通过 RESTful API 公开 Persons 和 Addrs.我看到两个可能的选项:
Now, I need to delete (rather than save) an existing Addr
when the user blanks the value
. Also, I'm exposing Persons and Addrs via a RESTful API. I see two possible options:
- 对
params
哈希进行后处理以添加神奇的_destroy=1
参数.IOW,模拟按下删除按钮的用户活动. - 将其封装在
Addr
模型中,以便将具有空白value
的更新有效地视为删除.
- Post process the
params
hash to add the magical_destroy=1
param. IOW, emulate the user activity of pressing the delete button. - Encapsulate this inside the
Addr
model such that an update with a blankvalue
is effectively considered a delete.
根据这里的建议,我是如何实现它的:
Based on the advice here is how I implemented it:
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
推荐答案
第三种选择是在 Person 上添加一个 before_save
回调,该回调将删除所有空白地址.这个想法有一些优点,但我可能不会同意.
A third alternative would be to add an before_save
callback on Person that will remove all addresses that are blank. This idea has some merit, but I probably won't go with it.
在您提供的两个选项中,我不会对参数进行后处理.它会成功,但工作量太大.此外,控制器代码会变得有点混乱,我坚信非常纤薄的控制器.
Out of the two options you present, I will not go with post-processing the params. It will work out, but it is too much work. Besides, to controller code will get a bit messier and I'm a firm believer in a very slim controller.
在我看来,最简单的选择是在保存后删除空白地址.您可以添加 Person#remove_blank_addresses()
然后在成功保存时调用它.您不需要传入参数 - 它可以只迭代地址并删除空白地址.它的缺点是创建空地址然后销毁它们,但无论如何您都需要它来更新人员.
The easiest option, in my head, is to remove the blank addresses after saving. You can add Person#remove_blank_addresses()
and then call it on successful save. You don't need to pass in the params - it can just iterate the addresses and remove the blank ones. It has the disadvantage of creating empty addresses and then destroying them, but you would need that for updating people anyway.
如果我们谈论的是最干净的解决方案(在我看来),我会引入第三个类来处理所有这些逻辑并让控制器委托给它.控制器很容易单独测试,然后您可以编写一个模型规范来检查所有细节.这需要更多的工作,我现在想不出一个好名字(PersonUpdater
?),但它可能是一个值得考虑的想法.
If we're talking about the cleanest solution (in my opinion), I would introduce a third class that would handle all that logic and have the controller delegate to it. The controller would be easy enough to test in isolation and then you can write a model spec that checks all the nitty-gritty details. It is a bit more work and I can't think of a good name right now (PersonUpdater
?), but it might be an idea worth thinking about.
这篇关于如何避免在嵌套的 rails 表单上保存空记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!