Chain has_many:通过关联

时间:2017-09-28 14:55:46

标签: ruby-on-rails activerecord has-many-through

我想知道是否有更优雅的方式通过关系链接has_many。在我的示例中,我有一个可以拥有多个角色的用户。每个角色都有多个权限。因此用户具有多个权限。下面的代码工作正常,但我很想知道是否有更好的方法来做到这一点。

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

我希望能够做到这一点。

user.permissions

编辑:尝试 在我尝试的事情上,至少干掉用户模型一点点就是将功能添加为关注点

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

2 个答案:

答案 0 :(得分:3)

你试过..

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

那应该给你

user.permissions

我不确定HMT通过HMT功能何时可用,我知道它在早期版本的rails中缺失,但它适用于我在Rails 5上。

答案 1 :(得分:1)

如果你这样做:

class Permission < ActiveRecord::Base
  has_many :permission_role_mappings
end

然后你应该能够做到这一点:

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    

顺便说一下,你可能已经知道了这一点,这可能就是你问这个问题的原因......但是这会给你一个N + 1查询:

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

此外,FWIW,当想要从集合中回来array时,您不需要这样做:

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

你可以这样做:

  roles.map do |role|
    ...
  end

由于map会返回array