Variables with conditionals - ruby-on-rails

I have a conditional statement which determines the color of my highcharts lines. I have multiple charts in which I'd like to repeat this conditional. Currently I'm finding that I have to repeat the code in each chart as I can't seem to do a variable with the conditionals stored. This goes against any DRY method, and will seem troublesome in the future.
My chart (using Lazy highcharts gem)
#chart_1 = LazyHighCharts::HighChart.new('graph') do |f|
#sales.sale_selections.flat_map { |ss|
f.series(animation: false, type: 'spline', name: ss.sale_type.name,
data: ts.sale_methods.map { |sm| { y: sm.sales_total.to_f, x: sm.days }}, color:
if ss.sale_type.name.include? 'soda'
'red'
elsif ss.sale_type.name.include? 'chips'
'blue'
else
'black'
end
)}
end
Is it possible to have the conditional as a variable in which to call upon when needed. For example (which doesn't work, but using as a example):
#colours = if ss.sale_type.name.include? 'soda'
'red'
elsif ss.sale_type.name.include? 'chips'
'blue'
else
'black'
end

Yes. Write a function to return the color you want.
def row_color(sale_type_name)
if sale_type_name.include? 'soda'
'red'
elsif sale_type_name.include? 'chips'
'blue'
else
'black'
end
end
Then call the function to get the color
#colour = row_color(ss.sale_type.name)

Related

Rails ActiveRecord Query Order by day

I'm trying to sort/order my records to display them in Chart.js
I want to display meal orders from Monday to Sunday with ascending order, there are 3 different meals every day. It's kinda working if every meal if present on each day, but if one kind of meal isn't ordered, for example, the order of the days gets weird.
Here is an example where it isn't working as I intended:
So as you see (don't mind the german language :D) the starting is right Monday, ... Thursday, ... Saturday, that's fine, but the order on Friday (the green one) is another meal as on the other days and so Friday is shown after Saturday, but I want it to be shown between Thursday and Saturday.
Here are my queries for ActiveRecord:
def self.weeklyVollkostOverview
where(day: Date.today.beginning_of_week..Date.today.end_of_week).where(dish_type: 0).group(:day).order("day ASC").count
end
def self.weeklySchonkostOverview
where(day: Date.today.beginning_of_week .. Date.today.end_of_week).where(dish_type: 1).group(:day).order("day ASC").count
end
def self.weeklyVegetarischOverview
where(day: Date.today.beginning_of_week .. Date.today.end_of_week).where(dish_type: 2).group(:day).order("day ASC").count
end
In my controller, I'm mapping the results:
#weeklyVoll = OrderCard.weeklyVollkostOverview.map { |key, value| [I18n.l(key, format: "%A", locale: :'de'), value]}
#weeklySchon = OrderCard.weeklySchonkostOverview.map { |key, value| [I18n.l(key, format: "%A", locale: :'de'), value]}
#weeklyVegetarisch = OrderCard.weeklyVegetarischOverview.map { |key, value| [I18n.l(key, format: "%A", locale: :'de'), value]}
Finally, I display the results in my chart.
Is there anything I could do different or that's easier?
I know I could use Groupdate-Gem, but there's an issue for date objects and time zone conversion, so I'm trying to do it manually.
EDIT:
The variables #weeklyVoll, #weeklySchon, and #weeklyVegetarisch are for display purposes in my view where the charts are:
<%= column_chart [
{ name: "# Bestellungen Vollkost", data: #weeklyVoll },
{ name: "# Bestellungen Schonkost", data: #weeklySchon },
{ name: "# Bestellungen Vegetarisch", data: #weeklyVegetarisch }
],
colors: ["red", "yellow", "green"],
xtitle: "Wochentag",
ytitle: "# Bestellungen",
legend: true,
legend: "bottom",
messages: { empty: "Noch keine Daten vorhanden!" },
library: { scales: { yAxes: [{ gridLines: { display: true }, ticks: { precision: 0 } } ] }, animation: {easing: 'easeOutQuad', duration: 2500} }
%>
Any help is appreciated! Thanks!
I think the issue is having the three different arrays. If you were to group on day/dish_type and then call count at the end it should give a results like ['Day', 'Dish Type'] => 3. You would then have to iterate through and format again as needed. I tend to use each_with_object.
OrderCard.where(day: Date.today.all_week)
.group(:day, :dish_type).count
# => ['Day', 'Dish Type'] => 3

Drawing linear function by using Chartkick gem and Google chart

I am trying to draw a linear function(like y=ax+b) by using Chartkick gem and google chart on my rails application.
'a' and 'b' will be given as parameters.
The problem is that I am trying to achieve an infinite line graph using google chart out of slope 'a' and 'b' and I don't know how to achieve this in a proper way.
I came up with the solution of drawing a line chart with two points, (-b/a, 0) and (0, b) and give trendlines option onto it.
<!-- y = 0.55x floatify(2,#datas[4][2]) + 1.47 floatify(2,#datas[3][2]) -->
<%= line_chart [
{name: "targets",
data: [
["#{-(#datas[3][2].to_f/#datas[4][2].to_f).round(2)}",0],
[0,"#{#datas[3][2].to_f}"]
]
},
],
library: {
title: "#{#simplereg.variable_name}",
subtitle: "#{#simplereg.data_name}",
legend: "right",
vAxis: {title: 'average'},
trendlines: {
0: {
type: 'exponential',
visibleInLegend: true
}
}
}
%>
However, rails cannot read a '0' value as an option of trendlines unlike what google chart documentation says.
-> https://developers.google.com/chart/interactive/docs/gallery/trendlines
I have no clue how to fix this code to work.
Please help me... I don't mind throwing up this code and writing in completely different way.
Thanks ahead.
Use something like below
<%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
<%= line_chart [
{name: "targets",
data: [
["-2/3",0],
[0,"2"]
]
},
],
library: {
title: "ABC",
subtitle: "XYZ",
legend: "right",
vAxis: {title: 'average'},
trendlines: {
"0"=> {
type: 'exponential',
visibleInLegend: true
}
}
}
%>
basically instead of symbo 0: use "0" =>

Can't see the labels on Pie HighCharts

I'm using Ruby on Rails and HighCharts:
So here is the print-screen that I see when setting my highchart:
Here is the code:
#chart = LazyHighCharts::HighChart.new('pie') do |f|
f.chart({:defaultSeriesType=>"pie" , :margin=> [50, 200, 60, 170]} )
series = {
:type => 'pie',
:name => 'Browser share',
:data => [['say', 100],['may', 500]]
}
f.series(series)
f.options[:title][:text] = "Total spend on services"
f.legend(:layout=> 'vertical',:style=> {:left=> 'auto', :bottom=> 'auto',:right=> '50px',:top=> '100px'})
f.plot_options(:pie=>{
:allowPointSelect=>true,
:cursor=>"pointer" ,
:dataLabels=>{
:enabled=>true,
:color=>"white",
:style=>{
:font=>"13px Trebuchet MS, Verdana, sans-serif"
}
}
})
end
All is good, apart from I don't see the labels on the pie... It seems there is a small string below the chart, however the label is not initialized.
Anyone know how to solve this issue?
Is it because you have it set to white?
:color=>"white",

afterSetExtremes callback for highcharts

I'm creating a highchart using the lazy_highcharts gem. I'd like to make use of the afterSetExtremes callback to regenerate some other data on the page on zooming. I've tried several ways, currently trying:
#chart = LazyHighCharts::HighChart.new('graph') do |f|
f.chart(:zoomType =>'x', :defaultSeriesType => 'spline')
f.x_axis(:type=> 'datetime', :events => {:afterSetExtremes => "functon(event){alert('something')}"} )
end
But that gives me the error
Uncaught TypeError: Object functon(event){alert('something')} has no method 'apply'
in the javascript console when I zoom the chart. I assume this has something to do with the generator not correctly setting up the callback function, setting it as a string instead of interpreting it as a function.
I've also tried to set it on my chart object via javascript after creation, but so far have had no luck with that. A few attempts below
chart_my_id4.xAxis.events = {setExtremes: function(event) {
alert('set extremes');
}};
chart_my_id4.xAxis[1].events = {setExtremes: function(event) {
alert('set extremes');
}};
No luck there either.
Any insight appreciated, thank you.
Not too familiar with ... ruby, but I took a look at the source on github and they do the following when they set functions into attributes:
:formatter => "function() { return this.x; }".js_code
It would be worth a try to add that .js_code and see if it works so you end up with:
#chart = LazyHighCharts::HighChart.new('graph') do |f|
f.chart(:zoomType =>'x', :defaultSeriesType => 'spline')
f.x_axis(:type=> 'datetime', :events => {
:afterSetExtremes => "functon(event){alert('something')}".js_code
})
end
I'm not familiar with that gem, but in standard Highcharts 3.0 you can add event in that way:
chart.yAxis[0].update({
events: {
afterSetExtremes: function(){
alert('x');
}
}
});
You can do this like that :
LazyHighCharts::HighChart.new('graph') do |f|
...
f.xAxis(:events => { :afterSetExtremes => after_set_extremes_function})
end
-
def after_set_extremes_function
%|function(e) {
chart = Highcharts.charts[0];
chart.showLoading('Loading data...');
$.getJSON("/path_to_your_action?start="+Math.round(e.min)+"&end="+Math.round(e.max), function(data) {
chart.series[0].setData(data);
chart.hideLoading();
}
}
);
}|.js_code
end

Highcharts - Rails array includes empty date entries

I'm working on a Rails 3.1.1 app with a dashboard of various line graphs using Highcharts. I implemented the sample code in Railcast 223 (highcharts) -- and everything works as expected. But on days when no entries exists, the array plots a 0 value -- but I'm only looking to line graph actual records.
Its not an issue with the Railscast because they sample has multiple Order entries each day. It appears to be the same issue posted by another user (Thomas)...though his code didn't work in my situation.
Index view:
$(function () {
new Highcharts.Chart({
chart: { renderTo: 'orders_chart' },
title: { text: 'Orders by Day' },
xAxis: { type: 'datetime' },
yAxis: {
title: { text: 'Dollars' }
},
tooltip: {
formatter: function () {
return Highcharts.dateFormat("%B %e %Y", this.x) + ': ' +
'$' + Highcharts.numberFormat(this.y, 2);
}
},
series: [{
pointInterval: <%= 1.day * 1000 %>,
pointStart: <%= 3.weeks.ago.at_midnight.to_i * 1000 %>,
data: <%= (3.weeks.ago.to_date..Date.today).map { |date| Order.total_on(date).to_f}.inspect %>
}]
});
});
class Order < ActiveRecord::Base
def self.total_on(date)
where("date(purchased_at) = ?",date).sum(:total_price)
end
end
Any input would be greatly appreciate -- new to rails and have already found the 100 ways the don't work! Thanks!
If you want nothing to be graphed but the date to still show up, then change any zeroes to a javascript null. If you want to not graph those days, then you should reject them from the array before output.
So:
(3.weeks.ago.to_date..Date.today).map{|date| total=Order.total_on(date).to_f; total.zero? ? "null" : total }.inspect
Or:
(3.weeks.ago.to_date..Date.today).map{|date| Order.total_on(date).to_f}.reject(&:zero?).inspect

Resources