从User类继承的多个基于角色的类 - Rails 4

时间:2016-07-30 01:44:48

标签: ruby class ruby-on-rails-4 inheritance single-table-inheritance

我有一个名为User的类和一些用于从Admin类继承的用户角色(例如ContributorMemberUser)的类:

class Admin < User; end

遵循STI原则,roles在用户表格中存储为jsonb,如下所示:

  t.jsonb :roles, default: {
    'admin':       false,
    'contributor': false,
    'member':      true
  }

是否可以将相应的子类设置为相应角色的User实例。换句话说,做一些像:

u = User.create(...)
u.class #<= returns 'User'
u.grant_role(admin)
u.class #<= should return 'Admin'

我正在考虑使用before_save回调,以便每次User实例被实例化或更新时,都会选择适当的类。我是在正确的轨道上吗?

1 个答案:

答案 0 :(得分:1)

我认为不可能动态更改实例的类型,但我不是100%肯定这一点,考虑到我们在这里谈论Ruby。 :)

而不是正在改变User类的STI,使用strategy pattern怎么样?

设置一组RoleStrategy类,根据role的值实例化。

对于你的情况,它可能是这样的:

class User
  # :foo and :bar are role dependent behaviors that you want to have.
  delegate :foo, :bar, to: :role_strategy

  private

  def role_strategy
    # Need to do some error handlings here, for example, if role is nil.
    "#{role.classify}RoleStrategy".constantize.new(self)
  end
end

class RoleStrategy
  def initialize(user)
    @user = user
  end

  def foo
    do_it
  end

  def bar
    do_something
  end
end

class AdminRoleStrategy < RoleStrategy
  def bar
    do_something_else
  end
end

行为会自动改变,具体取决于role的值。