Class: WeekSauce
- Inherits:
-
Object
- Object
- WeekSauce
- Defined in:
- lib/week_sauce.rb
Overview
The underlying ‘days` database column can be either a string or integer type.
Constant Summary collapse
- MAX_VALUE =
2**7 - 1
- DAY_NAMES =
%w(sunday monday tuesday wednesday thursday friday saturday).map(&:to_sym).freeze
- DAY_BITS =
Hash[ DAY_NAMES.zip(Array.new(7) { |i| 2**i }) ].freeze
Class Method Summary collapse
-
.dump(instance) ⇒ Object
ActiveRecord attribute serialization support.
-
.load(string) ⇒ Object
ActiveRecord attribute serialization support.
Instance Method Summary collapse
-
#==(arg) ⇒ Object
Compare this instance against another instance or a Fixnum.
-
#[](wday) ⇒ Object
Returns
trueif the given day is set,falseif it isn’t, andnilif the argument was invalid. -
#[]=(wday, bool) ⇒ Object
Set or unset the given day.
-
#all! ⇒ Object
Set all days to
true. -
#all? ⇒ Boolean
Returns
trueif all days are set,falseotherwise. -
#any? ⇒ Boolean
Returns
trueif any of the week’s 7 days are set,falseotherwise. -
#blank! ⇒ Object
Set all days to
false. -
#blank? ⇒ Boolean
Returns
trueif no days are set,falseotherwise. -
#count ⇒ Object
Returns the number of “set” days.
-
#dates_in(date_range) ⇒ Object
Return all dates in the given
date_rangethat match the bitmask. -
#initialize(value = nil) ⇒ WeekSauce
constructor
Init a new WeekSauce instance.
-
#inspect ⇒ Object
Returns a string with the bitmask value and a list of “set” days, or a simple message if all/no days are set.
-
#many? ⇒ Boolean
Returns
trueif two or days are set,falseotherwise. -
#next_date(from_date = nil) ⇒ Object
Return the next date matching the bitmask, or
nilif the week is blank. -
#one? ⇒ Boolean
Returns
trueif exactly one day is set,falseotherwise. -
#set(*days) ⇒ Object
Set the given days.
-
#set!(*days) ⇒ Object
Exclusive version of #set.
-
#to_a ⇒ Object
Returns an array of “set” day names as symbols.
-
#to_hash ⇒ Object
Returns a hash where the keys are the week’s 7 days as symbols, and the values are booleans.
-
#to_i ⇒ Object
Returns the raw bitmask integer.
-
#unset(*days) ⇒ Object
Unset the given days.
-
#unset!(*days) ⇒ Object
Exclusive version of #unset.
Constructor Details
#initialize(value = nil) ⇒ WeekSauce
Init a new WeekSauce instance. If value is omitted, the new instance will default to a bitmask of zero, i.e. no days set.
If a value argument is given, to_i will be called on it, and the resulting integer will be clamped to 0..127
76 77 78 |
# File 'lib/week_sauce.rb', line 76 def initialize(value = nil) @value = [[0, value.to_i].max, MAX_VALUE].min end |
Class Method Details
.dump(instance) ⇒ Object
ActiveRecord attribute serialization support
Dump a WeekSauce instance to a stringified bitmask value
62 63 64 65 66 67 68 |
# File 'lib/week_sauce.rb', line 62 def dump(instance) if instance.is_a?(self) instance.to_i.to_s else "0" end end |
.load(string) ⇒ Object
ActiveRecord attribute serialization support
Create a WeekSauce instance from a stringified integer bitmask. The value will be clamped (see #new)
53 54 55 56 57 |
# File 'lib/week_sauce.rb', line 53 def load(string) self.new(string.to_i) rescue NoMethodError => err self.new end |
Instance Method Details
#==(arg) ⇒ Object
Compare this instance against another instance or a Fixnum
81 82 83 84 85 86 87 88 |
# File 'lib/week_sauce.rb', line 81 def ==(arg) case arg when self.class, Fixnum to_i == arg.to_i else false end end |
#[](wday) ⇒ Object
Returns true if the given day is set, false if it isn’t, and nil if the argument was invalid.
The wday argument can be
-
a Fixnum from 0 (Sunday) to 6 (Saturday),
-
a day-name symbol, e.g.
:tuesday,:friday, -
a day-name string (case-insensitive), e.g.
"Monday","sunday" -
a Time object, or
-
a Date object
138 139 140 |
# File 'lib/week_sauce.rb', line 138 def [](wday) get_bit coerce_to_bit(wday) end |
#[]=(wday, bool) ⇒ Object
Set or unset the given day. See #[] for possible wday values. Invalid wday values are ignored.
144 145 146 |
# File 'lib/week_sauce.rb', line 144 def []=(wday, bool) set_bit coerce_to_bit(wday), bool end |
#all! ⇒ Object
Set all days to true. Returns self
187 188 189 190 |
# File 'lib/week_sauce.rb', line 187 def all! @value = MAX_VALUE self end |
#all? ⇒ Boolean
Returns true if all days are set, false otherwise
97 98 99 |
# File 'lib/week_sauce.rb', line 97 def all? @value == MAX_VALUE end |
#any? ⇒ Boolean
Returns true if any of the week’s 7 days are set, false otherwise. Opposite of #blank?
103 104 105 |
# File 'lib/week_sauce.rb', line 103 def any? !blank? end |
#blank! ⇒ Object
Set all days to false. Returns self
181 182 183 184 |
# File 'lib/week_sauce.rb', line 181 def blank! @value = 0 self end |
#blank? ⇒ Boolean
Returns true if no days are set, false otherwise. Opposite of #any?
92 93 94 |
# File 'lib/week_sauce.rb', line 92 def blank? @value == 0 end |
#count ⇒ Object
Returns the number of “set” days
209 210 211 |
# File 'lib/week_sauce.rb', line 209 def count to_a.count end |
#dates_in(date_range) ⇒ Object
Return all dates in the given date_range that match the bitmask. If the week’s blank, an empty array will be returned.
Note that the range is converted to an array, which is then filtered, so if the range is “backwards” (high to low) an empty array will be returned
259 260 261 262 |
# File 'lib/week_sauce.rb', line 259 def dates_in(date_range) return [] if blank? date_range.to_a.select { |date| self[date.wday] } end |
#inspect ⇒ Object
Returns a string with the bitmask value and a list of “set” days, or a simple message if all/no days are set
215 216 217 218 219 220 221 222 223 224 |
# File 'lib/week_sauce.rb', line 215 def inspect if blank? "0: No days set" elsif all? "#{MAX_VALUE}: All days set" else list = to_a.map { |day| day.to_s.sub(/./, &:upcase) }.join(", ") "#{@value}: #{list}" end end |
#many? ⇒ Boolean
Returns true if two or days are set, false otherwise
113 114 115 |
# File 'lib/week_sauce.rb', line 113 def many? any? && !one? end |
#next_date(from_date = nil) ⇒ Object
Return the next date matching the bitmask, or nil if the week is blank.
If no from_date argument is given, it’ll default to Date.current if ActiveSupport is available, otherwise it’ll use Date.today.
If from_date argument can be a Date or a Time object (the latter will be converted using #to_date)
If from_date is given, #next_date will return the first matching date from - and including - from_date
238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/week_sauce.rb', line 238 def next_date(from_date = nil) return nil if blank? from_date ||= if Date.respond_to?(:current) Date.current else Date.today end from_date = from_date.to_date until self[from_date.wday] from_date = from_date.succ end from_date.dup end |
#one? ⇒ Boolean
Returns true if exactly one day is set, false otherwise
108 109 110 |
# File 'lib/week_sauce.rb', line 108 def one? any? && @value & (@value - 1) == 0 end |
#set(*days) ⇒ Object
Set the given days. Like #[], arguments can be symbols, Fixnums, or Date/Time objects
150 151 152 153 154 |
# File 'lib/week_sauce.rb', line 150 def set(*days) days.each do |day| self[day] = true end end |
#set!(*days) ⇒ Object
Exclusive version of #set. Clears the week, and sets only the days passed. Returns self
158 159 160 161 162 |
# File 'lib/week_sauce.rb', line 158 def set!(*days) blank! set(*days) self end |
#to_a ⇒ Object
Returns an array of “set” day names as symbols
198 199 200 |
# File 'lib/week_sauce.rb', line 198 def to_a DAY_NAMES.select { |day| self[day] } end |
#to_hash ⇒ Object
Returns a hash where the keys are the week’s 7 days as symbols, and the values are booleans
204 205 206 |
# File 'lib/week_sauce.rb', line 204 def to_hash Hash[ DAY_NAMES.map { |day| [day, self[day]] } ] end |
#to_i ⇒ Object
Returns the raw bitmask integer
193 194 195 |
# File 'lib/week_sauce.rb', line 193 def to_i @value end |
#unset(*days) ⇒ Object
Unset the given days. Like #[], arguments can be symbols, Fixnums, or Date/Time objects
166 167 168 169 170 |
# File 'lib/week_sauce.rb', line 166 def unset(*days) days.each do |day| self[day] = false end end |
#unset!(*days) ⇒ Object
Exclusive version of #unset. Sets all days to true and then unsets days passed. Returns self
174 175 176 177 178 |
# File 'lib/week_sauce.rb', line 174 def unset!(*days) all! unset(*days) self end |