【问题标题】:Rails - Using join with custom-named associationsRails - 将 join 与自定义命名的关联一起使用
【发布时间】:2018-02-07 09:26:01
【问题描述】:

我有以下型号

class Measurement < ApplicationRecord
  belongs_to :examination, class_name: "TestStructure", foreign_key: "examination_id"

end

实际上是对TestStructure模型进行关联,但关联名称是examine。 没有检查台。

当我使用join 查询时出现问题。以下查询

Measurement.joins(:examination).where(examination: { year: 2016, month: 5 })

失败,出现此错误

ActiveRecord::StatementInvalid:
   PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "examination"
   LINE 1: ...d" = "measurements"."examination_id" WHERE "examinati...
# --- Caused by: ---
 # PG::UndefinedTable:
 #   ERROR:  missing FROM-clause entry for table "examination"
 #   LINE 1: ...d" = "measurements"."examination_id" WHERE "examinati...

很明显,examinations 表不存在,但我找不到方法告诉 ActiveRecord 我使用的是命名关联而不是默认关联。

有什么见解吗?

【问题讨论】:

  • 对于includesjoinsreferences,您需要使用模型中定义的关系名称。对于where,您需要使用准确的表名。因此,如果您的模型TestStructure 将数据存储在表custom_named_table 中,则需要执行Measurement.joins(:examination).where(custom_named_table: { year: 2016, month: 5 })(您可以使用TestStructure.table_name 找到表名)(请参阅我之前关于该主题的答案:stackoverflow.com/questions/24266069/…)跨度>

标签: ruby-on-rails ruby postgresql activerecord ruby-on-rails-5


【解决方案1】:

where 需要实际的表名,它只是将其插入 SQL:

Article.where(whatever: {you: 'want'}).to_sql
=> "SELECT `articles`.* FROM `articles` WHERE `whatever`.`you` = 'want'"

所以你可以使用:

Measurement.joins(:examination).where(test_structures: { year: 2016, month: 5 })

但是不好

然后你依赖表名,而模型应该抽象这些东西。你可以使用merge:

Measurement.joins(:examination).merge(TestStructure.where(year: 2016, month: 5))

【讨论】:

  • 你是对的。让我试试你的方法,希望它不会执行多个查询,我会回复你。
  • 我要说的是,在我为生的 Rails 项目中,使用 .merge().joins() 对我来说是一个巨大的救命稻草。我们有 Rails 引擎,因此我们的 ActiveRecord 模型的每个数据库表名称都以引擎名称作为前缀。这会导致在where() 调用中使用关联名称的复杂性,我将不得不使用数据库表的名称作为哈希键。 .joins()merge() 的结合使 ActiveRecord 查询这个项目的体验更加愉快。
【解决方案2】:

在某些情况下您需要添加.references(associations)

Measurement.joins(:examination).merge(TestStructure.where(year: 2016, month: 5)).references(:examination)

【讨论】:

    【解决方案3】:

    在此示例中,应提供表名称 examinations,而不是 where 方法中的关联名称 examination

    Measurement.jons(:examination).where(examinations: { year: 2016, month: 5 })
    

    【讨论】:

    • 如果我错了,请纠正我,eager_load 是否真的将记录检索到内存中?我的目标是不这样做,因此加入。
    • @Sebastialonso:根据 activerecord 文档,我错了,您可以使用 joins,但表名警告至关重要。
    【解决方案4】:

    对于连接,您使用关联名称,但对于需要使用表名称的地方

    Measurement.joins(:examination).where(test_structures: { year: 2016, month: 5 })
    

    Measurement.joins(:examination).where('test_structures.year': 2016, 'test_structures.month': 5 )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-17
      • 1970-01-01
      • 2018-01-21
      • 2019-11-14
      • 2012-06-14
      相关资源
      最近更新 更多