ActiveModel :: ForbiddenAttributesError เมื่อสร้างผู้ใช้ใหม่


223

ฉันมีโมเดลนี้ใน Ruby แต่มันพ่น 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

เมื่อฉันเรียกใช้การกระทำนี้

  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

ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]บน

คุณช่วยบอกวิธีกำจัดข้อผิดพลาดนี้หรือสร้างแบบฟอร์มลงทะเบียนผู้ใช้ที่เหมาะสมได้ไหม


2
ลองเพิ่ม attr_accessible: รหัสผ่าน,: password_confirmation,: ชื่อผู้ใช้,:, อีเมล์,: your-other-attributes ในรุ่นผู้ใช้
Bachan Smruty

1
เพิ่มstrong_parameterอัญมณีกับการใช้attr_accessible
Wenbing Li

พารามิเตอร์ที่แข็งแกร่งในการใช้ attr_accessible ?!
Thiem Nguyen

1
ผมเชื่อว่า @BruceLi หมาย: เพิ่มอัญมณีกับการใช้งานprotected_attributes attr_accessible
Stefan Magnuson

คำตอบ:


398

ฉันเดาว่าคุณกำลังใช้ Rails 4 อยู่ถ้าเป็นเช่นนั้นพารามิเตอร์ที่จำเป็นต้องทำเครื่องหมายตามต้องการ

คุณอาจต้องการทำสิ่งนี้:

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
มีเอกสารใดบ้างเกี่ยวกับสาเหตุที่ใช้งานได้หรือทำไมจึงจำเป็นต้องใช้?
DiverseAndRemote.com

20
@OmarJackman การทำงานที่ให้บริการโดยstrong_parameterอัญมณี มันถูกปกคลุมในคู่มือการ Rails: guides.rubyonrails.org/...
Domon

21
ผู้คนอาจประสบกับสิ่งนี้หากพวกเขาใช้CanCanกับ Rails 4.0 ลองวิธีแก้ปัญหาที่ค่อนข้างชัดเจนของ AntonTrappsจนกว่า CanCan จะได้รับการอัปเดต
mjnissim

@mjnissim คุณช่วยกรุณาโพสต์คำตอบนี้เป็นคำตอบแยกต่างหากได้ไหม ฉันพลาดมันเป็นครั้งแรกผ่านไป แต่มันก็ยังช่วยฉันได้หลายครั้ง
Paul Pettengill

64

สำหรับผู้ที่ใช้ Cancan คนอาจจะประสบนี้หากพวกเขาใช้Cancanกับทางรถไฟ 4+ ลองวิธีแก้ปัญหาที่ค่อนข้างชัดเจนของ AntonTrapps ที่นี่จนกว่า CanCan จะได้รับการอัปเดต:

ในApplicationController:

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

และในตัวควบคุมทรัพยากร (ตัวอย่างเช่น NoteController):

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

ปรับปรุง:

นี่คือโครงการต่อเนื่องสำหรับ CanCan ชื่อCanCanCanซึ่งดูมีแนวโน้ม:

CanCanCan


1
ขอบคุณ !! ฉันมีคำถามด้วย CanCanCan (ใช้งานอยู่) ได้รับการแก้ไขหรือไม่จำเป็นต้องใช้รหัสนี้หรือไม่?
Adriano Resende

สำหรับฉัน CanCanCan ยังคงมีปัญหา ไม่ใช้load_resourceหรือใช้load_resource :except => :createแก้ไขปัญหา ตรวจสอบคำตอบต้นฉบับที่นี่
Tun

24

มีวิธีที่ง่ายกว่าในการหลีกเลี่ยงพารามิเตอร์ที่แข็งแกร่งเลยคุณเพียงแค่แปลงพารามิเตอร์เป็นแฮชปกติเนื่องจาก:

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

สิ่งนี้เอาชนะจุดประสงค์ของพารามิเตอร์ที่แข็งแกร่งอย่างแน่นอน แต่ถ้าคุณอยู่ในสถานการณ์เช่นของฉัน (ฉันกำลังจัดการ params ที่อนุญาตในส่วนอื่นของระบบของฉัน) สิ่งนี้จะทำให้งานสำเร็จ


ไม่ทำงานในราง 6 ยกเว้น:unable to convert unpermitted parameters to hash
Tyler

20

หากใช้ ActiveAdmin อย่าลืมว่ามี allow_params ในบล็อกการลงทะเบียนโมเดลด้วย:

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

จำเป็นต้องตั้งค่าเหล่านี้พร้อมกับที่อยู่ในคอนโทรลเลอร์:

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

มิฉะนั้นคุณจะได้รับข้อผิดพลาด:

ActiveModel::ForbiddenAttributesError

18

สำหรับผู้ใช้CanCanCan :

คุณจะได้รับข้อผิดพลาดนี้หาก CanCanCan ไม่สามารถหาวิธีการพารามิเตอร์ที่ถูกต้องวิธี

สำหรับการ:createดำเนินการ CanCan จะพยายามเริ่มต้นอินสแตนซ์ใหม่ด้วยอินพุตที่ถูกสุขลักษณะโดยดูว่าตัวควบคุมของคุณจะตอบสนองต่อวิธีการต่อไปนี้ (ตามลำดับ):

  1. create_params
  2. <model_name>_params เช่น article_params (นี่เป็นแบบแผนเริ่มต้นในทางรถไฟสำหรับการตั้งชื่อวิธีการพารามิเตอร์ของคุณ)
  3. resource_params (วิธีการตั้งชื่อทั่วไปที่คุณสามารถระบุในแต่ละคอนโทรลเลอร์)

นอกจากload_and_authorize_resourceนี้ขณะนี้สามารถใช้param_methodตัวเลือกเพื่อระบุวิธีการที่กำหนดเองในตัวควบคุมเพื่อเรียกใช้เพื่อฆ่าเชื้ออินพุต

คุณสามารถเชื่อมโยงparam_methodตัวเลือกกับสัญลักษณ์ที่สอดคล้องกับชื่อของวิธีการที่จะได้รับเรียก:

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

แหล่งที่มา: https://github.com/CanCanCommunity/cancancan#33-strong-parameters


3

หรือคุณสามารถใช้อัญมณีที่ได้รับการป้องกันได้ แต่สิ่งนี้จะเอาชนะจุดประสงค์ของการเรียกใช้พารามิเตอร์ที่แข็งแกร่ง อย่างไรก็ตามหากคุณกำลังอัพเกรดแอปรุ่นเก่าแอตทริบิวต์ที่ได้รับการป้องกันจะให้เส้นทางที่ง่ายในการอัปเกรดจนกว่าจะถึงเวลาที่คุณสามารถปรับโครงสร้าง attr_accessible เป็นพารามิเตอร์ที่แข็งแกร่ง


0

หากคุณใช้งาน Rails 4 และคุณได้รับข้อผิดพลาดนี้อาจเกิดขึ้นได้หากคุณใช้enumกับโมเดลหากคุณกำหนดด้วยสัญลักษณ์แบบนี้:

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

แบบฟอร์มจะผ่านการพูดว่าตัวเลือกวิทยุเป็นพารามิเตอร์สตริง นั่นคือสิ่งที่เกิดขึ้นในกรณีของฉัน การแก้ไขอย่างง่ายคือการเปลี่ยนenumเป็นสตริงแทนสัญลักษณ์

enum preferred_phone: %w[home_phone mobile_phone work_phone]
# or more verbose
enum preferred_phone: ['home_phone', 'mobile_phone', 'work_phone']
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.