Rspec,模型加载顺序,夹具和named_scope挑战

时间:2009-11-12 04:45:43

标签: ruby-on-rails model rspec named-scope

我有一些球员,球员有交易状态。而不是硬编码交易状态,如“活动”和“非活动”,然后必须去寻找字符串,我认为我会聪明,并有一个单独的TradeState模型,以便玩家有一个trade_state_id(一个玩家可以只在一次一个贸易州。)

现在,通过使用命名范围然后通过说“Player.active”来获得所有活动玩家将是一种方便。为此,我需要获取与“活动”匹配的TradeState记录的ID,因此我在Player类中提出了这个:

named_scope :active, :conditions => {:trade_state_id => TradeState.active.first.id}

在脚本/控制台中测试时,这就像一个魅力,但是当我去测试时它不起作用。我正在使用RSpec,但我怀疑这是不相关的。当我运行最琐碎的测试时,我收到以下错误:

“被叫id为nil,这将错误地为4”

据我所知,测试框架按字母顺序加载和解析模型。框架解析Player模型中的named_scope调用,并尽职地查找活动的第一个TradeState记录的id。但是,该模型尚未处理,尚未准备就绪,因此获取id为nil的错误。

起初我以为是因为trade_states表中可能没有任何记录,所以我在before(:each)块中创建并保存了我需要的trade_states,但这没有用。所以我制作了一些灯具并尝试加载它们,但那不起作用。

这看起来似乎有道理吗?还有其他解释吗?如何解决问题?我可以尝试模拟TradeState对象,我会给它一个去。

非常感谢你的时间。

3 个答案:

答案 0 :(得分:0)

您提到的这段代码会在Player“加载”时执行。因此,即使您在before(:each)块中创建设置数据,此模型也可能在此之前加载。要解决此问题,您可以尝试以下方法:

named_scope :active, lambda { {:conditions => {:trade_state_id => TradeState.active.first.id} } }

这可确保在调用named_scope时调用TradeState.active。

但是你通过致电TradeState.active.first获得了什么。相反,你可以通过这种不错的方式实现这一目标

:conditions => {:trade_state_id => TradeState::ACTIVE}

在TradeState模型上使用以下代码:

class TradeState < ActiveRecord::Base
  def self.const_missing(sym)
    const_set(sym, find_by_name(sym.to_s))
  end
end

答案 1 :(得分:0)

这实际上是一种潜在的“预期”结果。如果你没有活跃的玩家,那么

TradeState.active

为空,因此

TradeState.active.first

是零,

因此

TradeState.active.first.id

在nil对象上调用Object::id

您可以尝试:

TradeState.active.empty? ? 0 : TradeState.active.first[:id]

在任何情况下,请确保包含trade_states只是为了确保它们存在于连接中。

答案 2 :(得分:0)

不幸的是,尽管所有这些建议都非常好,但在运行测试用例时没有任何可靠的工作。起初我退出了所有这些代码,但是我必须编写的代码没那么吸引人了,所以我开始重新思考这个问题。

因为我们将通过他们的交易状态大量查找玩家,所以在数字交易状态列上有一个索引是明确的优先事项。然而,没有任何迹象表明贸易状态需要成为一个表格,因为只定义了少数贸易状态,并且在定义的贸易状态中不太可能存在太多的波动。

因此,我将TradeState本身设为一个类,不再从ActiveRecord派生,并定义了我需要的常量。

感谢大家的想法和解决方案。