【问题标题】:Unpermitted Parameters adding new fields to Devise in rails 4.0未经许可的参数在 rails 4.0 中向 Devise 添加新字段
【发布时间】:2013-06-27 09:11:22
【问题描述】:

对使用 Rails 非常陌生。我已经使用 Devise 实现了一个基本的登录系统。我正在尝试将几个新字段(bio:string,name:string)添加到 sign_up 页面中。我的所有内容都正确显示,并且新字段已添加到数据库中(当我在 SQLbrowser 中查看时),但是它们没有填充,并且在用户提交注册表单后,会显示一条消息,其中一部分显示:

Unpermitted parameters: bio, name

我已将 2 个字符串添加到 _devise_create_users.rb

  # added
  t.string :bio
  t.string :name

我让它们出现在 schema.rb 中

ActiveRecord::Schema.define(version: 20130629002343) do

  create_table "users", force: true do |t|
    t.string   "email",                  default: "",    null: false
    t.string   "encrypted_password",     default: "",    null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "shortbio"
    t.boolean  "admin",                  default: false
    t.string   "realname"
    t.string   "name"
    t.string   "bio"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

end

我的用户.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
   #:token_authenticatable, :confirmable,
   #:lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

end

这个问题与强参数有关吗?我很难理解它们以及在哪里/如何实施。

【问题讨论】:

  • @mohamad 这并没有真正帮助他解决问题。
  • @simonmorley 确实如此。但这是评论,而不是答案。
  • 有时解决问题的最佳方法就是采用不同的方法,我感谢您的评论。
  • Devise 非常棒,如果您想使用的不仅仅是其中的一两个功能。基本身份验证非常容易从头开始构建,并且通常是您所需要的。但是,一旦您进入“记住我”令牌、确认电子邮件、忘记密码、登录/注销日志以及由于密码尝试次数过多而锁定帐户,设计开始显示其优势!
  • 我将大部分附加字段放入另一个模型Profile 并规避了人们在这里抱怨的大部分问题。无论如何,一个额外的模型可以说是更好的数据库/模型设计,尽管我不会在这里争论。

标签: ruby-on-rails ruby


【解决方案1】:

接受的解决方案足够好,但我看到两个问题:1)所有控制器都会检查当前控制器是否是设计控制器(if: :devise_controller?)和2)我们需要在方法中写入所有可接受的参数(...for(:sign_up) {|u| u.permit(:bio, :name)}),甚至是:email:password等等。

我认为更优雅的解决方案可能是:

# app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  before_filter :configure_permitted_parameters

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up).push(:name, :phone, :organization)
  end
end

# config/routes.rb
devise_for :users, :controllers => { :registrations => "users/registrations" }

注意:Rails 4.2+ 的更新

这个答案已经过时了:

【讨论】:

  • 上面给了我:undefined method 'push' for #&lt;ActionController::Parameters:0x007fa3bc96c2a8&gt;。有什么想法吗?
  • devise_parameter_sanitizer.for 给了我一个错误,但使用 devise_parameter_sanitizer.permit(:sign_up, keys: [model parameters] 对我有用 -- rubydoc.info/github/plataformatec/devise/Devise/…
  • @doub1ejack:您是否有使用permit 语法的工作示例,以便我们可以使用正确的 Rails 4 代码更新答案?我认为应该是这样的:devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :phone, :organization])
  • 我看到很多关于注册控制器的注册部分的问题,但是如果您想将此应用于编辑用户,您需要将 :sign_up 替换为 :account_update。我只想说,这绝对是一场噩梦。很好的答案。
【解决方案2】:

确保您至少使用的是 Devise 3.0.0。添加到您的应用程序控制器:

before_filter :update_sanitized_params, if: :devise_controller?

def update_sanitized_params
  devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:bio, :name)}
end

文档:https://github.com/plataformatec/devise#strong-parameters

