ruby-on-rails - 工厂女孩 - 操纵 transient 属性

标签 ruby-on-rails factory-bot

我有一个用例,我想根据所包含的特征来操作工厂中的 transient 属性。有没有办法做到这一点,或者有更好的方法来完成我想要完成的任务?

假设我正在构建一个 House目的。 house可以有很多windows 。我想创建一些子工厂来自动创建一些窗口,但我希望能够为特定类型的窗口添加特征。 window_types transient 属性实际上是 window 的特征列表工厂。

factory :house do
  floors 3
  exterior 'Brick'

  transient do
    window_types { [:bay, :double_hung] }
  end

  trait :with_picture_window do
    window_types.push(:picture)
  end

  factory :ranch_house do
    floors 1

    after(:create) do |house, evaluator|
      evaluator.window_types.each do |window_type|
        FactoryGirl.create :window, window_type
      end
    end
  end

  factory :mountain_house do
    floors 2
    exterior 'Log'

    after(:create) do |house, evaluator|
      evaluator.window_types.each do |window_type|
        FactoryGirl.create :window, window_type
      end
    end
  end
end

factory :window do
  material 'Glass'

  trait :bay do
    # bay window attributes
  end

  trait :double_hung do
    # double hung window attributes
  end

  trait :picture do
    # picture window attributes
  end
end

这会抛出 NoMethodError: undefined method 'push' for #<FactoryGirl::Declaration::Implicit> :with_picture_window 内的错误特征。

为了便于讨论,假设我确实需要不同的工厂来 build 这些房子。有没有办法可以从特征中修改 window_types transient 属性,然后让该 transient 属性反射(reflect)在我的子工厂中?

我希望能够做到:

FactoryGirl.create :ranch_house
# creates a ranch house with only bay and double_hung windows

FactoryGirl.create :ranch_house, :with_picture_window
# creates a ranch house with bay, double_hung, AND picture windows

如果没有,是否有更好的方法可以实现这一目标?

提前非常感谢。

最佳答案

根据 Ben 提出的想法,我找到了合适的解决方案。我使用本地数组变量来存储需要创建的窗口的类型。每个窗口的特征将窗口类型添加到 after(:build) block 中的数组中。然后,在 after(:create) block 中,我实际创建了窗口记录。

第一个 after(:build) block (不在 trait 中的 block )很重要,因为它会重置 window_types 数组对象创建。

FactoryGirl.define do
  window_types = []

  factory :house do
    floors 3
    exterior 'Brick'

    after(:build) do
      window_types = []
    end

    after(:create) do |house|
      window_types.each do |window_type|
        FactoryGirl.create(:window, window_type, house: house)
      end
    end

    trait :with_picture_window do
      after(:build) do
        window_types << :picture
      end
    end

    trait :with_double_hung_window do
      after(:build) do
        window_types << :double_hung
      end
    end

    trait :with_bay_window do
      after(:build) do
        window_types << :bay
      end
    end

    factory :house_with_bay_and_picture_window, traits: [:bay, :picture]
  end
end

我很好奇听到关于这种方法的任何想法。目前来说,这符合我的需求,而且非常灵活。

关于ruby-on-rails - 工厂女孩 - 操纵 transient 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36463468/

相关文章:

ruby-on-rails - 我在 Factory Girl 中使用序列来获取唯一值,但出现验证错误

javascript - 在 Ember 中保存关联记录

ruby-on-rails - 更新父级时未设置父级 ID

ruby-on-rails - Ruby on Rails 和 apache 的文件上传超时

ruby-on-rails - rails 2.3.8 : Fetching objects via ActiveRecord without building all the objects

ruby-on-rails - 我想将电子邮件消息保存到数据库而不是立即发送

ruby-on-rails - 你如何使用 Fabrication 定义特征

ruby-on-rails - AssociationTypeMismatch 和 FactoryGirl

ruby-on-rails - 如何定义返回带字符串键的哈希的 Factory Girl 工厂?

ruby-on-rails - 主要 :Object (NameError) 的未定义局部变量或方法 `user'