0

I have the following params:

params={"data"=> {"type"=>"book", "id"=>14, "attributes"=> {"id"=>14, "created_at"=>"2022-06-27 21:15:39", "title"=>"sdfdsf", "targeting"=> { "release_times"=>[["4:00", "5:00"], ["5:00", "6:00"]], "days"=>["Monday", "Tuesday", "Wednesday"], "gender"=>["male", "female"] } } } 

When I use this, I can get every value but release_times is always null:

When I use this:

safe_params = params.require(:data).permit( attributes: [:id, :created_at, :title, { targeting: {} }])

How can I extract the release times value? I tried doing this

safe_params = params.require(:data).permit( attributes: [:id, :created_at, :title, { targeting: [:days, :gender, release_times:[]]}])

But I get the error:

Validation failed: Targeting gender should be a list of values, Targeting days should be a list of values

How can I extract all the values from targeting including the release_times?

1 Answer 1

2

As Ruby on Rails API states, when using ActionController::Parameters you want to declare that a parameter should be an array (list) by mapping it to a empty array. Like you did with release_times.

You should permit targeting params with [days: [], gender: []] instead of [:days, :gender]. This should solve the error.

But even them, release_times is an array of arrays, which I believe is not supported at the moment (there is an old issue for it).

One way you could bypass this would be by changing the way you're communicating release_times. Using an arrays of hashes instead of nested arrays.

From this:

"release_times"=>[["4:00", "5:00"], ["5:00", "6:00"]] 

To this (or something similar):

"release_times"=>[{"start" => "4:00", "end"=>"5:00"}, {"start" =>"5:00", "end" => "6:00"}] 

That way, you could do this:

safe_params = params.require(:data).permit(attributes: [:id, :created_at, :title, { targeting: [days: [], gender: [], release_times: [:start, :end]] }]) 

Exactly how you would implement that is up to you, but I hope it helps.

**Also, there was a typo with release_times.


You can do some testing yourself. Open rails c and do something like this:

param = ActionController::Parameters.new("targeting"=> { "release_times"=>[["4:00", "5:00"], ["5:00", "6:00"]]}) param.require(:targeting).permit(release_times: []) # > Doesn't return times. new_param = ActionController::Parameters.new("targeting"=> { "release_times"=>[{"start" => "4:00", "end"=>"5:00"}, {"start" =>"5:00", "end" => "6:00"}] }) new_param.require(:targeting).permit(release_times: [:start, :end]) # > Return times. 

Just an observation, using permit! would work. But as strong params doc says:

Extreme care should be taken when using permit! as it will allow all current and future model attributes to be mass-assigned.

So you could try to slice arguments yourself and them permit! - but I can't tell you that's the way to go.

Learn more about Mass Assignment Vulnerability here.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks! release_time is still empty. Is it because it's an array of arrays?
I think we both mispelled "release_time". The final "s" is missing. It should be "release_times". My bad not spotting it :) let me know if it worked!
thanks! Apologies on the typo on my part. I'm still getting "release_times"=>[]
Yes, it seams nested arrays are not supported - I didn't know that. I am updating my asnwer.
I updated my answer with a alternative for what you're trying to do. I hope it helps :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.