Problem Caching Modell-Instanzen auf einem konstant in Rails
-
06-07-2019 - |
Frage
I Einzel-Table Vererbung (STI) für eine Rails App auf einem meiner Modelle verwenden und ich Probleme speichern Modellobjekte auf einer Konstante. Ich habe das Problem in einem Beispielprojekt isoliert und legte sie GitHub: http://github.com / fcoury / Schienen-sti-Caching
Was ich versuche, eine Modellinstanz zu tun wird geladen (in diesem Fall ein Musik-Modell, das von dem Medienmodell über STI erbt) auf einem Initialisierer (in Rails' /config/initializers/
Verzeichnis) und halten Sie sie auf einem konstanten:
MUSIC_CACHE = Hash.new
Music.all.each { |m| MUSIC_CACHE[m.id] = m }
Und ich habe eine Probe-Controller, macht folgendes:
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
Und eine Ansicht, mit ihm zu gehen:
<h1 id="music">Music</h1>
<ul>
<% for m in @musics %>
<li><%= m.name %> - <%= m.file %></li>
<% end %>
</ul>
<pre><%=h @debug.join("\n") %></pre>
Das erste Mal, dieser Code ausgeführt wird, ist die Ausgabe auf dem <pre>
Tag folgt aus:
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
Allerdings, wenn ich nur die Seite neu zu laden, hier ist was ausgegeben wird:
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?
Kennt jemand die Gründe für diesen Fehler?
Lösung
Meine erste Idee wäre, dass Rails freigibt (Ungültigmachungseinträge) alle Modellobjekte nach einer Anforderung dient. So wird class: Music - class obj_id: 13067420
unbrauchbar in der zweiten Anfrage. Ich würde vorschlagen, einen Blick auf die Active Quellcode hat und herauszufinden, wer Modellobjekte entkräftet.
Auch diese Schienen Modell Caching Tutorial können nützlich sein: http: / /railscasts.com/episodes/115-caching-in-rails-2-1
Andere Tipps
Im Grunde kann man nicht darauf.
In Entwicklungsumgebung, mit jeder Anforderung werden die Klassen neu geladen. Das heißt, sie sind völlig zerstört und neu erstellt. Das ursprüngliche Klassenobjekt ist weg, ein neuer an seine Stelle tritt.
Wenn Sie ein Objekt über Anfragen zu halten, in der zweiten Anforderung von der ursprünglichen Klasse des Objekt noch erben, die eine, die entfernt wurde. Die Konstante, die zu dieser Klasse darauf verweist nun auf ein neues Klasse-Objekt, das nicht auf die vorherigen je nach identisch ist oder nicht, ob Sie die Klassendefinition oder Plugins geändert, die es beeinflussen, aber es wird noch eine andere Klassenobjekt sein in Speicher und das alte Objekt nicht wissen, dass es aus diesem neuen Klasse Objekt erben sollte.
Ich gehe davon aus, wenn Sie Ihre Anwendung in der Produktionsumgebung ausführen, es wird funktionieren.