2010-10-21 45 views
1

我在访问Rails3中的连接属性时遇到了问题。如何在Rails3中访问连接的表格属性?

有两个模型/表格:地点和地址。一个地方可以有许多地址(即特定的街道地址,“地址的角落”等)。由于历史原因,这些表格并没有遵循标准的Rails约定:

class Place < ActiveRecord::Base 
set_table_name :PLACE 
set_primary_key :PLACE_ID 
has_many :addresses, :class_name => "Address", :foreign_key => :PLACE_ID 
end 

class Address < ActiveRecord::Base 
set_table_name :ADDRESS 
set_primary_key :ADDRESS_ID 
belongs_to :place, :foreign_key => "PLACE_ID" 
end 

我试图让所有的地址一个特别的地方:

pa = Place.joins(:addresses).where(:place_id => 68) 

的SQL产生的外观很好:

pa.to_sql 

"SELECT [PLACE].* FROM [PLACE] INNER JOIN [ADDRESS] ON [ADDRESS].[PLACE_ID] = [PLACE].[PLACE_ID] WHERE ([PLACE].[place_id] = 68)" 

返回的关系也有大小合适,作为特定的地方有与之相关联的6个地址:

irb(main):050:0> pa.size 
=> 6 

但是,返回的关系PA仅包含地方模型的属性,它不包含任何地址模型的属性。

Pre Rails3我曾经做过find_by_sql,可以在返回的Hash中轻松访问两个连接表的属性,但是我根本无法让Rails3向我显示连接地址表中的 属性。

我必须在这里丢失一些非常基本的东西 - 任何人都在意向我指出吗?

回答

4

您正在寻找包含而不是连接。这将做到你想要的。

pa = Place.includes(:addresses).where(:place_id => 68) 

如果您想在您的评论中通过address.street_name命令给captaintokyo的答案。你可以做,然后添加一个命令是这样的:

pa = Place.includes(:addresses).where(:place_id => 68).order(:addresses => :street_name) 

两者之间的不同点在于,并加入是joins将联合提供的车型为求匹配所产生的查询where子句。与includes相反,除includes之外,除了添加连接模型外,还将在select语句中包含该模型的字段。

因此,要回顾:

Place.includes(:addresses).where(:place_id => 68) 

产生这样的:

​​

Place.joins(:addresses).where(:place_id => 68) 

产生这样的:

"SELECT [PLACE].* FROM [PLACE] INNER JOIN [ADDRESS] ON [ADDRESS].[PLACE_ID] = [PLACE].[PLACE_ID] WHERE ([PLACE].[place_id] = 68)" 
+0

完美 - 感谢! – patschiboy 2010-10-21 12:23:14

0

你AREL方式需要的是就像

pa = Place.joins(:addresses).where(:place_id => 68).select('PLACE.*, ADDRESS.*') 

,然后你会得到所有的PA为这两个表的属性。

但我想知道是否有对你是一个更好的设计:

class Place < ActiveRecord::Base 
set_table_name :PLACE 
set_primary_key :PLACE_ID 
has_many :addresses, :class_name => "Address", :foreign_key => :PLACE_ID 
end 

class Address < ActiveRecord::Base 
set_table_name :ADDRESS 
set_primary_key :ADDRESS_ID 
belongs_to :place, :foreign_key => "PLACE_ID" 

scope :with_place, lambda {|place_id| joins(:place).where(:place_id => place_id).select('ADDRESS.*, PLACE.*')} 
end 

addresses = Address.with_place(68) 

或者只是使用委托功能,如果你需要同时使用地点例如

class Address < ActiveRecord::Base 
set_table_name :ADDRESS 
set_primary_key :ADDRESS_ID 
belongs_to :place, :foreign_key => "PLACE_ID" 

delegate :any_place_attribute, :to => :place 
end 

address = Address.find(x) 
address.any_place_attribute #you can access PLACE table attribute now