Rails — объединение областей видимости из разных таблиц

У меня есть пара прицелов на разных (и несколько связанных) моделях.

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)

Я пробовал связывать области (не могу заставить это работать) и пробовал объединять области (явно неправильно!)

Любые идеи - я рвал на себе волосы пару дней.

Спасибо,

Стив


person Steve Gooberman-Hill    schedule 16.08.2012    source источник


Ответы (1)


На первый взгляд, я представляю что-то подобное, но трудно сказать, потому что вы не дали нам модель Site:

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

Это, очевидно, не проверено и трудно сказать точно, но вот суть того, что происходит:

  1. Нетерпеливая загрузка сайта, сети и разрешений
  2. Обеспечьте соблюдение условий, которые вы описываете в своей теоретической инструкции SQL.

К вашему сведению, я не помню, работают ли такие множественные условия where, как я использовал выше, но, возможно, это заставит ваши колеса вращаться!

person Iamvery    schedule 16.08.2012
comment
Ламвери спасибо. Сайт довольно прост: class Site < ActiveRecord::Base; belongs_to :network; has_many :alarms, :primary_key => :mac_address, :foreign_key => :mac_address; end Я вижу, что вы пытаетесь сделать, но это все тот же запрограммированный код, от которого я хочу избавиться. гибкость моего кода (так, например, область Alarm#any_network является очень простым примером — у нас есть множество более сложных запросов, которые мы хотим выполнить для набора сигналов тревоги. Спасибо, Стив - person Steve Gooberman-Hill; 17.08.2012
comment
Возможно, путаница заключается в отсутствии подробностей, представленных в ваших примерах. Вы можете легко превратить мой пример выше в область действия с чем-то вроде: scope :with_permissions, lambda{ |user,mask| includes(:site => {:network => permissions}).where(['permissions.flags' && ?', mask], 'permissions.user_id' => user) } и использовать его, чтобы связать его в более сложные запросы. - person Iamvery; 17.08.2012