问题
Using javascript, I make a fetch post.
const game = {name: this.player, snake: this.snake, score: this.score, apple: this.apple, skull: this.skull, completed: this.completed}
return fetch("http://localhost:3000/games", {
method: "POST",
headers: {
"Content-Type": "application/json"},
body: JSON.stringify(game)
})
.then(resp => resp.json())
.then(json => Game.appendHighScores(json));
I access the data via params on the Ruby on Rails end. The data for params[:snake][:body]
are supposed to look like "body"=>[{"x"=>16, "y"=>15}, {"x"=>16, "y"=>14}, {"x"=>16, "y"=>15}]}
, yet when I type them into the command line, they look like this:
[<ActionController::Parameters {"x"=>16, "y"=>15} permitted: false>, <ActionController::Parameters {"x"=>16, "y"=>14} permitted: false>, <ActionController::Parameters {"x"=>16, "y"=>15} permitted: false>]
It is accessible via indexing, but I get everything along with the data I'm looking for.
I was hoping it would look like the original params when I typed it in
<ActionController::Parameters {"name"=>"Don", "snake"=>{"x"=>16, "y"=>15, "direction"=>"down", "speed"=>0, "directions"=>{"left"=>{"x"=>-1, "y"=>0}, "up"=>{"x"=>0, "y"=>-1}, "right"=>{"x"=>1, "y"=>0}, "down"=>{"x"=>0, "y"=>1}}, "image"=>{}, "body"=>[{"x"=>16, "y"=>15}, {"x"=>16, "y"=>14}, {"x"=>16, "y"=>15}]}, "score"=>0, "apple"=>{"image"=>{}, "x"=>2, "y"=>10}, "skull"=>{"image"=>{}, "x"=>12, "y"=>12}, "completed"=>true, "controller"=>"games", "action"=>"create", "game"=>{"score"=>0, "skull"=>{"image"=>{}, "x"=>12, "y"=>12}, "apple"=>{"image"=>{}, "x"=>2, "y"=>10}, "completed"=>true}} permitted: false>
Anyway to get the params as an array without it looking so messy with ActionController::Parameters
inside of the element?
回答1:
The reason everything is wrapped inside ActionController::Parameters
is for your security (mass assignment in particular). You should never trust data send from the internet. This class allows you to permit/whitelist what properties you trust and filter out everything that you don't trust.
snake_params = params.require(:snake).permit(body: [:x, :y])
You can then convert this into a hash with a simple to_h call, which will drill down into all other nested parameters that are also permitted.
snake_data = snake_params.to_h
#=> { "body" => [{"x"=>16, "y"=>15}, {"x"=>16, "y"=>14}, {"x"=>16, "y"=>15}] }
If you'd like to include other attributes as well you can add them to the permit
list.
.permit(:direction, :speed, directions: {left: [:x, :y], up: [:x, :y], ...}, body: [:x, :y])
For more info about permit
I suggest checking out the guide Action Controller Overview - 4.5 Strong Parameters.
If you don't care about permitting certain parameters you can permit everything with permit!.
Note that you don't have to permit parameters if you extract the values directly. The code below would work perfectly fine without permitting anything.
body = params[:snake][:body]
body.each |body_part|
x = body_part[:x]
y = body_part[:y]
// do stuff with x and y
end
回答2:
Because Rails utilize "strong parameters" you have to list and allow the parameters in the controller you want to use.
Since you have a list of parameters with dynamic keys the easiest way to do, while you are in development mode is to permit them like this:
# in your controller
def game_params
params.require(:game).tap do |permitted|
permitted[:name] = params[:name].permit!
permitted[:snake] = params[:snake].permit!
permitted[:apple] = params[:apple].permit!
permitted[:skull] = params[:skull].permit!
permitted[:completed] = params[:completed].permit!
end
end
and then you will be able to access your params:
game_params[:snake][:body]
In production tho, I will encourage you to whitelist all of the keys, for example like this.
来源:https://stackoverflow.com/questions/62199983/how-can-i-access-the-data-for-the-snake-object-sent-through-json-in-my-params