passing array through Net::HTTP - ruby-on-rails

I'm trying to pass an array through Net::HTTP to a ruby
def send_p
x = Net::HTTP.post_form(URI.parse('http://example_domain/example'), to_send)
render text: x
end
def to_send
{
param_a: "foo",
param_b: [1,2,3]
}
end
but when check the params in http://example_domain/example is getting me
{
"param_a"=>"foo",
"param_b"=>"3",
"action"=>"my_method",
"controller"=>"my_controller"
}
what can I do to receive the array in the proper way: [1,2,3]

Try using HTTParty:
x = HTTParty.post(URI.parse('http://example_domain/example'), to_send)

You can convert the array to string and then do the inverse when getting the params from the response.
Convert to String before to send it
param_b: [1,2,3].to_s
You will receive exactly as you sent it
"param_b"=>"[1,2,3]"
Convert it back to Array
eval(params[:param_b])
# => [1, 2, 3]

Related

Ruby on Rails: Get specific substring out of string

a little help with getting data out of a string.
Assuming I executed a sql query and now have a string(which set as hash on db):
"{\"users_associated\":{\"User:4\":6,\"User:22\":28,\"User:30\":36}}"
(Which stands for User:ID : User.display_id)
How can I get a substring the includes all users ids or all their display ids, so I'll have something like 4,22,30 or 6,22,36)?
Thanks!
It's common for data systems to return data in a serialized form, i.e. using data types that facilitate transmission of data. One of these serializable data types is String, which is how your JSON data object has been received.
The first step would be to de-serialize (or parse) this String into a Hash object using JSON.parse and tease out just the data value for key "users_associated".
your_string = "{\"users_associated\":{\"User:4\":6,\"User:22\":28,\"User:30\":36}}"
hash = JSON.parse(your_string)
data = hash["users_associated"]
#=> {"User:4":6, "User:22": 28, "User:30": 36}
Hash#keys gives you an array of a hash's keys.
Hash#values gives you an array of a hash's data values.
keys = data.keys
#=> ["User:4", "User:22", "User:30"]
values = data.values
#=> [6, 28, 36]
Array#join lets you string together the contents of an array with a defined separator, , in this case.
display_ids = keys.join(',')
#=> "6,28,36"
For the User IDs, you could Array#map every element of the values array to replace every string occurrence of "User:" with "", using String#gsub.
user_ids = values.map{|user_id| user_id.gsub("User:", "")}
#=> ["4", "22", "30"]
Then, in a similar way to display_ids, we can Array#join the contents of the user_ids array to a single string.
user_ids = user_ids.join(",")
#=> "4,22,30"
You can create two helper methods. I'm leaving return values as arrays because I assume you would need to iterate on them at some point and also converting the user id's to integers.
def extract_display_ids(json)
json['users_associated'].values
end
def extract_user_ids(some_data)
json['users_associated'].keys.map{ |key| key.split(':').last.to_i }
end
some_data = JSON.parse("{\"users_associated\":{\"User:4\":6,\"User:22\":28,\"User:30\":36}}")
extract_display_ids(some_data)
#=> [6, 28, 36]
extract_user_ids(some_data)
#=> [4, 22, 30]
If possible though, I would recommend trying to get a better data format:
{ users_associated:
[{ user_id : 4, display_id:6 }, { user_id : 4, display_id:6 }]
}
I wrote class for this. If you want, you can add it to your project and use it as follows:
require 'json'
class UserSubstringExtractor
def initialize(user_json_data)
#user_json_data = user_json_data
end
def display_ids
user_data.dig('users_associated').values
end
def user_ids
user_data.dig('users_associated').keys.map { |u| u.split(':').last.to_i }
end
private
def user_data
JSON.parse(#user_json_data)
end
end
user_json_data = '{"users_associated":{"User:4":6,"User:22":28,"User:30":36}}'
extractor = UserSubstringExtractor.new(user_json_data)
p extractor.display_ids
#=> [6, 28, 36]
p extractor.user_ids
#=> [4, 22, 30]

How can I get the value of the name only on this array?

This is the output array when I do
result = JSON.parse(response.body)
result.values.each {|element|
puts element
}
Result:
{"id"=>3, "code"=>"3", "name"=>"Market", "status"=>"A", "refcode"=>"001"}
{"id"=>4, "code"=>"4", "name"=>"Mall", "status"=>"A", "refcode"=>"002"}
From this array, I only want to get the name value. I tried this
puts result['data'][0]['name'] and it worked fine but I want to get all the name in the array
This is my expected output
Market
Mall
Try using Array#map and over each element, to access it's 'name' key, like:
p array.map { |element| element['name'] }
# ["Market", "Mall"]
I think it'd be something like:
result = JSON.parse(response.body)
result.values.map { |element| element['name'] }
# ["Market", "Mall"]
Since with each and puts you're only iterating and printing the hashes in the array, you could access the 'name' key from result.values.
I wont modify much. Since your name element is at position 3. access it like array because you are using values.each
result = JSON.parse(response.body)
result.values.each {|element|
puts element[2]
}

Decompose incoming JSON to array

I have incoming json request in this format:
{ "id":"1", "fields":{"attr1":"value1", "attr2":"value2", ... "attrN":"valueN"}}
I need to decompose json string in my controller to this:
id: 1
attr1: value1
attr2: value2
...
attrN: valueN
How can I do this? I use Rails 4. Thanks
if you wanna add entire json hash to array, you can do something like this.
arr = Array.new
json_arr = { "id":"1", "fields":{"attr1":"value1", "attr2":"value2", ... "attrN":"valueN"}}
json_arr.each do |arr|
temp_hash = Hash.new
temp_hash = arr
arr.push(arr)
end
I am not sure about your requirement.

How to refactor each function with map in Ruby?

I have a loop building a hash for use in a select field. The intention is to end up with a hash:
{ object.id => "object name", object.id => "object name" }
Using:
#hash = {}
loop_over.each do |ac|
#hash[ac.name] = ac.id
end
I think that the map method is meant for this type of situation but just need some help understanding it and how it works. Is map the right method to refactor this each loop?
Data transformations like this are better suited to each_with_object:
#hash = loop_over.each_with_object({}) { |ac, h| h[ac.name] = ac.id }
If your brain is telling you to use map but you don't want an array as the result, then you usually want to use each_with_object. If you want to feed the block's return value back into itself, then you want inject but in cases like this, inject requires a funny looking and artificial ;h in the block:
#hash = loop_over.inject({}) { |h, ac| h[ac.name] = ac.id; h }
# -------------------- yuck -----------------------------^^^
The presence of the artificial return value is the signal that you want to use each_with_object instead.
Try:
Hash[loop_over.map { |ac| [ac[:name], ac[:id]] }]
Or if you are running on Ruby 2:
loop_over.map { |ac| [ac[:name], ac[:id]] }.to_h
#hash = Hash[loop_over.map { |ac| {ac.name => ac.id} }.map(&:flatten)]
Edit, a simpler solution as per suggestion in a comment.
#hash = Hash[ loop_over.map { |ac| [ac.name, ac.id] } ]
You can simply do this by injecting a blank new Hash and performing your operation:
loop_over.inject({}){ |h, ac| h[ac.name] = ac.id; h }
Ruby FTW
No a map isn't the correct tool for this.
The general use-case of a map is to take in an array, perform an operation on each element, and spit out a (possibly) new array (not a hashmap) of the same length, with the individual element modifications.
Here's an example of a map
x = [1, 2, 3, 4].map do |i|
i+1 #transform each element by adding 1
end
p x # will print out [2, 3, 4, 5]
Your code:
#hash = {}
loop_over.each do |ac|
#hash[ac.name] = ac.id
end
There is nothing wrong with this example. You are iterating over a list, and populating a hashmap exactly as you wished.
Ruby 2.1.0 introduces brand new method to generate hashes:
h = { a: 1, b: 2, c: 3 }
h.map { |k, v| [k, v+1] }.to_h # => {:a=>2, :b=>3, :c=>4}
I would go for the inject version, but use update in the block to avoid the easy to miss (and therefore error prone) ;h suffix:
#hash = loop_over.inject({}) { |h, ac| h.update(ac.name: ac.id) }

Hash becomes array after post

I have a hash in Ruby:
params[:test]={:name=>'sharing'}
restPost(url, params)
on the other end, I output the params:
render :json=>{ :params=>params[:test] }
I get the result:
{"params":["name", "sharing"] }
It seems the hash is turned into a array. What I want is:
{"params": {"name":"sharing"}}
One way to deal with this might be to convert the array back to a Hash with Hash[], e.g.:
a = ["name", "sharing"]
h = Hash[*a]

Resources