문제

Rails 앱의 모델 중 하나에 STI (Single Table Henheritance)를 사용하고 있으며 모델 객체를 상수에 저장하는 데 문제가 있습니다. 문제를 샘플 프로젝트로 분리하여 Github에 제출했습니다. http://github.com/fcoury/rails-sti-caching

내가하려는 것은 모델 인스턴스 (이 경우 음악 모델, STI를 통해 미디어 모델에서 상속되는 음악 모델)를로드하는 것입니다 (Rails에서 /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?

이 오류의 이론적 근거를 아는 사람이 있습니까?

도움이 되었습니까?

해결책

첫 번째 아이디어는 Rails가 요청을 제공 한 후 모든 모델 객체를 해방 (무효화)한다는 것입니다. 그래서 class: Music - class obj_id: 13067420 두 번째 요청에서는 사용할 수 없습니다. ActiveRecord 소스 코드를 살펴보고 누가 모델 객체를 무효화하는지 알아내는 것이 좋습니다.

또한이 Rails 모델 캐싱 자습서는 다음과 같습니다. http://railscasts.com/episodes/115-caching-in-rails-2-1

다른 팁

기본적으로, 당신은 그것을 할 수 없습니다.

개발 환경에서 각 요청마다 클래스가 다시로드됩니다. 그것은 그들이 완전히 파괴되고 재창조된다는 것을 의미합니다. 원래 클래스 객체는 사라지고 새로운 개체가 자리를 차지합니다.

요청에 따라 객체를 유지하면 두 번째 요청에서 객체는 여전히 원래 클래스에서 상속됩니다. 해당 클래스를 가리키는 상수는 이제 새로운 클래스 객체를 가리 킵니다.이 클래스 정의를 변경했는지 여부에 따라 이전과 동일 할 수도 있고 동일하지 않을 수 있지만 여전히 다른 클래스 객체가됩니다. 메모리와 이전 객체는이 새로운 클래스 객체에서 상속되어야한다는 것을 알지 못할 것입니다.

제작 환경에서 응용 프로그램을 실행하면 작동한다고 가정합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top