2010-11-14 23 views
19
  1. Do méthodes d'association, tels que ceux définis par has_many et belongs_to utilisent ActiveRecord::Relation?Est-il possible d'obtenir le ActiveRecord :: objet Relation pour une association

  2. Si oui, est-il possible d'obtenir l'objet ActiveRecord::Relation qui est utilisé.

Nous sommes tous conscients que Rails 3 est fortement ActiveRecord::Relation utilise des objets et des objets Arel::Relation en arrière-plan, lors de la création de requêtes à l'aide du Query Interface. Chaque fois que nous utilisons les méthodes select, joins, etc. de l'interface de requête, un objet ActiveRecord::Relation est renvoyé. Cependant, cela ne semble pas être le cas lors de l'appel d'une méthode d'association d'un modèle. Au lieu de cela, la requête est exécutée immédiatement et une instance ou un tableau d'instances du modèle associé est renvoyé.

Tenir compte des modèles suivants:

post.rb

class Post < ActiveRecord::Base 
    belongs_to :user 
end 

user.rb

class user < ActiveRecord::Base 
    has_many :posts 
end 

Exemple:

u = User.first 
u.posts 

appel u.posts renvoie un tableau de publications, pas une instance de ActiveRecord::Relation. Je me demande s'il est possible d'obtenir le ActiveRecord::Relation qui est utilisé par l'association, s'il est utilisé, peut-être en utilisant Arel::Table?

Mon raisonnement pour vouloir le ActiveRecord::Relation devrait être évident: C'est parce que je veux enchaîner l'association existante et manipuler la requête pour adapter à un but différent.

Répondre

32

Pendant quelques minutes, j'ai utilisé le hack where(nil), alors j'avais un encéphalogramme et essayé quelque chose au hasard:

User.first.posts.scoped 

Ca y est! : D

Oui, Rails + Arel est vraiment mal documenté. J'attends avec impatience qu'il arrive à maturité au point où je peux réellement regarder les choses et obtenir des réponses réelles.

+0

Aimez-le. Beaucoup plus propre! Je vous donne le CHECKMARK. Et je suis d'accord avec la documentation d'Arel. J'ai lu des bribes et des bribes partout à propos de ça. Cela semble très puissant, mais sans une bonne documentation, cela peut aussi être très ennuyeux. :) – John

+0

Brillant, merci beaucoup! –

+0

est-il un moyen d'appeler '.scoped' sur un tableau personnalisé que j'ai fait? – brittohalloran

1

En prenant le temps de lire réellement la documentation des guides de bord, j'ai pu trouver une réponse dans Section 4.3 has_many Association Reference. En résumé, la documentation ne permet pas de savoir s'il est possible d'obtenir l'objet ActiveRecord::Relation ou si un objet ActiveRecord::Relation est utilisé, mais il fournit des détails sur la façon de réutiliser l'association et d'en adapter le résultat.

Section 4.3.1 Methods Added by has_many répertorie les collection.where comme étant l'une des méthodes qui est ajoutée par l'association has_many. Et la section 4.3.1.11 collection.where(…) montre que vous l'utiliseriez comme vous utiliseriez la méthode where de l'interface de requête. Plus important encore, il donne un indice que objets sont chargés paresseusement lors de l'utilisation de cette méthode sur la collection, et bien sûr, un objet ActiveRecord::Relation est retourné.

u.posts.where("").class # => ActiveRecord::Relation 
u.posts.where("").to_sql # => SELECT `posts`.* FROM `posts` WHERE `posts`.user_id = 1 

Certes, ce n'est pas la solution idéale, mais cela me donne quelque chose que je peux enchaîner.

3

dans Rails 4, utilisez .scope ou .spawn pour accéder à l'objet relation au lieu du CollectionProxy. Voir le documentation.

1

Dans un ActiveSupport::Concern, vous ne pouvez pas appeler la méthode privée spawn ou utiliser scope ou scoped.

J'avais besoin de l'utiliser.

where(true)