我有一些球员,球员有交易状态。而不是硬编码交易状态,如“活动”和“非活动”,然后必须去寻找字符串,我认为我会聪明,并有一个单独的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对象,我会给它一个去。
非常感谢你的时间。
答案 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派生,并定义了我需要的常量。
感谢大家的想法和解决方案。