web-dev-qa-db-fra.com

ActiveModel :: ForbiddenAttributesError lors de la création d'un nouvel utilisateur

J'ai ce modèle dans Ruby mais il jette un 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

quand je lance cette action

  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

sur Ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux].

Pouvez-vous s'il vous plaît me dire comment se débarrasser de cette erreur ou établir un formulaire d'enregistrement d'utilisateur approprié?

217
LeMike

Je suppose que vous utilisez Rails 4. Si tel est le cas, les paramètres nécessaires doivent être marqués comme requis.

Vous voudrez peut-être le faire comme ceci:

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
391
Domon

Pour ceux qui utilisent CanCan . Les gens peuvent en être victimes s’ils utilisent CanCan avec Rails 4 + . Essayez AntonTrapps solution de contournement plutôt propre ici jusqu'à ce que CanCan soit mis à jour:

Dans le ApplicationController:

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

et dans le contrôleur de ressources (par exemple NoteController):

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

Mise à jour:

Voici un projet de continuation pour CanCan appelé CanCanCan , qui semble prometteur:

CanCanCan

64
mjnissim

Il existe un moyen plus facile d'éviter les paramètres forts, il vous suffit de convertir les paramètres en un hachage normal, comme suit:

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

Bien sûr, cela va à l’encontre du but des paramètres forts, mais si vous êtes dans une situation comme la mienne (je gère moi-même les paramètres autorisés dans une autre partie de mon système), le travail sera fait.

23
Wilker Lucio

Si vous utilisez ActiveAdmin, n'oubliez pas qu'il y a aussi un permit_params dans le bloc de registre de modèle:

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

Ceux-ci doivent être définis avec ceux du contrôleur:

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

Sinon, vous obtiendrez l'erreur:

ActiveModel::ForbiddenAttributesError
20
StuR

Pour ceux qui utilisent CanCanCan :

Vous obtiendrez cette erreur si CanCanCan ne parvient pas à trouver la bonne méthode params .

Pour l'action :create, CanCan essaiera d'initialiser une nouvelle instance avec une entrée désinfectée en vérifiant si votre contrôleur répondra aux méthodes suivantes (dans l'ordre):

  1. create_params
  2. <model_name>_params tel que article_params (il s'agit de la convention par défaut dans Rails pour nommer votre méthode param)
  3. resource_params (une méthode générique que vous pouvez spécifier dans chaque contrôleur)

De plus, load_and_authorize_resource peut maintenant utiliser une option param_method pour spécifier une méthode personnalisée dans le contrôleur à exécuter pour nettoie l'entrée.

Vous pouvez associer l'option param_method à un symbole correspondant au nom d'une méthode qui sera appelée:

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

source: https://github.com/CanCanCommunity/cancancan#strong-parameters

14
Andreas

Alternativement, vous pouvez utiliser le Protected Attributes gem ; Cependant, si vous mettez à niveau une application plus ancienne, les attributs protégés constituent un chemin facile à mettre à niveau jusqu'à ce que vous puissiez refactoriser l'attr_accessible à des paramètres puissants.

3
Brian Dear