代码之家  ›  专栏  ›  技术社区  ›  kolrie

在Rails中的常量上缓存模型实例时出现问题

  •  1
  • kolrie  · 技术社区  · 17 年前

    我在Rails应用程序的一个模型上使用单表继承(STI),在常量上存储模型对象时遇到问题。我已将问题隔离到一个示例项目中,并将其提交给GitHub: http://github.com/fcoury/rails-sti-caching

    /config/initializers/ 目录)并使其保持恒定:

    MUSIC_CACHE = Hash.new
    Music.all.each { |m| MUSIC_CACHE[m.id] = m }
    

    class MusicsController < ApplicationController
      def index
        require 'pp'
        pp MUSIC_CACHE
        @debug = []
        MUSIC_CACHE.each_pair do |k, v|
          music = Music.find(k)
          d "Object for Music.find(#{k})  => class: #{music.class} - class obj_id: #{music.class.object_id} - #{music.inspect}"
          d "Object for MUSIC_CACHE[#{k}] => class: #{v.class} - class obj_id: #{v.class.object_id} - #{v.inspect}"
    
          begin
            d "  - Music.is_a?(Media) => #{v.is_a?(Media)}"
            d "  - Try to call name   => #{v.name}"
          rescue
            d "*** Error raised:\n#{$!}"
          end
        end
    
        @musics = Music.all
      end
    
      def d(s)
        puts s
        @debug << s
      end
    end
    

    以及随之而来的观点:

    <h1 id="music">Music</h1>
    
    <ul>
      <% for m in @musics %>
      <li><%= m.name %> - <%= m.file %></li>
      <% end %>
    </ul>
    
    <pre><%=h @debug.join("\n") %></pre>
    

    <pre> 标签如下:

      Object for Music.find(2)  => class: Music - class obj_id: 13067420 - #<Music id: 2, name: "5th Symphony", file: "5s.mp3", type: "Music", created_at: "2009-05-06 16:31:41", updated_at: "2009-05-06 16:31:41">
      Object for MUSIC_CACHE[2] => class: Music - class obj_id: 13067420 - #<Music id: 2, name: "5th Symphony", file: "5s.mp3", type: "Music", created_at: "2009-05-06 16:31:41", updated_at: "2009-05-06 16:31:41">
        - Music.is_a?(Media) => true
        - Try to call name   => 5th Symphony
    

    Object for Music.find(2)  => class: Music - class obj_id: 18452280 - #<Music id: 2, name: "5th Symphony", file: "5s.mp3", type: "Music", created_at: "2009-05-06 16:31:41", updated_at: "2009-05-06 16:31:41">
    Object for MUSIC_CACHE[2] => class: Music - class obj_id: 13067420 - #<Music id: 2, name: "5th Symphony", file: "5s.mp3", type: "Music", created_at: "2009-05-06 16:31:41", updated_at: "2009-05-06 16:31:41">
      - Music.is_a?(Media) => false
    *** Error raised:
    You have a nil object when you didn't expect it!
    You might have expected an instance of Array.
    The error occurred while evaluating nil.include?
    

    有人知道这个错误背后的原因吗?

    2 回复  |  直到 17 年前
        1
  •  2
  •   pts    17 年前

    class: Music - class obj_id: 13067420 在第二次请求中变得不可用。我建议看一看ActiveRecord源代码,找出是谁使模型对象无效。

    此外,本rails模型缓存教程也很有用: http://railscasts.com/episodes/115-caching-in-rails-2-1

        2
  •  0
  •   kch    17 年前

    基本上,你不能这么做。

    在开发环境中,每个请求都会重新加载类。这意味着它们被完全摧毁和重建。原来的类对象消失了,一个新的对象取而代之。