2011-10-10 73 views
1

我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 

记录仪线内创建显示,@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> 

我已经验证业务::销售:: RevenueByWeek :: Term.new返回正确的数据。任何想法,为什么我得到这个零对象错误?我认为实例变量保留了它们的值,但不知何故,这个变量会丢失。

谢谢。

+0

请显示您如何使用此代码,流程如何。 –

回答

1

我假设report.rb是一个活跃的记录模型。在该框架中,#create并不意味着是构造函数,它仅在基础表中创建行。不过,我看到你在那里设置了@terms = {}

如果您的报表实例从数据库中查询出来,#create永远不会运行,所以您的成员永远不会被初始化。

我建议你隐藏了一个名为terms方法背后的@terms(甚至是内部的)使用(也就是说,除非你已经宣布它作为AR属性,或类似)。您的方法懒惰初始化成员作为需要。

0

report.rb是不是活动记录模型 - 不使用数据库表。 创建方法用于创建报表实例,并将调用级联到获取报表值所需的其他类,如Term.new调用。

创建方法结束后,呈现一个视图 - 上面的错误来自该视图中的一个部分。

我已经把各种记录通话中创建方法来验证它确实得到调用,并且在创建方法变量@terms是什么,我希望它是。我无法弄清楚为什么填充的@terms散列在每个方法中都不可用。该创建方法记录器调用每个方法记录的调用之前出现,而@terms是好的在创建每个空或零。 @terms是否应该保留整个实例的价值 - 并且不要将其他方法隐藏起来?

0

我解决了这个问题。发生的事情是@terms变量应该被写入缓存。我们正在使用memcached,并且@terms数据的大小超过1 MB,所以Cache.write语句失败。然后,当@terms需要从'each'方法的缓存中提取时,那里什么也没有。这个快速而肮脏的解决方案是减少@term数据的大小,以便Cache.write成功。长期的解决方案是用Resque替换memcached,Resque对与一个键相对应的数据大小没有这样的限制。