Sql 如何访问Rails3中的联接表属性?

Sql 如何访问Rails3中的联接表属性?,sql,ruby,join,ruby-on-rails-3,relation,Sql,Ruby,Join,Ruby On Rails 3,Relation,我在访问Rails3中连接的属性时遇到问题 有两种型号/表格:地点和地址。一个地方可以有多个地址,即特定街道地址、地址角等。。由于历史原因,这些表不遵循标准Rails约定: class Place < ActiveRecord::Base set_table_name :PLACE set_primary_key :PLACE_ID has_many :addresses, :class_name => "Address", :foreign_key => :PLACE_

我在访问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
生成的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只包含位置模型的属性,不包含地址模型的任何属性

在Rails3之前,我曾使用sql查找两个联接表的属性,并可以在返回的哈希中轻松访问它们的属性,但是我无法让Rails3向我显示 来自联接地址表的属性


我一定是遗漏了一些非常基本的东西——有人愿意向我指出吗?

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

pa = Place.includes(:addresses).where(:place_id => 68)
如果您想在对东京队长回答的评论中按address.street_name排序。然后,您可以这样添加订单:

pa = Place.includes(:addresses).where(:place_id => 68).order(:addresses => :street_name)
两个include和join之间的区别在于,为了在where子句中进行匹配,join将提供的模型连接到生成的查询。与includes相反,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)"
"SELECT [PLACE].* FROM [PLACE] INNER JOIN [ADDRESS] ON [ADDRESS].[PLACE_ID] = [PLACE].[PLACE_ID] WHERE ([PLACE].[place_id] = 68)"

产生以下结果:

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

您正在查找包含而不是联接。这正是你想要的

pa = Place.includes(:addresses).where(:place_id => 68)
如果您想在对东京队长回答的评论中按address.street_name排序。然后,您可以这样添加订单:

pa = Place.includes(:addresses).where(:place_id => 68).order(:addresses => :street_name)
两个include和join之间的区别在于,为了在where子句中进行匹配,join将提供的模型连接到生成的查询。与includes相反,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)"
"SELECT [PLACE].* FROM [PLACE] INNER JOIN [ADDRESS] ON [ADDRESS].[PLACE_ID] = [PLACE].[PLACE_ID] WHERE ([PLACE].[place_id] = 68)"

产生以下结果:

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

你所需要的就是

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)
如果需要同时使用Place实例,也可以使用delegate函数

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

你所需要的就是

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)
如果需要同时使用Place实例,也可以使用delegate函数

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