2017-05-18 5 views
0

J'utilise Rails 5. J'ai ce modèleComment forcer Rails à utiliser mon cache au lieu de toujours aller à la base de données?

class MyObject < ActiveRecord::Base 
    ... 
    belongs_to :distance_unit 

et je remarque quand j'ai une ligne comme celle ci-dessous

distance = Distance.new({:distance => my_obj.distance, :distance_unit => my_obj.distance_unit}) 

il provoque les actions suivantes à exécuter

SELECT "distance_units".* FROM "distance_units" WHERE "distance_units"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 

Rien d'inhabituel, mais j'ai mis en cache une méthode créée dans mon modèle DistanceUnit

class DistanceUnit < ActiveRecord::Base 

    def self.cached_find_by_id(id) 
    Rails.cache.fetch("distanceunit-#{id}") do 
     puts "looking for id: #{id}" 
     find_by_id(id) 
    end 
    end 

et je voudrais la ligne "distance = Distance.new ({: distance => mon_obj.distance,: distance_unit => mon_obj.distance_unit})" pour invoquer ma fonctionnalité en cache au lieu de courir vers la base de données. Comment puis-je atteindre cet objectif?

+0

qu'utilisez-vous pour stocker le cache? – murb

+0

Oh bonne question. J'ai "config.cache_store =: memory_store" dans mon fichier de configuration. – Dave

Répondre

0

En ce qui concerne mon commentaire, notez que memory_store n'est utilisé que dans un processus, de sorte que chaque processus aura son propre magasin (considérez MemCacheStore si c'est un problème). Le cache est également parti lorsque le processus se termine. En règle générale, l'association belongs_to déclenche une recherche si l'objet n'a pas encore été extrait. Il y a beaucoup de caches construits dans le framework Rails et en général, je ne m'inquiéterais pas trop de l'optimisation prématurée au début (et j'optimiserais seulement si les requêtes sont trop lentes). En outre: L'accès au cache est également un appel à un type de base de données, et une recherche basée sur un identifiant probablement indexé n'est généralement pas un appel lourd. Aussi, s'il n'y a que quelques unités de distance, peut-être que vous utilisez simplement une constante pourrait fonctionner?

Mais pour répondre à votre question. Il ne semble pas y avoir quelque chose dans votre code qui dit cached_find_by_id (et alors que les rails font beaucoup de choses automagiquement, ce n'est pas l'un d'entre eux).

Vous pouvez créer la méthode suivante dans MyObject qui l'emporte sur le « getter » qui est créé par l'association belongs_to:

def distance_unit 
    DistanceUnit.cached_find_by_id(distance_unit_id) 
end 

Cependant, si vous l'initialisation simplement un objet ActiveRecord et vous ne pas besoin de la DistanceUnit dans cet appel vous pouvez également passer l'id directement, puisque c'est ce qui est stocké dans la base de données.

Distance.new({:distance => my_obj.distance, :distance_unit_id => my_obj.distance_unit_id})