Reputation: 3295
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+\-.]+@[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
when I run this action
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
on ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
.
Can you please tell me how to get rid of this error or establish a proper user registration form?
Upvotes: 245
Views: 229723
Reputation: 3258
One more reason is that you override permitted_params
by a method. For example
def permitted_params
params.permit(:email, :password)
end
Upvotes: 2
Reputation: 998
For those using CanCanCan:
You will get this error if CanCanCan cannot find the correct params method.
For the :create
action, CanCan will try to initialize a new instance with sanitized input by seeing if your controller will respond to the following methods (in order):
create_params
<model_name>_params
such as article_params (this is
the default convention in rails for naming your param method)resource_params
(a generically named method you could specify in
each controller)Additionally, load_and_authorize_resource
can now take a param_method
option to specify a custom method in the controller to run to sanitize input.
You can associate the param_method
option with a symbol corresponding to the name of a method that will get called:
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#33-strong-parameters
Upvotes: 29
Reputation: 11186
If you are on Rails 4 and you get this error, it could happen if you are using enum
on the model if you've defined with symbols like this:
class User
enum preferred_phone: [:home_phone, :mobile_phone, :work_phone]
end
The form will pass say a radio selector as a string param. That's what happened in my case. The simple fix is to change enum
to strings instead of symbols
enum preferred_phone: %w[home_phone mobile_phone work_phone]
# or more verbose
enum preferred_phone: ['home_phone', 'mobile_phone', 'work_phone']
Upvotes: 0
Reputation: 2749
There is an easier way to avoid the Strong Parameters at all, you just need to convert the parameters to a regular hash, as:
unlocked_params = ActiveSupport::HashWithIndifferentAccess.new(params)
model.create!(unlocked_params)
This defeats the purpose of strong parameters of course, but if you are in a situation like mine (I'm doing my own management of allowed params in another part of my system) this will get the job done.
Upvotes: 25
Reputation: 3112
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:
In the ApplicationController
:
before_filter do
resource = controller_name.singularize.to_sym
method = "#{resource}_params"
params[resource] &&= send(method) if respond_to?(method, true)
end
and in the resource controller (for example NoteController):
private
def note_params
params.require(:note).permit(:what, :ever)
end
Update:
Here's a continuation project for CanCan called CanCanCan, which looks promising:
Upvotes: 65
Reputation: 12218
If using ActiveAdmin don't forget that there is also a permit_params in the model register block:
ActiveAdmin.register Api::V1::Person do
permit_params :name, :address, :etc
end
These need to be set along with those in the controller:
def api_v1_person_params
params.require(:api_v1_person).permit(:name, :address, :etc)
end
Otherwise you will get the error:
ActiveModel::ForbiddenAttributesError
Upvotes: 24
Reputation: 343
Alternatively you can use the Protected Attributes gem, however this defeats the purpose of requiring strong params. However if you're upgrading an older app, Protected Attributes does provide an easy pathway to upgrade until such time that you can refactor the attr_accessible to strong params.
Upvotes: 3
Reputation: 6823
I guess you are using Rails 4. If so, the needed parameters must be marked as required.
You might want to do it like this:
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
Upvotes: 435