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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top