Formatting data array correctly for Highcharts - ruby

Seem to be struggling to get my data in the correct format for use with a highchart's pie chart.
If I force the data as follows my graph appears so I know I've done the integration correctly:
data: [
['Test', 30],
['Other', 70],
]
But when I try and use my actual data, it ain't working.
I've tried the following which doesn't work:
data: <%= Location.browsers.map { |o| [o.type, o.count] }.inspect %>
Have also tried:
data: <%= Location.browsers.map { |o| "#{o.type}, #{o.count}" }.to_json %>
The first one gives me a result like this:
"[[\"Safari\", 6448], [\"Microsoft\", 5253], [\"Microsoft-CryptoAPI\", 5185], [\"Dalvik\", 3870], [\"Chrome\", 3701], [\"Mozilla\", 3239], [\"Android\", 2285], [\"Windows-Update-Agent\", 2018], [\"Internet Explorer\", 1843], [\"Firefox\", 1459]]"
Which looks ok.
What's the correct way to run this query?

data: <%= raw Location.browsers.map { |o| [o.type, o.count] } %>
or
data: <%= raw Location.browsers.map { |o| [o.type, o.count] }.to_s %>
should work.

I
"[[\"A\", 10], [\"B\", 30], [\"C\", 0], [\"D\", -10]]"
II
[["A", 10], ["B", 30], ["C", 0], ["D", -10]]
I & II Are not the same
I is a String while II is a javascript Array<Array<Object>>
In your case the first one is the stringify-ed version of the second. You just need to do the reverse process of this to get back the Array from the String using $.parseJSON() or JSON.parse()
I don't have first hand experience with Ruby, but my guess is something like this will do the job
data: $.parseJSON(<%= Location.browsers.map { |o| [o.type, o.count] }.inspect %>)
Parsing string data into JSON # jsFiddle

Related

Skip certain indices while iterating each and maintaining group size

I have piece of code that currently takes an array of elements (in this case blog posts), sorts their numerical ID in descending order, puts them into groupings of 3, and iterates through each and every one of them.
I need to add a condition where if blog.published is false for any blog, do not display it and use the next blog.
Whenever a blog that has the published value set to false, the grouping will set the position in the grouping to nil, rather than filling it with the next blog entry, leaving some groupings with only 2 or 1 blogs on the view. I have attempted increasing the index by replacing each with each_with_index and iterating the index value when the condition is met, but this also yields the same issue. Here is my current code.
<% #blogs.order('created_at DESC').in_groups_of(3, false).each do |group| %>
<div class="row pt-3">
<% group.each do |blog| %>
<% next if blog.published == false && current_page?(root_path) %>
<%# Do View Stuff For Each Blog Here %>
<% end #each %>
</div>
<% end #grouping %>
Each grouping should always have 3 blogs and should skip over any blog that has the publication value set to false.
#blogs = Blog.where.not(published: false).order('created_at desc').in_groups_of(3, false)
PS. If you're doing #blogs = Blog.all in your controller, try not to build AR queries inside your view. Even queries aren't executed until you call it somehow, they should be fully-built in your controller method.
If I get the point, this is a possible solution. I'm using pure Ruby and a collection of hashes as example, but it should be easy to transpose it to Rails.
So, given the collection:
posts = [ {id: 1, pub: true}, {id: 2, pub: false}, {id: 3, pub: true}, {id: 4, pub: true}, {id: 5, pub: true}, {id: 6, pub: false}, {id: 7, pub: true}, {id: 8, pub: true}, {id: 9, pub: true}, {id: 10, pub: true}, {id: 11, pub: true}, {id: 12, pub: true}, {id: 13, pub: false}, {id: 14, pub: true} ]
Using Enumerable#each_slice and Array#reject:
groups_of_three = posts.each_slice(3).map { |group| group.reject { |h| h[:pub] == false } }
Printing out tho show the result:
groups_of_three.each { |group| p group }
# [{:id=>1, :pub=>true}, {:id=>3, :pub=>true}]
# [{:id=>4, :pub=>true}, {:id=>5, :pub=>true}]
# [{:id=>7, :pub=>true}, {:id=>8, :pub=>true}, {:id=>9, :pub=>true}]
# [{:id=>10, :pub=>true}, {:id=>11, :pub=>true}, {:id=>12, :pub=>true}]
# [{:id=>14, :pub=>true}]

Ruby array [ ] how can I get rid of quotations on the browser

Simple question. I am using Ruby V1.9.3 and I type;
<%= f_array = ['a','b','c'] %><br>
<%= f_array.join(' , ') %><br>
but they show up on the browser as;
["a", "b", "c"]
a,b,c
As far as I remember (until Ruby V1.8.3), it used to show up like;
abc
a,b,c
Did Ruby change their specification or did I miss something??
You error is here
<%= f_array = ['a','b','c'] %>
The statement <%= represents a print statement. Change it to
<% f_array = ['a','b','c'] %>
and the line will not be printed. ["a", "b", "c"] is the result of the inspection of an array.
2.1.5 :003 > puts ['a','b','c'].inspect
["a", "b", "c"]
For what it is worth, the code has another issue. Your view should not contain assignments. That's part of the business logic of your application.

ruby get part of a hash redis

