Самый простой способ объяснить эту загадку является примере:Как цепочки один метод на другой изменение оригинального метода
Скажем, у меня есть два Mongoid модели, которые связаны через has_many
отношений: блоге
class Post
include Mongoid::Document
field :body, type: String
has_many :comments
end
и это комментарии
class Comment
include Mongoid::Document
field :text, type: String
belongs_to :post
end
Теперь я создаю пост который имеет два комментария в IRB, и я пытаюсь загрузить их через отношения. У меня есть некоторые DB протоколирование включено, так что я могу видеть, когда запрос сделан:
post.comments #=>
2016-04-27 13:51:52.144 [DEBUG MONGODB | localhost:27017 | test.find | STARTED | {"find"=>"comments", "filter"=>{"post_id"=>BSON::ObjectId('571f315e5a4e491a6be39e02')}}]
2016-04-27 13:51:52.150 [DEBUG MONGODB | localhost:27017 | test.find | SUCCEEDED | 0.000492643s]
=> [#<Comment _id: 571f315e5a4e491a6be39e03, text: 'great post' >, #<Comment _id: 571f315e5a4e491a6be39e12, text: 'this!' >]
Поэтому комментарии загружаются из БДА и возвращаются как Mongoid::Relations::Targets::Enumerable
класса, который выглядит как массив, и он содержит два комментария ,
Теперь, когда я открываю свежий IRB консоль, и посмотрите на критерии, используемые для загрузки эти комментарии с помощью атрибута экземпляра Mongoid::Relations::Targets::Enumerable
класса post.comments
criteria
, я получаю этот выход:
post.comments.criteria #=>
=> #<Mongoid::Criteria
selector: {"post_id"=>BSON::ObjectId('571f315e5a4e491a6be39e02')}
options: {}
class: Comment
embedded: false>
Как приходят в этом примере не выполняются запросы БД? Это не проблема кэширования, так как я открыл новую консоль IRB.
Как можно связать criteria
с номером post.comments
изменить то, что делает метод .comments
? Я просмотрел реализацию Mongoid в классе Mongoid::Relations::Targets::Enumerable
(source on Github), но не смог найти подсказки, как это работает.
Редактировать
Для выяснения вопроса:
Этот код не запрашивает базу данных:
post.comments.criteria
Но этот код:
foo = post.comments
post.comments.criteria
Как так?
Вы спрашиваете, как «post.comments.criteria» показывает селектор ObjectId? Если это так, ваш 'post' является переменной (класса Post), и он исходит оттуда. Поскольку переменная 'post' является классом Post, она понимает, что #comments является отношением (has_many). Короче говоря, я считаю, что вызов БД был сделан, когда ваша переменная 'post' была инициализирована. –
Он не будет делать вызов БД до тех пор, пока вы не будете использовать метод запроса (см. Https://docs.mongodb.org/ecosystem/tutorial/mongoid-queries/). –
@ wes.hysell Благодарим вас за комментарии. Если он вообще не должен делать вызов БД, то почему он делает это для меня? Я использую версию «Mongoid» 5.1.3 и rails '4.2.6' –