创建新用户时出现ActiveModel::ForbiddenAttributesError

我在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]

你能告诉我如何消除这个错误或者建立一个正确的用户登记表吗?

219313 次浏览

我猜你用的是Rails 4。如果是这样,必需的参数必须标记为必需的。

你可能想这样做:

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

或者你也可以使用受保护属性gem,但是这违背了要求强参数的目的。然而,如果你正在升级一个旧的应用程序,Protected Attributes确实提供了一个简单的升级途径,直到你可以将attr_accessible重构为强参数。

对于使用CanCan的人。如果将康康舞Rails 4 +一起使用,人们可能会遇到这种情况。在CanCan更新之前,尝试AntonTrapps的而不是干净的解决方案在这里:

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,看起来很有前途:

< a href = " https://github.com/CanCanCommunity/cancancan " > CanCanCan < / >

如果使用ActiveAdmin,不要忘记在模型寄存器块中也有一个permit_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

有一种更简单的方法来避免强参数,你只需要将参数转换为常规散列,如下所示:

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)


model.create!(unlocked_params)

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

对于那些使用CanCanCan的人:

如果canancan不能找到正确的参数的方法,就会得到这个错误。

对于:create动作,CanCan将尝试初始化一个带有净化过的输入的新实例,方法是查看你的控制器是否会响应以下方法(按顺序):

  1. create_params
  2. <model_name>_params如article_params(这是 rails中命名参数方法的默认约定)
  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
< p >来源: https://github.com/CanCanCommunity/cancancan#33-strong-parameters < / p >

如果你在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']

另一个原因是你用一个方法重写了permitted_params。例如

def permitted_params
params.permit(:email, :password)
end