Module: Boffin::Utils

Defined in:
lib/boffin/utils.rb

Overview

A collection of utility methods that are used throughout the library

Constant Summary collapse

SECONDS_IN_HOUR =

The number of seconds in an hour

3600
SECONDS_IN_DAY =

Number of seconds in a day

24 * SECONDS_IN_HOUR
SECONDS_IN_MONTH =

Number of seconds in a month

30 * SECONDS_IN_DAY
SECONDS_IN_UNIT =

Number of seconds for a single value of each unit

{
  :hours  => SECONDS_IN_HOUR,
  :days   => SECONDS_IN_DAY,
  :months => SECONDS_IN_MONTH
}

Class Method Summary collapse

Class Method Details

.blank?(obj) ⇒ true, false

Returns true if the provided object is blank, examples of blank objects are: [], {}, nil, false, ''.

Parameters:

  • obj (Object)

    any Ruby object

Returns:

  • (true, false)

    true if the provided object is blank, examples of blank objects are: [], {}, nil, false, ''.


44
45
46
# File 'lib/boffin/utils.rb', line 44

def blank?(obj)
  obj.respond_to?(:empty?) ? obj.empty? : !obj
end

.extract_time_unit(hsh) ⇒ Array

Pulls time interval information from a hash of options.

Examples:

extract_time_unit(this: 'is ignored', days: 6, so_is: 'this')
#=> [:days, 6]

Parameters:

  • hsh (Hash)

    Any Hash that contains amoungst its keys one of :hours, :days, or :months.

Returns:

  • (Array)

    A two-element array containing the unit-type (:hours, :days, or :months) and the value.


74
75
76
77
78
79
80
81
82
# File 'lib/boffin/utils.rb', line 74

def extract_time_unit(hsh)
  case
  when hsh.key?(:hours)  then [:hours,  hsh[:hours]]
  when hsh.key?(:days)   then [:days,   hsh[:days]]
  when hsh.key?(:months) then [:months, hsh[:months]]
  else
    raise ArgumentError, 'no time unit exists in the hash provided'
  end
end

.object_as_identifier(obj, opts = {}) ⇒ String

