238

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

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

4

8 回答 8

422

我猜您使用的是 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
于 2013-06-27T06:21:16.810 回答
65

对于那些使用 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的延续项目,看起来很有希望:

康康康

于 2013-09-12T14:08:36.667 回答
25

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

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

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

于 2015-04-14T18:07:11.317 回答
24

如果使用 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
于 2014-03-26T17:55:40.987 回答
24

对于那些使用CanCanCan的人:

如果 CanCanCan 找不到正确的params 方法,您将收到此错误。

对于该: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

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

于 2017-02-06T14:42:27.273 回答
3

Alternatively you can use the Protected Attributes gem, however this defeats the purpose of requiring strong params. However if you're upgrading an older app, Protected Attributes does provide an easy pathway to upgrade until such time that you can refactor the attr_accessible to strong params.

于 2013-07-22T02:30:15.787 回答
0

另一个原因是您permitted_params被一种方法覆盖。例如

def permitted_params
   params.permit(:email, :password)
end
于 2021-09-05T12:24:45.683 回答
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']
于 2020-01-28T20:15:44.650 回答