I have this type of hash stored in variable foo
{:name=>"bobby", :data=>[[1, 2], [3, 4], [5, 6], [7, 8]]}
when I try foo[:data] I get no implicit conversion of Symbol into Integer
How do I get the 2d array?
EDIT
This is the entire code:
redis = Redis.new
redis.set "foo", {name: "bobby", :data => [
[1,2],[3,4],[5,6],[7,8]
]}
foo = redis.get "foo"
puts foo[:data][0]
redis.get returns a string, not a hash. This string is JSON representation of the hash. Try:
require 'json'
foo = JSON.parse(redis.get "foo")
puts foo['data']

Sorting by hash values inside an array of hashes

Im trying to return a list of values inside of of an array of hashes from lowest to highest. I am using the google_drive gem to pull numbers from a google spreadsheet, displaying football information:
Here is where I'm at:
require 'rubygems'
require 'google_drive'
session = GoogleDrive.login("EMAIL", "PASS")
v_qb_w1 = session.spreadsheet_by_key("xxxxxxxx").worksheets[0]
#quarterbacks = [
{ name: v_qb_w1[2, 1], projection: v_qb_w1[2, 2], salary: v_qb_w1[2, 3], dpp: v_qb_w1[2, 4], ppd: v_qb_w1[2, 5] },
{ name: v_qb_w1[3, 1], projection: v_qb_w1[3, 2], salary: v_qb_w1[3, 3], dpp: v_qb_w1[3, 4], ppd: v_qb_w1[3, 5] },
{ name: v_qb_w1[4, 1], projection: v_qb_w1[4, 2], salary: v_qb_w1[4, 3], dpp: v_qb_w1[4, 4], ppd: v_qb_w1[4, 5] }
]
puts "Value:"
#quarterbacks.sort_by do |key, value|
dpp = []
dpp << key[:dpp].to_f.to_s
puts dpp.flatten.sort.reverse
end
That last block was just one of my attempts to try and sort the :dpp key value from lowest to highest. Nothing fails, it just does not change anything. I've tried the grouby_by method and just have no luck arranging my key values
SOLUTION:
#quarterbacks.sort_by! { |qb| qb[:dpp] }
#quarterbacks.each { |qb| puts qb[:dpp] }
First of all, sort_by returns the sorted list, it doesn't sort it in place. That means that just:
#quarterbacks.sort_by { ... }
doesn't do anything useful as you're throwing away the sorted results. You'd need to add an assignment or use sort_by!:
#quarterbacks = #quarterbacks.sort_by { ... }
# or
#quarterbacks.sort_by! { ... }
Then you have understand how the sort_by block works. sort_by sorts using the block's return value, it is more or less like this:
array.map { |e| [ sort_by_block_value[e], e ] }
.sort { |a, b| a.first <=> b.first }
.map { |e| e.last }
so your block needs to return something sensible rather than the nil that puts returns:
#quarterbacks.sort_by! { |q| q[:dpp] }
Try this
#quarterbacks.sort_by!{|qb| qb[:dpp]}
You are trying to sort an Array. Right now you passing a Hash(k) and nil(v) because each quarterback is stored as a Hash so there is no key => value association in the Array. Also puts will return nil so you are telling it to sort nil against nil repetitively.
The code above will sort the Array of Hashes by the :dpp attribute of each Hash which seems like what you are asking for. The ! in this case means it will alter the receiver altering the #quarterbacks instance variable to be sorted in place.

How to output sorted hash in ruby template

I'm building a config file for one of our inline apps. Its essentially a json file. I'm having a lot of trouble getting puppet/ruby 1.8 to output the hash/json the same way each time.
I'm currently using
<%= require "json"; JSON.pretty_generate data %>
But while outputting human readable content, it doesn't guarantee the same order each time. Which means that puppet will send out change notifications often for the same data.
I've also tried
<%= require "json"; JSON.pretty_generate Hash[*data.sort.flatten] %>
Which will generate the same data/order each time. The problem comes when data has a nested array.
data => { beanstalkd => [ "server1", ] }
becomes
"beanstalkd": "server1",
instead of
"beanstalkd": ["server1"],
I've been fighting with this for a few days on and off now, so would like some help
Since hashes in Ruby are ordered, and the question is tagged with ruby, here's a method that will sort a hash recursively (without affecting ordering of arrays):
def sort_hash(h)
{}.tap do |h2|
h.sort.each do |k,v|
h2[k] = v.is_a?(Hash) ? sort_hash(v) : v
end
end
end
h = {a:9, d:[3,1,2], c:{b:17, a:42}, b:2 }
p sort_hash(h)
#=> {:a=>9, :b=>2, :c=>{:a=>42, :b=>17}, :d=>[3, 1, 2]}
require 'json'
puts sort_hash(h).to_json
#=> {"a":9,"b":2,"c":{"a":42,"b":17},"d":[3,1,2]}
Note that this will fail catastrophically if your hash has keys that cannot be compared. (If your data comes from JSON, this will not be the case, since all keys will be strings.)
Hash is an unordered data structure. In some languages (ruby, for example) there's an ordered version of hash, but in most cases in most languages you shouldn't rely on any specific order in a hash.
If order is important to you, you should use an array. So, your hash
{a: 1, b: 2}
becomes this
[{a: 1}, {b: 2}]
I think, it doesn't force too many changes in your code.
Workaround to your situation
Try this:
data = {beanstalkId: ['server1'], ccc: 2, aaa: 3}
data2 = data.keys.sort.map {|k| [k, data[k]]}
puts Hash[data2]
#=> {:aaa=>3, :beanstalkId=>["server1"], :ccc=>2}

Resources