Chaque fois que je frappe une page authentifiée, je remarque que l'élaboration d'une instruction SQL: p>
Charge utilisateur (0.2ms) Sélectionnez (J'utilise des rails 3 btw .. alors cache_money semble être une solution et malgré beaucoup de recherche que je n'ai trouvé aucun substitut). P>
J'ai essayé de nombreuses substitutions dans le modèle d'utilisateur et que seule la recherche_by_sql semble appelée. Qui est passé une chaîne de toute la déclaration SQL. Quelque chose d'intuitif comme Find_By_id ou Trouver ne semble pas être appelé. Je 'peut "remplacer cette méthode et glaner l'utilisateur-id et faire un système de cache raisonnable à partir de celui-ci - mais c'est assez moche. P>
J'ai aussi essayé d'authentifier_utilisateur sur lequel je peux intercepter une tentative SQL, mais ensuite appelle à Current_User semble l'essayer à nouveau. P>
Simplement, mes objets d'utilisateur changent rarement et c'est un état triste pour continuer à frapper le DB pour cela au lieu d'une solution memcache. (Supposons que je suis prêt à accepter toutes les responsabilités d'invalidation de ladite cache avec: après_save dans le cadre mais pas toute cette solution) p> Utilisateurs CODE>. * Du
Utilisateurs code> où (
utilisateurs code>. code> = 1 ) Limite 1 p>
3 Réponses :
AVERTISSEMENT: Il y a probablement une meilleure façon de faire cela. P>
J'ai chassé ce problème dans quelques mois. J'ai trouvé - ou du moins, je pense que j'ai trouvé - où Devise charge l'objet utilisateur ici: https://github.com/plataformatec/devise /blob/master/lib/devise/rails/warden_compat.rb#l31 p>
J'ai créé un patch de singe pour cette méthode désérialisée dans /initializers/warden.rb pour faire une fetch cache au lieu d'obtenir. Il se sentait sale et mal, mais cela a fonctionné. P>
Génial adam. Pourrait être sale et mal - mais en effet ça marche.
J'ai tellement lu avec cela aussi.
Une manière moins compliquée de cela consiste à ajouter cette méthode de classe à votre modèle utilisateur: p> La seule chose à craindre, bien sûr, invalide l'utilisateur dans le cache lorsque quelque chose change. Il aurait été agréable de stocker l'utilisateur dans le cache à l'aide de l'ID de session dans le cadre de la clé, mais la session n'est pas disponible dans la classe modèle et n'est pas transmise à cette méthode par congise. P> < / p>
Le code suivant mettra en cache l'utilisateur par son identifiant et Invalider le cache après chaque modification.
class User < ActiveRecord::Base after_save :invalidate_cache def self.serialize_from_session(key, salt) single_key = key.is_a?(Array) ? key.first : key user = Rails.cache.fetch("user:#{single_key}") do User.where(:id => single_key).entries.first end # validate user against stored salt in the session return user if user && user.authenticatable_salt == salt # fallback to devise default method if user is blank or invalid super end private def invalidate_cache Rails.cache.delete("user:#{id}") end end
Devise fait beaucoup de vérification. Vérifiez que vous veulent I> à faire (généralement). Mais vous avez raison, une quantité de cela devrait être macabotable. Avez-vous tiré de Ruby-Debug pour déterminer où viennent les différentes trouvailles? Je n'ai pas vu de Find_By_SQL dans la source. L'affaire commune est l'utilisateur connecté qui visite des pages protégées par Devise et Devise s'assure que l'utilisateur est vraiment valide. Si vous pouvez caresser ce voyage aller-retour, vous devriez avoir une grande partie du problème résolu. Plus difficile: il y a plusieurs façons de concevoir peut invalider le cache. Par exemple, si un utilisateur réinitialise le mot de passe.