2010-06-08 3 views
1

J'ai deux modèles:application Rails __gVirt_NP_NN_NNPS<__ perfomance ou comment mettre en cache résultat de la méthode

Program < ActiveRecord::Base 
    has_many :events 

    def federal_financing 
    events.sum(&:federal_financing) 
    end 

    def regional_financing 
    events.sum(&:regional_financing) 
    end 

    def local_financing 
    events.sum(&:local_financing) 
    end 
end 

Event < ActiveRecord::Base 
    belongs_to :program 
    # events table have this decimal fields: federal_financing, local_financing, regional_financing 
end 

toujours si je l'appelle l'un de ces trois méthodes que je vous appelle encore les. Donc, je veux éviter de charger des événements chaque fois que j'appelle l'une de ces méthodes. La solution actuelle est maintenant de définir

def after_initialize 
    @all_events = events 
end 

et d'utiliser @all_events à la place des événements dans les méthodes. MAIS je ne veux pas charger les événements lorsque l'objet se charge - Je veux des événements "cache" uniquement si l'une de ces trois méthodes a été appelée et d'autres méthodes doivent utiliser la version mise en cache des événements.

Répondre

1

Je crois que vous pouvez utiliser ce qui suit pour charger events juste une fois par program:

Program < ActiveRecord::Base 
    has_many :events 

    def federal_financing 
    all_events.sum(&:federal_financing) 
    end 

    def regional_financing 
    all_events.sum(&:regional_financing) 
    end 

    def local_financing 
    all_events.sum(&:local_financing) 
    end 

    def all_events 
    # if @events is not initialized yet or is nil or is false, 
    # self.events will be loaded. otherwise @events will remain unchanged. 
    @events ||= self.events 
    end 
end 
0

Rails cache la requête qui charge les événements automatiquement, donc il n'y a pas besoin de vous mettre en cache explicitement les événements. Cependant, pour que cela fonctionne, vous devrez convertir les événements en tableau avant de calculer la somme; events.sum signifie que vous voulez construire une requête SQL pour calculer la somme, et ne fonctionnera pas.

Changez votre modèle Program comme suit:

Program < ActiveRecord::Base 
    has_many :events 

    def federal_financing 
    events.to_a.sum(&:federal_financing) 
    end 

    def regional_financing 
    events.to_a.sum(&:regional_financing) 
    end 

    def local_financing 
    events.to_a.sum(&:local_financing) 
    end 
end 

Maintenant, en permettant l'enregistrement ActiveRecord dans la console, il est facile de voir que les requêtes en effet se cache:

$ script/console 
>> ActiveRecord::Base.logger = Logger.new(STDOUT) 
>> p = Program.first 
    Program Load (1.0ms) SELECT * FROM "programs" LIMIT 1 
=> #<Program id: 1, created_at: "2010-06-08 15:01:08", updated_at: "2010-06-08 15:01:08"> 
>> p.federal_financing 
    Event Load (1.0ms) SELECT * FROM "events" WHERE ("events".program_id = 1) 
=> 147 
>> p.regional_financing 
=> 23 
>> p.local_financing 
=> 11 

Comme vous pouvez le voir , les événements sont chargés une seule fois, lors du premier appel à federal_financing.

Questions connexes