I have a table of events that have start and end dates.
Now I want to fetch events for particular dates. i.e if I supply 1 May 2014, 2 May 2004, I need all events happening on that day (based on start and end dates). And I need to group the events based on the start date and display them as a list.
Now problem is if an event takes place on two days, say 1 May and 2 May, I need to display the event twice in the list like so:
1 May 2014
EventName
2 May 2014
EventName
I am not sure how to do this... Can anyone help me come up with an efficient way to do this?
To get the events to appear twice I would add separately created collections together.
events = []
(start_date..end_date).each do |date|
events += Event.where("start_date >= ? and end_date <= ?", date, date)
end
events
events = Event.where("start_date >= ? AND end_date <= ?", start_date, end_date)
display_events = Hash.new
(start_date..end_date).each do |date|
display_events[date] << events.select { |event| event.start_date <= date and event.end_date >= date }
end
Here you end up having a hash with events grouped by date. (I'm on cellphone, so I couldn't test it)
Try to fetch and display all events on each day.i.e iterate data not on the basis on event rather iterate on the basis of event dates.
s_date = Date.parse('2010-09-29')
e_date = Date.parse('2010-09-30')
sd.upto(ed) do |date|
#events = Event.event_on_date(date)
end
Related
Im trying to gather all sales made within a week and put each sale in day made. If Moday was two sales, then Monday => {...}, {...} etc
"Monday" would be ruby's date format.
In my db I have 5 sale objects: Two sales on Monday and two on Tuesday.
Controller:
def daily_customer_sale(created)
date_and_id = Sale.where('created_at >= ?', created).pluck(:created_at, :id)
date_and_id.each do |obj|
yield(obj.first, obj.last)
end
end
def daily_sales(created=nil)
sales_by_date = Hash.new(0)
daily_customer_sale(created) do |date, id|
s_date = date.to_date
sales_by_date[s_date] = Sale.find(id) # Seems to return only one object per day
end
return sales_by_date
end
For views:
daily_sales(1.week.ago.to_datetime)
What I get in two dates (correct) in which each data has only one object when it should be two or more per date. Is there something wrong?
You don't need complex logic to do it. Here is a cleaner way
Sale.where('created_at >= ?', created_at).group_by{ |sale| sale.created_at.to_date}
It will return All the sales grouped by day.
key will be date object and for each day there will be sale array containing all of the sales for that day.
If you need string based key you can format it as you like as per below
Sale.where('created_at >= ?', created_at).group_by{ |sale| sale.created_at.to_date.to_s } #default date format
Sale.where('created_at >= ?', created_at).group_by{ |sale| sale.created_at.to_date.strftime("%d/%m/%Y") } #23/09/2016
You can have a look at Group by method
I want to find signup count daily, for the date range say this month. so
starts_at = DateTime.now.beginning_of_month
ends_at = DateTime.now.end_of_month
dates = ((starts_at.to_date)..(ends_at.to_date)).to_a
dates.each_with_index do |date,i|
User.where("created_at >= ? and created_at <= ?", date, date.tomorrow)
end
So nearly 30 queries running, how to avoid running 30 query and do it in single query?
I need something like
group_by(:created_at)
But in group by if there is no data present for particular date it's showing nothing, but I need date and count as 0
I followed this:
How do I group by day instead of date?
def group_by_criteria
created_at.to_date.to_s(:db)
end
User.all.group_by(&:group_by_criteria).map {|k,v| [k, v.length]}.sort
Output
[["2016-02-05", 5], ["2016-02-06", 12], ["2016-02-08", 6]]
There is no data for 2016-02-05 so it should be included with count 0
I can't test it at the moment, but it should be possible to filter your date range and group it with a little help of your dbms like this:
User.select('DATE(created_at)').where("created_at >= ? and created_at <= ?", DateTime.now.beginning_of_month, DateTime.now.end_of_month).group('DATE(created_at)').count
Would this do?
starts_at = DateTime.now.beginning_of_month
ends_at = DateTime.now.end_of_month
User.where(created_at: starts_at..ends_at).group("date(created_at)").count
# => {Tue, 09 Feb 2016=>151, Mon, 08 Feb 2016=>130}
Note that you won't get any results for dates when there has been zero creations, so you might want to do something like this:
Hash[*(starts_at..ends_at).to_a.flat_map{|d| [d, 0]}].merge(
User.where(created_at: starts_at..ends_at).group("date(created_at)").count
)
Not pretty, but what happens there is you first create a hash with all dates in the range having zero values and merging the results from database into that hash.
I'm using Rails 4
I am trying to find all bookings with an arrival date within the next 5 days. arrival is a date datatype. Here is my attempt:
#bookings = Booking.where("? > arrival-5.days", Time.now.to_date)
I've also tried:
#bookings = Booking.where("? > ?", Time.now.to_date, arrival-5.days)
but neither work. How could I get this to work?
#bookings = Booking.where(["arrival <= ?", 5.days.from_now])
This would also pull in bookings from yesterday, but I'll let you figure that one out.
I'm trying to create an array of dates for a calendar where there are a few extra day for the next and previous month that will fill in the week.
Here is my current method to try and get the array
def calendar
selected_month = Date.civil((Time.zone.now.year).to_i, (Time.zone.now.month).to_i)
start_date = selected_month.beginning_of_month
start_date.sunday? ? start_date : start_date.beginning_of_week.advance(:days => -1)
end_date = selected_month.end_of_month
end_date.sunday? ? end_date.advance(:days => 1).end_of_week : end_date
#only puts 1-30/31 and does not include the extra off set of days from start and end. :(
date_range = (start_date..end_date).to_a
end
The problem is the rang only start at 1 and goes to the end of the month even though the start and end days exceed that.
I'm not married to this way of getting the array so maybe you have a better whole idea?
You forgot to reassign the values of start_date and end_date.
start_date = selected_month.beginning_of_month
start_date = start_date.sunday? ? start_date : start_date.beginning_of_week.advance(:days => -1)
end_date = selected_month.end_of_month
end_date = end_date.sunday? ? end_date.advance(:days => 1).end_of_week : end_date
I have a table with a float called 'cost' and timestamp called'created_at'.
I would like it to output an array with the summing the costs for each particular day in the last month.
Something like:
#newarray = [] #creating the new array
month = Date.today.month # Current Month
year = Date.today.year # Current Year
counter = 1 # First Day of month
31.times do #for each day of the month (max 31)
#adding sales figures for that day
#newarray.push(Order.sum(:cost, :conditions => {:created_at => "#{year}-#{month}-#{counter}"}))
counter = counter + 1 #go onto next day
end
However this doesn't work as all the timestamps have a time as well.
Apologies in advance for the poor title, I can't seem to think of a sensible one.
You should be able to use code like the following:
sales_by_day = Order.sum(:cost,
:group => 'DATE(created_at)',
:conditions => ['DATE(created_at) > ?', 31.days.ago])
(0..30).collect { |d| sales_by_day[d.days.ago.to_date.to_s] || 0 }.reverse
This will sum the order cost by day, then create an array with index 0 being the last 24 hours. It will also take only one query, whereas your example would take 31.
To change the cut off date, replace 31.days.ago with an instance of the Time class. Documentation here: http://ruby-doc.org/core/classes/Time.html
Good luck!
This should work:
(Date.today.beginning_of_month..Date.today.end_of_month).map { |d|
Order.sum(:cost, :conditions => ['created_at >= ? AND created_at < ?', d, d+1])
}
Although I think you should try getting it using a single query, instead of making one for each day.