【问题标题】:Rails access DB data as variablesRails 将数据库数据作为变量访问
【发布时间】:2017-05-11 06:29:20
【问题描述】:

老实说,我不确定标题应该是什么问题,所以我要实现的是,我有一个角色表,其中包含可以分配给管理员、所有者、卖方、购买者等用户的角色名称.

现在我要做的是在检查权限或分配角色时,我需要通过角色的名称获取角色的 id。假设我尝试将角色 admin(id 为 1)添加到用户,将在我的表 user_roles 中输入,然后它将是,user_roles.create(user_id: some_users_id, role_id: 1)

现在我没有做 role_id: 1,而是尝试做类似的事情 role_id: :admin。

网站中的所有内容都取决于角色和权限,因此我可以在某种会话或全局范围内保持相同。

我本可以将角色保留在模型中并从中创建枚举,但是角色是从数据库中读取的,因为管理员可以添加新角色。

我使用 Rails 5。

【问题讨论】:

  • role_id 的值如何实时保存?您是否显示一个包含所有角色的选择框并从中选择 ID?
  • @Pavan 分配时会有一个下拉菜单,但是我什么时候检查某人的角色呢。为了简单起见,我只是举了一个例子。
  • 假设role_id的数据类型是整数,那么你不能将角色的名字保存为role_id的值。您可能需要按照@SatishakumarAwati 的建议创建一个新列,并使用 Varchar 作为数据类型来存储角色名称。

标签: ruby-on-rails


【解决方案1】:

执行用户角色的一个非常灵活和健壮的模式是使用三个表:

class User << ApplicationRecord
  has_many :user_roles
  has_many :roles, through: :user_roles

  def has_role?(name, resource = nil)
    roles.where({ name: name, resource: resource }.compact).exists?
  end

  def add_role(name, resource = nil)
    role = Role.find_or_create_by({ name: name, resource: resource }.compact)
    user_roles.find_or_create_by(role: role)
  end
end

# rails g model role name:string:index resource:belongs_to:polymorpic 
class Role << ApplicationRecord
  has_many :user_roles
  has_many :users, through: :user_roles
  belongs_to :resource, polymorphic: true, optional: true
end

# rails g model user_role user:belongs_to role:belongs_to 
# add a unique compound index on user_id and role_id.
class UserRole << ApplicationRecord
  belongs_to :user
  belongs_to :role
  validates_uniqueness_of :user_id, scope: :role_id
end

role 表存储角色的规范化定义。而user_roles 连接表存储了应用的角色。

为什么?

  • 用户可以拥有无​​限数量的角色/角色组合。
  • 为角色使用规范化表可以避免重复。您不会为应用于用户的每个角色复制字符串“admin”。
  • 可以选择将角色限定为资源。
  • 无需修改用户记录即可添加/撤销角色。
  • 如果需要,甚至可以在运行时创建角色。例如,如果您在构建下一个 Drupal 的位置,可以通过 GUI 添加角色定义。

如果您不想重新发明轮子,请尝试Rolify

【讨论】:

  • 使用 redis/memcached 或将角色存储在会话中不是非常可靠的解决方案。由于授权是应用程序的关键部分,因此您需要 rbdms 为您提供的容错能力。但是,您可以将其与模型级缓存结合使用以提高性能。
【解决方案2】:

据我了解,您需要一个变量来以以下格式存储数据。

{'admin' => 1, 'owner' => '2', 'seller' => '3', 'customer' => '4'}

两种方式可以实现。1.Rails Cache,2.Redis。

在 rails 服务器启动期间,从 roles 表中收集每个角色的所有 role nameid 对并存储到 rails cache/redis。在这两种情况下,key 将是 role namevalue 将是 role id

每当用户添加新角色时,请确保在 rails cache/redis 存储中更新相同的角色。

同样处理角色删除,这里需要从 rails cache/redis 中删除键。

我推荐使用 Redis 存储,它可以用于跨多个 Rails 服务器保存单个数据副本。

【讨论】:

    【解决方案3】:

    如果您没有缓存服务器,只需在您的 initializers 文件夹中创建一个 role_mapping.rb 文件,

    ROLES = Role.select([:id, :name]).as_json.map{ |h| h.values.reverse }.to_h
    

    在您的控制器中,

    user_roles.create(user_id: some_users_id, role_id: ROLES[params[:role]])
    

    希望对你有帮助..


    在您的Role 模型中创建新角色时,

    after_create :update_roles_mapping
    
    def update_roles_mapping
      Constant.const_set('ROLES', Role.select([:id, :name]).as_json.map{ |h| h.values.reverse }.to_h)
    end
    

    【讨论】:

      猜你喜欢
      • 2018-09-23
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多