Почему мой звонок владельцу в отношениях has_many не работает? - PullRequest
0 голосов
/ 30 декабря 2018

Я использую Rails 5.0.7.1 и вижу в документах , что мой экземпляр CollectionProxy должен иметь доступ к переменной экземпляра "@owner":

Ассоциацияпрокси в Active Record являются посредниками между объектом, который содержит ассоциацию, известную как @owner, и фактическим связанным объектом, известным как @target.Тип ассоциации любого прокси доступен в @reflection.Это экземпляр класса ActiveRecord :: Reflection :: AssociationReflection.

прокси ассоциации в blog.posts имеет объект в блоге как @owner, коллекцию его сообщений как @target и объект @reflectionпредставляет макрос: has_many.

Этот класс делегирует неизвестные методы @target через method_missing.

В моем приложении Rails я получил следующий (довольно нереалистичный) тестовый код:

class Post < ApplicationRecord
  has_many :comments  do
    def number_five
      if owner.is_a? Post
        Comment.where(id: 5, post_id: self.id)
      end
    end
  end
end

class Comment < ApplicationRecord
  belongs_to :post
end

Когда я звоню Post.last.commments.number_five, я получаю следующую ошибку:

NameError (undefined local variable or method `owner' for #
<Comment::ActiveRecord_Associations_CollectionProxy:0x00007fcbb9106120>)

Когда я добавляю byebug к строке между def number_five и owner.is_a? Post,и я проверяю значение self, я вижу, что оно ActiveRecord::Associations::CollectionProxy, поэтому я думаю Я звоню owner в области, где оно должно быть определено.

I 'я пробовал Post.last.comments.instance_variables, и я не вижу :@owner, только следующее:

[:@association, :@klass, :@table, :@values, :@offsets, 
:@loaded, :@predicate_builder, :@scope]

Я также пробовал следующее:

comments = Post.last.comments
def comments.get_owner
  self.owner
end

Это возвращает то же самоеNameError как указано выше.

Для чего стоит, когда я запускаю Post.last.comments.class, я вижу, что это Comment::ActiveRecord_Associations_CollectionProxy.

Учитывая, как читают документы,Я ожидал, что смогу вызвать либо Post.last.comments.owner, либо @owner из Post.last.comments (оба из которых я пробовал), и он вернет значение Post.last.Мои ожидания неверны, или мой код неверен, или это что-то совсем другое?

1 Ответ

0 голосов
/ 30 декабря 2018

Документация немного сбивает с толку.Я помню, что мне пришлось потратить несколько часов на то, чтобы угадать, прочитать исходный код Rails и поэкспериментировать, чтобы понять это в первый раз, когда мне нужно выйти за пределы ассоциации с помощью метода расширения.

owner - это то, что выпосле, но это метод для ассоциации, и вы получаете ассоциацию через proxy_association (это просто метод доступа для @association):

has_many :comments  do
  def number_five
    if proxy_association.owner.is_a? Post
      #...
    end
  end
end

Я не уверен, что это "правильно""или" официальный "способ сделать это, но это то, что я делал со времен Rails 4.

...