일정한 레일의 문제 캐싱 모델 인스턴스
-
06-07-2019 - |
문제
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
다른 팁
기본적으로, 당신은 그것을 할 수 없습니다.
개발 환경에서 각 요청마다 클래스가 다시로드됩니다. 그것은 그들이 완전히 파괴되고 재창조된다는 것을 의미합니다. 원래 클래스 객체는 사라지고 새로운 개체가 자리를 차지합니다.
요청에 따라 객체를 유지하면 두 번째 요청에서 객체는 여전히 원래 클래스에서 상속됩니다. 해당 클래스를 가리키는 상수는 이제 새로운 클래스 객체를 가리 킵니다.이 클래스 정의를 변경했는지 여부에 따라 이전과 동일 할 수도 있고 동일하지 않을 수 있지만 여전히 다른 클래스 객체가됩니다. 메모리와 이전 객체는이 새로운 클래스 객체에서 상속되어야한다는 것을 알지 못할 것입니다.
제작 환경에서 응용 프로그램을 실행하면 작동한다고 가정합니다.