我有两个基本的ActiveRecord模型(Rails 4.2):
class ImportJob < ActiveRecord::Base
has_many :logs, class_name: 'ImportLog', foreign_key: 'job_id', dependent: :destroy
end
class ImportLog < ActiveRecord::Base
belongs_to :job, class_name: 'ImportJob', foreign_key: :job_id
end
我正在尝试使用ImportJob
上的INNER JOIN
在ImportLog
上运行查询,使用我在has_many
声明中提供的名称:
ImportJob.joins(:logs).where(logs: { stage: "load", status: "succeeded" })
但是,构建logs
时,ActiveRecord不会自动使用名称INNER JOIN
。这是它生成的SQL的错误:
PG::UndefinedTable: ERROR: missing FROM-clause entry for table "logs"
LINE 1: ..."import_logs"."job_id" = "import_jobs"."id" WHERE "logs"."st...
^
: SELECT "import_jobs".* FROM "import_jobs" INNER JOIN "import_logs" ON "import_logs"."job_id" = "import_jobs"."id" WHERE "logs"."stage" = $1 AND "logs"."status" = $2
这两个查询都有效,但它们似乎不直观或不优雅:
使用表名“import_logs”(非直观)来引用“logs”。
ImportJob.joins(:logs).where(import_logs: { stage: "load", status: "succeeded" })
自己编写INNER JOIN
并添加“AS日志”(不太优雅)。
ImportJob.joins("INNER JOIN import_logs AS logs ON logs.job_id = import_jobs.id")
.where(logs: { stage: "load", status: "succeeded" })
有比这些更好的解决方案吗?
答案 0 :(得分:0)
您必须为belongs_to
和其他关系声明提供的论据越多,您将来的痛苦就越多。与import_job.import_logs
听起来一样笨重,你的AR模型应该尽可能简单,即使是以一定程度的优雅为代价。
相反,将您漂亮,优雅的API构建为AR模型和控制器之间的层。将其限制为您需要的操作,而不是ActiveRecord::Base
允许的无限制操作。利用这个机会为您的导入系统定义一个干净,足够的界面,将AR模型作为实现细节。它将在未来支付股息。