带参数的FactoryBot序列

时间:2018-12-28 16:05:39

标签: ruby ruby-on-rails-4 sequence factory-bot

我希望能够以相同的方式递增不同的代码。例如:

  • 如果代码为12341234, 1234A, 1234B, ...
  • 如果代码为56785678, 5678A, 5678B, ...

如果我能以某种方式跳过第一次迭代会很好,但是我主要关心的是以某种方式能够传递不同的code来使用序列,因此我不必创建一个每个代码的顺序不同。

# Not ideal
FactoryBot.define do
  sequence(:1234, "A") { |n| "1234" + n }
  sequence(:5678, "A") { |n| "5678" + n }
end

我尝试使用调用序列的工厂,但是找不到使用创建字符串的工厂的任何示例。

FactoryBot.define do
  sequence(:letter, "A") { |n| n }

  factory :violation_code, :class => "String" do
    transient do
      code { "" }
    end
    base_code { code + generate(:letter) }
  end
end

build(:violation_code, :code => "1234")

我收到此错误NoMethodError: undefined method 'base_code=' for "":String

要求:

  • 使用代码和递增的字母生成字符串。

会很好:

  • 跳过第一次迭代,因此它仅在第一次调用generate()时返回代码。
  • 到达Z时,希望它转到AA而不是A

1 个答案:

答案 0 :(得分:1)

  

我不必为每个代码创建不同的顺序

这显然是不可能的,因为FactoryBot存储了 iterator 并在后台调用了#next。您无法在序列之间共享迭代器。

您可以做什么,可以直接从"1234A"开始:

"1234A".next
#⇒ "1234B"

很遗憾,它从"1235A""1234Z"。但是"Z".next产生"AA"。因此,将FactoryBot::DefinitionProxy#sequence包装到:

FactoryBot::DefinitionProxy.prepend(Module.new do
  def sequence(name, *args, &block)
    if args.last.is_a?(Hash) && prefix = args.last.delete(:prefix)
      super(name, *args) { |n| prefix + n }
    else
      super
    end
  end
end)

并这样称呼它:

FactoryBot.define do
  sequence("A", prefix: "1234")
end

我没有测试它,它肯定会得到显着改善,但是这个想法应该很清楚。