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

223

J'ai ce modèle en Ruby mais ça 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

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

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

LeMike
la source
2
essayez d'ajouter attr_accessible: password,: password_confirmation,: user_name,: email,: your-other-attributes dans le modèle User
Bachan Smruty
1
Ajoutez une gemme strong_parameter pour utiliser attr_accessible .
Wenbing Li
des paramètres forts pour utiliser attr_accessible?!
Thiem Nguyen
1
Je crois que @BruceLi voulait dire: ajoutez la protected_attributesgemme à utiliser attr_accessible.
Stefan Magnuson

Réponses:

398

Je suppose que vous utilisez Rails 4. Si c'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
Domon
la source
2
Existe-t-il une documentation expliquant pourquoi cela fonctionne ou pourquoi cela est nécessaire?
DiverseAndRemote.com
20
@OmarJackman La fonctionnalité est fournie par la strong_parametergemme. Il est couvert dans Rails Guides: guides.rubyonrails.org/… .
Domon
21
Les gens pourraient éprouver cela s'ils utilisent CanCan avec Rails 4.0. Essayez la solution de contournement plutôt propre d'AntonTrapps jusqu'à ce que CanCan soit mis à jour.
mjnissim
@mjnissim Souhaitez-vous s'il vous plaît publier ceci comme une réponse séparée? Je l'ai raté la première fois, mais cela m'a quand même fait gagner une tonne de temps.
Paul Pettengill
64

Pour ceux qui utilisent CanCan . Les gens pourraient éprouver cela s'ils utilisent CanCan avec Rails 4+ . Essayez la solution de contournement plutôt propre d' AntonTrapps 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

Mettre à jour:

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

CanCanCan

mjnissim
la source
1
Merci!! J'ai une question, avec CanCanCan (actif) est résolu ou pas besoin de ce code?
Adriano Resende
Pour moi, CanCanCan a toujours le problème. Ne pas utiliser load_resourceou utiliser load_resource :except => :createrésolu le problème. Vérifiez la réponse originale ici
Tun
24

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

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

Cela va à l'encontre du but des paramètres forts bien sûr, mais si vous êtes dans une situation comme la mienne (je fais ma propre gestion des paramètres autorisés dans une autre partie de mon système), cela fera le travail.

Wilker Lucio
la source
Ne fonctionne pas sur les rails 6, exception:unable to convert unpermitted parameters to hash
Tyler
20

Si vous utilisez ActiveAdmin, n'oubliez pas qu'il existe également 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
StuR
la source
18

Pour ceux qui utilisent CanCanCan :

Vous obtiendrez cette erreur si CanCanCan ne peut pas trouver la bonne méthode de paramétrage .

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

  1. create_params
  2. <model_name>_params comme article_params (c'est la convention par défaut dans rails pour nommer votre méthode param)
  3. resource_params (une méthode au nom générique que vous pouvez spécifier dans chaque contrôleur)

En outre, load_and_authorize_resourcepeut désormais prendre une param_methodoption pour spécifier une méthode personnalisée dans le contrôleur à exécuter pour nettoyer l'entrée.

Vous pouvez associer l' param_methodoption à 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#33-strong-parameters

Andreas
la source
3

Alternativement, vous pouvez utiliser la gemme Attributs protégés , mais cela va à l'encontre du but d'exiger des paramètres solides. Cependant, si vous mettez à niveau une ancienne application, les attributs protégés fournissent un chemin facile pour la mise à niveau jusqu'à ce que vous puissiez refactoriser l'attr_accessible en paramètres puissants.

Brian Dear
la source
0

Si vous êtes sur Rails 4 et que vous obtenez cette erreur, cela peut arriver si vous utilisez enumsur le modèle si vous avez défini avec des symboles comme celui-ci:

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

Le formulaire passera par exemple un sélecteur radio comme paramètre de chaîne. C'est ce qui s'est passé dans mon cas. La solution simple consiste à remplacer enumles chaînes par des symboles

enum preferred_phone: %w[home_phone mobile_phone work_phone]
# or more verbose
enum preferred_phone: ['home_phone', 'mobile_phone', 'work_phone']
lacostenycoder
la source