How to I reference an array member in Ruby? - ruby

Given this array in Ruby:
myarray = [name: "John", age: 35]
How do I refer to the age?
I tried myarray[:age] but got an error can't convert Symbol into Integer
Update:
I was trying to simplify my question by extracting what I thought my problem is. I may not understand completely.
I'm experimenting with Dashing and trying to send a number to a meter widget. I've created a variable, 'response_raw' and am trying to send it in the third send event. Here's my code:
SCHEDULER.every '1m', :first_in => 0 do
# Get checks
url = "https://#{CGI::escape user}:#{CGI::escape password}#api.pingdom.com/api/2.0/checks"
`enter code here`response = RestClient.get(url, {"App-Key" => api_key})
response = JSON.parse(response.body, :symbolize_names => true)
if response[:checks]
checks = response[:checks].map { |check|
if check[:status] == 'up'
state = 'up'
last_response_time = "#{check[:lastresponsetime]}ms"
response_raw = check[:lastresponsetime]
else
state = 'down'
last_response_time = "DOWN"
response_raw = 0
end
{ name: check[:name], state: state, lastRepsonseTime: last_response_time, pt: response_raw }
}
else
checks = [name: "pingdom", state: "down", lastRepsonseTime: "-", pt: 0]
end
checks.sort_by { |check| check['name'] }
send_event('pingdom', { checks: checks })
send_event('pingdom-meter', { value: checks[:pt] })
end

In CoffeeScript [name: "John", age: 35] is an array containing single object with two properties (name and age).
Here is how it'll look in plain JavaScript:
myarray = [
{
name: "John",
age: 35
}
];
So, answering your question, to access an age you should take the first element of an array and then reference an age property:
myarray[0].age
or
myarray[0]['age']
But, judging from your question, your're probably using wrong data structure. Why don't you want to use a plain object instead of an array?
person = name: "John", age: 35
console.log "#{person.name}'s age is #{person.age}"
Update
It looks like your question is actually about Ruby and not about CoffeeScript. Though, my answer will remain the same.
To access an age you should take the first element of an array and then reference an age property:
myarray[0][:age]
Since myarray is an array, Ruby expects an integer index, but you're giving it symbol :age instead.

I finally figured it out with Leonid's help. Thank you.
I changed:
send_event('pingdom-meter', { value: checks[:pt] })
to
send_event('pingdom-meter', { value: checks[0][:pt] })

Related

Convert and translate a Ruby hash into a human-readable string

I have the following Ruby hash:
{"limit"=>250, "days_ago"=>14, "days_ago_filter"=>"lt", "key"=>3}
I'd like to convert it to a human-readable string and translate some of the values as necessary:
Limit: 250 - Days Ago: 14 - Days Ago Filter: Less than - Key: D♯, E♭,
So lt, in this case, actually translates to Less than. and 3 for key translates to D♯, E♭.
I'm almost there with this:
variables.map {|k,v| "#{k.split('_').map(&:capitalize).join(' ')}: #{v}"}.join(' - ')
But translating those values is where I'm hitting a snag.
I'd suggest using hashes for mapping out the possible values, e.g.:
days_ago_filter_map = {
"lt" => "Less than",
# ...other cases here...
}
musical_key_map = {
3 => "D♯, E♭",
# ...other cases here...
}
Then you can switch on the key:
variables.map do |key, value|
label = "#{key.split('_').map(&:capitalize).join(' ')}"
formatted_value = case key
when "days_ago_filter" then days_ago_filter_map.fetch(value)
when "key" then musical_key_map.fetch(value)
else value
end
"#{label}: #{formatted_value}"
end.join(' - ')
Note that if you're missing anything in your maps, the above code will raise KeyNotFound errors. You can set a default in your fetch, e.g.
days_ago_filter_map.fetch(value, "Unknown filter")
musical_key_map.fetch(value, "No notes found for that key")
You can create YAML files too for such kind of mappings :
values_for_replacement = {
"lt" => "Less than",
3 => "D♯, E♭"
}
you can try following :
variables.map {|k,v|
value_to_be_replaced = values_for_replacement[v]
"#{k.humanize}: #{(value_to_be_replaced.present? ? value_to_be_replaced : v)}"}.join(' - ')

