【问题标题】:Rails, ActiveRecord: has_one where column names matchRails,ActiveRecord:列名匹配的 has_one
【发布时间】:2019-06-12 01:15:25
【问题描述】:

我有一个关联,其中 project has_many steps 和我想为 project 找到“当前”stepproject 表存储一个current_step 值,即当前stepstep.name

class Project < ApplicationRecord
  # attributes: step_name:string

  has_many :steps
  has_one :current_step, -> { where("steps.name = projects.step_name") }, class_name: "Step"
end

class Step < ApplicationRecord
  # attributes: project_id:integer, name:string

  belongs_to :project
end

我正在尝试将其设置为 ActiveRecord 关联,因此我可以使用project 优化加载current_step 并避免n+1 问题。

但是,我不断收到错误消息:

ActiveRecord::StatementInvalid: TinyTds::Error: The multi-part identifier "projects.step_name" could not be bound.

我在 SO 上做了一些查看,发现其他人遇到了这个 TinyTds 错误,但我不完全确定它的含义或它与我的特定情况有何关系。

如何选择current_step 以便可以有效地包含它以避免n+1

【问题讨论】:

  • 尝试在您的where 中添加.first
  • 尝试用has_one :current_step, -&gt; { joins(:steps).where("steps.name = ?", step_name) }, class_name: "Step"之类的东西定义has_one关系

标签: ruby-on-rails rails-activerecord tiny-tds


【解决方案1】:

您实际上没有has_one 关联,您有has_many 的特殊成员,所以我会这样表达。 steps 关联上的扩展方法可以让你这样做:

has_many :steps do
  def current
    project = proxy_association.owner
    find_by(name: project.step_name)
  end
end

ActiveRecord 为关联设置的proxy_association 允许您回溯到包含projectproxy_association.owner。扩展方法中的find_by 将作用于关联。

然后你可以这样说:

project.steps.current

得到你期望你的has_one做的事情。

【讨论】:

  • 这很有趣。这是否允许我做Project.includes(:current)?我需要在页面上显示project 记录的集合以及它们当前step 中的一些数据,并希望避免n+1 问题。
  • 您可以添加一个范围以使用 WHERE 子句加入步骤以获取适当的行。或者尝试在您的 has_one 中包含一个 JOIN 以使两个表都可见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-12
  • 2010-10-18
  • 1970-01-01
相关资源
最近更新 更多