如何很好地实现多态current_user

时间:2016-01-09 21:03:46

标签: ruby-on-rails ruby

在我的应用中,我有两种类型的用户(UserShop现在,将很快添加Admin),这些用户通过相同的身份验证策略进行身份验证,因此存储在相同的current_profile变量。所以,它可能是几个模型的一个实例,这就是我用以下方法获取它的原因:

class ApplicationController < ActionController::Base
  before_action :fetch_current_user

  private

  def fetch_current_user
    if session[:current_profile_type].blank?
      @current_profile = nil
      return
    end

    case session[:current_profile_type]
    when 'Shop'
      model = Shop
    when 'User'
      model = User
    end

    @current_profile = model.find_by(id: session[:current_profile_id])
  end
end

但是我对这个解决方案不满意,对我来说它看起来太吵了。也许有更好/更简单的方法?

P.S。我不想在这里使用constantize:虽然更具可读性,但它会减慢每个应用的请求。

1 个答案:

答案 0 :(得分:1)

这是一种可能性

class ApplicationController < ActionController::Base
  PROFILE_TYPES = {
    'Shop': Shop,
    'User': User
  }

  before_action :fetch_current_user

  private

  def fetch_current_user
    profile_type = PROFILE_TYPES[session[:current_profile_type]]
    @current_profile = profile_type && profile_type.find_by(id: session[:current_profile_id])
  end
end

或者如何缓存constantize的结果?这样您就不需要像上面的示例那样手动维护哈希映射。

class ApplicationController < ActionController::Base
  before_action :fetch_current_user

  private

  def fetch_current_user
    profile_type = (self.class.cached_profile_types[session[:current_profile_type]] ||= session[:current_profile_type].constantize)  # Constantizes each type only once after each application boot.
    @current_profile = profile_type && profile_type.find_by(id: session[:current_profile_id])
  end

  def self.cached_profile_types
    @@cached_profile_types ||= {}  # Cache across all subclasses of ApplicationController
  end
end