Module: Invoicing::TimeDependent::ClassMethods

Defined in:
lib/invoicing/time_dependent.rb

Instance Method Summary collapse

Instance Method Details

#default_record_at(point_in_time) ⇒ Object

Returns the default record which is valid at a particular point in time. If there is no record marked as default, nil is returned; if there are multiple records marked as default, results are undefined. This method only works if the model objects have an is_default column.


267
268
269
270
# File 'lib/invoicing/time_dependent.rb', line 267

def default_record_at(point_in_time)
  info = time_dependent_class_info
  valid_records_at(point_in_time).select{|record| info.get(record, :is_default)}.first
end

#default_record_nowObject

Returns the default record which is valid at the current moment.


273
274
275
# File 'lib/invoicing/time_dependent.rb', line 273

def default_record_now
  default_record_at(Time.now)
end

#default_value_at(point_in_time) ⇒ Object

Finds the default record for a particular point_in_time (using default_record_at), then returns the value of that record's value column. If value was renamed to another_method_name (option to acts_as_time_dependent), then default_another_method_name_at is defined as an alias for default_value_at.


281
282
283
# File 'lib/invoicing/time_dependent.rb', line 281

def default_value_at(point_in_time)
  time_dependent_class_info.get(default_record_at(point_in_time), :value)
end

#default_value_nowObject

Finds the current default record (like default_record_now), then returns the value of that record's value column. If value was renamed to another_method_name (option to acts_as_time_dependent), then default_another_method_name_now is defined as an alias for default_value_now.


289
290
291
# File 'lib/invoicing/time_dependent.rb', line 289

def default_value_now
  default_value_at(Time.now)
end

#valid_records_at(point_in_time) ⇒ Object

Returns the list of all records which are valid at one particular point in time. If you need to consider a period of time rather than a point in time, use valid_records_during.


252
253
254
255
256
257
258
259
260
261
# File 'lib/invoicing/time_dependent.rb', line 252

def valid_records_at(point_in_time)
  info = time_dependent_class_info
  all.select do |record|
    valid_from  = info.get(record, :valid_from)
    valid_until = info.get(record, :valid_until)
    has_taken_effect = (valid_from <= point_in_time) # N.B. less than or equals
    not_yet_expired  = (valid_until == nil) || (valid_until > point_in_time)
    has_taken_effect && not_yet_expired
  end
end

#valid_records_during(not_before, not_after) ⇒ Object

Returns a list of records which are valid at some point during a particular date/time range. If there is a change of rate during this time interval, and one rate replaces another, then only the earliest element of each replacement chain is returned (because we can unambiguously convert from an earlier rate to a later one, but not necessarily in reverse).

The date range must not be empty (i.e. not_after must be later than not_before, not the same time or earlier). If you need the records which are valid at one particular point in time, use valid_records_at.

A typical application for this method would be where you want to offer users the ability to choose from a selection of rates, including ones which are not yet valid but will become valid within the next month, for example.


231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/invoicing/time_dependent.rb', line 231

def valid_records_during(not_before, not_after)
  info = time_dependent_class_info

  # List of all records whose validity period intersects the selected period
  valid_records = all.select do |record|
    valid_from  = info.get(record, :valid_from)
    valid_until = info.get(record, :valid_until)
    has_taken_effect = (valid_from < not_after) # N.B. less than
    not_yet_expired  = (valid_until == nil) || (valid_until > not_before)
    has_taken_effect && not_yet_expired
  end

  # Select only those which do not have a predecessor which is also valid
  valid_records.select do |record|
    record.predecessors.empty? || (valid_records & record.predecessors).empty?
  end
end