Class: LucidWorks::Datasource::Schedule
- Defined in:
- lib/lucid_works/datasource/schedule.rb
Overview
Datasource::Schedule supplies numerous convenience methods to make it easy and clean to display and set schedules in simple formats
The simple formats supported are:
hourly at 15 minutes past the hour # => {:frequency => 'hourly', :start => {:minutes => 15}}
daily at 3:15 # => {:frequency => 'daily', :start => {:hours => 3, :minutes => 15}}
weekly at 3:15 on Tuesday # => {:frequency => 'weekly', :start => {:days => 1, :hours => 3, :minutes => 15}}
Notes:
day of week is specified as the # of days from Monday b/c Rails day of week helpers are monday-based
:start hash keys are pluralized b/c we feed them direcly to Time.advance, e.g. Time.now.advance(:days => 3)
Constant Summary
Constants included from Utils::BoolConverter
Utils::BoolConverter::FALSE_VALUES, Utils::BoolConverter::TRUE_VALUES
Instance Attribute Summary
Attributes inherited from Base
#attributes, #id, #parent, #persisted, #raw_response, #response_data
Instance Method Summary collapse
-
#custom? ⇒ Boolean
convenience method for detecting whether schedule can be represented in simple format or should be described as custom (meaning it is beyond the capabilities of the convenience methods).
-
#day_of_week ⇒ Object
convenince method for setting the current value in a view selector.
-
#frequency ⇒ Object
returns hourly, daily, weekly based on period returns custom if it doesn’t fit a supported interval.
-
#frequency=(frequency) ⇒ Object
accepts hourly, daily, weekly, and sets period to respective # of seconds.
-
#hour ⇒ Object
convenince method for setting the current value in a view selector.
-
#min ⇒ Object
convenince method for setting the current value in a view selector.
-
#next_start ⇒ Object
predict when action will occur next if active at that time.
-
#schedule=(all_attributes) ⇒ Object
phantom attribute for compiling real start time and frequency from appropriate form data Allows the user to specify a schedule simply with repeat interval (hourly, daily, weekly) and time within the interval to run (e.g 5 past, or Tuesdays at 2:15).
- #start_is_more_than_one_period_in_the_future? ⇒ Boolean
-
#ui_appropriate_defaults! ⇒ Object
convenience method for setting defaults in a UI that make sense for a user.
Methods inherited from Base
all, #collection_url, collection_url, create, #destroy, extract_parent_from_options, find, first, human_attribute_value, #human_attribute_value, #initialize, #inspect, last, #member_url, #persisted?, #read_attribute_for_validation, #save, schema, singleton_name, to_select, #update_attributes
Methods included from SimpleNaming
Methods included from Utils::BoolConverter
Constructor Details
This class inherits a constructor from LucidWorks::Base
Instance Method Details
#custom? ⇒ Boolean
convenience method for detecting whether schedule can be represented in simple format or should be described as custom (meaning it is beyond the capabilities of the convenience methods)
164 165 166 167 168 169 |
# File 'lib/lucid_works/datasource/schedule.rb', line 164 def custom? return true if self.frequency == 'custom' return false unless self.start_time return true if self.start_is_more_than_one_period_in_the_future? return false end |
#day_of_week ⇒ Object
convenince method for setting the current value in a view selector
149 150 151 152 |
# File 'lib/lucid_works/datasource/schedule.rb', line 149 def day_of_week # subract 1 because '%u' returns 1-7, and this is working with zero-indexed ruby arrays self.start_time.localtime.strftime('%u').to_i - 1 rescue nil end |
#frequency ⇒ Object
returns hourly, daily, weekly based on period returns custom if it doesn’t fit a supported interval
32 33 34 35 36 37 38 39 40 |
# File 'lib/lucid_works/datasource/schedule.rb', line 32 def frequency case period when 1.weeks.seconds then 'weekly' when 1.days.seconds then 'daily' when 1.hours.seconds then 'hourly' when 0 then nil else 'custom' end end |
#frequency=(frequency) ⇒ Object
accepts hourly, daily, weekly, and sets period to respective # of seconds
45 46 47 48 49 50 51 52 53 |
# File 'lib/lucid_works/datasource/schedule.rb', line 45 def frequency=(frequency) self.period = case frequency when 'hourly' then 1.hours.seconds.to_i when 'daily' then 1.days.seconds.to_i when 'weekly' then 1.weeks.seconds.to_i when 'custom' then period # don't change anything else raise "unknown frequency" end end |
#hour ⇒ Object
convenince method for setting the current value in a view selector
135 136 137 |
# File 'lib/lucid_works/datasource/schedule.rb', line 135 def hour self.start_time.localtime.hour rescue nil end |
#min ⇒ Object
convenince method for setting the current value in a view selector
142 143 144 |
# File 'lib/lucid_works/datasource/schedule.rb', line 142 def min self.start_time.localtime.min rescue nil end |
#next_start ⇒ Object
predict when action will occur next if active at that time
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/lucid_works/datasource/schedule.rb', line 58 def next_start return start_time if (now = Time.now) <= start_time # require 'ruby-debug'; debugger time_since_start = now - start_time last_interval_num = (time_since_start / period).to_i next_interval_num = if (time_since_start % period) == 0 # this is sort of a stupid condition b/c time precision is millisecond or less # for human purposes we wouldn't care if the result were as though the call # happened a millisecond later. But whatever. last_interval_num # the next interval *is* the last interval if it is exactly now else last_interval_num + 1 end start_time + period * next_interval_num end |
#schedule=(all_attributes) ⇒ Object
phantom attribute for compiling real start time and frequency from appropriate form data Allows the user to specify a schedule simply with repeat interval (hourly, daily, weekly) and time within the interval to run (e.g 5 past, or Tuesdays at 2:15)
We have to figure out when the actual start time will be because we are not asking the user for this. It needs to be:
* at the requested time relative to the interval chosen
* as soon as possible
* in the future
This is obvious to humans, but when computing it, you run into the following problem. It happens with all interval sizes, but for the sake of example, we’ll use weekly:
Problem 1) If today is Thursday, and the user asks for “weekly on Wednesdays,” Wednesday has already happened this week. We have to make sure we pick the nearest wednesday that is in the future
Problem 2) If today is Tuesday, and the user asks for “weekly on Wednesdays,”, the simple solution to problem 1 (start next week instead of this week) causes you to skip this Tuesday, even though it is valid and is what the user would expect
The algorith to solve both problems at once is this:
* From Time.now, back up to the beginning of the interval even if it is in the past.
* Fast forward to the requested siimple start time
* If you are still in the past, advance by one interval
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/lucid_works/datasource/schedule.rb', line 101 def schedule=(all_attributes) # convert to format accepted by Time.advance if all_attributes['start'] all_attributes['start']. all_attributes['start'].each{|k,v| all_attributes['start'][k]=v.to_i} end self.active = all_attributes['active'] if all_attributes.keys.include?('active') now = Time.now self.frequency = all_attributes['frequency'] self.start_time = case all_attributes['frequency'] when 'weekly' # require 'ruby-debug'; debugger start = now.beginning_of_week.advance(all_attributes['start']) start < now ? start.advance(:weeks => 1) : start when 'daily' start = now.beginning_of_day.advance(all_attributes['start']) start < now ? start.advance(:days => 1) : start when 'hourly' start = now.change(:min => 0).advance(all_attributes['start']) start < now ? start.advance(:hours => 1) : start when 'custom' # don't change this schedule's start_time else puts "*** frequency: <#{all_attributes[:frequency]}>" raise "unexpected frequency encountered" end end |
#start_is_more_than_one_period_in_the_future? ⇒ Boolean
154 155 156 157 158 |
# File 'lib/lucid_works/datasource/schedule.rb', line 154 def start_is_more_than_one_period_in_the_future? # This works fine with start times that are multiple periods in the past # because that gives a negative difference, and period is always >= 0 (self.start_time - Time.now) > self.period end |
#ui_appropriate_defaults! ⇒ Object
convenience method for setting defaults in a UI that make sense for a user
174 175 176 177 178 |
# File 'lib/lucid_works/datasource/schedule.rb', line 174 def ui_appropriate_defaults! if self.start_time.blank? || self.period == 0 self.active = true end end |