ActiveModel :: ForbiddenAttributesError при створенні нового користувача


223

У мене є модель в Ruby, але вона кидає 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: пароль,: підтвердження пароля,: ім'я користувача
,: електронна пошта,:

1
Додайте strong_parameter gem, щоб використовувати attr_accessible .
Венбінг Лі

сильні параметри для використання attr_accessible ?!
Тіем Нгуен

1
Я вважаю, що @BruceLi означав: Додайте protected_attributesдорогоцінний камінь для використання attr_accessible.
Стефан Магнусон

Відповіді:


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самоцвіт. Він висвітлюється в Посібниках по рейках: guides.rubyonrails.org/… .
Домон

21
Люди можуть відчувати це, якщо вони використовують CanCan з Rails 4.0. Спробуйте AntonTrapps в досить чисте рішення тимчасового рішення , поки CanCan не оновлюється.
mjnissim

@mjnissim Чи можете ви опублікувати це як окрему відповідь? Я пропустив це вперше, але це все-таки врятувало мені тонну часу.
Пол Петтенгілл

64

Для тих, хто використовує CanCan . Люди можуть відчувати це, якщо вони використовують CanCan з Rails 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 (активно) вирішено чи не потрібен цей код?
Адріано Ресенде

Для мене проблема CanCanCan все ще є. Не використовуючи load_resourceта не load_resource :except => :createвирішуючи проблему. Ознайомтесь з оригінальною відповіддю тут
Tun

24

Існує простіший спосіб уникнути сильних параметрів взагалі, вам просто потрібно перетворити параметри в звичайний хеш, як:

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

Це, звичайно, перемагає призначення сильних параметрів, але якщо ви опинилися в такій ситуації, як моя (я займаюся власним управлінням дозволеними парамами в іншій частині моєї системи), це дозволить виконати роботу.


Не працює в рейках 6, виняток:unable to convert unpermitted parameters to hash
Тайлер

20

Якщо ви використовуєте ActiveAdmin, не забувайте, що в блоці регістру моделі також є дозвіл_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 не зможе знайти правильний метод парам .

Для цього :createCanCan спробує ініціалізувати новий екземпляр із санітарним входом, побачивши, чи відповість ваш контролер на такі методи (по порядку):

  1. create_params
  2. <model_name>_params наприклад, Article_params (це умовна умова в рейках для назви вашого методу param)
  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

Крім того, ви можете використовувати дорогоцінний камінь Protected Attributes , однак це перемагає мету вимагати сильних парам. Однак якщо ви оновлюєте більш старий додаток, захищені атрибути забезпечують простий шлях до оновлення до тих пір, поки ви не зможете повторно змінити 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']
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.