2

我已经为此苦苦挣扎了几天。我有这个模型:

class BusinessEntity < ActiveRecord::Base

  has_many :business_locations
  accepts_nested_attributes_for :business_locations, :allow_destroy => true,
        :reject_if => proc { |attributes| attributes.all? { |key, value| key == '_destroy' || value.blank? } }

 after_initialize :build_child

  ....

  def build_child
    self.business_locations.build if self.business_locations.empty?    
  end

business_entites.rb(工厂)

FactoryGirl.define do
  factory :business_entity do
    name "DaveHahnDev"
    association :company, :factory => :company
    association :default_currency, :factory => :currency

    factory :business_entity_with_locations do
      after(:build) do |business_entity|
        business_entity.class.skip_callback(:create, :after, :set_primary_business_info)
        business_entity.business_locations << FactoryGirl.build(:business_location)
      end
    end
  end

  factory :business_location do
    name "Main Office"
    business_entity
    address1 "139 fittons road west"
    address2 "a different address"
    city { Faker::Address.city }
    province "Ontario"
    country "Canada"
    postal_code "L3V3V3"

  end
end

现在,当我调用FactoryGirl.create(:business_entity)规范时,我得到关于 business_locations 的验证错误有空白属性。这是由 after_initialize 回调初始化的孩子。我认为 reject_if 会处理这个问题,就像你从浏览器使用应用程序一样。如果我添加:

  before_validation :remove_blank_children

  def remove_blank_children
    self.business_locations.each do |bl|
        bl.mark_for_destruction if bl.attributes.all? {|k,v| v.blank?}
    end
  end

一切都会好起来的,但我觉得我不应该这样做。

是否有可能我正在测试这个错误,或者在模型中建立孩子是不好的做法。

任何想法都会有很大帮助。

4

1 回答 1

1

在模型中建立孩子是不好的做法

不一定,但我会避免after_initialize——它在模型的每个实例化时执行,甚至是直接的find.

我认为您最好隔离需要添加 business_location 并明确执行的情况。而且您的工厂似乎business_entity_with_locations正在这样做,我不确定您为什么需要回调。

至于为什么accepts_nested_attributes_for不起作用,我相信那是因为你没有使用它。它需要一个属性哈希,如:

{ :business_locations => { 0 => { :name => "样本名称 } } }

被传递到类似的方法new中。这不是你在做的——你build在没有任何参数的情况下调用关联。所以accepts_nested_attributes_for永远不会调用由提供的属性设置器逻辑。

于 2012-11-15T03:39:13.947 回答