module StateOfTheNation::ClassMethods
Attributes
finish_key[RW]
ignore_empty[RW]
parent_association[RW]
prevent_multiple_active[RW]
start_key[RW]
Public Instance Methods
considered_active(ignore_empty: false)
click to toggle source
# File lib/state_of_the_nation.rb, line 18 def considered_active(ignore_empty: false) @ignore_empty = ignore_empty def from(start_key) @start_key = start_key self end def until(finish_key) @finish_key = finish_key define_method "active?" do |time = Time.now.utc| (finish.blank? || round_if_should(finish) > round_if_should(time)) && round_if_should(start) <= round_if_should(time) end define_method "active_in_interval?" do |interval_start, interval_end| record_start = round_if_should(start) record_end = round_if_should(finish) if ignore_empty && record_start == record_end false elsif interval_start.nil? && interval_end.nil? true elsif interval_start == interval_end active?(interval_start) elsif interval_start.nil? record_start < interval_end elsif interval_end.nil? record_end.nil? || record_end > interval_start elsif record_end.nil? interval_end > record_start else record_start < interval_end && record_end > interval_start end end scope :active, lambda { |time = Time.now.utc| where(QueryString.query_for(:active_scope, self), round_if_should(time), round_if_should(time)) } end private def round_if_should(time) return time if !should_round_timestamps? time.respond_to?(:round) ? time.round : time end private def should_round_timestamps? # MySQL datetime fields do not support millisecond resolution while # PostgreSQL's do. To prevent issues with near identical timestamps not # comparing as expected in .active? methods we'll choose the resolution # appropriate for the database adapter backing the model. case self.connection.adapter_name when /PostgreSQL/ false else true end end self end
from(start_key)
click to toggle source
# File lib/state_of_the_nation.rb, line 21 def from(start_key) @start_key = start_key self end
has_active(association_plural)
click to toggle source
# File lib/state_of_the_nation.rb, line 79 def has_active(association_plural) @association_plural = association_plural add_child_methods(plural: @association_plural, single: false, with_identity_cache: false) def with_identity_cache add_child_methods(plural: @association_plural, single: false, with_identity_cache: true) self end self end
has_uniquely_active(association_singular)
click to toggle source
# File lib/state_of_the_nation.rb, line 91 def has_uniquely_active(association_singular) @association_plural = association_singular.to_s.pluralize add_child_methods(plural: @association_plural, single: true, with_identity_cache: false) def with_identity_cache add_child_methods(plural: @association_plural, single: true, with_identity_cache: true) self end self end
round_if_should(time)
click to toggle source
# File lib/state_of_the_nation.rb, line 58 def round_if_should(time) return time if !should_round_timestamps? time.respond_to?(:round) ? time.round : time end
should_round_timestamps?()
click to toggle source
# File lib/state_of_the_nation.rb, line 63 def should_round_timestamps? # MySQL datetime fields do not support millisecond resolution while # PostgreSQL's do. To prevent issues with near identical timestamps not # comparing as expected in .active? methods we'll choose the resolution # appropriate for the database adapter backing the model. case self.connection.adapter_name when /PostgreSQL/ false else true end end
until(finish_key)
click to toggle source
# File lib/state_of_the_nation.rb, line 26 def until(finish_key) @finish_key = finish_key define_method "active?" do |time = Time.now.utc| (finish.blank? || round_if_should(finish) > round_if_should(time)) && round_if_should(start) <= round_if_should(time) end define_method "active_in_interval?" do |interval_start, interval_end| record_start = round_if_should(start) record_end = round_if_should(finish) if ignore_empty && record_start == record_end false elsif interval_start.nil? && interval_end.nil? true elsif interval_start == interval_end active?(interval_start) elsif interval_start.nil? record_start < interval_end elsif interval_end.nil? record_end.nil? || record_end > interval_start elsif record_end.nil? interval_end > record_start else record_start < interval_end && record_end > interval_start end end scope :active, lambda { |time = Time.now.utc| where(QueryString.query_for(:active_scope, self), round_if_should(time), round_if_should(time)) } end
with_identity_cache()
click to toggle source
# File lib/state_of_the_nation.rb, line 83 def with_identity_cache add_child_methods(plural: @association_plural, single: false, with_identity_cache: true) self end
Private Instance Methods
add_child_methods(plural:, single:, with_identity_cache:)
click to toggle source
# File lib/state_of_the_nation.rb, line 105 def add_child_methods(plural:, single:, with_identity_cache:) child_class = self.reflect_on_association(plural).klass name = self.name.demodulize.underscore.to_sym child_class.instance_variable_set(:@parent_association, name) child_class.instance_variable_set(:@prevent_multiple_active, single) association = single ? plural.singularize : plural define_method "active_#{association}" do |time = Time.now.utc| method_name = with_identity_cache ? "fetch_#{plural}" : plural.to_sym collection = send(method_name).select { |r| r.send("active?", time) } single ? collection.first : collection end end