I am using Rails 4.0.2, Ruby 2.0.0p353
I am trying to use strong parameters in my Rails project but I can't get the ActiveModel::ForbiddenAttributesError to appear.
If there are params that are not permitted, those params will be set to nil or 0, but I thought that the error ActiveModel::ForbiddenAttributesError should appear. So as a result, params that are not permitted by the strong parameters will be passed into my User model as nil or 0 and this is a problem for me.
Below is the following for my UsersController:
class UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
sign_in @user
flash[:notice] = "Welcome to the league!"
redirect_to root_url
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :alias,
:email, :password, :password_confirmation)
end
end
Here is the User sign-up form using, simple_form 3.0.1, new.html.erb:
<%= simple_form_for(@user) do |f| %>
<h1>Sign Up</h1>
<%= f.input :first_name %>
<%= f.input :last_name %>
<%= f.input :alias %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
<%= f.button :submit, class: "btn-lg btn-primary" %>
<% end %>
And here are the validations for my User model user.rb:
class User < ActiveRecord::Base
...
# Validations
validates :first_name, presence: true, length: { maximum: MAX_LENGTH_FIRST_NAME }
validates :last_name, presence: true, length: { maximum: MAX_LENGTH_LAST_NAME }
validates :alias, presence: true
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: MIN_LENGTH_PASSWORD }
...
end
Now let's say that I remove :alias from user_params like so:
private
def user_params
params.require(:user).permit(:first_name, :last_name,
:email, :password, :password_confirmation)
end
From my understanding, if there is an :alias hash (or any other hash) in my :user params, then I should get the ActiveModel::ForbiddenAttributesError to appear.
So what I have tried is removing :alias from from user_params and keeping alias on the user sign up form so that I can have :alias in user_params to raise the error. In order to keep it on my form and be able to submit it, I had to comment out my alias validation in my model to like so:
# validates :alias, presence: true
But when I create a new user with all of the fields, including alias, no error appears. Instead, I create a new user in the database with all of the information, but the alias attribute is nil no matter what I entered on the form.
If anyone could tell me how to have unpermitted params raise an exception, please let me know.
Thanks in advance.
*EDIT*
The reason I posted this was actually for an update_attributes().
My issue was that I was trying to update only 3 (out of 5) of a user's attributes. I tried to make strong parameters to make sure that only those 3 attributes were being updated and nothing else, but I guess that is the wrong way to do it.
Thanks again to Brian for the clarification on the error and how it is actually raised.
Nope, ActiveModel::ForbiddenAttributesError
is only raised if you pass unsanitized objects to the record update call.
@user.update_attributes(params[:user]) # This would be an issue
User.where(params[:user]) # This would not
@user.update_attributes(user_params) # Neither would this
def user_params
params.require(:user).permit(:name)
end
It can actually be kind of a pain, because if you forget to explicitly include an attribute, say, after a db migration, this can be a sneaky bug.
Judging by this snippet from the documentation
params = ActionController::Parameters.new(user: { name: 'Francesco', age: 22, role: 'admin' })
permitted = params.require(:user).permit(:name, :age)
permitted.permitted? # => true
permitted.has_key?(:name) # => true
permitted.has_key?(:age) # => true
permitted.has_key?(:role) # => false
If you really wanted an exception you could just write
ActionController::Parameters.action_on_unpermitted_parameters = :raise