Josh
Josh

Reputation: 676

How do you use Rails 5.2 wrap_parameters?

I have a Rails 5.2 app built as API only. I am using Postman to test the endpoints. Currently, I am wrapping all of my JSON POSTS with the root element in order to get it to pass the 'strong parameters'. According to the Rails docs, however, with wrap_parameters set to accept JSON, I shouldn't have to be doing this, however, my POSTs fail if I don't. What am I doing wrong?


# users_controller.rb

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :update, :destroy]

  .....

  # POST /users
  def create
    @user = User.new(user_params)

    if @user.save
      render json: @user, status: :created, location: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  .....

  private
  .....

    # Only allow a trusted parameter "white list" through.
    def user_params
      params.require(:user).permit(:email, :password, :is_admin, :is_agent)
    end
end

# config/initializers/wrap_parameters.rb

ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json]
end

enter image description here

If I wrap the JSON in a user it works just fine, however, according to the Rails docs, I shouldn't have to do that.

http://api.rubyonrails.org/v5.2.0/classes/ActionController/ParamsWrapper.html

I have tried adding wrap_parameters User and wrap_parameters :user and wrap_parameters format: [:json] directly to the users_controller.rb but that doesn't do anything.

What am I doing wrong?

Upvotes: 7

Views: 6018

Answers (2)

Josh
Josh

Reputation: 676

I figured it out. I had to add wrap_parameters :user, include: %i[email password is_admin is_agent] to the Users controller like so:

# users_controller.rb

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :update, :destroy]

  wrap_parameters :user, include: %i[email password is_admin is_agent]

  .....

  # POST /users
  def create
    @user = User.new(user_params)

    if @user.save
      render json: @user, status: :created, location: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  .....

  private
  .....

    # Only allow a trusted parameter "white list" through.
    def user_params
      params.require(:user).permit(:email, :password, :is_admin, :is_agent)
    end
end

I still don't fully understand why, but, it works. The docs imply this should be happening automagically through the wrap parameters module.

Upvotes: 5

Chakreshwar Sharma
Chakreshwar Sharma

Reputation: 2610

This is because of the parameter whitelisting.

 def user_params
   params.require(:user).permit(:email, :password, :is_admin, :is_agent)
 end

Here , user key is required. As per the security point of view, its a good feature in RoR to whitelist the parameters

If you write only params.permit(:email, :password, :is_admin, :is_agent) , then you same request will work but removing the user object is not recommended.

Upvotes: 0

Related Questions