mongoid-historicals 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +36 -1
- data/lib/mongoid/historicals/version.rb +1 -1
- data/lib/mongoid/historicals.rb +57 -26
- data/test/historicals_test.rb +29 -9
- metadata +2 -1
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.
|
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
|
|
data/lib/mongoid/historicals.rb
CHANGED
@@ -14,8 +14,11 @@ module Mongoid
|
|
14
14
|
class_attribute :historical_options
|
15
15
|
end
|
16
16
|
|
17
|
-
# Save the current values
|
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
|
-
|
33
|
-
|
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] -
|
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
|
data/test/historicals_test.rb
CHANGED
@@ -95,18 +95,38 @@ describe Mongoid::Historicals do
|
|
95
95
|
@player.record!('test')
|
96
96
|
end
|
97
97
|
|
98
|
-
describe "
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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 "
|
107
|
-
it "should return
|
108
|
-
@
|
109
|
-
|
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.
|
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:
|