【问题标题】:Rails - combining scopes from different tablesRails - 组合来自不同表的范围
【发布时间】:2012-08-16 19:05:59
【问题描述】:

我有几个不同(并且有些关联)模型的示波器

class Alarm
   has_one :site #use mac_address field in Alarm and Site as key / foreign key

   scope :any_network, lambda{ joins(:network) } #more complex stuff can be done :-)
   #etc
end

class Network
   has many :permissions
   has_many :sites

   scope :has_permission, lambda{|level, user| #etc - returns a list of networks that a                  
                                               # user has the `level` permission for }

   #etc
end

class Permission
    has_one :network, :user
    #etc -uses a flags field to hold permision levels
end

这样我就可以了

Alarm.any_network

生成

SELECT `alarm`.* FROM `alarm` INNER JOIN `site` ON 
`site`.`mac_address` = `alarm`.`mac_address` INNER JOIN `network` ON 
`network`.`id` = `site`.`network_id`

我能做到

Network.has_permission('manager',1) 

生成

SELECT `network`.* FROM `network` INNER JOIN `permission` ON 
`permission`.`network_id` = `network`.`id` 
WHERE (permission.user_id = 1 and permission.flags && 8)

这一切都应该如此。

我无法解决的是如何加入这两个范围以生成源自用户具有适当权限的任何网络的所有警报的集合。类似于

SELECT `alarm`.* FROM `alarm` INNER JOIN `site` 
ON `site`.`mac_address` = `alarm`.`mac_address` 
INNER JOIN `network` ON `network`.`id` = `site`.`network_id` 
INNER JOIN `permission` ON `permission`.`network_id` = `network`.`id` 
WHERE (permission.user_id = 1 and permission.flags && 8)

我已尝试链接范围(无法使其工作)并且我已尝试合并范围(显然是错误的做法!)

任何想法 - 这几天我一直在扯头发。

谢谢,

史蒂夫

【问题讨论】:

    标签: ruby-on-rails named-scope


    【解决方案1】:

    乍一看,我想像这样,但很难说,因为你没有给我们Site模型:

    Alarm.includes(:site => {:network => :permissions}).where(['permissions.flags' && ?', 8], 'permissions.user_id' => 1)
    

    这显然是未经测试的,很难准确地说,但这里是发生了什么的要点:

    1. 渴望加载网站、网络和权限
    2. 强制执行您在理论 SQL 语句中概述的条件。

    仅供参考,我不记得这种多重条件wheres 是否像我上面使用的那样工作,但也许它会让你的车轮转动!

    【讨论】:

    • 谢谢 lamvery。网站非常简单:class Site < ActiveRecord::Base; belongs_to :network; has_many :alarms, :primary_key => :mac_address, :foreign_key => :mac_address; end 我明白你在做什么,但这是我想要尝试摆脱的所有类型的硬连线代码 - 我希望能够使用范围来尝试添加一个我的代码的灵活性程度(例如,Alarm#any_network 范围是一个非常简单的示例 - 我们想要对警报集进行各种更复杂的查询。谢谢史蒂夫
    • 也许混淆在于您的示例范围中缺少详细信息。您可以轻松地将我上面的示例转换为类似以下内容的范围:scope :with_permissions, lambda{ |user,mask| includes(:site => {:network => permissions}).where(['permissions.flags' && ?', mask], 'permissions.user_id' => user) },并使用它将其链接到更复杂的查询中。
    猜你喜欢
    • 1970-01-01
    • 2012-03-31
    • 2021-08-25
    • 2013-11-20
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 2016-02-01
    • 2014-07-27
    相关资源
    最近更新 更多