Reputation: 3998
I need a way to modify the params hash. I tried a couple of things but none of it actually worked.
Unpermitted parameters: :players, :leaders
Params
{"utf8"=>"✓", "authenticity_token"=>"asa", "user"=>{"first_name"=>"anikeeet", "last_name"=>"tiwariii", "friend_attributes"=>{"players"=>"50589,50590", "leaders"=>"16,6,18", "phone_number"=>"", "title"=>"aasdassd", "role"=>"abcdef"}}}
I tried this way
(friend_params.dig(:friend_attributes) || []).each do |_, attributes|
attributes['players'] = attributes['players'].split(',').map(&:to_i)
attributes['leaders'] = attributes['leaders'].split(',').map(&:to_i)
end
this way
(friend_params.dig(:friend_attributes) || []).each do |key, val|
friend_params["friend_attributes"]["#{key}"] = val.split(',').map(&:to_i) if key == 'players' || key == 'leaders'
end
this way
(params.dig(:user, :friend_attributes) || []).each do |key, val|
params["user"]["friend_attributes"]["#{key}"] = val.split(',').map(&:to_i) if key == 'players' || key == 'leaders'
end
and this way
if (attributes = params.dig(:user, :friend_attributes))
%i[players leaders].each do |key|
next unless attributes.has_key?(key)
attributes[key] = attributes[key].split(',').map(&:to_i)
end
end
But none of the ways worked for me. I am sharing my full controller code
class FriendsController < ApplicationController
def update
# (friend_params.dig(:friend_attributes) || []).each do |_, attributes|
# attributes['players'] = attributes['players'].split(',').map(&:to_i)
# attributes['leaders'] = attributes['leaders'].split(',').map(&:to_i)
# end
# (friend_params.dig(:friend_attributes) || []).each do |key, val|
# friend_params["friend_attributes"]["#{key}"] = val.split(',').map(&:to_i) if key == 'players' || key == 'leaders'
# end
# (params.dig(:user, :friend_attributes) || []).each do |key, val|
# params["user"]["friend_attributes"]["#{key}"] = val.split(',').map(&:to_i) if key == 'players' || key == 'leaders'
# end
if (attributes = params.dig(:user, :friend_attributes))
%i[players leaders].each do |key|
next unless attributes.has_key?(key)
attributes[key] = attributes[key].split(',').map(&:to_i)
end
end
if current_user.update(friend_params)
render json: { success: true }
else
render json: {error: "something went wrong"}
end
end
private
def friend_params
params.require(:user).permit(:first_name, :last_name, friend_attributes: [:phone_number, :title, :role, :players, :leaders])
end
end
Association
Class User < ApplicationRecord
has_one :friend, foreign_key: :user_id, dependent: :destroy
accepts_nested_attributes_for :friend
end
class Friend < ApplicationRecord
self.table_name = 'schema.friends'
belongs_to :user
end
players and leaders are the array field stored in friends table Can anyone tell what I am doing wrong?
Upvotes: 2
Views: 2463
Reputation: 21120
Something like this would do the job:
if (attributes = params.dig(:user, :friend_attributes))
%i[players leaders].each do |key|
next unless attributes.has_key?(key)
attributes[key] = attributes[key].split(',').map(&:to_i)
end
end
The problem currently lies in (friend_params.dig(:friend_attributes) || []).each
which loops though the key-value pairs, or if not present through an empty array. You then call the #[]
method on the value (which is a string). eg. "50589,50590"['players']
tries the find the substring 'players'
inside "50589,50590"
the result of this should be nil
. Followed by an "NoMethodError: undefined method `split' for nil:NilClass" exception.
You should simply use the returned collection, rather than looping through the key-value pairs.
The better question is, why do you need to transform your parameters at all?
Can't the view be arranged in such a way to provide the parameters in array format?
<input name="user[friend_attributes][players][]" type="checkbox" value="1" />
<input name="user[friend_attributes][players][]" type="checkbox" value="2" />
<input name="user[friend_attributes][players][]" type="checkbox" value="3" />
Would send an array of numbers to the controller to start with, eliminating the need to convert parameters into the correct format.
Note: If you supply the parameters in the above format you should update your permited params to:
params.require(:user).permit(:first_name, :last_name, friend_attributes: [:phone_number, :title, :role, players: [], leaders: []])
# players and leaders are now expecting an array instead of a scalar value
Upvotes: 2
Reputation: 1
Your params are hash, require and permit method are instance method of ActionController::Parameters. Also you try dig by symbol instead string.
params.dig('user', 'friend_attributes')
Or if you want to continue using the symbol you can write it like this
params.with_indifferent_access.dig(:user, :friend_attributes)
Please, read more about with_indifferent_access method.
:)
Upvotes: 0