Reputation: 303
Getting this error when trying to call the method validate_create_action. The error occurs on the line @element = klass.new(params[:element]).
NoMethodError in Analyses::MitigationMatricesController#validate_create_action
undefined method `map' for #<ActionController::Parameters {"0"=>{"phase"=>"Launch", "reason"=>"test"}} permitted: false>
Did you mean? tap
Extracted source (around line #7):
#5 class ManyEmbeddedProxy < EmbeddedCollection
#6 def replace(values)
*7 @_values = (values || []).compact.map do |v|
#8 v.respond_to?(:attributes) ? v.attributes : v
#9 end
#10 reset
In the post request the element object below is sent to the backend. The issue seems to be the array critical_phases.
element[applicable_during][critical_phases][0][phase] "Launch"
element[applicable_during][critical_phases][0][reason] "test"
If I add the method to_unsafe_h to params[:element].to_unsafe_h I get a different error involving the critical_phases array saying "TypeError: no implicit conversion of String into Integer". Any ideas on how to solve this?
element_controller.rb
def validate_create_action
rejigger_dynamic_lists
remove_associations_from_params
@element = klass.new(params[:element])
...
def klass
unless @klass
klass_str = params[:controller].split("/").last.singularize.camelize
namespace_str = SITE_CONFIG['adaptation_name'].camelize
@klass = "#{namespace_str}::#{klass_str}".constantize
end
@klass
end
UPDATE:
I updated my code to the working code params[:element].permit!
params2 = ActionController::Parameters.new(params[:element][:applicable_during][:critical_phases].to_h)
params2.permit!
params[:element][:applicable_during][:critical_phases] = params2.values.map do |h|
ActionController::Parameters.new(h.permit!.to_h).permit(:phase, :reason) # use permit! instead if you want to live dangerously
test_mapping = {}
end
Upvotes: 1
Views: 1301
Reputation: 102001
The problem here is that it the parameters aren't actually an array. Its a hash with the keys "0", "1" etc. This is done to avoid the potential ambigiuty thats happens when Rack parses form data keys containing arrays of hashes:
irb(main):015:0> Rack::Utils.parse_nested_query("foo[][bar]=1&foo[][bar]=2")
=> {"foo"=>[{"bar"=>"1"}, {"bar"=>"2"}]}
# should this be one or two hashes? Discuss
irb(main):016:0> Rack::Utils.parse_nested_query("foo[][bar]=1&foo[][baz]=2")
=> {"foo"=>[{"bar"=>"1", "baz"=>"2"}]}
irb(main):017:0> Rack::Utils.parse_nested_query("foo[0][bar]=1&foo[1][baz]=2")
=> {"foo"=>{"0"=>{"bar"=>"1"}, "1"=>{"baz"=>"2"}}}
Typically normalizing this is handled by accepts_nested_attributes_for
. But what you're doing doesn't look the least bit ordinary.
If you want to jury rig a system that processes this and returns an array of whitelisted hashes you could do:
params = ActionController::Parameters.new("0"=>{"phase"=>"Launch", "reason"=>"test"}, "1"=>{"phase"=>"Foo", "reason"=>"bar"})
params.values.map do |h|
ActionController::Parameters.new(h)
.permit(:phase, :reason) # use permit! instead if you want to live dangerously
end
# [<ActionController::Parameters {"phase"=>"Launch", "reason"=>"test"} permitted: true>, <ActionController::Parameters {"phase"=>"Foo", "reason"=>"bar"} permitted: true>]
Upvotes: 1