0

我有一些球员,球员有交易状态。而不是硬编码贸易状态,如“活动”和“非活动”,然后必须去寻找字符串,我想我会很聪明,有一个单独的 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。但是,该模型尚未处理并且尚未准备好,因此有关获取 nil 的 id 的错误。

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

这看起来有道理吗?还有其他解释吗?变通工作怎么样?我可以尝试模拟 TradeState 对象,我会试一试。

非常感谢您的宝贵时间。

4

3 回答 3

0

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

TradeState.active

是空的,因此

TradeState.active.first

为零,

因此

TradeState.active.first.id

调用Object::id一个 nil 对象。

你可以试试:

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

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

于 2009-11-13T22:24:20.273 回答
0

您提到的这段代码在“加载”播放器时执行。因此,即使您在 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
于 2009-11-13T09:14:51.410 回答
0

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

因为我们将大量按贸易状态查找玩家,所以在数字贸易状态列上建立索引是一个明确的优先事项。然而,并没有说贸易状态需要是一个表格,因为只定义了几个贸易状态,而且在定义的贸易状态中不太可能有很大的波动性。

因此,我使 TradeState 成为一个独立的类,不再从 ActiveRecord 派生,并定义了我需要的常量。

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

于 2009-11-14T22:34:32.057 回答