2012-01-10 56 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

相关问题