1

Rails3の結合の属性にアクセスできません。

場所と住所の2つのモデル/テーブルがあります。1つの場所に多くの住所を含めることができます(つまり、特定の番地、「の角」の住所など)。歴史的な理由から、テーブルは標準の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

1つの特定の場所のすべてのアドレスを取得しようとしています。

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には、Placeモデルの属性のみが含まれ、Addressモデルの属性は含まれていません。

Rails3より前以前はfind_by_sqlを実行し、返されたハッシュで2つの結合されたテーブルの属性に簡単にアクセスできましたが、Rails3に結合されたAddressテーブルの属性を表示させることはできません。

私はここで非常に基本的な何かを見逃しているに違いありません-誰かが私にそれを指摘することを気にしますか?

4

2 に答える 2

4

結合ではなくインクルードを探しています。これはあなたが望むことを正確に行います。

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

キャプテン東京の回答へのコメントでaddress.street_nameで注文したい場合。次に、次のような注文を追加できます。

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

2つのincludeとjoinの違いはjoins、where句で照合するために、提供されたモデルを生成されたクエリに結合することです。これとは対照的にincludes、モデルへの結合を追加することに加えて、selectステートメントにそのモデルのフィールドも含めます。

要約すると:

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

これを生成します:

"SELECT [PLACE].*, [ADDRESS].* FROM [PLACE] INNER JOIN [ADDRESS] ON [ADDRESS].[PLACE_ID] = [PLACE].[PLACE_ID] WHERE ([PLACE].[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)"
于 2010-10-21T11:51:05.500 に答える
0

あなたがアリーの方法で必要なものはちょうどのようなものです

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

次に、これら2つのテーブルの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)

または、Placeインスタンスを同時に使用する必要がある場合は、デリゲート関数を使用します

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
于 2011-01-07T04:15:20.667 に答える