How to sum fields after group_by - ruby-on-rails

I need to group some records by date, then sum one field for each of those days.
This is the code I'm trying to refactor:
<% #startdate.upto(#enddate) do |date| %>
<% visitors = #links.where("created_at >= ? AND created_at < ?", date, date+1).order("created_at ASC").select("id, visit_count") %>
<%= datevisitors.sum("visit_count") || 0 %>
<% end %>
I've started with:
<% visitors = #links.select("visit_count, created_at").group_by{|l| l.created_at.day} %>
<% #startdate.upto(#enddate) do |date| %>
<%= visitors[date] ...?
<% end %>

When you group_by something, you receive an array of the day and the element. So if you group by day, you'll have the Day and the elements that are part of the array:
<% #links.group_by{|l| l.created_at.day}.each do |day, links| %>
<p><%= day %>: <%= links.sum(&:visit_count) %></p>
<% end %>
EDIT --
OK, in that case your code looks like it was very close:
<% visitors = #links.select("visit_count, created_at").group_by{|l| l.created_at.day} %>
<% #startdate.upto(#enddate) do |date| %>
<% if visitors[date] %>
<%= visitors[date].sum(&:visit_count) %>
<% else %>
0
<% end %>
<% end %>
It's probably better to move this to a helper (or presenter)
def daily_visits(links, from, to)
links_by_day = links.select("visit_count, created_at").group_by{|l| l.created_at.day}
range = from.upto(to).to_a
range.inject({}) do |date, hash|
hash[date] = links_by_day.fetch(date, 0)
end
end
Then, in the view:
<% daily_visits(#links, #startdate, #enddate).each do |day, count| %>
<%= day %>: <%= count %>
<% end %>

This should be on controller
#dates_with_visitors = #links.select("visit_count, created_at").group_by(&:created_at)
This should be on the view
<% #dates_with_visitors.each do |date_with_visitors| %>
<%= "#{date_with_visitor[0]} - Visits: #{date_with_visitors[1].sum(&:visit_count)}" %>
<% end %>

Hi can you give me the Model that will be used?
Here's my example on a Activerecord with a aggregate sum function:
<% #sum_visit_count = Visitor.find(:all, :select => "SUM(visit_count)", :group => "id, date_visit") %>
and
<%= #sum_visit_count.sum %>

Related

Output sum of decimal/float array rails

I have the following which i thought would get me the sum of the array but doesnt:
<% #orders.each do |order| %>
<% if Product.exists?(sku: order.line_items.where().map {|li| li.sku }) %>
<%= order.line_items.where(vendor_name: #vendor.vendor_name).map do |li| %>
<% if Product.exists?(sku: li.sku) %>
<% product = Product.find_by(sku: li.sku ) %>
<% ((li.store_price.to_d * li.store_fulfillable_quantity) - (product.production_price * li.store_fulfillable_quantity)) * (0.70) %>
<% end %>
<% end.compact.sum %>
<% end %>
<% end %>
The output is something like:
25.21 25.21 12.66 5.33 12.66 9.01
I need to add these numbers. How can I do this with the decimals/floats?
When I use
<%= #orders.each do |order| %>
I get undefined method + for nilclass for the line that is on, and it's not nil but obviously I'm missing some factor on how sum works.
<%= #orders.map do |order| %>
<% if Product.exists?(sku: order.line_items.where().map {|li| li.sku }) %>
<% order.line_items.where(vendor_name: #vendor.vendor_name).map do |li| %>
<% if Product.exists?(sku: li.sku) %>
<% product = Product.find_by(sku: li.sku ) %>
<% ((li.store_price.to_d * li.store_fulfillable_quantity) - (product.production_price * li.store_fulfillable_quantity)) * (0.70) %>
<% end %>
<% end.compact.sum %>
<% end %>
<% end.compact.sum %>
Is how i got it to work
method reduce in arrays designed for getting reduced value of collection:
array.compact.reduce(:+)
# => Sum of array
more info about reduce

Get ActiveRecord value with outer index on Rails4

When I get List of Members in controller, I think #Members is array of ActiveRecord.
member_controller.rb
#members = Member.where(params[:param1])
So I know normally I write below to display.
member.html.erb
<% #members.each do |member| %>
<%= member.name %>
<% end %>
But in case of below, I would like to write index number at least loop 10 times like this.
<% (0..10).each do |idx| %>
<%= idx %>:
<%= members[idx].name %>
<% end %>
But it does not work. It can not be displayed members[idx].name
How can I make it?
Why don't you just use each_with_index method?
<% #members.each_with_index do |member, index| %>
<%= index %>
<%= member.name %>
<% end %>
If you need only 10 records, limit #members at the controller:
#members = Member.where(column: params[:column]).limit(10)
Does this help you?
Fix is
<% (0..10).each do |idx| %>
<%= idx %>:
<%= #members[idx].name %>
<% end %>
You forgot to use #. It should be #members, not members. And, if your query to the controller returns less than 10, then your looping way will crash. You will get the error,NoMethodError like NoMethodError: undefined method name' for nil:NilClass.
You can do as,
<% #members.each_index do |idx| %>
<%= idx %>:
<%= #members[idx].name %>
<% end %>
You can use each_with_index:
<% #members.each_with_index do |member, idx| %>
<%= idx %>:
<%= member.name %>
<% end %>
You could then use limit to limit the number of records returned.
Shouldn't it be
<% (0..10).each do |idx| %>
<%= idx %>:
<%= #members[idx].name %> #you forgot '#'here
<% end %>
Though each_with_index is a better option here
Thank you all. It worked!!
<% (0..10).each do |idx| %>
<%= idx %>:
<%= #members[idx].nil? ? '': #members[idx].name %>
<% end %>

Rails element if first time appearance

I have a model Post with :mark, :text
I have a list with my post
<% #posts.each do |p| %>
# todo
<% if p.mark? %>
<%= p.mark %> <%= sweet_thing(p.text) %>
<% else %>
<%= sweet_thing(p.text) %>
<% end %>
<% end %>
I need to show p.mark name instead #todo where p.mark first time appearance.
Final txt example:
Audi
Audi, text-text-text-text.
Audi, text-text-text-text.
Audi, text-text-text-text.
Ford
Ford, text-text-text-text.
Ford, text-text-text-text.
Ford, text-text-text-text.
Ford, text-text-text-text.
UPDATE
My txt render in controller
def txt_receiver
#posts = Post.where("created_at >= ?", 7.days.ago.utc).find(:all, order: "mark, LOWER(post)")
render "txt_for_newspapper", formats: ["text"]
end
An obvious solution is to keep track of seen marks.
<% seen_marks = {} %>
<% #posts.each do |p| %>
<% unless seen_marks[p.mark] %>
<%= p.mark %>
<% seen_marks[p.mark] = true %>
<% end %>
# rest of your code
<% end %>
A better solution (I think) involves grouping posts by their mark and then outputting in groups. But I'm not sure whether it will match your logic regarding missing marks.
<% #posts.group_by(&:mark).each do |mark, posts| %>
<%= mark %>
<% posts.each do |p| %>
<%= p.mark if mark %> <%= sweet_thing(p.text) %>
<% end %>
<% end %>

How to show parent and child in view with will paginate?

I'm having trouble showing my view correctly. I have this as my code right now:
<% for store in #stores %>
<% store.name %>
<% #stores.products.each do |p| %>
<% p.name %>
<% end %>
<% end %>
def index
#stores = Store.paginate(:page => params[:page], :per_page => 20)
end
But end up with the error:
undefined method `products'
I'm trying to show a store and then all of its products, repeating this on the same page as much as possible e.g:
Store1
Product1
Product2
Store2
Product1
Product2
Product3
Product4
How can I do this?
Instead of <% #stores.products.each do |p| %> I think you mean <% store.products.each do |p| %>:
Also, do you not mean to have <%= on the store.name and p.name lines?
<% for store in #stores %>
<%= store.name %>
<% store.products.each do |p| %>
<%= p.name %>
<% end %>
<% end %>
Shouldn't that be store.products inside the loop, where you're accessing store?
<% for store in #stores %>
<%= store.name %>
<% store.products.each do |p| %>
<%= p.name %>
<% end %>
<% end %>
And = is added to the output lines. <%=

how can i compare the selected values with the existing one in rails

I have a view like this,
<% count = 1 %>
<% for voting in #voting %>
<% if voting.question_id.eql?(count) %>
<%= radio_button( count, voting.vote_count, :radio_id => voting.nominees ) %>
<%= voting.nominees %>
<% end %>
<% if voting.nominees.eql?(radio_id) %>
<% voting.update_attribute('vote_count', voting.vote_count+1 ) %>
<% end %>
<% count += 1 %>
<% end %>
how can i compare the selected nominees with the existing one.
any help on this would be very useful...
Some models and associations would be handy here. I suspect options_from_collection_for_select will be your best friend. Also look at increment.

Resources