Ruby on rails 当方法存在时,Rails NoMethodError在循环中
大家好 我在生产环境中运行脚本时遇到了一点问题,尽管它在我的开发环境中运行得很好。我已经验证了所有必要的宝石和这些是相同的版本 我应该提到,该脚本打算使用script/runner命令运行 以下是我试图做的超级浓缩版本,以断裂部分为中心:Ruby on rails 当方法存在时,Rails NoMethodError在循环中,ruby-on-rails,ruby,methods,Ruby On Rails,Ruby,Methods,大家好 我在生产环境中运行脚本时遇到了一点问题,尽管它在我的开发环境中运行得很好。我已经验证了所有必要的宝石和这些是相同的版本 我应该提到,该脚本打算使用script/runner命令运行 以下是我试图做的超级浓缩版本,以断裂部分为中心: def currentDeal marketTime = self.convertToTimeZone(Time.new) deal = Deal.find(:first, :conditions => ["start_time ? AND marke
def currentDeal
marketTime = self.convertToTimeZone(Time.new)
deal = Deal.find(:first, :conditions => ["start_time ? AND market_id = ? AND published = ?", marketTime, marketTime, self.id, 1])
return deal
end
markets = Market.find(all)
markets.each do |market|
deal = market.currentDeal
puts deal.subject
end
现在convertToTimeZone是附加到模型的方法。如前所述,这段代码在我的开发机器上运行良好。但是,尝试在我的生产机器上运行它会导致:
undefined method `subject' for nil:NilClass (NoMethodError)
但是,如果我进入生产箱上的控制台并执行以下操作:
def currentDeal
marketTime = self.convertToTimeZone(Time.new)
deal = Deal.find(:first, :conditions => ["start_time ? AND market_id = ? AND published = ?", marketTime, marketTime, self.id, 1])
return deal
end
market = Market.find(1)
deal = market.currentDeal
puts deal.subject
它返回正确的值,没有问题。那么到底发生了什么
这是在rails V2.3.5上,在两台机器上
感谢您的帮助您正在循环浏览生产代码中的所有
市场
,但是您的测试片段只在寻找一个。问题是数据库中的一个市场
的currentDeal
为nil
(它没有与之关联的对象)
改为在生产控制台上运行此操作
markets = Market.find(all)
markets.each do |market|
deal = market.currentDeal
if deal
puts deal.subject
else
puts "NO currentDeal for Market with id: #{market.id}"
end
end
这将准确地告诉您,在没有当前交易的情况下,哪个市场
记录正在爆炸
所以问题是如何修复它?或者所有的
市场
预计都会有当前交易
,或者有时候没有,这没关系。如果市场总是有一个currentDeal,那么您需要调整您的验证,现在允许在没有currentDeal的情况下保存市场。但鉴于currentDeal是一个基于时间的东西,我认为有时没有安排任何交易,因此currentDeal
将返回nil
因此,更可能的情况是,您需要允许当前交易为nil
。您的测试代码不会这样做。它向市场索要交易,然后向市场索要交易标的。如果市场返回的是nil
交易,那么您立即向nil
询问其主题,您会得到例外,因为nil
没有名为subject
的方法。一些简单的零保护代码的方法:
deal = market.currentDeal
# simple if
if deal
puts deal.subject
end
# rails try method returns nil if the receiver is nil
# or executes the method if the object supports it
puts deal.try(:subject)
# ternary
puts deal ? deal.subject : "NO DEAL!"
# conditional execution
puts deal && deal.subject
最后,一个红宝石提示。这种方法比需要的复杂得多
def currentDeal
marketTime = self.convertToTimeZone(Time.new)
deal = Deal.find(:first, :conditions => ["start_time ? AND market_id = ? AND published = ?", marketTime, marketTime, self.id, 1])
return deal
end
Ruby将始终在方法中返回最后一个表达式的结果,而基于has的条件查找器将相当多地清理该查询
def currentDeal
marketTime = self.convertToTimeZone(Time.new)
Deal.find(:first, :conditions => ["start_time > ? AND market_id = ? AND published = ?", marketTime, marketTime, id, true])
end
但这看起来更像是一种联系。因此,您可能希望使用关联方法来进一步清理此问题。显然您正在调用
nil.subject
,因此Deal.find在生产代码中返回nil。您的测试用例只关注一个特定的市场对象,但一般情况下会循环遍历市场对象。您的代码需要处理找不到市场对象的currentDeal的问题我认为您在Deal.find调用中复制了marketTime参数。