ActiveModel :: ForbiddenAttributesError durante la creazione di un nuovo utente


223

Ho questo modello in Ruby ma lancia 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

quando eseguo questa azione

  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

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

Potete per favore dirmi come eliminare questo errore o stabilire un modulo di registrazione utente adeguato?


2
prova ad aggiungere attr_accessible: password,: password_confirmation,: user_name,: email,: your-other-attributi nel modello Utente
Bachan Smruty

1
Aggiungi gemma strong_parameter per usare attr_accessible .
Wenbing Li,

parametri forti da usare attr_accessible ?!
Thiem Nguyen,

1
Credo che @BruceLi intendesse: aggiungere la protected_attributesgemma da usare attr_accessible.
Stefan Magnuson,

Risposte:


398

Suppongo che tu stia utilizzando Rails 4. In tal caso, i parametri necessari devono essere contrassegnati come richiesto.

Potresti voler farlo in questo modo:

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

2
Esiste una documentazione sul perché funziona o perché è necessario?
DiverseAndRemote.com

20
@OmarJackman La funzionalità è fornita dalla strong_parametergemma. È coperto in Rails Guides : guides.rubyonrails.org/… .
Domon,

21
Le persone potrebbero riscontrare questo problema se usano CanCan con Rails 4.0. Prova la soluzione piuttosto pulita di AntonTrapps fino a quando CanCan non viene aggiornato.
mjnissim,

@mjnissim Pubblica questo post come risposta separata? L'ho perso la prima volta, ma mi ha comunque salvato un sacco di tempo.
Paul Pettengill,

64

Per quelli che usano CanCan . Le persone potrebbero riscontrare questo problema se usano CanCan con Rails 4+ . Prova la soluzione piuttosto pulita di AntonTrapps qui fino a quando CanCan non viene aggiornato:

Nel ApplicationController:

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

e nel controller delle risorse (ad esempio NoteController):

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

Aggiornare:

Ecco un progetto di continuazione per CanCan chiamato CanCanCan , che sembra promettente:

CanCanCan


1
Grazie!! Ho una domanda, con CanCanCan (attivo) è risolto o non è necessario questo codice?
Adriano Resende,

Per me, CanCanCan ha ancora il problema. Non utilizzare load_resourceo utilizzare load_resource :except => :createrisolto il problema. Controlla qui la
Tun

24

Esiste un modo più semplice per evitare i parametri forti, devi solo convertire i parametri in un hash normale, come:

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

Questo ovviamente vanifica lo scopo di parametri forti, ma se ti trovi in ​​una situazione come la mia (sto facendo la mia gestione dei parametri consentiti in un'altra parte del mio sistema), questo farà il lavoro.


Non funziona in Rails 6, eccezione:unable to convert unpermitted parameters to hash
Tyler

20

Se si utilizza ActiveAdmin, non dimenticare che c'è anche un permesso_param nel blocco di registro del modello:

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

Questi devono essere impostati insieme a quelli nel controller:

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

Altrimenti otterrai l'errore:

ActiveModel::ForbiddenAttributesError

18

Per quelli che usano CanCanCan :

Questo errore verrà visualizzato se CanCanCan non è in grado di trovare il metodo params corretto .

Per l' :createazione, CanCan tenterà di inizializzare una nuova istanza con input disinfettato verificando se il controller risponderà ai seguenti metodi (in ordine):

  1. create_params
  2. <model_name>_params come article_params (questa è la convenzione predefinita in rotaie per nominare il metodo param)
  3. resource_params (un metodo di nome generico che potresti specificare in ciascun controller)

Inoltre, load_and_authorize_resourceora può prendere param_methodun'opzione per specificare un metodo personalizzato nel controller da eseguire per disinfettare l'input.

È possibile associare l' param_methodopzione a un simbolo corrispondente al nome di un metodo che verrà chiamato:

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

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


3

In alternativa puoi usare la gemma degli Attributi Protetti , tuttavia ciò vanifica lo scopo di richiedere parametri forti. Tuttavia, se stai aggiornando un'app precedente, gli Attributi protetti forniscono un percorso semplice per l'aggiornamento fino a quando non puoi trasformare l'attr_accessible in parametri forti.


0

Se sei su Rails 4 e ricevi questo errore, potrebbe accadere se stai usando enumsul modello se hai definito con simboli come questo:

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

Il modulo passerà, ad esempio un selettore radio come parametro stringa. Questo è quello che è successo nel mio caso. La semplice soluzione è passare enumalle stringhe anziché ai simboli

enum preferred_phone: %w[home_phone mobile_phone work_phone]
# or more verbose
enum preferred_phone: ['home_phone', 'mobile_phone', 'work_phone']
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.