How do I search within a nested hash for the value of a specific key?

Say I have a hash like this:
[82] pry(main)> commit2
=> {:sha=>"4df2b779ddfcb27761c71e00e2b241bfa06a0950",
:commit=>
{:author=>
{:name=>"asasa asasa",
:email=>"asa#asasad.com",
:date=>2016-08-06 16:24:04 UTC,
:sha=> "876239789879ab9876c8769287698769876fed"},
:committer=>
{:name=>"asasa asasa",
:email=>"asa#asasad.com",
:date=>2016-08-06 16:26:45 UTC},
:message=>
"applies new string literal convention in activerecord/lib\n\nThe current code base is not uniform. After some discussion,\nwe have chosen to go with double quotes by default.",
:tree=>
{:sha=>"7a83cce62195f7b20afea6d6a8873b953d25cb84",
:url=>
"https://api.github.com/repos/rails/rails/git/trees/7a83cce62195f7b20afea6d6a8873b953d25cb84"},
:url=>
"https://api.github.com/repos/rails/rails/git/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950",
:comment_count=>0},
:url=>
"https://api.github.com/repos/rails/rails/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950",
:html_url=>
"https://github.com/rails/rails/commit/4df2b779ddfcb27761c71e00e2b241bfa06a0950",
:comments_url=>
"https://api.github.com/repos/rails/rails/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950/comments"
}
}
}
This hash has many nested hashes, but I want to check to see if any of the nested hashes have a :sha value of 876239789879ab9876c8769287698769876fed.
In the above example, it should return the [:commit][:author] hash, because that one has :sha key whose value is the same as the one we are looking for.
How do I do this?
Here's a recursive method :
data = {a: {b: :c, d: :e}, f: {g: {h: {i: :j}}}}
def find_value_in_nested_hash(data, desired_value)
data.values.each do |value|
case value
when desired_value
return data
when Hash
f = find_value_in_nested_hash(value, desired_value)
return f if f
end
end
nil
end
p find_value_in_nested_hash(data, :e)
# {b=>:c, :d=>:e}
With your example :
repo = { sha: '4df2b779ddfcb27761c71e00e2b241bfa06a0950',
commit: { author: { name: 'asasa asasa',
email: 'asa#asasad.com',
date: '2016-08-06 16:24:04 UTC',
sha: '876239789879ab9876c8769287698769876fed' },
committer: { name: 'asasa asasa',
email: 'asa#asasad.com',
date: '2016-08-06 16:26:45 UTC' },
message: "applies new string literal convention in activerecord/lib\n\nThe current code base is not uniform. After some discussion,\nwe have chosen to go with double quotes by default.",
tree: { sha: '7a83cce62195f7b20afea6d6a8873b953d25cb84',
url: 'https://api.github.com/repos/rails/rails/git/trees/7a83cce62195f7b20afea6d6a8873b953d25cb84' },
url: 'https://api.github.com/repos/rails/rails/git/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950',
comment_count: 0 },
url: 'https://api.github.com/repos/rails/rails/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950',
html_url: 'https://github.com/rails/rails/commit/4df2b779ddfcb27761c71e00e2b241bfa06a0950',
comments_url: 'https://api.github.com/repos/rails/rails/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950/comments' }
p find_value_in_nested_hash(repo, '876239789879ab9876c8769287698769876fed')
#=> {:name=>"asasa asasa", :email=>"asa#asasad.com", :date=>"2016-08-06 16:24:04 UTC", :sha=>"876239789879ab9876c8769287698769876fed"}

How to save and display Dashing historical values?

