如何避免在嵌套的 rails 表单上保存空记录 [英] how to avoid saving empty records on a nested rails form

查看:46
本文介绍了如何避免在嵌套的 rails 表单上保存空记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 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

  1. valid? 通过验证保持我的空白地址
  2. a[:id].blank? 避免在用户空白和现有记录时被拒绝
  1. valid? keeps my blank Addrs around through validation
  2. a[: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:

  1. params 哈希进行后处理以添加神奇的 _destroy=1 参数.IOW,模拟按下删除按钮的用户活动.
  2. 将其封装在 Addr 模型中,以便将具有空白 value 的更新有效地视为删除.
  1. Post process the params hash to add the magical _destroy=1 param. IOW, emulate the user activity of pressing the delete button.
  2. Encapsulate this inside the Addr model such that an update with a blank value 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