Rolify:添加过期日期时间

Rolify: Add Expire Datetime

我是 Rails 的新手,我想知道是否有办法使用 gem“Rolify”来创建“expired_at”字段,所以我可以添加一段时间内对用户的角色,如果字段为 NULL,则为永久角色。

我想到将字段添加到迁移中:

class RolifyCreateRoles < ActiveRecord::Migration[6.1]
  def change
    create_table(:roles) do |t|
      t.string :name
      t.references :resource, :polymorphic => true

      t.timestamps
    end

    create_table(:users_roles, :id => false) do |t|
      t.references :user
      t.references :role

      t.datetime :expired_at     # Adding field to the "join_table"
    end
    
    add_index(:roles, [ :name, :resource_type, :resource_id ])
    add_index(:users_roles, [ :user_id, :role_id ])
  end
end

但我不知道如何“覆盖”像“add_role”或“has_role”这样的方法?考虑到这个“expired_at”字段,所以我可以做类似的事情:

room = Chat::Room.find(1)

sarah = User.find(1)
david = User.find(2)

# Today
sarah.add_role :muted, room, 7.days.from_now
david.add_role :muted, room

sarah.has_role? :muted, room     # should return true
david.has_role? :muted, room     # should return true

# A week later
sarah.has_role? :muted, room    # should return false
david.has_role? :muted, room    # should return true

谢谢。

我有一个想法,你不需要添加expired_at字段,你可以扩展rolify gem在角色名称后附加过期时间,然后我们可以解析过期时间,判断角色是否过期,看下面代码:

# lib/rolify/role.rb
module Rolify
  module Role
    def add_expire_role(role_name, expire_time, resource = nil)
      expire_role_name = "#{role_name}  expire_at #{expire_time}"
      add_role(expire_role_name, resource)
    end

    def check_role(role_name, resource = nil)
      expire_roles = self.class.adapter.where(self.roles).where("roles.name LIKE ?","%#{role_name}%")
      # filter still available roles
      avail_roles = expire_roles.select do |role|
        _, expire_role_time = role.name.split("expire_at")
        expired = expire_role_time.present? && expire_role_time.to_time < Time.now
        # remove expired role
        self.class.adapter.remove(self, role.name, resource) if expired
        !expired
      end
      # return true if there's still any role
      avail_roles.any?
    end
  end
end

# config/initializers/rolify.rb
Rolify.configure do |config|
 # ...
end
Dir[File.join(Rails.root, "lib", "rolify", "**/*.rb")].each {|l| require l }

演示

user = User.first
user.add_expire_role :test, 1.minute.from_now
user.check_role :test # true
# 1 minute later
user.check_role :test # false

user.add_role :test
user.check_role :test # always true
# try override
user.add_expire_role :test, 1.minute.from_now
# 1 minute later
user.check_role :test # still true