使用 ActiveRecord 语法从 Rails 中的连接表中选择或按列排序

Posted

技术标签:

【中文标题】使用 ActiveRecord 语法从 Rails 中的连接表中选择或按列排序【英文标题】:select from or order by a column from the joins table in Rails using ActiveRecord syntax 【发布时间】:2021-11-23 20:58:49 【问题描述】:

这是我想做的:

Aquarium
  .select(:id, :name, :yr_built, 'fishes.name')
  .joins(:fishes)
  .where(fishes: name: "Nemo")
  .order('fishes.bday DESC')

这目前按预期工作,因为我输入了原始 SQL 代码。但是,因为有人告诉我使用原始 SQL 是一种不好的做法,并且会让您容易受到漏洞的影响,所以我想使用正确的 ActiveRecord 语法重构 select 和 order 行。

我知道在.where 中,您可以使用table_name: column_name: "value" 语法从连接表中查找值。而且我知道,如果我想按 aquariums 表中的列排序,我可以这样做:.order(col_name: :desc),因为 aquariums 是开头的表。但是当我尝试像这样将它添加到.order 时,这似乎不起作用:.order(fishes: bday: :desc) 我也不确定如何从原始 SQL 转换 .select 中的 'fishes.name',因为它也来自连接表。

【问题讨论】:

此查询实际上不会按您希望的方式工作。由于您要加入一个包含许多行的表,因此它非常模棱两可。 'fishes.name' 应该包含什么?第一条鱼的名字?最后一个?他们都是?如果是这样,它应该是什么数据类型?例如,Postgres 不允许此查询,您需要使用 array_aggjson_agg 之类的聚合函数来获取名称数组。 【参考方案1】:

您的解决方案没有任何风险。即使您为 ActiveRecord 使用一些字符串参数 - 也无处可将 SQL 注入放在那里。 只需将 'fishes.name' 更改为 'fishes.name AS fish_name' 即可在结果中保留这两个名称。

但是,如果您更喜欢无 SQL 字符串的解决方案(就像我一样),您可以使用 Arel 来白化这样的东西。

Aquarium
  .joins(:fishes)
  .select(:id, :name, :yr_built, Fish.arel_table[:name].as('fish_name'))
  .where(fishes:  name: 'Nemo')
  .order(Fish.arel_table[:updated_at].desc)

【讨论】:

以上是关于使用 ActiveRecord 语法从 Rails 中的连接表中选择或按列排序的主要内容,如果未能解决你的问题,请参考以下文章

Rails ActiveRecord 查询不等于

如何从 Rails 中的查询中排除 id 数组(使用 ActiveRecord)?

Rails 4 ActiveRecord 有很多通过关系不能从 sql 文件读取

Rails 4,ActiveRecord,查找当前用户未评论的所有帖子

Rails,activerecord,从 hstore 记录中删除键值对

如何在 Rails 中链接原始 SQL 查询或如何从 Rails 中的原始 SQL 查询返回 ActiveRecord_Relation?