2017-09-28 2 views
0

Ich würde gerne wissen, ob es eine elegantere Möglichkeit gibt, has_many durch Beziehungen zu verketten. In meinem Beispiel habe ich einen Benutzer, der mehrere Rollen haben kann. Jede Rolle hat mehrere Berechtigungen. Ein Benutzer hat also mehrere Berechtigungen. Der Code unten funktioniert gut, aber ich frage mich, ob es einen besseren Weg gibt, dies zu tun.Kette has_many: durch Assoziationen

class User < ActiveRecord::Base 
    has_many :role_user_mappings 
    has_many :roles, through: :role_user_mappings 

    def permissions 
    permitted_actions = [] 
    self.roles.each do |role| 
     role.permissions.each do |permission| 
     permitted_actions << permission 
     end 
    end 
    permitted_actions 
    end 
end 

class Role < ActiveRecord::Base 
    has_many :permission_role_mappings 
    has_many :permissions, through: :permission_role_mappings 
end 

class Permission < ActiveRecord::Base 
end 

class PermissionRoleMapping < ActiveRecord::Base 
    belongs_to :permission 
    belongs_to :role 
end 

class RoleUserMapping < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :role 
end 

Ich würde gerne in der Lage sein, dies zu tun.

user.permissions 

EDIT: Versuchte auf, was ich versucht, dass zumindest DRYS die User-Modell ein wenig ist die Funktion als Besorgnis Zugabe

module Permittable 
    extend ActiveSupport::Concern 

    def permissions 
    permitted_actions = [] 
    self.roles.each do |role| 
     role.permissions.each do |permission| 
     permitted_actions << permission 
     end 
    end 
    permitted_actions 
    end 
end 

Antwort

3

Haben Sie versucht, ..

class User < ActiveRecord::Base 
    has_many :role_user_mappings 
    has_many :roles, through: :role_user_mappings 
    has_many :permissions, through: roles 

, dass Sie

user.permissions 

Ich bin nicht sicher geben sollte, wenn das HMT über HMT-Funktion zur Verfügung gestellt wurde, ich weiß, es war in früheren Versionen fehlt von Schienen, aber es funktioniert für mich auf Schienen 5.

1

Wenn Sie dies tun:

class Permission < ActiveRecord::Base 
    has_many :permission_role_mappings 
end 

Dann sollten Sie in der Lage sein, dies zu tun:

class User < ActiveRecord::Base 
    has_many :role_user_mappings 
    has_many :roles, through: :role_user_mappings 

    def permissions 
    Permission. 
     joins(:permission_role_mappings). 
     where(permission_role_mappings: {role: roles}) 
    end 
end  

By the way, können Sie bereits wissen, und es kann sein, warum Sie die Frage fragen ... aber das wird Ihnen eine N + 1 Abfrage geben:

permitted_actions = [] 
    self.roles.each do |role| 
    role.permissions.each do |permission| 
     permitted_actions << permission 
    end 
    end 
    permitted_actions 

Auch FWIW wenn eine array zurück aus einer Sammlung wollen, brauchen Sie nicht zu tun:

permitted_actions = [] 
    self.roles.each do |role| 
    ... 
    end 
    permitted_actions 

Sie können einfach tun:

roles.map do |role| 
    ... 
    end 

Seit map gibt array zurück.

Verwandte Themen