如何正确选择连接表中的字段?

Nom*_*Nom 9 activerecord ruby-on-rails ruby-on-rails-4 rails-activerecord

这是我的简化模型,我加入了模型,

样板房

   has_many :towers
Run Code Online (Sandbox Code Playgroud)

模型塔

   belong_to :apartment
Run Code Online (Sandbox Code Playgroud)

然后我试图加入控制器中的两个表也尝试在rails控制台,如下所示:

Apartment.joins(:塔).select('apartments.id','apartments.name','towers.id','towers.name')

问题是上面的查询只返回

apartments.id和apartments.name

也尝试使用这样的别名,仍然没有运气

Apartment.joins(:塔).select('apartments.id','apartments.name','towers.id as towerid','towers.name as towername')

我已经确认所有塔楼都有公寓,我知道我可以做到这一点来获得1条记录

Apartment.joins(:塔).select('apartments.id','apartments.name','towers.id','towers.name').first.towers.id

等等,但我需要所有记录和所有这些字段,请咨询.

这是我在rails控制台中获得的最新结果:

 Apt Load (1.0ms)  SELECT apts.id, apts.apt_name, towers.id as towerid, towers.
    tower_name as towername FROM `apts` INNER JOIN `towers` ON `towers`.`apt_id` = `
    apts`.`id`
    => #<ActiveRecord::Relation [#<Apt id: 5, apt_name: "basura">, #<Apt id: 5, apt_
    name: "basura">, #<Apt id: 124, apt_name: "hydra">, #<Apt id: 124, apt_name: "hy
    dra">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 142, apt_name: "apartement gajah mada">, #<Apt id: 142, apt_name: "apartement gajah mada">]>
Run Code Online (Sandbox Code Playgroud)

如你所见,上面的查询只返回2个字段,我需要结果如下:

#<Apt id: 126, apt_name: "mediterania", tower_id: 12, tower_name: "tower A">, 
#<Apt id: 126, apt_name: "mediterania", tower_id: 15, tower_name: "tower F">
Run Code Online (Sandbox Code Playgroud)

ETCC ...

dns*_*nsh 8

我看到这一点的唯一方法就是使用 as

q = Apartment.joins(:towers).select('apartments.id, apartments.name, towers.id as t_id, towers.name as t_name')

q.first.t_id
q.first.t_name
Run Code Online (Sandbox Code Playgroud)

为什么first.towers.id不起作用?

apartment.towers会回来的ActiveRecord::Associations::CollectionProxy.你可以把它想象成塔的集合.在SQL查询中,您指的是towers表.但是当你运行apartment.towers.id时,你在CollectionProxy对象上调用id是行不通的.你可以使用第一塔towers.first.

关于,

Apt Load (1.0ms)  SELECT apts.id, apts.apt_name, towers.id as towerid, towers.
    tower_name as towername FROM `apts` INNER JOIN `towers` ON `towers`.`apt_id` = `
    apts`.`id`
    => #<ActiveRecord::Relation [#<Apt id: 5, apt_name: "basura">, #<Apt id: 5, apt_
    name: "basura">, #<Apt id: 124, apt_name: "hydra">, #<Apt id: 124, apt_name: "hy
    dra">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 126, apt_name: "mediterania">, #<Apt id: 142, apt_name: "apartement gajah mada">, #<Apt id: 142, apt_name: "apartement gajah mada">]>
Run Code Online (Sandbox Code Playgroud)

您在控制台中看到的结果是inspsect方法返回的结果.该inspect方法不是为了显示非列属性而设计的.因此,即使您在内存中有塔名,它也只会显示属于公寓模型列的属性. 更多关于 检查

我还建议尝试以下方法:

Apartment.joins(:towers).pluck('apartments.id, apartments.name, towers.id as t_id, towers.name as t_name')
Run Code Online (Sandbox Code Playgroud)

上面的语句将获取数组中的所有数据.select得到的结果与select相同,不会加载数组中的所有数据.


Saj*_*jan 7

你应该用

Apartment.joins(:towers).select('apartments.id, apartments.name, towers.id , towers.name')
Run Code Online (Sandbox Code Playgroud)

这是单个字符串中的所有列名.

请参阅此.

  • @sajan我已经解决了这个问题,我们最初的方法没有任何问题,只是这些字段没有显示在控制台中(tower.id,tower.name),但是这些字段在那里,并且可以直接使用,非常感谢, 投了赞成票。 (3认同)
  • 这有效!它确实返回所有字段,但它仅在控制台中显示“Apparment”。`.as_json` 将向您显示所有内容都包含在内! (2认同)

mec*_*cov 6

Rails 7.1添加了对此类查询的支持,现在select接受哈希

您可以像这样使用别名

Apartment
  .joins(:towers)
  .select(
    apartments: { id: :apartment_id, name: :apartment_name },
    towers: { id: :tower_id, name: :tower_name }
  )
Run Code Online (Sandbox Code Playgroud)

它产生这样的查询

Apartment
  .joins(:towers)
  .select(
    apartments: { id: :apartment_id, name: :apartment_name },
    towers: { id: :tower_id, name: :tower_name }
  )
Run Code Online (Sandbox Code Playgroud)

  • 我尝试了这个(因为我更喜欢使用哈希而不是字符串进行查询)但收到此错误:`不支持的参数类型:哈希。而是构造一个 Arel 节点。` (2认同)
  • 仅 Rails 7.1 支持该功能。 (2认同)