我的report.rb类包含以下代码:
def create
@start_term = ::SchoolTerm.find(1705265)
@end_term = ::SchoolTerm.currently_enrolling
current = 0
total = all_terms.size
@terms = {}
all_terms.each do |t|
@terms[t.id] = Business::Sales::RevenueByWeek::Term.new(t)
Rails.logger.info("#{@terms} is @terms in report#create")
current += 1
self.progress = 100.0 * (Float(current) / Float(total))
end
end
def all_terms
::SchoolTerm.between(@start_term, @end_term) - RevenueGoal.terms_without
end
def each
Rails.logger.info("#{@terms} is @terms in report.each")
all_terms.each do |t|
yield @terms[t.id] if @terms[t.id]
end
end
create中的记录器行显示@terms在循环浏览不同的学期时具有正确的值。但是,每个方法中的记录器行将@terms显示为空。当我尝试加载报告时,出现此错误:
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
Extracted source (around line #24):
</tr>
</thead>
<% report.each do |term| %>
<tbody class="term_<%= term.id %>">
<tr class="term">
<th><%= term.term %></th>
我已经验证Business :: Sales :: RevenueByWeek :: Term.new返回正确的数据。任何想法为什么我得到这个零对象错误?我认为实例变量保留了它们的值,但不知何故,这个变量会丢失。
感谢。
答案 0 :(得分:1)
我假设report.rb
是一个活跃的记录模型。在该框架中,#create
并不意味着是构造函数,它只在基础表中创建行。不过,我看到你在那里设置了@terms = {}
。
如果从数据库中查询报表实例,则#create
永远不会运行,因此您的成员永远不会被初始化。
我建议你隐藏名为@terms
的方法后面terms
(甚至是内部的)的使用(也就是说,除非你已经将它声明为AR属性,或类似的。)你的方法可以根据需要延迟初始化成员。
答案 1 :(得分:0)
report.rb 不是活动记录模型 - 不使用数据库表。 create 方法用于创建报告的实例,并通过级联调用获取报告值所需的其他类,例如Term.new调用。
创建方法完成后,将呈现视图 - 上述错误来自该视图中的某个部分。
我已经在 create 方法中放置了各种记录器调用,以验证它确实被调用,并且 create 方法中的@terms变量是我期望的成为。我无法弄清楚为什么填充的@terms哈希在每个方法中都不可用。 创建方法记录器调用在每个方法记录器调用之前显示,而@terms在创建中是可以的,但在中为空或为零每个。 @terms不应该为整个实例保留它的值 - 并且不用在另一个方法中隐藏它来做它吗?
答案 2 :(得分:0)
我解决了这个问题。发生的事情是@terms变量应该被写入缓存。我们正在使用memcached,而@terms数据的大小超过1 MB,因此Cache.write语句失败了。然后当需要在'each'方法中从缓存中提取@terms时,那里什么都没有。快速而肮脏的解决方案是减少@term数据的大小,以便Cache.write成功。长期解决方案是用Resque替换memcached,它对与一个键对应的数据大小没有这样的限制。