Class: Chronicle::ChronicleHash

Inherits:
Hash
  • Object
show all
Defined in:
lib/chronicle.rb

Instance Method Summary collapse

Constructor Details

#initialize(collection, options) ⇒ ChronicleHash

Returns a new instance of ChronicleHash.



98
99
100
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/chronicle.rb', line 98

def initialize(collection, options)
  
  eras = options[:eras]
        
  # Remove objects with nil timestamps
  collection.reject! {|obj| obj.send(options[:date_attr]).nil? }
  
  # Determine whether collection contains future or past timestamps
  if collection.all? { |obj| obj.send(options[:date_attr]) < Time.now }
    order = :past
  elsif collection.all? { |obj| obj.send(options[:date_attr]) > Time.now }
    order = :future
  else
    raise "Chronicle collections must be entirely in the past or the future."
  end
        
  # Sort collection by date
  # For past collections, newest objects come first 
  # For future collections, oldest objects come first
  collection = collection.sort_by {|obj| obj.send(options[:date_attr]) }
  collection.reverse! if order == :past

  # Force inclusion of 'now' era in case it's missing.
  eras.push('right now').uniq!
  
  # Parse era strings using Chronic
  # Ensure all eras can be parsed
  # { "7 years ago" => 2006-01-02 23:29:05 -0800, ... }
  era_date_pairs = eras.inject({}) {|h,era|
    h[era] = Chronic.parse(era)
    raise "Could not parse era: #{era}" if h[era].nil?
    h
  }

  # Sort eras by date
  # For past collections, newest eras come first
  # For future collections, oldest eras come first
  eras = eras.sort_by {|era| era_date_pairs[era] }
  eras.reverse! if order == :future

  # Initialize all hash keys chronologically
  eras.reverse.each {|era| self[era] = [] }
  
  collection.each do |obj|
    era = eras.find do |era|
      if order == :future
        # Find newest possible era for the object
        obj.send(options[:date_attr]) > era_date_pairs[era]
      else
        # Find oldest possible era for the object
        obj.send(options[:date_attr]) < era_date_pairs[era]
      end
    end
    self[era] << obj
  end

  # Remove empty eras
  self.keys.each {|k| self.delete(k) if self[k].empty? }

  self
end