Разница между двумя стратегиями активной загрузки обсуждается в комментариях здесь
https://github.com/rails/rails/blob/3-0-stable/activerecord/lib/active_record/association_preload.rb
Из документации:
# The second strategy is to use multiple database queries, one for each
# level of association. Since Rails 2.1, this is the default strategy. In
# situations where a table join is necessary (e.g. when the +:conditions+
# option references an association's column), it will fallback to the table
# join strategy.
Я считаю, чтоточка в "foo.bar" заставляет активную запись думать, что вы помещаете условие в таблицу, которая находится за пределами исходной модели, которая предлагает вторую стратегию, обсуждаемую в документации.
Два отдельных запроса выполняются один с моделью Person, а второй - с моделью Item.
Person.includes(:items).where(:name => 'fubar')
Person Load (0.2ms) SELECT "people".* FROM "people" WHERE "people"."name" = 'fubar'
Item Load (0.4ms) SELECT "items".* FROM "items" WHERE ("items".person_id = 1) ORDER BY items.ordinal
Поскольку второй запрос выполняется для модели Item, он наследует область по умолчанию, гдеВы указали order(:ordinal)
.
Второй запрос, который он пытается загружать с полным набором, запускает модель person и не будет использовать область ассоциации по умолчанию.
Person.includes(:items).where(:name => 'foo.bar')
Person Load (0.4ms) SELECT "people"."id" AS t0_r0, "people"."name" AS t0_r1,
"people"."created_at" AS t0_r2, "people"."updated_at" AS t0_r3, "items"."id" AS t1_r0,
"items"."person_id" AS t1_r1, "items"."name" AS t1_r2, "items"."ordinal" AS t1_r3,
"items"."created_at" AS t1_r4, "items"."updated_at" AS t1_r5 FROM "people" LEFT OUTER JOIN
"items" ON "items"."person_id" = "people"."id" WHERE "people"."name" = 'foo.bar'
Itэто немного глючит, но я вижу, как это будет с несколькими различными способами представления списка опций, чтобы быть уверенным, что вы поймаете все из них, будет сканировать выполненные условия "ГДЕ"для точки и использовать вторую стратегию, и они оставляют это таким образом, потому что обе стратегии являются функциональными.Я бы на самом деле зашёл так далеко, что сказал, что аномальное поведение в первом запросе, а не во втором.Если вы хотите, чтобы порядок для этого запроса сохранялся, я рекомендую одно из следующего:
1) Если вы хотите, чтобы у ассоциации был порядок, когда он вызывается, то вы можете указать это с помощью ассоциации,Как ни странно, это есть в документации, но я не смог заставить его работать.
Источник: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many
class Person < ActiveRecord::Base
has_many :items, :order => 'items.ordinal'
end
2) Другим способом было бы просто добавить оператор заказак рассматриваемому запросу.
Person.includes(:items).where(:name => 'foo.bar').order('items.ordinal')
3) В тех же строках будет задана именованная область действия
class Person < ActiveRecord::Base
has_many :items
named_scope :with_items, includes(:items).order('items.ordinal')
end
И для вызова этого:
Person.with_items.where(:name => 'foo.bar')