实例变量似乎失去了它们的价值

时间:2011-10-10 17:52:37

标签: ruby-on-rails ruby

我的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返回正确的数据。任何想法为什么我得到这个零对象错误?我认为实例变量保留了它们的值,但不知何故,这个变量会丢失。

感谢。

3 个答案:

答案 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,它对与一个键对应的数据大小没有这样的限制。