ruby-on-rails - 使用 :reject_if => :all_blank on double nested forms

标签 ruby-on-rails ruby

所以我有以下模型

宠物

class Pet < ActiveRecord::Base

  # Associations
  has_and_belongs_to_many :owners

  accepts_nested_attributes_for :owners, :reject_if => :all_blank
end

所有者

class Owner < ActiveRecord::Base

  # Associations
  has_and_belongs_to_many :pets
  has_one :phone_number, :as => :callable, :dependent => :destroy
  has_one :address, :as => :addressable, :dependent => :destroy

  accepts_nested_attributes_for :phone_number
  accepts_nested_attributes_for :address
end

电话号码

class PhoneNumber < ActiveRecord::Base
  belongs_to :callable, polymorphic: true
end

地址

class Address < ActiveRecord::Base
  belongs_to :addressable, polymorphic: true
end

我有一个顶级 form_for @pet ,其中 f.fields_for :owners 嵌套在 f.fields_for :phone_number 中f.fields_for :address 都嵌套在 f.fields_for :owners block 中。这意味着我的 params.require 看起来像这样。

params.require(:pet).permit(:name, :breed, :color, :neutered, :microchip, :flee_control,
        :heartworm_prevention, :date_of_birth, :gender, :species_id, :avatar,
        :owners_attributes => [ :first_name, :last_name, :email,
            :phone_number_attributes => [:number],
            :address_attributes => [:line1, :city, :state, :zip_code] ])

我的参数都是正确的,我可以创建新记录,一切正常。当我尝试使用 :reject_if => :all_blank 拒绝空白所有者时,问题就出现了。

因为存在第二层嵌套属性,所以 phone_number_attributesaddress_attributes 都被视为 not_blank,因为它们在技术上属于 !ruby/hash:ActionController 类型::Parameters,它允许在不应使用空白属性的情况下构建对象。

我已经搜索了大约 2 个小时,但找不到任何提及此问题的内容。我错过了一些明显的东西吗?我尝试在所有者模型上添加 :reject_if => :all_blank 作为电话号码和地址,但也没有成功。

编辑:我能够让它工作,但必须有更好的内置方法来做到这一点。

accepts_nested_attributes_for :owners, reject_if: proc { |attributes|
    attributes.all? do |key, value|
      if value.is_a? ActionController::Parameters
        value.all? { |nested_key, nested_value| nested_key == '_destroy' || nested_value.blank? }
      else
        key == '_destroy' || value.blank?
      end
    end
  }

最佳答案

我还没有看到一种内置的方法来完成你想要做的事情,但我使用的解决方法是扩展 api 文档中找到的示例,如下所示:

# Add an instance method to application_record.rb / active_record.rb
def all_blank?(attributes)
  attributes.all? { |key, value| key == '_destroy' || value.blank? || (all_blank?(value) if value.is_a?(Hash)) }
end

# Then modify your model pet.rb to call that method
accepts_nested_attributes_for : owners, reject_if: :all_blank?

API 的原始示例

REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? } }

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

关于ruby-on-rails - 使用 :reject_if => :all_blank on double nested forms,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26621177/

相关文章:

mysql - Rails 搜索 `has_many :through` 文本字段

javascript - 向应用程序用户提供分析数据的最佳方式是什么?

ruby-on-rails - ruby rails 3 : help with sending emails

c++ - Ruby 模仿 C 整数数据类型和 union

mysql - 为什么使用 Ruby 将 AES 加密字符串保存为空白到 MySQL 表?

mysql - 在 ActiveRecord 模型的所有查询中更改 FROM

ruby-on-rails - 如何为资源调用动态设置用户密码

ruby-on-rails - 将 Rails 项目从 MySQL 迁移到 MongoDB

c++ - swig 对基类 'std::string' 一无所知,忽略

ruby-on-rails - 升级到 Rails 3.1.1 和 Authlogic