mongoid-historicals 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,5 +1,40 @@
1
1
  Mongoid Historicals
2
2
  ===================
3
3
 
4
- Record a snapshot of current values to reference later as historical values. Useful for showing changes in values over time.
4
+ Record a snapshot of current values to reference later as historical values.
5
+
6
+
7
+ Installation
8
+ ------------
9
+
10
+ Add to your Gemfile
11
+
12
+ gem 'mongoid-historicals', :require => 'mongoid/historicals'
13
+
14
+
15
+ Usage
16
+ -----
17
+
18
+ Here is an example of how to track the week-to-week score for the players in my fictional MMORPGFPS:
19
+
20
+ class Player
21
+ include Mongoid::Document
22
+ include Mongoid::Historicals
23
+
24
+ field :username, type: String
25
+ field :score, type: Integer
26
+
27
+ historicals :score, :max => 52, :frequency => :weekly
28
+ end
29
+
30
+ In a cron task, I could run the following every Sunday before midnight:
31
+
32
+ Player.all.each do |player|
33
+ player.record!
34
+ end
35
+
36
+ Then, I could show each player's historical score like this:
37
+
38
+ <h2>Your Current Score: <%= @player.score %></h2>
39
+ <p>Your Score Last Week: <%= @player.historical(:score, 1.week.ago) %> / Difference: <%= @player.historical_difference(:score, 1.week.ago) %></p>
5
40
 
@@ -1,7 +1,7 @@
1
1
  module Mongoid
2
2
  module Historicals
3
3
 
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
 
6
6
  end
7
7
  end
@@ -14,8 +14,11 @@ module Mongoid
14
14
  class_attribute :historical_options
15
15
  end
16
16
 
17
- # Save the current values for historicals by label
17
+ # Save the current values as a historical record
18
18
  #
19
+ # @param [String, #to_datetime] label The label as a String, Symbol or DateTime that the historical record will be saved as. If you pass a DateTime object, it
20
+ # will use the <tt>:frequency</tt> option from historicals to save as a date/time.
21
+ # @return [Record] the historical record that is saved
19
22
  def record!(label = nil)
20
23
  label ||= Time.now
21
24
  record = historical(label) || self.historicals.build(:'_label' => labelize(label))
@@ -29,24 +32,72 @@ module Mongoid
29
32
  record
30
33
  end
31
34
 
32
- def historical(label)
33
- self.historicals.where(:'_label' => labelize(label)).first
35
+ # Retrieve the historical record or a single attribute value from the
36
+ # specified label. If only one argument is given, it will return
37
+ # the entire record with that label. If two arguments are given, the
38
+ # first argument will specify the attribute and the second argument is the
39
+ # label to use.
40
+ #
41
+ # @param [String, #to_datetime] attr_or_label If only one argument is given,
42
+ # this is the <tt>label</tt> for the record to be returned. If two arguments
43
+ # are given, this should be the symbol of the attribute whose value should
44
+ # be returned.
45
+ # @return With one argument given, the historical record or nil if none
46
+ # exists. With two arguments given, it should return the value of the
47
+ # requested attribute for the specified label.
48
+ def historical(attr_or_label, label = nil)
49
+ if label.nil?
50
+ self.historicals.where(:'_label' => labelize(attr_or_label)).first
51
+ else
52
+ record = self.historicals.where(:'_label' => labelize(label)).first
53
+
54
+ if record
55
+ record[attr_or_label]
56
+ else
57
+ nil
58
+ end
59
+ end
34
60
  end
35
61
 
62
+ # Return the difference between the current value of the attribute and the value of attribute from the
63
+ # <tt>label</tt> historical record.
64
+ #
65
+ # @param [Symbol] attr The attribute on which you are calculating the difference
66
+ # @param [String, Symbol, #to_datetime] label The label as a String, Symbol or Datetime for the historical record against which you are comparing
67
+ # @param [Hash] options
68
+ # @option options [Object] :default The value you want returned if there is no historical for comparison (default: 0)
36
69
  def historical_difference(attr, label, options = {})
