Adding Rails data to Highcharts series - ruby-on-rails

I am trying to make a chart to display a users weight, using highcharts. I have all of the correct js files included and when passed a simple array of integers, it works just fine.
However I am unsure, having read the highcharts docs, how to pass the correct data into the series options using rails.
my user model is as follows:
A user has many weigh_ins, which has weight:float user_id:integer id:integer created_at:datetime fields. (if this is relevant)
Below is my view, as you can see i have tried to iterate through the users weights and then pass that as the data. I know it needs to be fed json and an array, but im not sure how to format my data to fit in that way.
borderWidth: 0
},
series: [{
pointInterval: <%= 1.day * 1000 %>,
name: 'weight',
data: <% #user.weigh_ins.each do |weight| %>
<%= weight.weight.to_json %>
<% end %>
}]
If there is any more code that needs posting, just shout.
any suggestions would be greatly appreciated.
Thata defo on the right track, however, the data is dynamic so a user can update their weights everyday, so the chart needs to update aswell. If i use the square brackets like above then the graph doesnt even render. Now i have this but it doesnt produce the correct output either. I need to find the weigh_ins for the correct user, then iterate through all of them and select the weight figure which is a float. Not sure how to tackle it.
data: <% user = #user.weigh_ins %>
<% user.each do |user_weight| %>
[<%= user_weight.weight %> ]
<% end %>

I'm something similar with this code:
<% bio_array = Array.new(#bio.size) %>
<% #biometrics.each_with_index {|x, index| %>
<% bio_array += [x[:weight]] %>
<% } %>
(... some code ...)
series: [{
name: 'Some Name',
data: <%= bio_array %>
Please note that this code is not optimized for you case (in my case i have other logic that i omitted for being useless to your case - i had a multidimensional arrays with [data and value]).

if you want to parse data like that , you don't really have to use Json , becoz since yo don't update dynamically , you can just echo it like [34,32,24,25,12] bt first you hv to make that String from Ruby , and that's exactly what is json is used for too , check your Json output,
btw try echo some Ruby String like
=> 1,2,3,4,5 [<% echo str %> ]
and if your json out put hv no squre brackets [] then try adding them
data:[ <% #user.weigh_ins.each do |weight| %> ]

Related

Rails 5.1, chartkick a sum with multiple currencies

I'm stuck on a tiny problem regarding chartkick. I have a rail app where you can create different currencies. You can then create a expense with a title, a amount and choose the currency from a list and the user_id. The relations are made and working. I have in my user controller something like this :
#user_spendings = #current_user.spendings.all.order('date DESC').paginate(:page => params[:page], :per_page => 15)
#sums_by_currency = Currency.joins(:spendings).
select(:symb, 'SUM(spendings.amount) AS amount').
where(spendings: { id: #user_spendings.map(&:id) }).
group(:symb)
And in my show view (as I want the expense from each user to be shown there) something like this :
<% #sums_by_currency.each do |currency| %>
<%= '%.02f' % "#{currency.amount}" %> <%= "#{currency.symb}" %>
<% end %>
That shows me the sum for each spending depending on the currency.
I would like to use this total and use chartkick to display the spending, with the date when this spending has been created.
I've tried several things already
First I went with this just to see :
<% #sums_by_currency.each do |currency| %>
<%= bar_chart currency.amount %>
<% end %>
Well I have to charts appearing but nothing shows up. Maybe the loop isn't the solution. Then I thought about the .map but I don't really know how to put that in place to be honnest.
I tried this aswell :
<%= line_chart #current_user.spendings.group(:date).sum(:amount) %>
That shows me the total spendings from all the currencies. I have to find out how to split all the currencies in different charts and show only the total amount from each currency.
If anyone can give me a clue I would appreciate it.
Thanks alot.
Ok guys I got it !
Took me 2 days only...
For the one interested in the answer here is what I did. I actually didn't change anything in the controller and I let the #sums_by_currency like it is.
Instead I went for that :
<%= column_chart #current_user.spendings.all.joins(:currency).group('currencies.symb').group_by_month(:date, format: "%B %Y").sum(:amount) %>
Give me all the spendings from the current_user from where I joined the currency that I grouped by symb. Then I grouped everything by month and I get the sum from the amount.
Yeah, you need to pass a set of data to the chart, not lots of individual pieces of data for individual charts (ie what you've got with the loop). Using map to convert your currency-objects to their amounts makes sense eg
<%= bar_chart #sums_by_currency.map{|c| c.amount } %>
or if you need a name something like:
<%= bar_chart #sums_by_currency.map{|c| {name: c.unit, data: c.amount} } %>
Where unit is whatever currency unit eg AUD

RoR - Link_to with nested hash from an each loop

Having some trouble with nested hash parameters. Product has many features. Say product 1 has features foo and baz.
I'd like to pass both the product and all of the features to query string parameters in a link_to so that it ends up looking like this:
"/puppies/new?features%5Bbaz%5D=qux&features%5Bfoo%5D=bar&product=1"
I am currently trying this, which gets a syntax error for reasons that are probably obvious to people that are not me.
<% Product.each do | product | %>
<%= link_to(new_puppy_path(product: product, features: { product.features.each
{ | feature| feature.name : 'feature.'} } ), class: 'slorp') do %>
// stuff inside the link
<% end %>
<% end %>
Any idea what I'm doing stupid here?
UPDATE: I have updated the code to:
<%= link_to(new_puppy_path(product: product, features: product.features.each{|feature| {feature.name.to_sym => feature.feature_colors.first}}), class: 'image') do %>
This is much closer, as my output URL is now:
/puppies/new?features%5B%5D=3&features%5B%5D=2&product=2
I am just missing the name of the feature in-between the %5B and %5D - not sure why the feature name is not showing up.
You need to use map instead of each. Each returns the original array itself on which it is operating. While map returns the elements from the block.
Fixed. Pulled creating the hash up into the model:
def reco_features
list = Hash.new
feature_colors.each do |feature_color|
list[feature_color.feature.name] = feature_color.id
end
return list
end
Then updated the link_to:
<%= link_to(new_puppies_path(product: product, features: features.reco_features ), class: 'slorp') do %>
Not sure why the inline wasn't working, but this fixed it. Required some additional context outside of the initial question, which I did not realize at the time. Apologies and thanks to all.

How to use JSON data returned by API call in Rails 4

I am making a call to an external API and get the following response data in JSON.
{
"count": 1,
"styles": [
{
"vehicle_id": "400882961",
"style": "AWD Titanium 4dr Sedan"
}
]
}
I am wondering how I can use the data in my view. I am using #details to represent my data. If I put #details.inspect in my view I give me the data as you see it here.
I'd like to be able to put the vehicle_id and style info in my view.
Completely new to Rails so I am little lost. Any help would be greatly appreciated.
The first thing you need to do is parse the JSON. This functionality is part of the Ruby language as of 1.9+:
#api_response = JSON.parse(data)
This converts the raw JSON (a string) into a queryable Ruby data structure (a hash). Next, you lookup items in the hash. Note that styles is an array, so there could be more than one vehicle_id returned.
Here are some examples of how you could use this in your template:
<%= #api_response["styles"].first["vehicle_id"] %>
Or, if you want to iterate over all styles:
<% #api_response["styles"].each do |h| %>
<%= h["vehicle_id"] %>: <%= h["style"] %>
<% end %>
You can read more about Ruby hashes in the Ruby docs.

Labels and Chartkick

Chartkick is amazing, and I can do super simple things like
<%= column_chart Device.joins(:reviews).group(:brand).average(:average_rating) %>
and get results like:
Now, the problem is that the labels aren't fed through to chartkick. This is what chartkick uses to render the chart:
Chartkick.ColumnChart("chart-5", {"#<Brand:0x00000008a3c048>":"78.8","#<Brand:0x0000000879e840>":"80.70000712076823","#<Brand:0x0000000853e9d8>":"81.11111111111111","#<Brand:0x000000082808e0>":"73.42857142857143"}, {});
So, the big question is... How can I use this super easy querying method but get the brand names on the chart?
I tried:
<%= column_chart Device.joins(:reviews).group(:'brand.name').average(:average_rating) %>
...and other variations to no avail...
Basically I just needed to make a small change to my query:
<%= column_chart Device.joins(:reviews).includes(:brand).group(:'brands.name').average(:average_rating) %>
Then I ended up re-ordering this by average ratings instead of brand name:
devices = Device.joins(:reviews).includes(:brand).group('brands.name').average(:average_rating)
arr = styles.to_a
arr.map! { |pair| [pair.first, pair.second.to_f] }
arr.sort! { |a, b| a.second <=> b.second }
#sorted_hash = ActiveSupport::OrderedHash[arr]
View:
<%= column_chart #sorted_hash %>
Bingo:

How to add "0," after each loop in Ruby

How to add "0," after each loop in Ruby (At the data: part of the series)
So first loop would
show only the value
next loop 0,value
next loop 0,0,value
next loop 0,0,0,value
etc..
series: [
<% #prot = ProjectTask.where("project_id = ? AND taskType = ?" ,#project.id, "Pre-Sales")%>
<% #prot.each do |prt| %>
<% hoursSum = 0 %>
{
name: '<%= prt.task_name%>',
data: [(here after each loop of #prot i want to add "0," here)<% #taskHours = Effort.where(:project_task_id => prt.id) %>
<% #taskHours.each do |th| %>
<% hoursSum = hoursSum + th.hours %>
<% end %>
<%= hoursSum%>
]
},<% end %>
<% #prot.each_with_index do |index, prt| %>
...
<%= "0," * index %>
...
<% end %>
This logic seems too complex to be in a view - I would migrate it to a helper function that builds up the data array and call that instead.
I think you'll find it a lot easier to do what you want then without having to deal with all the clutter of the erb tags etc. There's lots of ways you could do it - Yossi's suggestion of using each_with_index is a perfectly good one.
Two little things though - I would advise against shortened names for stuff like #prot - just call it #project_task. It's more readable and you can guarantee you call it the same thing throughout your code (instead of having some places where you call it #prot, others where it's #ptask etc) which will save you more time than you lose typing a longer name, I promise you.
Also - you use camelCase for some of your variables - I would advise sticking with the Ruby convention of snake_case.

Resources