Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 5.1 - JSON parameter is permitted but still prints as unpermitted in the log

In Rails 4 here is the question about HOW to do this. What I would like to know is, although this works, WHY does the log still complain?

In Rails 5.1.3 I have a JSON column (letterhead) as one of my model attributes (and inside that json is a hash with various attributes that I don't care about whitelisting). I just want to permit/whitelist the column itself.

Note on Rails 5.1.4

There is a Rails way to do this in 5.1.4, see this commit. There is a rather long discussion here on github about this. In Rails 5.1.4 it is simply this:

def account_params
  params.require(:account).permit(:id, :name, :plan_id, letterhead: {})
end

The :letterhead parameter is permitted, no error shows in the log and the model saves. But obviously it allows arbitrary input inside that parameter, so use with care.

If you did want to restrict which hash keys were allowed inside such a parameter, then you can also whitelist those, like this for example:

def account_params
  params.require(:account).permit(:id, :name, :plan_id, letterhead: [:address, :logo, :contact_info])
end

This now prevents any other arbitrary keys inside :letterhead since I have explicitly only permitted these 3 - :address, :logo, :contact_info

Rails 5.1.3 (and earlier)

I can permit this column using either of the following (see the linked discussion for other possible options also):

Option 1

def account_params
  params.require(:account).permit(:id, :name, :plan_id, :letterhead).tap do |whitelisted|
    whitelisted[:letterhead] = params[:account].fetch(:letterhead, ActionController::Parameters.new).permit!
  end
end

Option 2

def account_params
  params.require(:account).permit(:id, :name, :plan_id, :letterhead).tap do |whitelisted|
    whitelisted[:letterhead] = params[:account][:letterhead].permit!
  end
end

In both cases the model saves but in the log it still says "unpermitted parameters :letterhead"

  1. Why is still saying that when I have explicitly permitted it?

  2. Also, is there any real difference between Option 1 and Option 2?

EDIT

Data is like this:

{"id"=>"a61151b8-deed-4efa-8cad-da1b143196c9", 
"plan_id"=>"1dc49acf-3111-4030-aea1-7db259b53a51", 
"name"=>"Test Account 1", 
"is_active"=>true, 
"letterhead"=>{"left"=>"", "center"=>"", "right"=>""}, 
"created_by"=>nil, 
"updated_by"=>nil, 
"created_at"=>"2017-10-14T19:05:40.197Z", 
"updated_at"=>"2017-10-20T15:14:08.194Z"}
like image 415
rmcsharry Avatar asked Oct 20 '17 13:10

rmcsharry


1 Answers

Why is still saying that when I have explicitly permitted it?

The log comes from #unpermitted_parameters! which is called by #permit. All this happens before the call to #tap.

Is there any real difference between Option 1 and Option 2?

The difference boils down to

params[:account].fetch(:letterhead, ActionController::Parameters.new).permit!

vs

params[:account][:letterhead].permit!

The latter will result in NoMethodError if :letterhead isn't passed because params[:account][:letterhead] will return nil. The former returns an empty hash of parameters instead.

like image 156
Greg Navis Avatar answered Nov 02 '22 23:11

Greg Navis