Est-ce que quelqu'un connaît un moyen de déterminer si une association Rails a été chargée avec impatience?
Ma situation: j'ai un ensemble de résultats où parfois une des associations est impatiente et parfois non. S'il n'est pas chargé avec impatience, je souhaite rechercher des associations à l'aide de la recherche d'ActiveRecord. S'il est chargé, je veux utiliser détecter.
Par exemple, supposons que j'ai un tableau "has_many" d'objets shipping_info dans mon modèle d'article. Ensuite:
Si l'article est chargé avec impatience, la charge la plus efficace est:
item.shipping_infos.detect { |si| si.region == "United States" }
Si l'élément n'est pas chargé avec impatience, la charge la plus efficace est:
item.shipping_infos.where(region: "United States").first
Mais à moins que je sache s'il est chargé, je ne sais pas quel code appeler pour obtenir le disque efficacement. Si j'utilise la première méthode alors qu'elle n'était pas chargée, je dois rechercher plus d'enregistrements de base de données que nécessaire. Et si j'utilise la deuxième méthode quand elle était chargée avec impatience, mes objets chargés avec impatience sont ignorés.
item.shipping_infos.loaded?
vous le dira.
Je dois dire cependant: ce chemin mène à la folie ... avant d'écrire du code qui teste loaded?
pour décider entre #detect
et #find
, assurez-vous que cette instance vraiment est importante par rapport à tout ce qui se passe.
Si ce n'est pas la tâche la plus lente de votre application, l'ajout de chemins de code supplémentaires ajoute une complexité inutile. Ce n'est pas parce que vous gaspillez un peu d'effort dans la base de données que vous devez le réparer, cela n'a probablement aucune importance mesurable.
Utilisez .association(name).loaded?
sur un enregistrement.
Pour Rails <3.1, utilisez loaded_foo?
.
(Il est obsolète depuis Rails 3.1. Voir: https://github.com/Rails/rails/issues/472 .)
Je suggérerais d'utiliser item.association_cache.keys qui fournira une liste des associations chargées avec impatience. Vous êtes donc item.association_cache.keys.include? : name_of_association
Vous pouvez détecter si une seule association a été chargée avec chargé _ foo ?. Par exemple, si shipping_info était une association d'appartenance, alors item.loaded_shipping_info? retournera vrai quand il a été chargé avec impatience. Bizarrement, il semble renvoyer nil (plutôt que false) lorsqu'il n'a pas été chargé (de toute façon dans Rails 2.3.10).
La solution à ce problème devrait être foo.association(:bla).loaded?
, MAIS cela ne fonctionne pas correctement - cela vérifie et marque l'association comme sale:
class Foo; has_one :bla, :autosave => true end
foo.association(:bla).loaded? #=> false
foo.save # saves foo and fires select * from bla
J'ai donc ajouté l'extension suivante à ActiveRecord:
module ActiveRecord
class Base
def association_loaded?(name)
association_instance_get(name).present?
end
end
end
et maintenant:
class Foo; has_one :bla, :autosave => true end
foo.association_loaded?(:bla) #=> false
foo.save # saves foo
Jetez un coup d'œil au joyau Bullet. . Cela vous indiquera quand vous devriez et ne devriez pas utiliser un chargement rapide.
association_cached?
pourrait être un bon choix:
item.association_cached?(:shipping_infos)