在 FactoryGirl 中使一个变量依赖于另一个变量的值

Making a variable depend on the value of another in FactoryGirl

我有以下问题。我有一个模型,其中根据另一个枚举变量(种类)的值验证变量(数量)。

class ScopeChange < ActiveRecord::Base

enum kind: [ :add, :remove, :change ]

validates :amount, :numericality => { :greater_than_or_equal_to => 1 } , if: "self.add?"
validates :amount, :numericality => { :less_than_or_equal_to => -1 } , if: "self.remove?"

end

我想创建一个构建它的工厂,我尝试将 if 语句放入变量的实际创建者中(它应该是一个 if elsif else 语句,这只是为了测试)

FactoryGirl.define do
  factory :sprint_scope_change do
    association :sprint
    kind { Faker::Number.between(0,2) }
    amount { kind == :add ? Faker::Number.between(-7,7) }
    date { Faker::Date.between(sprint.start_date, sprint.end_date) }
    description { Faker::Lorem.sentence }
  end
end

没有用,它完全忽略了 if 语句,只是创建了一个介于 -7 和 7 之间的随机数。接下来我尝试在工厂外部创建一个变量:sprint_scope_change 并在工厂内部创建一个变量:

FactoryGirl.define do

  factory :sprint_scope_change do

    sprint_scope_change.kind = Faker::Number.between(0,2)

    sprint_scope_change.amount = if sprint_scope_change.kind == 0
      Faker::Number.between(1,7)
    elsif sprint_scope_change.kind == 1
      Faker::Number.between(-7,-1)
    else
      Faker::Number.between(-7,7)
    end

    association :sprint
    kind { kind }
    amount { amount }
    date { Faker::Date.between(sprint.start_date, sprint.end_date) }
    description { Faker::Lorem.sentence }
  end
end

它在某种程度上起作用,但每次我调用工厂时它给出的值完全相同。我尝试的最后一种方法是使用 before(:create),但现在程序爆炸了,"stack level is too deep",我试图重现一些我见过的例子,但肯定有问题:

FactoryGirl.define do

factory :sprint_scope_change do
  before(:create) { |sprint_scope_change|

    sprint_scope_change.kind = Faker::Number.between(0,2)

    sprint_scope_change.amount = if sprint_scope_change.kind == 0
      Faker::Number.between(1,7)
    elsif sprint_scope_change.kind == 1
      Faker::Number.between(-7,-1)
    else
      Faker::Number.between(-7,7)
    end
  }

  association :sprint
  kind { kind }
  amount { amount }
  date { Faker::Date.between(sprint.start_date, sprint.end_date) }
  description { Faker::Lorem.sentence }

  end
end

我可以做些什么来实现我想做的事情?到目前为止我尝试过的有什么问题?很高兴知道这些问题中的任何一个。

(值得一提的是我也是rails和ruby的新手)

很确定你只需要一个块:

sprint_scope_change.amount do
  if kind == 0
    Faker::Number.between(1,7)
  elsif kind == 1
    Faker::Number.between(-7,-1)
  else
    Faker::Number.between(-7,7)
  end
end

你真的需要这种随机行为吗?您在规格中想要的是控制。我建议使用特征。

FactoryGirl.define do
  factory :sprint_scope_change do

    trait :add do
      kind { 0 }
      amount { random_valid_amount_for_add }
    end

    trait :remove do
      kind { 1 }
      amount { ... }
    end
  end
end

FactoryGirl.create :sprint_scope_change, :add

如果你想要随机性,再次强调,你是掌控者

let(:random_scope_changes) {
  3.times.map do |i|
    case rand(2)
    when 0 then FactoryGirl.create(:sprint_scope_change, :add)
    when 1 then FactoryGirl.create(:sprint_scope_change, :remove)
      # etc.
    end
  end
}