37
70
  opts = {
38
71
  default: 0
39
72
  }.merge(options)
40
73
 
41
- record = historical(labelize(label))
42
-
43
74
  begin
44
- self[attr] - record[attr]
75
+ self[attr] - historical(attr, label)
45
76
  rescue # Pokemon exception handling, but actually seems appropriate here
46
77
  opts[:default]
47
78
  end
48
79
  end
49
80
 
81
+ module ClassMethods
82
+
83
+ # This model should record historical values for the specified
84
+ # attributes.
85
+ #
86
+ # @overload historicals(*attrs, options = {})
87
+ # @param [Array] attrs The symbol(s) for the attributes for which you want to store historicals
88
+ # @param [Hash] options
89
+ # @option options [Integer] :max The maximum number of entries to store (default: unlimited)
90
+ # @option options [:monthly,:weekly,:daily] :frequency The frequency to use for DateTime labels (default: :daily)
91
+ def historicals(*attrs)
92
+ options = attrs.extract_options!
93
+ options[:max] ||= nil
94
+ options[:frequency] ||= :daily
95
+
96
+ self.historical_options = options
97
+ self.historical_attributes = attrs
98
+ end
99
+ end
100
+
50
101
  private
51
102
 
52
103
  def labelize(label)
@@ -79,25 +130,5 @@ module Mongoid
79
130
  end
80
131
  end
81
132
  end
82
-
83
- module ClassMethods
84
-
85
- # This model should record historical values for the specified
86
- # attributes.
87
- #
88
- # Options:
89
- #
90
- # <tt>max</tt>: The maximum number of entries to store (default: none)
91
- # <tt>frequency</tt>: :monthly, :weekly, or :daily (default: :daily)
92
- #
93
- def historicals(*attrs)
94
- options = attrs.extract_options!
95
- options[:max] ||= nil
96
- options[:frequency] ||= :daily
97
-
98
- self.historical_options = options
99
- self.historical_attributes = attrs
100
- end
101
- end
102
133
  end
103
134
  end
@@ -95,18 +95,38 @@ describe Mongoid::Historicals do
95
95
  @player.record!('test')
96
96
  end
97
97
 
98
- describe "when record exists" do
99
- it "should return record" do
100
- @record = @player.historical('test')
101
- @record.must_be_instance_of(Mongoid::Historicals::Record)
102
- @record._label.must_equal 'test'
98
+ describe "with one argument" do
99
+ describe "when record exists" do
100
+ it "should return record with specified label" do
101
+ @record = @player.historical('test')
102
+ @record.must_be_instance_of(Mongoid::Historicals::Record)
103
+ @record._label.must_equal 'test'
104
+ end
105
+ end
106
+
107
+ describe "when record does not exist" do
108
+ it "should return nil" do
109
+ @record = @player.historical('unknown-label')
110
+ @record.must_equal nil
111
+ end
103
112
  end
104
113
  end
105
114
 
106
- describe "when record does not exist" do
107
- it "should return nil" do
108
- @record = @player.historical('unknown-label')
109
- @record.must_equal nil
115
+ describe "with two arguments" do
116
+ it "should return historical value (from label) of specified attribute" do
117
+ @player.historical(:score, 'test').must_equal 95.0
118
+ end
119
+
120
+ describe "when record does not exist" do
121
+ it "should return nil" do
122
+ @player.historical(:score, 'invalid').must_equal nil
123
+ end
124
+ end
125
+
126
+ describe "when attribute does not exist" do
127
+ it "should return nil" do
128
+ @player.historical(:invalid, 'test').must_equal nil
129
+ end
110
130
  end
111
131
  end
112
132
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-historicals
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -99,3 +99,4 @@ signing_key:
99
99
  specification_version: 3
100
100
  summary: ''
101
101
  test_files: []
102
+ has_rdoc: