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?
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
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.
I have a controller in ruby on rails 4 and i need to pre-process its params during request processing.
I receive parameters:
{"_json"=>[{"date"=>"9/15/2014", "name"="James"},{"date"=>"2/11/2014","name"=>"John"}]}
And i need to iterate through all json array elements and update name parameter by adding 'User' post fix. So, finally my json should be:
[{"date"=>"9/15/2014", "name"="James **User**"},{"date"=>"2/11/2014","name"=>"John **User**"}]
How can i do it in my controller?
You can try this way
params = {"_json"=>[{"date"=>"9/15/2014", "name"=>"James"},{"date"=>"2/11/2014","name"=>"John"}]}
Then modify params using using
params["json"].each { |h| h["name"] = "#{h['name']} **User**" }
puts params["_json"]
if you want to preprocess for each action then used before_filter
I am using the HTTParty gem to make a patch request to update an object via an API call as follows:
params = { first_name: "John"}
#options = {params: params}
#response = HTTParty.patch("http://localhost:3000/1/kites/4", #options)
But on the API side, within the update method that the above PATCH request is supposed to call I only see the following parameters available:
{"format"=>"json",
"controller"=>"api/v1/kites",
"action"=>"update",
"version"=>"1",
"id"=>"4"}
An error message is passed back to the #response for pasrsing.
What happened to first_name and/or how do I call HTTParty.patch appropriately if that is indeed what is causing the loss of the parameters passed to the API?
EDIT:
As it turns out, if I do
#options = {query: params}
that will work but only if I keep a query under a certain size....
Not sure what your 'patch' action does exactly in your API but the documentation says that you need to pass a URL and params in a body: key, like so:
HTTParty.patch('site/your_url', body: { key1: value, key2: value })
Alternalitvely, you can pass the params in query: key which appends the params to the URI.
HTTParty.patch('site/your_url', query: { key1: value, key2: value })
I'm trying to sort out a problem where I need to write the following and test to see if a params key is being passed:
if params.has_key? :transfer_date(1i)
params[:call].parse_time_select! :transfer_date
end
I can test against a params key like :transfer but the params being passed by my time parsing gem passes transfer_date(1i), transfer_date(2i), etc.
How do I write the above statement with the right syntax so I can test for the transfer_date(1i) params key?
You can quote the symbol's content:
if params.has_key? :'transfer_date(1i)'
or, if params is guaranteed to be the usual ActiveSupport::HashWithIndifferentAccess, you could just check for a string key:
if params.has_key? 'transfer_date(1i)'
I am doing an http get using the url http://localhost/add?add_key[0][key]=1234&add_key[0][id]=1.
I have a rails app which gives me a neat params hash {"add_key"=>{"0"=>{"key"=>"1234", "id"=>"1"}}. However when I try to post this to a different server using
new_uri = URI.parse("http://10.10.12.1/test")
res = Net::HTTP.post_form new_uri,params
The server handling the post is seeing this parameter in the request
{"add_key"=>"0key1234id1"}
Looks like post_form requires a String to String hash. So how do I convert the params hash to
{"add_key[0][key]" => "1234", add_key[0][id]" => "1"}
From the fine manual:
post_form(url, params)
Posts HTML form data to the specified URI object. The form data must be provided as a Hash mapping from String to String.
So you're right about what params needs to be.
You could grab the parsed params in your controller:
{"add_key"=>{"0"=>{"key"=>"1234", "id"=>"1"}}
and then recursively pack that back to the flattened format that post_form expects but that would be a lot of pointless busy work. An easy way to do this would be to grab the raw URL and parse it yourself with URI.parse and CGI.parse, something like this in your controller:
u = URI.parse(request.url)
p = CGI.parse(u.query)
That will leave you with {"add_key[0][key]" => "1234", "add_key[0][id]" => "1"} in p and then you can hand that p to Net::HTTP.post_form.