首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何将实例方法转换为关联?

如何将实例方法转换为关联?
EN

Stack Overflow用户
提问于 2021-09-23 14:55:19
回答 2查看 81关注 0票数 0

Subscription has_many :versions模型

我正在编写一个查询,以获取订阅并按照关联的versions最后一个authorized_at日期对它们进行排序,但由于joinsgroup语句,我不确定查询能否多次返回相同的订阅。

代码语言:javascript
代码运行次数:0
运行
复制
Subscription
      .joins(:versions)
      .group("subscriptions.id, users.id")
      .order("MAX(versions.authorized_at) ASC")

另一方面,我有一个Subscription实例方法current_version,它返回最后一个授权的version

subscription.rb

代码语言:javascript
代码运行次数:0
运行
复制
  def current_version
    versions.authorized.last
  end

我认为关联(而不是实例方法)可以帮助我,因此我可以加入订阅表和版本表,并按照关联的表授权日期对结果进行排序。

但是,如何像类方法那样编写执行查询的关联呢?

,我试过做了如下的事情:

代码语言:javascript
代码运行次数:0
运行
复制
has_one     :current_version,
              -> { versions.authorized.last },
              class_name: "Version", inverse_of: "Subscription"

但我得到了NameError: undefined local variable or method 'versions' for #<Version::ActiveRecord_Relation

EN

回答 2

Stack Overflow用户

发布于 2021-09-23 17:47:27

读取性能的最佳解决方案是将一个单独的外键列作为捷径添加到表中:

代码语言:javascript
代码运行次数:0
运行
复制
add_reference :subscriptions, 
              :current_version,
              foreign_key: {
                to_table: :versions  ​
             ​}
代码语言:javascript
代码运行次数:0
运行
复制
class Subscription < ApplicationRecord
  has_many :versions, 
    after_add: :set_current_version
  belongs_to :current_version,
    class_name: 'Version'

  def set_current_version(version)
     update_attribute(:current_version_id, version.id) 
  end
end

这将使用一组位置回调来设置关联,但也可以使用DB触发器或服务对象来处理它。

如果你真的想使用has_one,你需要像子查询一样使用黑客,窗口函数或后置连接

代码语言:javascript
代码运行次数:0
运行
复制
class Subscription
  has_one :current_version, 
    -> {
      where(
        id: Version.select(:id)
                   .group(:subscription_id)
                   .order("MAX(versions.authorized_at) ASC")
      )
    },
    class_name: 'Version'
end
票数 1
EN

Stack Overflow用户

发布于 2021-09-24 11:42:13

我通过max尝试了上面的答案,它在控制台中工作(我只尝试了has_one的提议),但是我无法使视图正常工作(我一直得到未定义的表错误)。

最后,我创建了一个使用它的current_version (上一次授权version)获取订阅的范围,并使用了该范围。

代码语言:javascript
代码运行次数:0
运行
复制
  scope :with_current_version, -> {
    select("subscriptions.*, last_version.authorized_at AS last_version_authorized_at")
      .joins("LEFT OUTER JOIN (SELECT DISTINCT ON (subscription_id) * FROM versions
      ORDER BY versions.subscription_id,
      versions.authorized_at DESC) AS last_version
      ON last_version.subscription_id = subscriptions.id")
  }

然后在我的控制器里:

代码语言:javascript
代码运行次数:0
运行
复制
@subscriptions = current_account.subscriptions.with_current_version
                         .order("last_version_authorized_at ASC")
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69302391

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档