Currently to setup a graph widget, the job should pass all values to be displayed:
data = [
{ "x" => 1980, "y" => 1323 },
{ "x" => 1981, "y" => 53234 },
{ "x" => 1982, "y" => 2344 }
]
I would like to read just current (the latest) value from my server, but previous values should be also displayed.
It looks like I could create a job, which will read the current value from the server, but remaining values to be read from the Redis (or sqlite database, but I would prefer Redis). The current value after that should be saved to the database.
I never worked with Ruby and Dashing before, so the first question I have - is it possible? If I will use Redis, then the question is how to store the data since this is key-value database. I can keep it as widget-id-1, widget-id-2, widget-id-3 ... widget-id-N etc., but in this case I will have to store N value (like widget-id=N). Or, is there any better way?
I came to the following solution:
require 'redis' # https://github.com/redis/redis-rb
redis_uri = URI.parse(ENV["REDISTOGO_URL"])
redis = Redis.new(:host => redis_uri.host, :port => redis_uri.port, :password => redis_uri.password)
if redis.exists('values_x') && redis.exists('values_y')
values_x = redis.lrange('values_x', 0, 9) # get latest 10 records
values_y = redis.lrange('values_y', 0, 9) # get latest 10 records
else
values_x = []
values_y = []
end
SCHEDULER.every '10s', :first_in => 0 do |job|
rand_data = (Date.today-rand(10000)).strftime("%d-%b") # replace this line with the code to get your data
rand_value = rand(50) # replace this line with the code to get your data
values_x << rand_data
values_y << rand_value
redis.multi do # execute as a single transaction
redis.lpush('values_x', rand_data)
redis.lpush('values_y', rand_value)
# feel free to add more datasets values here, if required
end
data = [
{
label: 'dataset-label',
fillColor: 'rgba(220,220,220,0.5)',
strokeColor: 'rgba(220,220,220,0.8)',
highlightFill: 'rgba(220,220,220,0.75)',
highlightStroke: 'rgba(220,220,220,1)',
data: values_y.last(10) # display last 10 values only
}
]
options = { scaleFontColor: '#fff' }
send_event('barchart', { labels: values_x.last(10), datasets: data, options: options })
end
Not sure if everything is implemented correctly here, but it works.

trouble assigning value to nested hash

I have a nested hash I want to assign a value to, but ruby keeps complaining about it.
the hash:
data = {
name: contact.xpath('./span[1]').text.delete("\r\n").strip,
email: contact.xpath('./a').text,
offices: [
postal: contact.text.split("\r\n")[4].strip,
tel: /(\d{3}[-\.\s]??\d{3}[-\.\s]??\d{4}|\(\d{3}\)\s*\d{3}[-\.\s]??\d{4}|\d{3}[-\.\s]??\d{4})/.match(contact).to_s
],
url: url
}
my assignment
data[:offices][:postal] = ""
error:
Line 42 - data[:offices][:postal] = "" -- in `[]='
#<TypeError: can't convert Symbol into Integer>
I've tried a handful of other syntaxes, but to no avail. Any help is appreciated :)
offices: [
postal: contact.text.split("\r\n")[4].strip,
tel: /(\d{3}[-\.\s]??\d{3}[-\.\s]??\d{4}|\(\d{3}\)\s*\d{3}[-\.\s]??\d{4}|\d{3}[-\.\s]??\d{4})/.match(contact).to_s
],
That is not a nested hash. Use curly braces:
offices: {
postal: contact.text.split("\r\n")[4].strip,
tel: /(\d{3}[-\.\s]??\d{3}[-\.\s]??\d{4}|\(\d{3}\)\s*\d{3}[-\.\s]??\d{4}|\d{3}[-\.\s]??\d{4})/.match(contact).to_s
},

Issue in parsing Json response in ruby

#response = Typhoeus::Request.get(FOUR_SQUARE_API_SERVER_ADDRESS+'search?ll=' + current_user.altitude.to_s + "&query="+ params[:query] + FOUR_SQUARE_API_ACESS_CODE)
#venues = ActiveSupport::JSON.decode(#response.body)
#venues['response']['groups'][0]['items'].each do |venue|
venue['name'] //working
venue['name']['location'][0]['address'] //issues
venue['name']['categories'][0]['id'] //issues
end
Please check inline comments for issues.
First of all, the venue['name'] is a scalar, not an array; secondly, venue['location'] (which I think you're trying to access) is not encoded as an array, that's just an object:
location: {
address: "...',
city: "...",
// ...
}
So here you want:
venue['location']
Then, your venue['name']['categories'][0]['id'] will fail because, again, venue['name'] is a scalar; for this one, you want:
venue['categories'][0]['id']

Resources