lib/groupdate/series.rb in groupdate-1.0.5 vs lib/groupdate/series.rb in groupdate-2.0.0

- old
+ new

@@ -1,19 +1,20 @@ module Groupdate class Series - def initialize(relation, field, column, time_zone, time_range, week_start) + def initialize(relation, field, column, time_zone, time_range, week_start, day_start) if time_range.is_a?(Range) # doesn't matter whether we include the end of a ... range - it will be excluded later @relation = relation.where("#{column} >= ? AND #{column} <= ?", time_range.first, time_range.last) else @relation = relation.where("#{column} IS NOT NULL") end @field = field @time_zone = time_zone @time_range = time_range @week_start = week_start + @day_start = day_start end def build_series(count) utc = ActiveSupport::TimeZone["UTC"] @@ -41,41 +42,46 @@ # use first and last values sorted_keys = count.keys.sort sorted_keys.first..sorted_keys.last end - # determine start time - time = time_range.first.to_time.in_time_zone(@time_zone) - starts_at = - case @field - when "second" - time.change(:usec => 0) - when "minute" - time.change(:sec => 0) - when "hour" - time.change(:min => 0) - when "day" - time.beginning_of_day - when "week" - # same logic as MySQL group - weekday = (time.wday - 1) % 7 - (time - ((7 - @week_start + weekday) % 7).days).midnight - when "month" - time.beginning_of_month - else # year - time.beginning_of_year - end + if time_range.first + # determine start time + time = time_range.first.to_time.in_time_zone(@time_zone) - @day_start.hours + starts_at = + case @field + when "second" + time.change(:usec => 0) + when "minute" + time.change(:sec => 0) + when "hour" + time.change(:min => 0) + when "day" + time.beginning_of_day + when "week" + # same logic as MySQL group + weekday = (time.wday - 1) % 7 + (time - ((7 - @week_start + weekday) % 7).days).midnight + when "month" + time.beginning_of_month + else # year + time.beginning_of_year + end - series = [starts_at] + starts_at += @day_start.hours + series = [starts_at] - step = 1.send(@field) + step = 1.send(@field) - while time_range.cover?(series.last + step) - series << series.last + step - end + while time_range.cover?(series.last + step) + series << series.last + step + end - series.map{|s| s.to_time.utc } + series.map{|s| s.to_time.utc } + else + [] + end end Hash[series.map do |k| [k, count[k] || 0] end] @@ -83,9 +89,11 @@ def method_missing(method, *args, &block) # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/calculations.rb if ActiveRecord::Calculations.method_defined?(method) build_series(@relation.send(method, *args, &block)) + elsif [:joins, :includes, :where].include?(method) + raise NoMethodError, "#{method} must come before the group_by_#{@field} method" else raise NoMethodError, "valid methods are: #{ActiveRecord::Calculations.instance_methods.join(", ")}" end end