2010-10-21 109 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 
相關問題