2012-01-10 40 views
4

我有4款車型,A,B,C和d有效的連接查詢 - 它可以使用ActiveRecord

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 %> 

獲得所有C for A的最佳方式是什麼? 什麼是最好的方式獲得所有D的A?

我想所有的「C」使用ORDER_BY與「created_at」價值條款,而不是通過迭代B.

可能是我錯過了一些ActiveRecord的魔力?

我很感激任何幫助。

+0

因爲通過B A的使用C的關係,我也可以做A.C直接吧? – Atarang 2012-01-10 04:36:01

回答

6

首先,你需要做一些改變。

  1. class C需要的關聯D

    class C < ActiveRecord::Base 
        belongs_to :B 
        has_one :D 
    end 
    
  2. 如果您要訪問AD的,你需要指定這一點。如何當你調用a.C不執行另一個查詢

    -> 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">] 
    

    注意:

    class A < ActiveRecord::Base 
        has_many :B 
        has_many :C, :through => :B 
        has_many :D, :through => :C 
    end 
    

現在,訪問所有AC的的。這是因爲ActiveRecord知道您希望通過include調用訪問找到的AC,並生成最小數量的查詢。這同樣適用於D的:

-> 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) 

說你想要的所有AD的,但希望C的命令:

A.where(:id => 1).includes(:C).order('cs.created_at DESC').includes(:D) 

注意您還可以設置此爲在關聯默認:

:order選項規定將接收關聯對象的順序(在SQL語句使用的語法中爲ORDER BY條款)。

class Customer < ActiveRecord::Base 
    has_many :orders, :order => "date_confirmed DESC" 
end 
+2

+1對'has_one:D'表情和堅實的答案 – iwasrobbed 2012-01-10 05:49:10

+0

@iWasRobbed謝謝! B通過一個非常傷心的傢伙有很多表情符號。 (現在我不能停止看到他們。) – 2012-01-10 05:51:01

+0

布蘭登謝謝。我會嘗試這個,但我認爲有關聯可以解決這個問題。 – Atarang 2012-01-10 06:16:24

相關問題