Rails has_one:通过不同的型号名称

时间:2017-10-14 00:03:38

标签: ruby-on-rails activerecord has-one-through

transaction_record有很多workflows,每个workflow都有很多milestones。其中一个milestones标记为current: true,我希望从transaction_record转到current_milestone

class TransactionRecord < ApplicationRecord
  has_many :workflows
  has_many :milestones, through: :workflows

  # DOES NOT WORK, but what I want to do...
  has_one :current_milestone, through: :workflows, class: Milestone, source: :milestones

  # Works, but want to make an association for including
  def current_milestone
    milestones.where(current: true).first
  end
end

class Workflow < ApplicationRecord
  belongs_to :transaction_record
  has_many :milestones
end

class Milestone < ApplicationRecord
  belongs_to :workflow
end

我可以创建一个返回所需milestone的方法,但我想让它成为一个实际的关联,这样我就可以将其包含在DB性能中。

我有一个transaction_records#index页面,其中列出了每个transaction_recordscurrent_milestone。这是一个n+1,除非我能解决这个问题。

我真的希望能够做到这样的事情:

@transaction_records = TransactionRecord.includes(:current_milestone)

<% @transaction_records.each do |transaction_record| %>
  <%= transaction_record.name %> - <%= transaction_record.current_milestone.name %>
<% end %>

更新

我可以指定transaction_recordmilestone之间的方向关系,然后执行transaction_record has_one :current_milestone, -> { where(current: true) }, class_name: Milestone。但是现在我正在更改我的数据库架构以实现更高效的加载查询。如果我已经有了联系,那么这不是世界末日,而是我的偏好。

1 个答案:

答案 0 :(得分:0)

说实话,我不喜欢这个概念,transaction_record有某种active_milestone而没有提及加入current_workflow

好的解决方案是考虑workflowmilestone能够成为current然后:

class TransactionRecord < ApplicationRecord
  has_one :current_workflow, ....
  has_one :current_milestone, through: current_workflow, ....
end

class Workflow < ApplicationRecord
  has_one :current_milestone, condition: ....
end

这对我来说要好得多,但您仍然需要在current中添加其他workflow标记属性。

这就是为什么更好的解决方案是重写你的概念。 从里程碑中删除current并将current_milestone_id添加到工作流程。如果它为零,则此workflow没有current_milestone。如果它包含一些ID,那么这是您的current_workflowcurrent_milestone_id

代码看起来非常相似,但在Workflow

中不会有丑陋的条件