web-dev-qa-db-fra.com

Comment déterminer si l'association Rails est chargée?

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.

45
wbharding

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.

45
Bryan Stearns

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 .)

50
gamov

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

21
dabobert

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).

3
Jim Stewart

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
3
Lev Lukomsky

Jetez un coup d'œil au joyau Bullet. . Cela vous indiquera quand vous devriez et ne devriez pas utiliser un chargement rapide.

2
Bitterzoet

association_cached? pourrait être un bon choix:

item.association_cached?(:shipping_infos)
0
phil pirozhkov