gpt4 book ai didi

ruby-on-rails - 多个 belongs_to 连接到同一个表(在 Rails 4.2 中,以干净的方式执行此操作的能力是否发生了变化?)

转载 作者:数据小太阳 更新时间:2023-10-29 07:35:47 27 4
gpt4 key购买 nike

在 Rails 4.2 中使用最新的连接方式和 where 子句,似乎没有一种干净的方式(使用符号......或者只是不使用字符串 SQL)从单个查询连接到同一个表。

例如,我们有一个用户模型,它有一个家庭地址和工作地址的引用。如果我们想要获取在印第安纳波利斯生活和工作的所有用户,构建此查询的最佳方式是什么?

理想的选择是这样的:

User.joins(:home_address).join(:work_address).
where(home_address: { city: 'Indianapolis' } ).
where(work_address: { city: 'Indianapolis' } ).count

但是,home_address 和 work_address(它们是 User 模型上的 belongs_to 关联)对 where 子句没有任何影响。您有两个用户地址,显然这已经足够了(因为我对该表进行了两次查询)。

这里有一些可行的方法,但不如上面的解决方案干净:

User.joins('INNER JOIN addresses as home_address ON home_address_id = home_address.id').
joins('INNER JOIN addresses as work_address ON work_address_id = work_address.id').
where(home_address: { city: 'Indianapolis' } ).
where(work_address: { city: 'Indianapolis' } ).count

所以问题的关键是,这是故意的吗(在以前的 Rails 版本中,belongs_to 关联名称可以在 where 子句中引用)?而且,如果是的话,是否有一种技术我没有看到如何在不使用字符串 SQL 的情况下清理它?

需要说明的是,在早期版本的 Rails 中,belongs_to 关联适用于此类查询:这曾经有效……在 Rails 4.2 中它不再有效:

irb(main):001:0> User.joins(:home_address, :work_address).where(home_address: { city: 'Indianapolis' }, work_address: { city: 'Indianapolis' }).to_sql
"SELECT \"users\".* FROM \"users\" INNER JOIN \"addresses\" ON \"addresses\".\"id\" = \"users\".\"home_address_id\" INNER JOIN \"addresses\" \"work_addresses_users\" ON \"work_addresses_users\".\"id\" = \"users\".\"work_address_id\" WHERE ((\"addresses\".\"city\" = 'Indianapolis' AND \"work_addresses_users\".\"city\" = 'Indianapolis'))"
irb(main):002:0> Rails::VERSION::STRING
"4.0.5"
irb(main):003:0>

但是在最新版本的 Rails 中,它不再有效:

[1] pry(main)> User.joins(:home_address, :work_address).
[1] pry(main)* where(home_address: { city: 'Indianapolis' }, work_address: { city: 'Indianapolis' }).count
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: missing FROM-clause entry for table "home_address"
LINE 1: ...ses_users"."id" = "users"."work_address_id" WHERE "home_addr...
^
: SELECT COUNT(*) FROM "users" INNER JOIN "addresses" ON "addresses"."id" = "users"."home_address_id" INNER JOIN "addresses" "work_addresses_users" ON "work_addresses_users"."id" = "users"."work_address_id" WHERE "home_address"."city" = $1 AND "work_address"."city" = $2
from /Users/ar3/.rvm/gems/ruby-2.2.1/gems/activerecord-4.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:637:in `prepare'
[2] pry(main)> Rails::VERSION::STRING
"4.2.1"
[3] pry(main)> User.last.home_address.present?
true
[4] pry(main)> User.last.work_address.present?
true
[5] pry(main)> User.joins(:home_address, :work_address).where(home_address: { city: 'Indianapolis' }, work_address: { city: 'Indianapolis' }).to_sql
"SELECT \"users\".* FROM \"users\" INNER JOIN \"addresses\" ON \"addresses\".\"id\" = \"users\".\"home_address_id\" INNER JOIN \"addresses\" \"work_addresses_users\" ON \"work_addresses_users\".\"id\" = \"users\".\"work_address_id\" WHERE \"home_address\".\"city\" = 'Indianapolis' AND \"work_address\".\"city\" = 'Indianapolis'"
[6] pry(main)>

请注意 .to_sql 中的区别...一个使用 belongs_to 关联定义的别名,新的一个使用我们放入 where 哈希中的任何内容。

最佳答案

ActiveRecord 中的

where 子句总是使用表名。只要您在两个关联上查询相同的内容,您就可以执行以下操作:

User.joins(:home_address, :work_address)
.where(addresses: { city: 'Indianapolis' }).count

addresses 是包含地址的表格。

但是,如果您需要为 home_addresswork_address 使用不同的 where 子句,那么据我所知您就不走运了。如果我错了,请有人纠正我,我找不到办法。

这是一个很好的例子,您可以在其中使用 STI虽然是为了让您能够做到这一点并改进您的架构。

关于ruby-on-rails - 多个 belongs_to 连接到同一个表(在 Rails 4.2 中,以干净的方式执行此操作的能力是否发生了变化?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30712412/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com