创建新用户时ActiveModel :: ForbiddenAttributesError

时间:2013-06-27 05:41:33

标签: ruby-on-rails rails-activerecord

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

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

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

8 个答案:

答案 0 :(得分:386)

我猜您正在使用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

答案 1 :(得分:64)

对于那些使用CanCan 的人。如果人们使用 CanCan 并使用 Rails 4 + ,则可能会遇到此问题。尝试使用AntonTrapps's而不是干净的解决方案here,直到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 ,看起来很有希望:

CanCanCan

答案 2 :(得分:23)

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

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

这当然会破坏强参数的目的,但是如果你处在像我这样的情况下(我在我系统的另一部分中自己管理允许的参数),这将完成工作。< / p>

答案 3 :(得分:20)

如果使用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

答案 4 :(得分:14)

对于那些使用 CanCanCan

的人

如果CanCanCan无法找到正确的参数方法,您将收到此错误。

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

  1. create_params
  2. <model_name>_params例如article_params(这是 rails中用于命名param方法的默认约定)
  3. resource_params(您可以指定的通用名称方法 每个控制器)
  4. 此外,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#strong-parameters

答案 5 :(得分:3)

或者你可以使用Protected Attributes gem,但是这会破坏要求强对数的目的。但是,如果您要升级较旧的应用程序,受保护的属性确实提供了一个简单的升级途径,直到您可以将attr_accessible重构为强params。

答案 6 :(得分:0)

在学习本教程时发现了这一点。 https://guides.rubyonrails.org/getting_started.html#installing-rails

尝试通过提交表单来创建新文章 my_domain /文章/新 前往 my_domain / articles

ArticlesController#create中的ActiveModel :: ForbiddenAttributesError ActiveModel :: ForbiddenAttributesError

articles_controller.rb 提取的来源(第10行附近):   def创建     @article = Article.new(params [:article])

意识到这不是一个格式正确的问题。希望找到一个比本教程更简单的教程。

我的git回购 https://github.com/aspiringguru/RubyRailsDemo1/tree/3b889f833069ff924d92c011224a289cc13558d7

答案 7 :(得分: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']