当前位置 : 主页 > 编程语言 > ruby >

ruby-on-rails – Rails:在连接上使用.references,即使它不是必需的

来源:互联网 收集:自由互联 发布时间:2021-06-23
我知道当你使用includes并在join表上指定where子句时,你应该使用.references 例: # will error out or throw deprecation warning in logscustomers = Customer.includes(:orders).where("Orders.cost ?", 100) 否则,在rails 4或更
我知道当你使用includes并在join表上指定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:

06001

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’)

说得通.当您使用包含时,Rails不希望成为SQL解析器.因此,为了让铁路开心,我们这样做:

# 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)

但是,当您在连接表上使用连接和where子句时:Rails不会出错,并且rails也不会抛出弃用警告,因为它包含:

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

这对我来说没有意义.我认为如果rails不想成为包含的SQL解析器,那么它也不希望成为连接的SQL解析器.我认为rails会更喜欢我使用这样的引用:

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

所以我的问题:

>我错过了什么吗?是否绝对可以不为连接表的where子句指定连接的引用,即使包含它几乎是必需的?如果是这样的话:为什么包含和加入之间的区别?
>我应该指定关于联接的参考吗?也许一旦rails的SQL解析器消失了所有这些连接,连接表上的where子句将不再起作用了?

连接和包含(两个方法的包装:eager_load和preload)之间的根本区别在于:

> joinsbluntly执行SQL并不加选择地返回所有记录
> includes将确定哪些记录属于哪个模型并构建模型树:author1 – > [post,post,post],author2 – > [帖子,帖子]

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

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

因此,当您执行包含(或eager_load或preload)以帮助区分SQL连接中的数据并将其分配给正确的模型时,此处的引用仅对Rails有用.

通过连接,您可以在SQL世界中独立完成.大多数时候我会将它与group(“orders.id”)和一个聚合函数一起使用:

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

网友评论