ActiveModel :: ForbiddenAttributesError podczas tworzenia nowego użytkownika

223

Mam ten model w Ruby, ale rzuca 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

kiedy uruchamiam tę akcję

  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

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

Czy możesz mi powiedzieć, jak pozbyć się tego błędu lub ustalić odpowiedni formularz rejestracyjny użytkownika?

LeMike
źródło
2
spróbuj dodać attr_accessible: hasło
,: potwierdzenie_ hasła,: nazwa_użytkownika,:
1
Dodaj klejnot strong_parameter, aby użyć attr_accessible .
Wenbing Li
mocne parametry do użycia attr_accessible ?!
Thiem Nguyen,
1
Uważam, że @BruceLi oznaczało: Dodaj protected_attributesklejnot do użycia attr_accessible.
Stefan Magnuson

Odpowiedzi:

398

Wydaje mi się, że używasz Rails 4. Jeśli tak, wymagane parametry należy oznaczyć jako wymagane.

Możesz to zrobić w ten sposób:

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
źródło
2
Czy istnieje dokumentacja dotycząca tego, dlaczego to działa lub dlaczego jest to potrzebne?
DiverseAndRemote.com
20
@OmarJackman Funkcję zapewnia strong_parameterklejnot. Jest to omówione w Rails Guides: guide.rubyonrails.org/… .
Domon,
21
Ludzie mogą tego doświadczyć, jeśli używają CanCan z Rails 4.0. Wypróbuj raczej czyste rozwiązanie obejścia firmy AntonTrapps, dopóki CanCan nie zostanie zaktualizowany.
mjnissim
@mjnissim Czy mógłbyś zamieścić to jako osobną odpowiedź? Tęskniłem za pierwszym razem, ale wciąż oszczędzało mi to mnóstwo czasu.
Paul Pettengill,
64

Dla osób używających CanCan . Ludzie mogą tego doświadczyć, jeśli używają CanCan z Railsami 4+ . Spróbuj AntonTrapps jest raczej czystą obejście problemu tutaj aż CanCan zostanie zaktualizowany:

W ApplicationController:

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

oraz w kontrolerze zasobów (na przykład NoteController):

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

Aktualizacja:

Oto kontynuacja projektu CanCan o nazwie CanCanCan , która wygląda obiecująco:

CanCanCan

mjnissim
źródło
1
Dzięki!! Mam pytanie, czy CanCanCan (aktywny) jest rozwiązany czy nie potrzebujesz tego kodu?
Adriano Resende
Dla mnie CanCanCan nadal ma problem. Nieużywanie load_resourcelub używanie load_resource :except => :createrozwiązało problem. Sprawdź oryginalną odpowiedź tutaj
Tun
24

Jest łatwiejszy sposób na uniknięcie Mocnych parametrów, wystarczy przekonwertować parametry na zwykły skrót, ponieważ:

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

To oczywiście niweczy cel silnych parametrów, ale jeśli jesteś w sytuacji takiej jak moja (ja sam zarządzam dozwolonymi parametrami w innej części mojego systemu), to załatwi sprawę.

Wilker Lucio
źródło
Nie działa w szynach 6, wyjątek:unable to convert unpermitted parameters to hash
Tyler
20

Jeśli korzystasz z ActiveAdmin, nie zapomnij, że w bloku rejestru modelu znajdują się także parametry perm_params

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

Należy je ustawić razem z tymi w kontrolerze:

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

W przeciwnym razie pojawi się błąd:

ActiveModel::ForbiddenAttributesError
StuR
źródło
18

Dla osób używających CanCanCan :

Ten błąd pojawi się, jeśli CanCanCan nie będzie w stanie znaleźć właściwej metody params .

W przypadku :createakcji CanCan spróbuje zainicjować nową instancję z dezynfekowanym wejściem, sprawdzając, czy kontroler zareaguje na następujące metody (w kolejności):

  1. create_params
  2. <model_name>_params na przykład article_params (jest to domyślna konwencja w szynach do nazywania twojej metody param)
  3. resource_params (ogólna nazwa metody, którą można określić w każdym kontrolerze)

Ponadto load_and_authorize_resourcemożna teraz wybrać param_methodopcję określenia niestandardowej metody w kontrolerze, aby uruchomić w celu dezynfekcji danych wejściowych.

Możesz powiązać param_methodopcję z symbolem odpowiadającym nazwie metody, która zostanie wywołana:

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

źródło: https://github.com/CanCanCommunity/cancancan#33-strong-parameters

Andreas
źródło
3

Alternatywnie możesz użyć klejnotu Chronione Atrybuty , ale to nie wystarcza, aby wymagać silnych parametrów. Jeśli jednak aktualizujesz starszą aplikację, Chronione Atrybuty zapewniają łatwą ścieżkę aktualizacji do czasu, kiedy będziesz mógł zmienić atrybut attr_accessible na silne parametry.

Brian Drogi
źródło
0

Jeśli korzystasz z Rails 4 i pojawia się ten błąd, może się to zdarzyć, jeśli korzystasz enumz modelu, jeśli zdefiniowałeś za pomocą takich symboli:

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

Formularz przejdzie powiedz selektor radia jako parametr ciągu. Tak się stało w moim przypadku. Prostym rozwiązaniem jest zmiana enumna ciągi zamiast symboli

enum preferred_phone: %w[home_phone mobile_phone work_phone]
# or more verbose
enum preferred_phone: ['home_phone', 'mobile_phone', 'work_phone']
lacostenycoder
źródło