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

I have this model in ruby but it throws 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+\-.][email protected][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 версія 35410) [x86_64-linux] .

Скажіть, будь ласка, як позбутися цієї помилки або створити правильну реєстраційну форму користувача?

206
сильні параметри для використання attr_accessible ?!
додано Автор Thiem Nguyen, джерело
Додати strong_parameter gem для використання attr_accessible .
додано Автор Wenbing Li, джерело
спробуйте додати attr_accessible: password,: password_confirmation,: user_name,: email,: your-other-attributes в моделі користувача
додано Автор Bachan Smruty, джерело
Я вважаю, що @BruceLi мав на увазі: додайте gem protected_attributes для використання attr_accessible .
додано Автор Stefan Magnuson, джерело

7 Відповіді

Думаю, ви використовуєте 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
374
додано
@Domon відмінно працював.
додано Автор Michael Roberts, джерело
Чи є документація про те, чому це працює або чому це потрібно?
додано Автор Omar Jackman, джерело
@mjnissim Будь ласка, напишіть це як окрему відповідь? Я пропустив це перший час наскрізь, але це досі врятувало мені тонна часу.
додано Автор Paul Pettengill, джерело
Можливо, люди відчувають це, якщо використовують CanCan з Rails 4.0. Спробуйте AntonTrapps достатньо очистити рішення, поки CanCan не буде оновлено.
додано Автор mjnissim, джерело
@OmarJackman Функціональність забезпечується gem strong_parameter . Він висвітлюється у довідниках Rails: guides.rubyonrails.org/… .
додано Автор Domon, джерело

For those using CanCan. People might be experiencing this if they use CanCan with Rails 4+. Try AntonTrapps's rather clean workaround solution here until CanCan gets updated:

У 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

63
додано
Дякую!! У мене є питання, з CanCanCan (активний) вирішується або не потрібен цей код?
додано Автор Adriano Resende, джерело

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

unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)

model.create!(unlocked_params)

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

22
додано
Це також не працює для мене, я занадто заплутаний прямо зараз ...
додано Автор Zia Ul Rehman Mughal, джерело
Це саме те, що мені потрібно. Дякую!
додано Автор Chris Scott, джерело

Якщо ви використовуєте 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
19
додано

Для користувачів, які використовують CanCanCan :

Ви отримаєте цю помилку, якщо CanCanCan не зможе знайти правильний метод params .

Для дії : create CanCan намагатиметься ініціалізувати новий екземпляр з дезактивованим входом, переконавшись, що ваш контролер відповість на такі методи (в порядку):

  1. create_params
  2. _params such as article_params (this is the default convention in rails for naming your param method)
  3. resource_params (a generically named method you could specify in each controller)

Крім того, 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

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

8
додано

Крім того, ви можете скористатися знаком із захищеними атрибутами , однак це призводить до втрати цільового призначення. Однак, якщо ви оновлюєте старі програми, Protected Attributes надає простий шлях до оновлення до тих пір, поки ви не зможете рефактувати attr_accessible до сильних параметрів.

3
додано

Привіт у моєму випадку помилка виправлена, але отримання порожнього результату - це база даних.

 def create
@worklog = Worklog.new(user_params)
@worklog.day = Date.today
@worklog.week = Date.today.strftime("%W").to_i
@worklog.author = User.current
@worklog.save
redirect_to worklogs_path()
 end

 def user_params
params.require(:worklog).permit(:utf8, :authenticity_token, {:worklog => [:typee, :do, :todo, :feel, :plan_done, :plan, :week_feel, :score, :good, :nogood]}, :commit)

}

My orginal plugin is https://github.com/IceskYsl/worklogs

1
додано