在常量中创建ActiveRecord对象是不是很糟糕?

时间:2015-08-20 12:56:33

标签: ruby-on-rails ruby ruby-on-rails-4 activerecord

我有一些代码,我在我的模型中创建ActiveRecord对象作为常量,如下所示:

class OrderStage < ActiveRecord::Base
  validates :name, presence: true, uniqueness: true

  DISPATCHED = find_or_create_by(name: 'Dispatched')
end

每个订单都有一个OrderStage:

class Order < ActiveRecord::Base
  belongs_to :order_stage
end

现在这似乎在整个网站和我的集成测试中都能正常工作。然而,它在我的单元测试中打破了。以下测试

it 'lists all order stages' do
  # using FactoryGirl
  create(:order, order_stage: OrderStage::DISPATCHED)
  expect(Order.all.map(&:order_stage)).to eq [OrderStage::DISPATCHED]
end
当我单独运行时,或者当我只运行order_spec.rb时,

会正常传递。但是当我运行整个测试套件,甚至只是spec/models时,我收到了这个错误:

Failure/Error: expect(Order.all.map(&:order_stage)).to eq [OrderStage::DISPATCHED]

   expected: [#<OrderStage id: 1, name: "Dispatched">]
        got: [nil]

如果我像这样编写测试,那个错误就会消失:

it 'lists all order stages' do
  order_stage = OrderStage.find_or_create_by(name: 'Dispatched')
  create(:order, order_stage: order_stage)
  expect(Order.all.map(&:order_stage)).to eq [order_stage]
end

所以它必须与在常量中创建ActiveRecord对象有关,这是一件坏事吗?

1 个答案:

答案 0 :(得分:1)

你应该使用类方法。

attr_accessible :name

def self.dispatched
  @dispatched ||= find_or_create_by_name('Dispatched')
end

private

def self.reset!
  @dispatched = nil
end