【讨论】:

  • 这仍然给了我相同的“不允许的参数”。在阅读更多内容后,我认为这肯定会起作用。
  • 同样的问题。这是我的 application_controller:gist.github.com/r-s-/5892634
  • 谢谢佩德罗。我想我现在明白了。我只需要添加我需要传递给该函数的所有参数,但我不确定这是否安全。 gist.github.com/r-s-/5892670
  • 如果您需要在注册时允许他们,那么可以。只需确保它们都是您允许用户输入的参数,即不允许使用管理员密钥。
  • 仅供参考,Devise 文档将其称为“懒惰方式”。下面的答案显示了一种在不更改应用程序范围控制器的情况下执行此操作的方法。
【解决方案3】:

我也遇到了这个问题。设计网站上的文档以及一些论坛都有帮助。这是我最终做的:

在自定义 RegistrationsController (app/controllers/users/registrations_controller.rb) 中

# app/controllers/users/registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController
    before_filter :update_sanitized_params, if: :devise_controller?

    def update_sanitized_params
       devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:name, :email,   :password, :password_confirmation)}
    end
end

然后在你的路由文件 (config/routes.rb) 中我们为你的 devise_for 声明:

devise_for :users, controllers: {registrations: "users/registrations"}

【讨论】:

  • 这很好用,但不适用于嵌套属性。如何克服这一点? profile_attributes 添加到 params 仍然会引发 Unpermitted parameters: profile_attributes。我想在我的注册表单中添加一些个人资料属性。
  • 也许不需要指定“if::devise_controller”,因为控制器是从设计控制器继承的:)
  • 非常感谢这对我有帮助。
【解决方案4】:

这是在我的 rails 4.2.1 应用程序中工作的另一种直接方式:

创建以下文件

/config/initializers/devise_permitted_parameters.rb

还有代码..

module DevisePermittedParameters
  extend ActiveSupport::Concern

  included do
    before_filter :configure_permitted_parameters
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) << :name
    devise_parameter_sanitizer.for(:account_update) << :name

    devise_parameter_sanitizer.for(:sign_up) << :bio
    devise_parameter_sanitizer.for(:account_update) << :bio
  end

end

DeviseController.send :include, DevisePermittedParameters

【讨论】:

  • 这比杂乱无章的应用控制器要好得多!
【解决方案5】:

对于 sign_up 和 account_update 都为 controllers/applcation_controller.rb 执行此操作

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :authenticate_user!

  before_action :configure_permitted_parameters, if: :devise_controller?
  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:password, :password_confirmation,:current_password,:email,:name, :phonenumber,:province,:city,:area,:idcardimg,:role) }
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:password, :password_confirmation,:current_password,:email,:name, :phonenumber,:province,:city,:area,:idcardimg,:role) }
  end
end

【讨论】:

  • 那么 application_controller 与两个关于用户注册的非常具体的动作有什么关系呢?显然,这属于registrations_controller
【解决方案6】:

问题似乎出在强参数上,看这里复制代码。

https://github.com/plataformatec/devise/blob/rails4/app/controllers/devise/registrations_controller.rb

将该文件复制到项目中的同一位置app/controllers/devise/registrations_controller.rb

并更改创建操作的代码

# POST /resource
def create
  # THIS LINE IS THE ONE YOU CHANGE
  self.resource = build_resource(sign_up_params.merge(:bio, :name))

  if resource.save
    if resource.active_for_authentication?
      set_flash_message :notice, :signed_up if is_navigational_format?
      sign_up(resource_name, resource)
      respond_with resource, :location => after_sign_up_path_for(resource)
    else
      set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
      expire_session_data_after_sign_in!
      respond_with resource, :location => after_inactive_sign_up_path_for(resource)
    end
  else
    clean_up_passwords resource
    respond_with resource
  end
end

我必须告诉你,我不太确定这是否可行,因为我不使用 devise,但看到代码似乎它会起作用。

【讨论】:

    【解决方案7】:

    Devise为此做好了一切准备:

    在你拥有的用户控制器中

    private
    
    # Never trust parameters from the scary internet, only allow the white list through.
    def user_params
      params.require(:user).permit(:full_name <add your parameter>)
    end
    

    【讨论】:

      猜你喜欢
      • 2016-11-30
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 1970-01-01
      • 2013-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多