Эффективные запросы соединения - это можно сделать с помощью ActiveRecord
У меня есть 4 модели, A, B, C и D
class A < ActiveRecord::Base
has_many :B
has_many :C, :through => :B
end
class B < ActiveRecord::Base
belongs_to :A
has_many :C
has_many :D, :through => :C
end
class C < ActiveRecord::Base
belongs_to :B
end
class D < ActiveRecord::Base
belongs_to :C
end
У меня очень наивная реализация, которая очень очевидна...
<% A.B.each do |b| %>
<%= b.number %>
<% b.C.each do |c| %>
<%= c.name %>
<% end %>
<% end %>
Какой лучший способ получить All C для A? Какой лучший способ получить все D для A?
Я хочу получить все "C", используя предложение order_by со значением "create_at" вместо итерации по B.
Может быть, мне не хватает волшебства ActiveRecord?
Я ценю любую помощь.
1 ответ
Прежде всего, вам нужно внести пару изменений.
class C
нужна ассоциация дляD
class C < ActiveRecord::Base belongs_to :B has_one :D end
Если вы хотите получить доступ
A
"sD
Это нужно указать и вам.class A < ActiveRecord::Base has_many :B has_many :C, :through => :B has_many :D, :through => :C end
Теперь, чтобы получить доступ ко всем A
"s C
"S:
-> a = A.where(:id => 1).includes(:C).first
A Load (0.2ms) SELECT "as".* FROM "as" WHERE "as"."id" = 1 LIMIT 1
B Load (0.1ms) SELECT "bs".* FROM "bs" WHERE "bs"."a_id" IN (1)
C Load (0.1ms) SELECT "cs".* FROM "cs" WHERE "cs"."b_id" IN (1, 2)
=> #<A id: 1, created_at: "2012-01-10 04:28:42", updated_at: "2012-01-10 04:28:42">
-> a.C
=> [#<C id: 1, b_id: 1, created_at: "2012-01-10 04:30:10", updated_at: "2012-01-10 04:30:10">, #<C id: 2, b_id: 1, created_at: "2012-01-10 04:30:11", updated_at: "2012-01-10 04:30:11">, #<C id: 3, b_id: 2, created_at: "2012-01-10 04:30:21", updated_at: "2012-01-10 04:30:21">, #<C id: 4, b_id: 2, created_at: "2012-01-10 04:30:21", updated_at: "2012-01-10 04:30:21">]
Обратите внимание, как другой запрос не выполняется, когда вы звоните a.C
, Это потому, что ActiveRecord знает, что вы захотите получить доступ к найденному A
"s C
это по include
позвонить, и генерирует минимальное количество запросов. То же самое касается D
"S:
-> a = A.where(:id => 1).includes(:D).first
A Load (0.1ms) SELECT "as".* FROM "as" WHERE "as"."id" = 1 LIMIT 1
B Load (0.1ms) SELECT "bs".* FROM "bs" WHERE "bs"."a_id" IN (1)
C Load (0.1ms) SELECT "cs".* FROM "cs" WHERE "cs"."b_id" IN (1, 2)
D Load (0.1ms) SELECT "ds".* FROM "ds" WHERE "ds"."c_id" IN (1, 2, 3, 4)
Скажи, что ты хотел всего A
"s D
х но хотел C
заказано:
A.where(:id => 1).includes(:C).order('cs.created_at DESC').includes(:D)
Обратите внимание, что вы также можете установить это по умолчанию для ассоциации:
:order
опция определяет порядок, в котором будут получены связанные объекты (в синтаксисе, используемом SQLORDER BY
пункт).class Customer < ActiveRecord::Base has_many :orders, :order => "date_confirmed DESC" end