ActiveModel :: ForbiddenAttributesError saat membuat pengguna baru

223

Saya memiliki model ini di Ruby tetapi melempar a 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

ketika saya menjalankan tindakan ini

  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

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

Bisakah Anda memberi tahu saya cara menghilangkan kesalahan ini atau membuat formulir pendaftaran pengguna yang tepat?

LeMike
sumber
2
coba dengan menambahkan attr_accessible: password
,: password_confirmation,: user_name,: email,:
1
Tambahkan permata strong_parameter untuk menggunakan attr_accessible .
Wenbing Li
parameter kuat untuk menggunakan attr_accessible ?!
Thiem Nguyen
1
Saya percaya @BruceLi berarti: Tambahkan protected_attributespermata untuk digunakan attr_accessible.
Stefan Magnuson

Jawaban:

398

Saya kira Anda menggunakan Rails 4. Jika demikian, parameter yang diperlukan harus ditandai sesuai kebutuhan.

Anda mungkin ingin melakukannya seperti ini:

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
sumber
2
Apakah ada dokumentasi tentang mengapa ini berhasil atau mengapa ini diperlukan?
DiverseAndRemote.com
20
@OmarJackman Fungsionalitas disediakan oleh strong_parameterpermata. Hal ini tercakup dalam Rails Guides: guides.rubyonrails.org/… .
Domon
21
Orang-orang mungkin mengalami ini jika mereka menggunakan CanCan dengan Rails 4.0. Coba solusi penyelesaian AntonTrapps yang agak bersih hingga CanCan diperbarui.
mjnissim
@ mjnissim Tolong posting ini sebagai jawaban terpisah? Saya melewatkannya pertama kali, tetapi masih menghemat banyak waktu.
Paul Pettengill
64

Bagi yang menggunakan CanCan . Orang-orang mungkin mengalami ini jika mereka menggunakan CanCan dengan Rails 4+ . Coba solusi penyelesaian AntonTrapps yang agak bersih di sini sampai CanCan diperbarui:

Dalam ApplicationController:

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

dan di pengontrol sumber daya (misalnya NoteController):

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

Memperbarui:

Berikut adalah proyek lanjutan untuk CanCan yang disebut CanCanCan , yang terlihat menjanjikan:

CanCanCan

mjnissim
sumber
1
Terima kasih!! Saya punya pertanyaan, dengan CanCanCan (aktif) terpecahkan atau tidak perlu kode ini?
Adriano Resende
Bagi saya, CanCanCan masih memiliki masalah. Tidak menggunakan load_resourceatau menggunakan load_resource :except => :creatememecahkan masalah. Periksa jawaban asli di sini
Tun
24

Ada cara yang lebih mudah untuk menghindari Parameter Kuat sama sekali, Anda hanya perlu mengubah parameter ke hash biasa, seperti:

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

Ini mengalahkan tujuan parameter yang kuat tentu saja, tetapi jika Anda berada dalam situasi seperti milik saya (saya melakukan manajemen saya sendiri dari params yang diizinkan di bagian lain dari sistem saya) ini akan menyelesaikan pekerjaan.

Wilker Lucio
sumber
Tidak berfungsi di rel 6, kecuali:unable to convert unpermitted parameters to hash
Tyler
20

Jika menggunakan ActiveAdmin jangan lupa bahwa ada juga permit_params di blok register model:

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

Ini perlu diatur bersama dengan yang ada di controller:

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

Kalau tidak, Anda akan mendapatkan kesalahan:

ActiveModel::ForbiddenAttributesError
StuR
sumber
18

Bagi mereka yang menggunakan CanCanCan :

Anda akan mendapatkan kesalahan ini jika CanCanCan tidak dapat menemukan metode params yang benar .

Untuk :createtindakan tersebut, CanCan akan mencoba menginisialisasi instance baru dengan input yang disanitasi dengan melihat apakah controller Anda akan merespons metode berikut (secara berurutan):

  1. create_params
  2. <model_name>_params seperti article_params (ini adalah konvensi default di rails untuk memberi nama metode param Anda)
  3. resource_params (metode yang diberi nama umum yang dapat Anda tentukan di setiap pengontrol)

Selain itu, load_and_authorize_resourcesekarang dapat mengambil param_methodopsi untuk menentukan metode kustom di controller untuk menjalankan untuk membersihkan input.

Anda dapat mengaitkan param_methodopsi dengan simbol yang sesuai dengan nama metode yang akan dipanggil:

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

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

Andreas
sumber
3

Atau Anda dapat menggunakan permata Atribut Terlindungi , namun ini mengalahkan tujuan yang membutuhkan params yang kuat. Namun jika Anda memutakhirkan aplikasi yang lebih lama, Atribut Terlindungi memang menyediakan jalur mudah untuk memutakhirkan hingga Anda dapat mengubah attr_accessible menjadi params yang kuat.

Brian Dear
sumber
0

Jika Anda menggunakan Rails 4 dan Anda mendapatkan kesalahan ini, itu bisa terjadi jika Anda menggunakan enumpada model jika Anda telah mendefinisikan dengan simbol seperti ini:

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

Formulir akan lulus katakanlah pemilih radio sebagai param string. Itulah yang terjadi dalam kasus saya. Perbaikan sederhana adalah mengubah enumstring bukan simbol

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