【问题标题】:Chain has_many :through associations链 has_many :通过关联
【发布时间】:2017-09-28 14:55:46
【问题描述】:

我想知道是否有更优雅的方式通过关系链接 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

编辑:尝试过 在我尝试过的事情上,至少 DRY 用户模型有点添加功能作为关注点

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

【问题讨论】:

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


    【解决方案1】:

    你试过了吗..

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

    那应该给你

    user.permissions
    

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

    【讨论】:

      【解决方案2】:

      如果你这样做:

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-09
        • 1970-01-01
        • 1970-01-01
        • 2015-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多