查询 has_one 是 has_many 的子集

Query has_one that is a subset of a has_many

我有一些多态规则可以跟踪更改,我想查询最后一个(当前)规则。我知道我可以使用 belongs_to 来跟踪它,但我想保留 has_one。这是模块的一部分

has_many :rule_transitions, class_name: "#{name}AppliedRuleTransition", dependent: :destroy

has_one :current_rule_transition, -> { order created_at: :desc }, class_name: "#{name}AppliedRuleTransition", inverse_of: model_name.param_key.to_sym
has_one :current_rule, through: :current_rule_transition, source: :rule

我想查询 current_rule,但是 rule_transitions 被完整查询了。

我目前的尝试是使用 postgres 的 FIRST_VALUE

scope :rule, lambda { |q|
  joins(:current_rule)
  .select("#{model_name.plural}.*, rules.id = FIRST_VALUE(#{model_name.param_key}_applied_rule_transitions.rule_id) OVER(PARTITION BY #{model_name.param_key}_applied_rule_transitions.id ORDER BY #{model_name.param_key}_applied_rule_transitions.created_at DESC)")
  .where(rules: { slug: q })
}

不过,我对这个函数的理解还不够好,这仍然不能满足我的需求。

只需使用 belongs_to 并将外键放在 table 上。它会让您正确地急切加载关联以避免 n+1 问题 - 特别是您想要记录列表和最新关联项目而不加载整个关联的常见情况。

它的性能也会比其他替代品好得多。

belongs_to :current_rule_transition, class_name: "#{name}AppliedRuleTransition"
has_many :rule_transitions, 
  class_name: "#{name}AppliedRuleTransition", 
  dependent: :destroy,
  after_add: ->(model, transition) { model.update(current_rule_transition: transition) }

不必为难自己。