gpt4 book ai didi

ruby-on-rails - Ruby on Rails 3 : Combine results from multiple has_many or has_many_through associations

转载 作者:行者123 更新时间:2023-12-04 15:48:39 25 4
gpt4 key购买 nike

我有以下型号。用户有 UserActions,一个可能的 UserAction 可以是 ContactAction(UserAction 是一种多态)。还有其他操作,如 LoginAction 等。所以

类用户 < AR::Base
has_many :contact_requests, :class_name => "ContactAction"
has_many :user_actions
has_many_polymorphs :user_actionables, :from => [:contact_actions, ...], :through => :user_actions
结尾

类 UserAction < AR::Base
归属地:用户
归属地:用户可操作,:多态 => 真
结尾

类 ContactAction < AR::Base
归属地:用户
命名范围:待定,...
命名范围:事件,...
结尾

这个想法是一个 ContactAction 加入两个用户(在应用程序中产生其他结果)并且总是有一个接收端和一个发送端。同时,一个 ContactAction 可以有不同的状态,例如过期、待处理等

我可以说 @user.contact_actions.pending@user.contact_requests.expired列出用户发送或接收的所有待处理/过期请求。这工作正常。

我现在想要的是一种方式 加入 两种类型的 ContactAction。 IE。 @user.contact_actions_or_requests .我尝试了以下方法:

类用户

def contact_actions_or_requests
self.contact_actions + self.contact_requests
结尾

# 或者
has_many :contact_actions_or_requests, :finder_sql => ..., :counter_sql => ...

结尾

但所有这些都存在一个问题,即无法在关联之上使用额外的查找器或 named_scopes,例如@user.contact_actions_or_requests.find(...)@user.contact_actions_or_requests.expired .

基本上,我需要一种方法来表达具有两条不同路径的 1:n 关联。一个是User -> ContactAction.user_id ,另一个是User -> UserAction.user_id -> UserAction.user_actionable_id -> ContactAction.id .然后将结果 (ContactActions) 加入一个列表中,以便使用 named_scopes 和/或查找器进行进一步处理。

由于我实际上在几十个地方都需要这种关联,因此为每种情况编写(和维护!)自定义 SQL 将是一个主要的麻烦。

我更愿意在 Rails 中解决这个问题,但我也愿意接受其他建议(例如 PostgreSQL 8.3 过程或类似的东西)。重要的是,最后,我可以像使用任何其他关联一样使用 Rails 的便利功能,更重要的是,还可以嵌套它们。

任何想法将不胜感激。

谢谢!

为我自己的问题提供某种答案:

我可能会使用数据库 View 解决这个问题,并根据需要添加适当的关联。对于以上,我可以

  • 使用 finder_sql 中的 SQL 创建 View ,
  • 将其命名为“contact_actions_or_requests”,
  • 修改 SELECT 子句以添加 user_id 列,
  • 添加一个 app/models/ContactActionsOrRequests.rb,
  • 然后将“has_many :contact_actions_or_requests”添加到 user.rb。

  • 我还不知道我将如何处理更新记录——这在 View 中似乎是不可能的——但也许这是一个开始。

    最佳答案

    您正在寻找的方法是合并。如果你有两个 ActiveRecord::Relations,r1 和 r2,你可以调用 r1.merge(r2) 来获得一个新的 ActiveRecord::Relation 对象,它结合了两者。

    这是否适合您在很大程度上取决于您的范围的设置方式以及您是否可以更改它们以产生有意义的结果。让我们看几个例子:

    假设您有一个 Page 模型。它具有正常的 created_at 和 updated_at 属性,因此我们可以具有如下范围:
    :updated -> { where('created_at != updated_at') }
    :not_updated -> { where('created_at = updated_at') }

    如果你把它从数据库中拉出来,你会得到:

    r1 = Page.updated # SELECT `pages`.* FROM `pages` WHERE (created_at != updated_at)
    r2 = Page.not_updated # SELECT `pages`.* FROM `pages` WHERE (created_at = updated_at)
    r1.merge(r2) # SELECT `pages`.* FROM `pages` WHERE (created_at != updated_at) AND (created_at = updated_at)
    => []

    所以它确实结合了这两种关系,但不是以一种有意义的方式。另一个:
    r1 = Page.where( :name => "Test1" ) # SELECT `pages`.* FROM `pages` WHERE `pages`.`name` = 'Test1'
    r2 = Page.where( :name => "Test2" ) # SELECT `pages`.* FROM `pages` WHERE `pages`.`name` = 'Test2'
    r1.merge(r2) # SELECT `pages`.* FROM `pages` WHERE `pages`.`name` = 'Test2'

    所以,它可能对你有用,但也可能不适合,这取决于你的情况。

    另一种推荐的方法是在你的模型上创建一个新的范围:
    class ContactAction < AR::Base
    belongs_to :user
    scope :pending, ...
    scope :active, ...
    scope :actions_and_requests, pending.active # Combine existing logic
    scope :actions_and_requests, -> { ... } # Or, write a new scope with custom logic
    end

    它结合了您想要在一个查询中收集的不同特征......

    关于ruby-on-rails - Ruby on Rails 3 : Combine results from multiple has_many or has_many_through associations,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4085972/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com