Можно ли получить объект ActiveRecord :: Relation для ассоциации? - PullRequest
20 голосов
/ 14 ноября 2010
  1. Используют ли методы сопоставления, такие как определенные has_many и belongs_to, ActiveRecord::Relation?

  2. Если это так, возможно ли получить объект ActiveRecord::Relation, который используется.

Мы все знаем, что Rails 3 активно использует ActiveRecord::Relation объекты и Arel::Relation объекты в фоновом режиме при создании запросов с использованием Query Interface . Всякий раз, когда мы используем методы select, joins и т. Д. Интерфейса запроса, возвращается объект ActiveRecord::Relation. Однако, похоже, что это не тот случай, когда вызывается метод ассоциации модели. Вместо этого запрос выполняется немедленно, и возвращается экземпляр или массив экземпляров связанной модели.

Рассмотрим следующие модели:

post.rb

class Post < ActiveRecord::Base
  belongs_to :user
end

user.rb

class user < ActiveRecord::Base
  has_many :posts
end

Пример: * 1 034 *

u = User.first
u.posts

Вызов u.posts возвращает массив сообщений, а не экземпляр ActiveRecord::Relation. Мне интересно, возможно ли получить ActiveRecord::Relation, который используется ассоциацией , если он вообще используется, возможно, с использованием Arel::Table?

Мое обоснование желания ActiveRecord::Relation должно быть очевидным: это потому, что я хочу отключить существующую ассоциацию и манипулировать запросом для достижения другой цели.

Ответы [ 4 ]

34 голосов
/ 18 ноября 2010

В течение нескольких минут я использовал хак where(nil), потом у меня была мозговая волна и я попробовал что-то случайное:

User.first.posts.scoped

Вот и все! : D

Да, Rails + Arel действительно плохо документированы. С нетерпением жду, когда он созреет до такой степени, что я действительно смогу найти вещи и получить реальные ответы.

3 голосов
/ 18 мая 2014

в Rails 4, используйте .scope или .spawn для доступа к объекту отношения вместо CollectionProxy.См. документацию .

1 голос
/ 29 января 2016

В ActiveSupport::Concern нельзя вызывать закрытый метод spawn или использовать scope или scoped.

Мне нужно было использовать это.

where(true)
1 голос
/ 14 ноября 2010

Потратив время на фактическое прочтение документации по Edge Guides, я смог найти ответ в Раздел 4.3 has_many Ссылка на ассоциацию .Вкратце, документация не проливает свет на то, возможно ли получить объект ActiveRecord::Relation или используется ли объект ActiveRecord::Relation, но в ней подробно описывается, как повторно использовать ассоциацию и адаптировать ее результат.

Раздел 4.3.1 Методы, добавленные has_many, перечисляют collection.where как один из методов, добавляемых ассоциацией has_many.А в разделе 4.3.1.11 collection.where(…) показано, что вы будете использовать его так же, как если бы вы использовали метод where интерфейса запроса.Что еще более важно, он дает подсказку, что объекты лениво загружаются при использовании этого метода в коллекции, и, конечно же, возвращается объект ActiveRecord::Relation.

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

По общему признанию, неидеальное решение, но оно дает мне то, от чего я могу избавиться.

...