2011-10-30 3 views
4

Je veux écrire un cache ActiveRecord personnalisé, juste pour find_by_id maintenant. Pour ce faire, je veux écraser la méthode find, quand un seul entier est utilisé, utilisez mon cache, sinon utilisez l'implémentation par défaut. Tout fonctionne, sauf dans le cas d'une association avec d'autres instances de X, par exemple. une relation parent-enfant:Cache et associations Custom Rails - écrasement ActiveRecord.find

has_many :x_children 
has_many :children, :class_name => "X", :through => :x_children 

Quand j'appelle X.find(1).children je reçois un Enumerator au lieu d'un Array, ce qui est mauvais depuis que je l'utilise parfois l'opérateur [].

Même en utilisant le recenseur ne fonctionne pas bien - quand itérer la dernière entrée je reçois:

NoMethodError: undefined method `call' for :all:Symbol 

Toute aide sera très appréciée

Des explications complémentaires:

XCache est juste un classe qui met en cache les instances d'ActiveRecord. Une mise en œuvre peut être simpliste

class XCache 
    @@cache = {} 
    def self.[id] 
     return @@cache[id] ||= X.find(id) 
    end 
end 

(Une implémentation plus avancée peut inclure l'expiration du temps, Memcached etc., et une solution plus générique peut prendre en charge plusieurs classes de modèle).

Je ne pense pas que mon problème est lié à la mise en œuvre du cache (mais je peux me tromper)

+0

Que voulez-vous voulez réaliser ici? Une bibliothèque à usage général ou une solution à un problème spécifique? –

+0

Pourriez-vous expliquer ce qu'est le 'XCache'? Je recherche sur internet, mais je n'ai rien trouvé. Si vous avez implémenté vous-même (et si ce n'est pas trop de code), ajoutez simplement ce code à votre question. – mliebelt

+0

ne sait pas si cela aide, mais le fait est que [Enregistrement actif met en cache les enregistrements associés par défaut] (http://www.kickasslabs.com/2009/04/23/rails-gotcha-activerecord-caches-associated- records-by-default /) –

Répondre

0

Je ne sais pas si ça aide, mais ... C'est ce qui ressemble à trouver à l'intérieur:

def find(*args) 
    options = args.extract_options! 
    validate_find_options(options) 
    set_readonly_option!(options) 

    case args.first 
     when :first then find_initial(options) 
     when :last then find_last(options) 
     when :all then find_every(options) 
     else    find_from_ids(args, options) 
    end 
    end 

vous n'avez pas besoin de surcharger « trouver », mais « find_from_ids »

qui vous permettra de laisser seul tous les autres moyens qui trouvent est utilisé et cibler seulement votre propre usage.Given que les recenseurs sont ce retourné par find (: all) ... cela pourrait aider votre situation (ou non).

La seule possibilité est que Xcache retourne un seul ActiveRecord ou est-il possible qu'il renvoie parfois un ensemble ... ou même un ensemble vide?

Peut-être que vous pouvez essayer des variations sur:

def self.find(*args) 
    if args.size == 1 && args[0].is_a?(Numeric) 
     rval = XCache[args[0]] 
     return rval if rval.present? 
    end 
    super.find(*args) 
end 
1

Comme vous l'avez vu, il y a beaucoup de complexité cachée ici. Vous pouvez regarder dans la gemme cache-money, ces gars-là ont passé beaucoup d'efforts à comprendre.

Autres pierres précieuses pour regarder: simple_cacheable