How do I add hash elements to another hash? - ruby-on-rails

I do not seem to be able to add items to a hash.
I have the following method that has a hash passed in and the intent is to pass out a new hash made from the original. I have verified that the key is a string and the other two elements are floats. b_name, lat and lng all print to the logs when I request.
def construct_paint_hash(list)
full_list = Hash.new
num = 100
list.each do |thing|
puts num
b_name = thing["name"]
puts b_name
lng = thing["longitude"]
lat = thing["latitude"]
full_list["#{b_name}"]=[lng, lat]
# full_list[:dsfsd] = "dsfdsfds"
num +=100
end
return full_list
end
Here is the error I am getting:
Completed 500 Internal Server Error in 377ms (ActiveRecord: 0.0ms)
TypeError (no implicit conversion of String into Integer):
app/controllers/welcome_controller.rb:42:in `[]'
app/controllers/welcome_controller.rb:42:in `block in construct_paint_hash'
app/controllers/welcome_controller.rb:39:in `each'
app/controllers/welcome_controller.rb:39:in `construct_paint_hash'
app/controllers/welcome_controller.rb:11:in `index'
What the heck am I doing wrong here?

Your code seems okay, but you can use the following code snippet. I assume your list params as following
list = [{"name" => "dhaka", "longitude" => 23.44, "latitude" => 24.55}, {"name" => "usa", "longitude" => 23.44, "latitude" => 24.55}]
Then rewrite your construct_paint_hash as following
def self.construct_paint_hash(list)
data = list.collect { |l| {l["name"] => [l["longitude"], l["latitude"]]} }
return data.inject(:merge)
end

Related

Why am I getting "no implicit conversion of String into Integer" when trying to get Nested JSON attribute?

My Rails app is reading in JSON from a Bing API, and creating a record for each result. However, when I try to save one of the nested JSON attributes, I'm getting Resource creation error: no implicit conversion of String into Integer.
The JSON looks like this:
{
"Demo": {
"_type": "News",
"readLink": "https://api.cognitive.microsoft.com/api/v7/news/search?q=european+football",
"totalEstimatedMatches": 2750000,
"value": [
{
"provider": [
{
"_type": "Organization",
"name": "Tuko on MSN.com"
}
],
"name": "Hope for football fans as top European club resume training despite coronavirus threat",
"url": "https://www.msn.com/en-xl/news/other/hope-for-football-fans-as-top-european-club-resume-training-despite-coronavirus-threat/ar-BB12eC6Q",
"description": "Bayern have returned to training days after leaving camp following the outbreak of coronavirus. The Bundesliga is among top European competitions suspended."
}
}
The attribute I'm having trouble with is [:provider][:name].
Here's my code:
def handle_bing
#terms = get_terms
#terms.each do |t|
news = get_news(t)
news['value'].each do |n|
create_resource(n)
end
end
end
def get_terms
term = ["European football"]
end
def get_news(term)
accessKey = "foobar"
uri = "https://api.cognitive.microsoft.com"
path = "/bing/v7.0/news/search"
uri = URI(uri + path + "?q=" + URI.escape(term))
request = Net::HTTP::Get.new(uri)
request['Ocp-Apim-Subscription-Key'] = accessKey
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
http.request(request)
end
response.each_header do |key, value|
# header names are coerced to lowercase
if key.start_with?("bingapis-") or key.start_with?("x-msedge-") then
puts key + ": " + value
end
end
return JSON(response.body)
end
def create_resource(news)
Resource.create(
name: news['name'],
url: news['url'],
description: news['description'],
publisher: news['provider']['name']
)
end
I looked at these questions, but they didn't help me:
Extract specific field from JSON nested hashes
No implicit conversion of String into Integer (TypeError)?
Why do I get "no implicit conversion of String into Integer (TypeError)"?
UPDATE:
I also tried updating the code to:
publisher: news['provider'][0]['name'], but I received the same error.
because "provider" is an array.
it should be accessed with index.
[:value][0][:provider][0][:name]
same goes with "value".

Rails join array inside map without escaping

I have an array of hashes that I map into a string
Example:
array_of_hashes = [{
:me => 'happy',
:you => 'notsohappy',
:email => [
{"Contact"=>"", "isVerified"=>"1"},
{"Contact"=>"me#example.com", "isVerified"=>"1"},
{"Contact"=>"you#example.com", "isVerified"=>"1"}
]
},{another instance here...}]
Now I want to convert this to a new array that will give me:
["happy", "notsodhappy", "me#example.com", "you#example.com"]
I need to map and reject empty email addresses in the "email" array of hashes.
So far I tried:
array_of_hashes.map{|record| [
record['me'],
record['you'],
record['email'].map { |email| email['Contact']}.reject { |c| c.empty? }.join('", "')
] }
But this returns ["happy", "notsohappy", "me#example.com\", \"you#example.com"]
The quotes are escapes even if I add .html_safe after the .join
In short, it's insisting to keep the joined array a single string. I need it split to separate strings... as many as are in the array.
I need to get rid of these quotes because I am trying to export the array as CSV and so far it's not splitting the email addresses to separate columns.
Suggestions?
array_of_hashes.map do |h|
[h[:me], h[:you]].push(
h[:email].map {|e|e["Contact"]}.reject(&:empty?)
).flatten
end
# => [["happy", "notsohappy", "me#example.com", "you#example.com"], ...]
results = []
array_of_hashes.each do |hash|
single_result = []
single_result << hash[:me]
single_result << hash[:you]
hash[:email].each do |email|
single_result << email["Contact"] if email["Contact"].present?
end
results << single_result
return results
end
This will results : -
2.3.1 :091 > results
=> [["happy", "notsohappy", "me#example.com", "you#example.com"], ["happy", "notsohappy", "me#example.com", "you#example.com"], ["happy", "notsohappy", "me#example.com", "you#example.com"]]

How to get "key" from params?

<%= params[:select] %> # key=qwerty secret=qwerty token=qwerty token_secret=qwerty
Please tell me how I can get "key" ? I do not understand:
<%= params{[:select[:key]]} %> # {"tweet"=>"", "select"=>"key=qwerty secret=qwerty token=qwerty token_secret=qwerty", "controller"=>"twitter_postings", "action"=>"index"}
You can access to the select key and over its value to split the content, getting the first one you have "key":
params = {
"tweet"=>"",
"select"=>"key=qwerty secret=qwerty token=qwerty token_secret=qwerty",
"controller"=>"twitter_postings",
"action"=>"index"
}
p params['select'].split.first
# "key=qwerty"
You can also turn it into a hash if it's easier for you:
select_hash = params['select'].split.each_with_object(Hash.new(0)) do |element, hash|
key, value = element.split('=')
hash[key] = value
end
p select_hash['key']
# "qwerty
Hope this will helping you.
params = {
"tweet"=>"",
"select"=>"key=qwerty secret=qwerty token=qwerty token_secret=qwerty",
"controller"=>"twitter_postings",
"action"=>"index"
}
for getting key value (qwerty) from this params following query will helping you.
params["select"].split.first.split("=").second
# => "qwerty"
steps: 1
params["select"].split
# => ["key=qwerty", "secret=qwerty", "token=qwerty", "token_secret=qwerty"]
find the value and split them
steps: 2
params["select"].split.first.split("=")
# => ["key", "qwerty"]
pick first value and split again with =
steps: 3
params["select"].split.first.split("=").second
# => "qwerty"
finally pick the second value.

How can I access an array inside a hash?

I have a hash within an array:
values = {}
values.merge!(name => {
"requested_amount" => #specific_last_pending_quota.requested_amount,
"granted" => #specific_last_pending_quota.granted,
"pending_final" => pending_final
})
#o_requests[request.receiving_organization][request.program_date][:data] = values
I send it to the view and then when I get it so:
= quota[:data].inspect
# {"theme"=>{"requested_amount"=>2, "granted"=>false, "pending_final"=>0}}
I want to fetch the object like this:
= quota[:data]["theme"].inspect
But I got this error
can't convert String into Integer
I guess quota[:data] may return array of hash
Try:
= quota[:data][0]["theme"]
Here I tried case to get same error and check:
> h[:data]
#=> [{"theme"=>{"requested_amount"=>2, "granted"=>false, "pending_final"=>0}}]
> h[:data]["theme"]
TypeError: no implicit conversion of String into Integer
from (irb):10:in `[]'
from (irb):10
from /home/ggami/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
> h[:data][0]["theme"]
#=> {"requested_amount"=>2, "granted"=>false, "pending_final"=>0}
Try convert it to proper hash I guess it should work fine.
values = {}
values.merge!(name => {:requested_amount => #specific_last_pending_quota.requested_amount, :granted => #specific_last_pending_quota.granted, :pending_final => pending_final})
#o_requests[request.receiving_organization][request.program_date][:data] = values

Ruby convert all values in a hash to string

I have the following snippet of code to fetch certain columns from the db:
#data = Topic.select("id,name").where("id in (?)",#question.question_topic.split(",")).map(&:attributes)
In the resulting Array of Hashes which is :
Current:
#data = [ { "id" => 2, "name" => "Sports" }]
To be changed to:
#data = [ { "id" => "2", "name" => "Sports" }]
I want to convert "id" to string from fixnum. Id is integer in the db. What is the cleanest way to do this?
Note: After using .map(&:attributes) it is not an active record relation.
You can do it with proper map usage:
topics = Topic.select("id,name").where("id in (?)",#question.question_topic.split(","))
#data = topics.map do |topic|
{
'id' => topic.id.to_s,
'name' => topic.name
}
end
What you're looking for is simply
#data.each { |obj| obj["id"] = obj["id"].to_s }
There isn't really a simpler way (I think that's straightforward enough anyway).
Going by the title which implies a different question - converting every value in the hash to a string you can do this:
#data.each do |obj|
obj.map do |k, v|
{k => v.to_s}
end
end
Just leaving that there anyway.
You can use Ruby's #inject here:
#data.map do |datum|
new_datum = datum.inject({}) do |converted_datum, (key, value)|
converted_datum[key] = value.to_s
converted_datum
end
end
This will work to convert all values to strings, regardless of the key.
If you are using Rails it can be even cleaner with Rails' #each_with_object:
#data.map do |datum|
datum.each_with_object({}) do |(key, value), converted_datum|
converted_datum[key] = value.to_s
end
end
This will iterate all the key names in the hash and replace the value with the #to_s version of the datum associated with the key. nil's converted to empty strings. Also, this assumes you don't have complex data within the hash like embedded arrays or other hashes.
def hash_values_to_string(hash)
hash.keys.each {|k| hash[k]=hash[k].to_s}; hash
end

Resources