创建新用户时ActiveModel :: ForbiddenAttributesError


223

我在Ruby中有这个模型,但是它抛出了一个 ActiveModel::ForbiddenAttributesError

class User < ActiveRecord::Base
  attr_accessor :password
  validates :username, :presence => true, :uniqueness => true, :length => {:in => 3..20}
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, :uniqueness => true, format: { with: VALID_EMAIL_REGEX }

  validates :password, :confirmation => true
  validates_length_of :password, :in => 6..20, :on => :create

  before_save :encrypt_password
  after_save :clear_password

  def encrypt_password
    if password.present?
      self.salt = BCrypt::Engine.generate_salt
      self.encrypted_password= BCrypt::Engine.hash_secret(password, salt)
    end
  end

  def clear_password
    self.password = nil
  end
end

当我执行此操作时

  def create
    @user = User.new(params[:user])
    if @user.save
      flash[:notice] = "You Signed up successfully"
      flash[:color]= "valid"
    else
      flash[:notice] = "Form is invalid"
      flash[:color]= "invalid"
    end
    render "new"
  end

ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]

您能告诉我如何摆脱此错误或建立正确的用户注册表格吗?


2
尝试在用户模型中添加attr_accessible:password,:password_confirmation,:user_name,:email,:your-other-attributes
Bachan Smruty

1
添加strong_parameter gem以使用attr_accessible
李文冰2014年

要使用attr_accessible的强大参数吗?
Thiem Nguyen 2015年

1
我相信@BruceLi的意思是:添加protected_attributes要使用的gem attr_accessible
Stefan Magnuson

Answers:


398

我猜您正在使用Rails4。如果是这样,则必须将所需的参数标记为必需。

您可能想要这样做:

class UsersController < ApplicationController

  def create
    @user = User.new(user_params)
    # ...
  end

  private

  def user_params
    params.require(:user).permit(:username, :email, :password, :salt, :encrypted_password)
  end
end

2
是否有任何文件说明为何有效或为何需要?
DiverseAndRemote.com

20
@OmarJackman该功能由strong_parametergem 提供。Rails指南中对此进行了介绍:guides.rubyonrails.org/…
多蒙(Domon)2013年

21
如果人们将CanCan与Rails 4.0 一起使用,人们可能会遇到这种情况。在更新CanCan之前,请尝试使用AntonTrapps相当干净的解决方法。
mjnissim 2013年

@mjnissim您可以将其作为单独的答案发布吗?我第一次错过了它,但是它仍然为我节省了大量时间。
Paul Pettengill 2013年

64

对于那些使用CanCan的人。如果人们将CanCanRails 4+一起使用,人们可能会遇到这种情况。在这里尝试AntonTrapps相当干净的解决方法直到CanCan得到更新:

ApplicationController

before_filter do
  resource = controller_name.singularize.to_sym
  method = "#{resource}_params"
  params[resource] &&= send(method) if respond_to?(method, true)
end

并在资源控制器中(例如NoteController):

private
def note_params
  params.require(:note).permit(:what, :ever)
end

更新:

这是CanCan的延续项目,称为CanCanCan,看起来很有希望:

可以可以


1
谢谢!!我有一个问题,用CanCanCan(active)是否已解决或不需要此代码?
阿德里亚诺·雷森德

对我来说,CanCanCan仍然有问题。不使用load_resource或使用已load_resource :except => :create解决问题。检查原来的答案在这里

24

有一种更简单的方法可以完全避免使用“强参数”,您只需要将参数转换为常规哈希即可,如下所示:

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

当然,这违背了使用强参数的目的,但是,如果您处在像我这样的情况下(我正在对系统另一部分中的允许参数进行自己的管理),则可以完成工作。


在Rails 6中不起作用,例外:unable to convert unpermitted parameters to hash
Tyler

20

如果使用ActiveAdmin,请不要忘记模型寄存器块中还有一个allow_params:

ActiveAdmin.register Api::V1::Person do
  permit_params :name, :address, :etc
end

这些需要与控制器中的一起设置:

def api_v1_person_params
  params.require(:api_v1_person).permit(:name, :address, :etc)
end

否则,您将得到错误:

ActiveModel::ForbiddenAttributesError

18

对于那些使用CanCanCan

如果CanCanCan无法找到正确的params方法,则会出现此错误。

对于该:create操作,CanCan将通过查看控制器是否响应以下方法(顺序)来尝试使用经过清理的输入初始化新实例:

  1. create_params
  2. <model_name>_params 例如article_params(这是Rails中用于命名您的param方法的默认约定)
  3. resource_params (您可以在每个控制器中指定的通用方法)

此外,load_and_authorize_resource现在可以param_method选择在控制器中指定一个自定义方法来运行以清理输入。

您可以将param_method选项与对应于将被调用的方法名称的符号相关联:

class ArticlesController < ApplicationController
  load_and_authorize_resource param_method: :my_sanitizer

  def create
    if @article.save
      # hurray
    else
      render :new
    end
  end

  private

  def my_sanitizer
    params.require(:article).permit(:name)
  end
end

来源:https : //github.com/CanCanCommunity/cancancan#33-strong-parameters


3

另外,您可以使用Protected Attributes gem,但是这违背了需要强参数的目的。但是,如果您要升级较旧的应用程序,那么在可以将attr_accessible重构为强参数之前,Protected Attributes确实提供了简便的升级途径。


0

如果您在Rails 4上遇到此错误,则enum在模型上使用以下符号定义时,可能会发生此错误:

class User
  enum preferred_phone: [:home_phone, :mobile_phone, :work_phone]
end

该表单将通过一个无线电选择器作为字符串参数传递。这就是我的情况。简单的解决方法是更改enum为字符串而不是符号

enum preferred_phone: %w[home_phone mobile_phone work_phone]
# or more verbose
enum preferred_phone: ['home_phone', 'mobile_phone', 'work_phone']
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.