设计 - 覆盖 Parameter Sanitizer

Devise - overriding ParameterSanitizer

我正在尝试按照以下说明为每个模型配置不同的 Devise 强参数消毒剂; https://github.com/plataformatec/devise#strong-parameters

我在我的雇主模型目录中创建了一个名为 parameter_sanitizer 的新文件;

app/controllers/Employers/paramater_sanitizer.rb

class Employer::ParameterSanitizer < Devise::ParameterSanitizer
  def initialize(*)
    super
    devise_parameter_sanitizer.permit(:sign_up, keys: [:forename, :surname, :username)
  end
end

在我的应用程序控制器中我有;

    require 'employers/parameter_sanitizer'

    class ApplicationController < ActionController::Base
          before_filter :devise_parameter_sanitizer, if: :devise_controller?
          protect_from_forgery with: :exception

          protected

          def devise_parameter_sanitizer
            if resource_class == Employer
              Employer::ParameterSanitizer.new(Employer, :employer, params)
            else
              super # Use the default one
            end
          end
    end

我在注册 Employer 对象时遇到的错误是;

Devise::ConfirmationsController#show 中的名称错误 #

的未定义局部变量或方法“devise_parameter_sanitizer”

关于如何克服这个问题有什么建议吗?

谢谢, 马克

在这个 initialize 方法中,您将 params 保存为实例变量 @params 因此在您的方法中您应该这样做:

class Employer::ParameterSanitizer < Devise::ParameterSanitizer
  def initialize(*)
    super
    @params.permit(:sign_up, keys: [:forename, :surname, :username])
  end

我也相信这应该可以在不指定 @params

的情况下工作

说明

要找到此问题的解决方案,请查看 devise api 以更好地理解您正在调用的方法并阅读 `Devise::ParameterSanitizer 源代码

我引用了他们的 ruby-rocs 关于 #permit() method

Instance Method Details

#permit(action, keys: nil, except: nil, &block) ⇒ Object

Add or remove new parameters to the permitted list of an action.

Arguments action - A Symbol with the action that the controller is performing, like sign_up, sign_in, etc.

keys: - An Array of keys that also should be permitted.

except: - An Array of keys that shouldn't be permitted.

block - A block that should be used to permit the action parameters instead of the Array based approach. The block will be called with an ActionController::Parameters instance.

Examples

# Adding new parameters to be permitted in the `sign_up` action.

devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])

# Removing the `password` parameter from the `account_update` action.
devise_parameter_sanitizer.permit(:account_update, except: [:password])

# Using the block form to completely override how we permit the
# parameters for the `sign_up` action.
devise_parameter_sanitizer.permit(:sign_up) do |user|
  user.permit(:email, :password, :password_confirmation)
end

Returns nothing.

我也引用

If you have multiple Devise models, you may want to set up a different parameter sanitizer per model. In this case, we recommend inheriting from Devise::ParameterSanitizer and adding your own logic:

class ApplicationController < ActionController::Base
  protected

  def devise_parameter_sanitizer
    if resource_class == User
      User::ParameterSanitizer.new(User, :user, params)
    else
      super # Use the default one
    end
  end
end

User::ParameterSanitizer.new(User, :user, params) 将从 parameter_sanitizer.rb source code

调用此初始化方法
def initialize(resource_class, resource_name, params)
   @auth_keys      = extract_auth_keys(resource_class)
   @params         = params
   @resource_name  = resource_name
   @permitted      = {}

   DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
     permit(action, keys: keys)
   end
end

所以基本上你在调用 initialize(User, :user, params),我不明白为什么设计在这个方法中接受 params,因为它有自己的方式通过保存允许的静态散列来允许属性场.

DEFAULT_PERMITTED_ATTRIBUTES = {
   sign_in: [:password, :remember_me],
   sign_up: [:password, :password_confirmation],
   account_update: [:password, :password_confirmation, :current_password]
}

并允许他们使用循环

DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
   permit(action, keys: keys)
end

在这个 initialize 方法中,您将 params 保存为实例变量 @params 因此在您的方法中您应该这样做:

class Employer::ParameterSanitizer < Devise::ParameterSanitizer
  def initialize(*)
    super
    @params.permit(:sign_up, keys: [:forename, :surname, :username])
  end