2008-11-22 8 views
0

J'ai une classe dans laquelle la recherche d'une instance est coûteuse, si les instances sont mises en cache:Comment puis-je mettre (parties de) un graphe d'objet volumineux dans Rails.cache?

class Foo 
    def self.find(id) 
    Rails.cache.fetch("Foo.#{id}") do 
     // some expensive lookup, like an HTTParty request, or a long SQL query 
     ... 
    end 
    end 
end 

Cela fonctionne bien jusqu'à ce que Foo s ont lié Foo s:

class Foo 
    def children 
    @child_foo_ids.map { |id| Foo.find(id) } 
    end 
end 

Je voudrais utiliser la mise en cache ||= pour sauver des voyages répétés:

class Foo 
    def children 
    @children ||= @child_foo_ids.map { |id| Foo.find(id) } 
    end 
end 

Mais Rails.cache gèle e J'ai trouvé Foo s, donc je ne peux pas définir la variable d'instance après avoir créé et mis en cache l'objet. (Par exemple cette méthode soulève un TypeError.)

Une solution serait de précharger le parent quand je fais la découverte cher, mais qui pourrait finir par charger un objet graphique gigantesque quand je ne veux un ou deux instances.

Répondre

5

Vous pouvez utiliser ||= mise en cache; il vous suffit d'utiliser un peu indirection:

class Foo 
    def initialize 
    @related_objects = {} 
    end 
    def children 
    @related_objects[:children] ||= @child_foo_ids.map { |id| Foo.find(id) } 
    end 
end 

Rails.cache ne gèle pas les variables d'instance de chaque Foo, de sorte que Hash peut être modifié! PS: oui, j'ai juste posté cette question et la réponse à la même heure. Je pensais que la communauté pourrait bénéficier de ma lutte.