我一直在为此苦苦挣扎几天。我有这个模型:
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上获得了valdation错误,其中包含空白属性。这是由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
一切都会顺利通过,但我觉得我不应该这样做。
我是否有可能测试这个错误,或者在模型中构建子项是不好的做法。
任何想法都会有很大的帮助。
答案 0 :(得分:1)
在模型
中构建子项是不好的做法不一定,但我会避免after_initialize
- 它会在模型的每个实例化中执行,甚至是直的find
。
我认为您最好隔离需要添加business_location并明确执行的情况。由于您的business_entity_with_locations
工厂似乎正在这样做,我不确定您为什么需要回调。
至于为什么accepts_nested_attributes_for
不起作用,我相信这是因为你没有使用它。它期望一个属性哈希,如:
{:business_locations =&gt; {0 =&gt; {:name =&gt; “样品名称}}}
传递给像new
这样的方法。这不是你正在做的事情 - 你在没有任何参数的情况下在关联上调用build
。因此,accepts_nested_attributes_for
提供的属性设置器逻辑永远不会被调用。