Parameters:

  • obj (#as_member, #id, #to_s)
  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :namespace (true, false)

    If true the generated value will be prefixed with a namespace

  • :encode (true, false)

    If true and object fails to respond to #as_member or #id, the generated value will be Base64 encoded.

Returns:

  • (String)

152
153
154
155
156
157
158
159
160
161
# File 'lib/boffin/utils.rb', line 152

def object_as_identifier(obj, opts = {})
  if obj.respond_to?(:as_member) || respond_to_id?(obj)
    ''.tap do |s|
      s << "#{underscore(obj.class)}:" if opts[:namespace]
      s << (obj.respond_to?(:as_member) ? obj.as_member : obj.id).to_s
    end
  else
    opts[:encode] ? [obj.to_s].pack("m0").chomp : obj.to_s
  end
end

.object_as_key(obj) ⇒ String

Returns A string that can be used as part of a Redis key

Parameters:

  • obj (#as_member, #id, #to_s)

Returns:

  • (String)

    A string that can be used as part of a Redis key

See Also:

  • #object_as_identifier

182
183
184
# File 'lib/boffin/utils.rb', line 182

def object_as_key(obj)
  object_as_identifier(obj, :encode => true)
end

.object_as_member(obj) ⇒ String

Parameters:

  • obj (#as_member, #id, #to_s)

Returns:

See Also:

  • #object_as_identifier

168
169
170
# File 'lib/boffin/utils.rb', line 168

def object_as_member(obj)
  object_as_identifier(obj)
end

.object_as_namespace(obj) ⇒ String

Returns a string that can be used as a namespace in Redis keys

Parameters:

  • obj (String, Symbol, Object)

Returns:

  • (String)

    Returns a string that can be used as a namespace in Redis keys


135
136
137
138
139
140
141
142
# File 'lib/boffin/utils.rb', line 135

def object_as_namespace(obj)
  case obj
  when String, Symbol
    obj.to_s
  else
    underscore(obj)
  end
end

.object_as_uid(obj) ⇒ String

Returns A string that can be used as a member in Keyspace#hits.

Parameters:

  • obj (#as_member, #id, #to_s)

Returns:

  • (String)

    A string that can be used as a member in Keyspace#hits.

See Also:

  • #object_as_identifier

175
176
177
# File 'lib/boffin/utils.rb', line 175

def object_as_uid(obj)
  object_as_identifier(obj, :namespace => true)
end

.respond_to_id?(obj) ⇒ true, false

Returns true if the provided object responds to :id, other than it's internal object identifier false if the object does not respond to :id

Parameters:

  • obj (Object)

    any Ruby object

Returns:

  • (true, false)

    true if the provided object responds to :id, other than it's internal object identifier false if the object does not respond to :id


53
54
55
56
57
58
59
60
61
62
# File 'lib/boffin/utils.rb', line 53

def respond_to_id?(obj)
  # NOTE: this feels like a hack. I'm sure there is a more elegant way
  # to determine whether the :id method is the built in Object#id but
  # I can't think of it
  if RUBY_VERSION < "1.9"
    obj.respond_to?(:id) and obj.id != obj.object_id
  else
    obj.respond_to?(:id)
  end
end

.time_ago(time, unit) ⇒ Time

Returns The time in the past offset by the specified amount

Examples:

time_ago(Time.local(2011, 1, 3), days: 2)
# => 2011-01-01 00:00:00

Parameters:

  • time (Time)

    The initial time that the offset will be calculated from

  • unit (Hash)

    (see #extract_time_unit)

Returns:

  • (Time)

    The time in the past offset by the specified amount


93
94
95
96
# File 'lib/boffin/utils.rb', line 93

def time_ago(time, unit)
  unit, unit_value = *extract_time_unit(unit)
  time - (unit_value * SECONDS_IN_UNIT[unit])
end

.time_ago_range(upto, unit) ⇒ Array<Time>

Returns An array of times in the calculated range

Examples:

time_ago_range(Time.local(2011, 1, 5), days: 3)
# => [2011-01-03 00:00:00, 2011-01-04 00:00:00, 2011-01-05 00:00:00]

Parameters:

  • upto (Time)

    The base time of which to calculate the range from

  • unit (Hash)

    (see #extract_time_unit)

Returns:

  • (Array<Time>)

    An array of times in the calculated range


107
108
109
110
111
112
113
114
115
# File 'lib/boffin/utils.rb', line 107

def time_ago_range(upto, unit)
  unit, size = *extract_time_unit(unit)
  ago = time_ago(upto, unit => (size - 1))
  max, count, times = upto.to_i, ago.to_i, []
  begin
    times << Time.at(count)
  end while (count += SECONDS_IN_UNIT[unit]) <= max
  times
end

.underscore(thing) ⇒ String

Note:

Originally pulled from ActiveSupport::Inflector

Returns The underscored version of #to_s on thing

Parameters:

  • thing (#to_s)

    A Module, Class, String, or anything in which the underscored value of #to_s is desirable.

Returns:

  • (String)

    The underscored version of #to_s on thing


30
31
32
33
34
35
36
37
38
# File 'lib/boffin/utils.rb', line 30

def underscore(thing)
  thing.to_s.dup.tap do |word|
    word.gsub!(/::/, '_')
    word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
    word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
    word.tr!('-', '_')
    word.downcase!
  end
end

.uniquenesses_as_uid(*aspects) ⇒ String

Generates a unique set member based off the first object in the provided array that is not nil. If the array is empty or only contains nil element then NIL_SESSION_MEMBER is returned.

Parameters:

  • aspects (Array)

    An array of which the first non-nil element is passed to #object_as_uid

Returns:

  • (String)

124
125
126
127
128
129
130
# File 'lib/boffin/utils.rb', line 124

def uniquenesses_as_uid(*aspects)
  if (obj = aspects.flatten.reject { |u| blank?(u) }.first)
    object_as_uid(obj)
  else
    NIL_SESSION_MEMBER
  end
end