Transpose, Slice and Inject From Multipe Arrays - ruby-on-rails

I don't know how appropriate title for this question.
Well, This is my problem
I have index action on homes_controller.rb looks like :
def index
#r = 2
#datas = [[1, 10], [2, 10], [3, 15], [4, 20], [5, 70], [6, 180], [7, 250], [8, 270], [9, 230], [10, 40], [11, 0], [12, 10]]
end
I want to result from above like this:
And on view looks like :
<table>
<thead>
<tr>
<th>Month</th>
<th>Forecast</th>
<th>Order</th>
<th>Begining Inventory</th>
<th>Ending Inventory</th>
</tr>
</thead>
<tbody>
<% ei = 0 %>
<% #datas.each_with_index do |d, index| %>
<tr>
<td><%= d[0] %></td>
<td><%= d[1] %></td>
<td><% if d[1] > bi %>
<% #datas.transpose.at(1).slice(index, #r).inject do |sum, s| -%>
<%= #biu = sum + s %>
<% end %>
<% end %>
</td>
<td><%= #bi = ei + #biu %></td>
<td><%= #ei = #bi - d[1] %></td>
</tr>
<% #biu = 0 %>
<% ei = #ei %>
<% end %>
</tbody>
</table>
State :
When the forecast d[1] is bigger than ei the calculation order #biu is 2 (#r) next of forecast.
Begining Inventory #bi is calculation from ei plus order #biu
Ending Inventory #ei is calculation from #bisubtracted with forecast d[1]
And then #ei put to ei
But the result like this :
I want 12th months must have : Order = 10, Begining invetory = 10, and Ending Inventory = 0

Your problem is here:
<% #datas.transpose.at(1).slice(index, #r).inject do |sum, s| -%>
<%= #biu = sum + s %>
<% end %>
When an array has only one item, inject without a starting value does not run the block at all:
puts [1,2].inject { |sum, s| puts 'was here!'; sum + s }
# was here!
# 3
puts [1].inject { |sum, s| puts 'was here!'; sum + s }
# 1
puts [1].inject(0) { |sum, s| puts 'was here!'; sum + s }
# was here!
# 1
If you add a starting value 0 to your code, though, #biu will be printed twice. To avoid that you need to move the assignment outside of the block:
<% #biu = #datas.transpose.at(1).slice(index, #r).inject do |sum, s| -%>
<% sum + s %>
<% end %>
<%= #biu %>
Or, more succinctly:
<%= #biu = #datas.transpose.at(1).slice(index, #r).inject(:+) %>

Related

Subtract current item with next indexed item

