变量取决于FactoryGirl中另一个变量的值

时间:2015-10-01 13:45:35

标签: ruby-on-rails ruby automated-tests conditional factory-bot

我有以下问题。我有一个模型,其中有一个变量(金额)的验证,取决于另一个枚举变量(种类)的值。

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),但是现在程序只是爆炸并且“堆栈级别太深”,我试图重现一些我见过的例子但是肯定是错的:

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

我可以做些什么来实现我的目标?到目前为止我尝试过的是什么问题?任何这些问题都很高兴知道。

(值得一提的是,我也是铁杆和红宝石的新手)

2 个答案:

答案 0 :(得分:2)

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

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
}

答案 1 :(得分:1)

很确定你只需要一个块:

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