gpt4 book ai didi

ruby-on-rails - Rails : Using . 对连接的引用,即使它不是必需的

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

我知道当您使用 includes 并在联接表上指定 where 子句时,您应该使用 .references

例子:

# will error out or throw deprecation warning in logs
customers = Customer.includes(:orders).where("Orders.cost < ?", 100)

否则,在 rails 4 或更高版本中,您将收到如下错误:

Mysql2::Error: Unknown column 'Orders.cost' in 'where clause': SELECT customers.* FROM customers WHERE (Orders.cost < 100)

否则您将收到弃用警告:

DEPRECATION WARNING: It looks like you are eager loading table(s) (one of: users, addresses) that are referenced in a string SQL snippet. For example:

Post.includes(:comments).where("comments.title = 'foo'")

Currently, Active Record recognizes the table in the string, and knows to JOIN the comments table to the query, rather than loading comments in a separate query. However, doing this without writing a full-blown SQL parser is inherently flawed. Since we don't want to write an SQL parser, we are removing this functionality. From now on, you must explicitly tell Active Record when you are referencing a table from a string:

Post.includes(:comments).where("comments.title = 'foo'").references(:comments)

If you don't rely on implicit join references you can disable the feature entirely by setting config.active_record.disable_implicit_join_references = true. (

SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, "users"."email" AS t0_r2, "users"."created_at" AS t0_r3, "users"."updated_at" AS t0_r4, "addresses"."id" AS t1_r0, "addresses"."user_id" AS t1_r1, "addresses"."country" AS t1_r2, "addresses"."street" AS t1_r3, "addresses"."postal_code" AS t1_r4, "addresses"."city" AS t1_r5, "addresses"."created_at" AS t1_r6, "addresses"."updated_at" AS t1_r7 FROM "users" LEFT OUTER JOIN "addresses" ON "addresses"."user_id" = "users"."id" WHERE (addresses.country = 'Poland')

有道理。当您使用 includes 时,Rails 不想成为 SQL 解析器。所以为了让 Rails 开心,我们这样做:

# No error and no deprecation warning because we are explicitly specifying what table is referenced within that where clause
customers = Customer.includes(:orders).where("Orders.cost < ?", 100).references(:orders)

但是,当您在联接表上使用 joinswhere 子句时:Rails 不会出错,并且 rails 也不会抛出弃用警告使用包含:

# No error and no deprecation warning.  What????
customers = Customer.joins(:orders).where("Orders.cost < ?", 100)

这对我来说没有意义。我认为,如果 Rails 不想成为 includes 的 SQL 解析器,那么它也不想成为 joins 的 SQL 解析器。我认为 Rails 更喜欢我像这样使用 references:

customers = Customer.joins(:orders).where("Orders.cost < ?", 100).references(:orders)

所以我的问题是:

  1. 我错过了什么吗?在联接表上使用 where 子句为 joins 指定 references 是否绝对没问题,即使 includes 非常需要?如果是这样:为什么 includesjoins 之间存在这种差异?
  2. 我应该在 joins 上指定 references 吗?也许一旦 rails 的 sql 解析器消失,所有那些在连接表上使用 where 子句的 joins 将不再有效?

最佳答案

joinsincludes 之间的根本区别(它是 2 种方法的包装器:eager_loadpreload) 是:

  • join直截了本地执行SQ​​L并无差别返回所有记录
  • includes 将确定哪些记录属于哪个模型并构建模型树:author1 -> [post, post, post], author2 -> [post, post]

例如,如果您加入 Order.joins(:product_items),您将获得:

  • 所有与订单交织在一起的 ProductItem 记录。
  • 而使用 Order.includes(:product_items),您将获得Orders,每个相应订单中嵌套了 product_items。

所以这里的reference只有在你includes(或eager_loadpreload)时对Rails有用帮助它区分来自 SQL 连接的数据并将其分配给适当的模型。

有了joins,您就可以在SQL 世界中独自一人了。大多数时候,我会将它与 group("orders.id") 和聚合函数一起使用:

select(orders.*, count(product_items.id) as cart_size)...

关于ruby-on-rails - Rails : Using . 对连接的引用,即使它不是必需的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34597473/

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