I'm trying to subtract the current item in the loop with the next indexed item, but I'm just getting the following error: undefined method `[]' for 0.0:Float
<% #trial.methods.each_with_index do |e, index| %>
<%= (e.total - e.total[index+1]) %><br />
<%= Time.at(e.try(:assessment).try(:assessment_date)/1000).strftime("%d/%m/%Y") %><br />
<%= e.try(:assessment).try(:degrees) %>
<% end %>
I think there is an easier way of doing that. Look at the following example.
# An array of 5 random numbers
a = [7,12,1,2,3]
# Iterate through the indices of the array
a.each_index do |i|
# We only show the result of a[i+1] - a[i]
# given i+1 is still in range of the array
puts "#{a[i+1] - a[i]}" if (i+1) < a.length
end
This should output 5 -11 1 1 each on a new line.
Similarly, you could do something like this:
<% #trial.methods.each_index do |i| %>
<% if i + 1 < e.total.length %>
<%= (e.total[i] - e.total[index+1]) %>
<% else %>
<%= 0 %>
<% end %>
<% end %>
Use #each_cons to build a subarray of consecutive pairs, then map it:
array = [7,12,1,2,3]
array.each_cons(2).map{ |e| e.last - e.first }
# => [5, -11, 1, 1]
A slight alternative:
array.each_cons(2).map{ |a, b| b - a }
Of course, you can change to a - b or whatever you need.
The first part does this:
array.each_cons(2).each {|e| p e}
# => [7, 12]
# => [12, 1]
# => [1, 2]
# => [2, 3]
You can use Enumerable#reduce to achieve this:
a = [7,12,1,2,3]
a.reduce(&:-) # -11
So for your case:
#trial.methods.map{|e| e.total}.reduce(&:-)
See https://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-reduce on its usage

Rails Multiple Variables

I have multiple variables which I'm having issues lining up in a table. I have each grouping by year, but when the table is generated if there is only one results for one of the columns it puts it in the first row, instead of the corresponding year.
Here is an image of what it's doing. The Drylands column should be in the year 2006.
View
<% #all.zip(#irrigated, #semi, #dryland) do |a, b, c, d| %>
<tr>
<td><%= a.year %></td>
<td><% if a.nil? %>0<% else %><%= a.trial_id %><% end %></td>
<td><% if a.nil? %>0<% else %><%= "%.2f" % (a.lint/227) %><% end %></td>
<td><% if b.nil? %>0<% else %><%= b.trial_id %><% end %></td>
<td><% if b.nil? %>0<% else %><%= "%.2f" % (b.lint/227) %><% end %></td>
<td><% if c.nil? %>0<% else %><%= c.trial_id %><% end %></td>
<td><% if c.nil? %>0<% else %><%= "%.2f" % (c.lint/227) %><% end %></td>
<td><% if d.nil? %>0<% else %><%= d.trial_id %><% end %></td>
<td><% if d.nil? %>0<% else %><%= "%.2f" % (d.lint/227) %><% end %></td>
</tr>
<% end %>
Controller
#variety = Variety.where(variety_id: params[:variety_select]).group('variety_name')
#all = Result.where(variety_id: params[:variety_select]).group('results.year').where('results.lint > 0').select('AVG(results.lint) AS lint, results.year as year, COUNT(results.trial_id) AS trial_id').joins(:trial)
#irrigated = Result.where(variety_id: params[:variety_select]).group('results.year').where('results.lint > 0').select('AVG(results.lint) AS lint, results.year as year, COUNT(results.trial_id) AS trial_id').joins(:trial).where('trials.irrigated = ?', '1')
#dryland = Result.where(variety_id: params[:variety_select]).group('results.year').where('results.lint > 0').select('AVG(results.lint) AS lint, results.year as year, COUNT(results.trial_id) AS trial_id').joins(:trial).where('trials.irrigated = ?', '0')
#semi = Result.where(variety_id: params[:variety_select]).group('results.year').where('results.lint > 0').select('AVG(results.lint) AS lint, results.year as year, COUNT(results.trial_id) AS trial_id').joins(:trial).where('trials.irrigated = ?', '2')
I first would check what the queries actually return. Do you have records in Drylands for years 2004 and 2005? It doesn't seem so.
Maybe you can do this
a is never nil, otherwise a.year would crash, so no need for a.nil?
for the other values (b, c, d) you can check if !b.nil? and b.year == a.year ...
This should only print values in the respective year rows

How can I iterate through an array in rails view?

I did a query in MySql but is working in Rails and mysql2 gem.
Here is the information:
http://sqlfiddle.com/#!2/9adb8/6
The query is working fine without problems and showing this result:
UNIT V1 A1 N1 V2 A2 N2 V3 A3 N3 V4 A4 N4 V5 A5 N5
LIFE 2 0 0 1 2 0 0 0 0 0 0 0 0 0 0
ROB 0 1 0 0 1 2 0 0 0 0 0 0 0 0 0
-Installed mysql2 gem for rails 2.3.8
gem install mysql2 -v0.2.6
-Created the controller:
class PolicyController < ApplicationController
def index
#result = ActiveRecord::Base.connection.execute("select distinct #sql := concat('SELECT pb.name as unit,',group_concat(concat('SUM(CASE WHEN p.state =0 AND ce.id=',id,' THEN 1 ELSE 0 END ) AS v',id,',SUM(CASE WHEN p.state =1 AND ce.id=',id,' THEN 1 ELSE 0 END ) AS a',id,',SUM(CASE WHEN p.state =2 AND ce.id=',id,' THEN 1 ELSE 0 END ) AS n',id)),' FROM cia_ensures ce LEFT JOIN policies p on ce.id = p.cia_ensure_id INNER JOIN policy_business_units pb ON pb.id = p.policy_business_unit_id INNER JOIN comercial_areas ca ON ca.id = pb.comercial_area_id AND ca.id=1 Group by p.policy_business_unit_id') from cia_ensures where id in(1,2,3,4,5);")
#result2 = ActiveRecord::Base.connection.execute("prepare stmt from #sql;")
#result3 = ActiveRecord::Base.connection.execute("execute stmt;")
end
end
Here is the log:
SQL (0.9ms) select distinct #sql := concat('SELECT pb.name as unit,',group_concat(concat('SUM(CASE WHEN p.state =0 AND ce.id=',id,' THEN 1 ELSE 0 END ) AS v',id,',SUM(CASE WHEN p.state =1 AND ce.id=',id,' THEN 1 ELSE 0 END ) AS a',id,',SUM(CASE WHEN p.state =2 AND ce.id=',id,' THEN 1 ELSE 0 END ) AS n',id)),' FROM cia_ensures ce LEFT JOIN policies p on ce.id = p.cia_ensure_id INNER JOIN policy_business_units pb ON pb.id = p.policy_business_unit_id INNER JOIN comercial_areas ca ON ca.id = pb.comercial_area_id AND ca.id=1 Group by p.policy_business_unit_id') from cia_ensures where id in(1,2,3,4,5);
SQL (0.9ms) prepare stmt from #sql;
SQL (0.2ms) execute stmt;
Here is the view (is working fine and without problems but seems to be too long write several times the same code)
<table>
<% #result3.each do |policy| %>
<tr>
<td><%= policy[0] %></td>
<td><%= policy[1] %></td>
<td><%= policy[2] %></td>
<td><%= policy[3] %></td>
<td><%= policy[4] %></td>
<td><%= policy[5] %></td>
...
</tr>
<%end%>
</table>
I tried to use inspect but it shows all the information in one td and not on each td:
<% #result3.each do |policy| %>
<tr>
<td align="center"><%= policy.inspect %></td>
</tr>
<%end%>
How can I do to show all this without writing lots of lines?
Is it possible to make this in one line? without writing <%= policy[#NUMBER] %>
Please somebody can help me with this?
I will really appreciate it.
Hmmm, might have missunderstood your question since it looks really simple, are you trying to shorten this?
Change:
<td><%= policy[0] %></td>
<td><%= policy[1] %></td>
<td><%= policy[2] %></td>
<td><%= policy[3] %></td>
<td><%= policy[4] %></td>
<td><%= policy[5] %></td>
To:
<% policy.each do |p| %>
<td><%= p %></td>
<% end %>
Do this
<% #result3.each do |policy| %>
<tr>
<% policy.each { |p| raw "<td>#{p}</td>" } %>
</tr>
<%end%>
Just iterate over each collection in each policy object.
<table>
<% #result3.each do |policy| %>
<tr>
<%policy.each do |item| %>
<td><%= item %></td>
<%end%>
</tr>
<%end%>
</table>

Dynamically display table based on conditions

Hello my fellow programmers, I am a ruby on rails noob and need some help:
Based on today's date I am querying the db and getting the results as an array.
#cr = [#<CRate id: 1, currency: "AUD", rate: 2.0, datetime: "2013-10-09 22:59:59">,
#<CRate id: 7, currency: "USD", rate: 10.0, datetime: "2013-10-09 29:50:50">,
#<CRate id: 9, currency: "EUR", rate: 20.0, datetime: "2013-10-09 22:59:59">,
#<CRate id: 12, currency: "RUB", rate: 12.0, datetime: "2013-10-09 22:59:59">,
#<CRate id: 14, currency: "AUD", rate: 18.0, datetime: "2013-10-09 29:50:50">]
Question: I need to dynamically display the table based on currency(header), depending on the time, if rate exist then I display it else output is nil. Like this table below:
I have tried to do this:
<table>
<thead>
<th>Time</th>
<% #currency = #cr.collect(&:currency) %>
<% #currency.each do |cur| %>
<th><%= cur %></th>
<% end %>
</thead>
<tbody>
<tr class="<%= cycle('odd', 'even') %>">
<td><%= #datetime = #cr.collect(&:datetime) %></td>
<% #rate = #cr.collect(&:rate) %>
<% #rate.each do |r| %>
<td><%= r %></td>
<% end %>
</tr>
</tbody>
</table>
This doesn't work because the thead is updated with 2 AUD's and I don't know how to proceed. Please help.
Thanks a lot.
First, you need unique currency types, so line no. 4 will be:
<% #currency = #cr.collect(&:currency).uniq %>
Secondly, you need to get rates based on datetime and currency type (since you have not specified Rails version, I will try and write a working solution which might not be best solution):
<tbody>
<% #datetime = #cr.collect(&:datetime).uniq %>
<% #datetime.each do |dt| %>
<tr class="<%= cycle('odd', 'even') %>">
<td><%= dt %></td>
<% #currency.each do |curr| %>
<td><%= #cr.select {|o| o.currency == curr && o.datetime == dt}.rate %></td>
<% end %>
</tr>
<% end %>
</tbody>
HTH
Edit: This seems to be an inefficient way to solve this problem because you are relying too much on arrays in a way that they will always come in order you are expecting. I would like rather create a Hash (better known as key-value pair) of #cr like {'first_datetime' => {'AUD' => '10', 'RUB' => '20'}, 'second_datetime' => {'AUD' => '50', 'RUB' => ''}} and so forth.
Edit 2: In your controller, create a hash and 2 sets like:
#currencies = Set.new
#datetimes = Set.new
#currency_rate_datewise = Hash.new {|h, k| h[k] = {}}
#cr.each do |cr|
#currencies.add cr.currency
#datetimes.add cr.datetime
#currency_rate_datewise[cr.datetime][cr.currency] = cr.rate
end
Now your view could be simplified to:
<table>
<thead>
<th>Time</th>
<% #currencies.each do |cur| %>
<th><%= cur %></th>
<% end %>
</thead>
<tbody>
<% #datetimes.each do |datetime| %>
<tr class="<%= cycle('odd', 'even') %>">
<td><%= datetime %></td>
<% #currencies.each do |currency| %>
<td><%= #currency_rate_datewise[datetime][currency] || 'nil' %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
Although, I would have used group_by selectively, but I guess, it is better if you stick with learning such things at beginner's stage. I have written this from top of my head, please post a comment if something's wrong.
HTH
you can use the group_by rails helper for that. see the documentation:
group_by() Collect an enumerable into sets, grouped by the result of a
block. Useful, for example, for grouping records by date.
Example:
latest_transcripts.group_by(&:day).each do |day, transcripts|
p "#{day} -> #{transcripts.map(&:class).join(', ')}"
end
"2006-03-01 -> Transcript"
"2006-02-28 -> Transcript"
"2006-02-27 -> Transcript, Transcript"
"2006-02-26 -> Transcript, Transcript"
"2006-02-25 -> Transcript"
"2006-02-24 -> Transcript, Transcript"
"2006-02-23 -> Transcript"

Creating a table in HTML with Ruby?

I am trying to make a table with ten values across on each row starting at 1 and going to 100.
My Ruby code looks like this:
<table border="1">
<% (1..100).each do |i|
d3 = (i % 3 == 0)
d5 = (i % 5 == 0)
i = "<b>#{i}</b>" if d5
i = "<i>#{i}</i>" if d3 %>
<tr>
<td><%= i %></td>
</tr>
<% end %>
</table>
How would I put this in an HTML table in a 10 X 10?
Using ERB:
<table>
<%10.times do |row|%>
<tr>
<%10.times do |col|%>
<td><%=
i = row*10+col+1
if i%5==0
"<b>#{i}</b>"
elsif i%3==0
"<i>#{i}</i>"
else
i
end
%></td>
<%end%>
</tr>
<%end%>
</table>
Using Haml:
%table
- 10.times do |row|
%tr
- 10.times do |col|
%td
- i = row*10+col+1
= i%5==0 ? "<b>#{i}</b>" : i%3==0 ? "<i>#{i}</i>" : i
<table border="1">
<% (1..100).each do |i|
d3 = (i % 3 == 0)
d5 = (i % 5 == 0)
s = "#{i}"
s = "<b>#{i}</b>" if d5
s = "<i>#{i}</i>" if d3 %>
<% if i % 10 == 1 %><tr><% end %>
<td><%= s %></td>
<% if i % 10 == 0 %></tr><% end %>
<% end %>
</table>
Basically, you want to start a table row before elements 1, 11, 21, etc. and end a row after elements 10, 20, 30, etc.

Resources