changeling 0.0.1 → 0.0.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/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format documentation
@@ -2,3 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.2
4
4
  - 1.9.3
5
+ services:
6
+ - mongodb
7
+ - elasticsearch
data/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  [travis-image]: https://secure.travis-ci.org/hahuang65/Changeling.png?branch=master
4
4
  [travis-link]: http://travis-ci.org/hahuang65/Changeling
5
5
  [travis-home]: http://travis-ci.org/
6
+ [brew-home]: http://mxcl.github.com/homebrew/
7
+ [elasticsearch-home]: http://www.elasticsearch.org
6
8
 
7
9
  A flexible and lightweight object change tracking system.
8
10
 
@@ -28,7 +30,12 @@ $ gem install changeling
28
30
 
29
31
  ## Requirements
30
32
 
31
- * Redis (Tested on 2.4.x)
33
+ * [ElasticSearch][elasticsearch-home] (Tested on 0.19.9 with JVM 20.10-b01-428)
34
+ * Install via [Homebrew][brew-home]
35
+
36
+ ```sh
37
+ $ brew install elasticsearch
38
+ ```
32
39
 
33
40
  ## Usage
34
41
 
@@ -94,7 +101,7 @@ log = @post.history.first
94
101
  log.klass # class of the object that the Logling is tracking.
95
102
  => "posts"
96
103
 
97
- log.object_id # the ID of the object that the Logling is tracking.
104
+ log.oid # the ID of the object that the Logling is tracking.
98
105
  => "1"
99
106
 
100
107
  log.before # what the before state of the object was.
@@ -106,11 +113,11 @@ log.after # what the after state of the object is.
106
113
  log.modifications # what changes were made to the object that this Logling recorded. Basically a roll up of the .before and .after methods.
107
114
  => {"title" => ["Old Title", "New Title"]}
108
115
 
109
- log.changed_at # what time these changes were made.
116
+ log.modified_at # what time these changes were made.
110
117
  => Sat, 08 Sep 2012 10:21:46 UTC +00:00
111
118
 
112
119
  log.as_json # JSON representation of the changes.
113
- => {:modifications=>{"title" => ["Old Title", "New Title"], :changed_at => Sat, 08 Sep 2012 10:21:46 UTC +00:00}
120
+ => {:modifications=>{"title" => ["Old Title", "New Title"], :modified_at => Sat, 08 Sep 2012 10:21:46 UTC +00:00}
114
121
  ```
115
122
 
116
123
  ## Testing
@@ -120,7 +127,7 @@ against the following interpreters (with corresponding ORM/ODMs) and datastores:
120
127
 
121
128
  * MRI 1.9.2 (Mongoid 2.4.1, ActiveRecord 3.1.3)
122
129
  * MRI 1.9.3 (Mongoid 3.0.3, ActiveRecord 3.2.7)
123
- * Redis 2.4.x
130
+ * ElasticSearch (Tested on 0.19.9 with JVM 20.10-b01-428)
124
131
 
125
132
  ## Contributing
126
133
 
@@ -133,7 +140,8 @@ against the following interpreters (with corresponding ORM/ODMs) and datastores:
133
140
  ## TODO
134
141
 
135
142
  * Restore state from a Logling
136
- * Use Mongo / SQL as a datastore rather than Redis (not sure about this one yet.)
137
- * Sinatra app to monitor changes as they happen in real-time
138
- * Analytics for changes
143
+ * Filter Loglings by which fields have changed.
144
+ * Performance testing against large data loads.
145
+ * Sinatra app to monitor changes as they happen in real-time.
146
+ * Analytics for changes.
139
147
  * Much more...
@@ -16,16 +16,19 @@ Gem::Specification.new do |gem|
16
16
  gem.version = Changeling::VERSION
17
17
 
18
18
  # Dependencies
19
- gem.add_dependency "redis"
19
+ gem.add_dependency "tire"
20
+ gem.add_dependency "activemodel"
20
21
 
21
22
  # Development Dependencies
22
23
  case RUBY_VERSION
23
24
  when "1.9.2"
24
25
  gem.add_development_dependency "mongoid", "2.4.1"
25
26
  gem.add_development_dependency "activerecord", "3.1.3"
27
+ gem.add_development_dependency "ruby-debug19"
26
28
  when "1.9.3"
27
29
  gem.add_development_dependency "mongoid", "3.0.3"
28
30
  gem.add_development_dependency "activerecord", "3.2.7"
31
+ gem.add_development_dependency "debugger"
29
32
  end
30
33
  gem.add_development_dependency "rake"
31
34
  gem.add_development_dependency "rspec"
@@ -1,8 +1,10 @@
1
1
  require 'rubygems'
2
- require 'redis'
2
+ require 'tire'
3
3
  require "changeling/version"
4
4
 
5
5
  module Changeling
6
+ Tire::Model::Search.index_prefix "changeling"
7
+
6
8
  autoload :Trackling, 'changeling/trackling'
7
9
  autoload :Probeling, 'changeling/probeling'
8
10
 
@@ -1,11 +1,27 @@
1
1
  module Changeling
2
2
  module Models
3
3
  class Logling
4
- attr_accessor :klass, :object_id, :modifications, :before, :after, :changed_at
4
+ extend ActiveModel::Naming
5
+ attr_accessor :klass, :oid, :modifications, :before, :after, :modified_at
6
+
7
+ include Tire::Model::Search
8
+ include Tire::Model::Persistence
9
+
10
+ property :klass, :type => 'string'
11
+ property :oid, :type => 'string'
12
+ property :modifications, :type => 'string'
13
+ property :modified_at, :type => 'date'
14
+
15
+ mapping do
16
+ indexes :klass, :type => "string"
17
+ indexes :oid, :type => "string"
18
+ indexes :modifications, :type => 'string'
19
+ indexes :modified_at, :type => 'date'
20
+ end
5
21
 
6
22
  class << self
7
- def create(object, changes)
8
- logling = self.new(object, changes)
23
+ def create(object)
24
+ logling = self.new(object)
9
25
  logling.save
10
26
  end
11
27
 
@@ -21,59 +37,74 @@ module Changeling
21
37
  [before, after]
22
38
  end
23
39
 
24
- def redis
25
- @redis ||= Redis.new
26
- end
27
-
28
- def redis_key(klass, object_id)
29
- "changeling::#{klass}::#{object_id}"
40
+ def klassify(object)
41
+ object.class.to_s.underscore
30
42
  end
31
43
 
32
44
  def records_for(object, length = nil)
33
- key = self.redis_key(object.class.to_s.underscore.pluralize, object.id.to_s)
34
- length ||= self.redis.llen(key)
35
-
36
- results = self.redis.lrange(key, 0, length).map { |value| self.new(object, JSON.parse(value)['modifications']) }
45
+ self.tire.index.refresh
46
+
47
+ results = self.search do
48
+ query do
49
+ filtered do
50
+ query { all }
51
+ filter :terms, :klass => [Logling.klassify(object)]
52
+ filter :terms, :oid => [object.id.to_s]
53
+ end
54
+ end
55
+
56
+ sort { by :modified_at, "desc" }
57
+ end.results
58
+
59
+ if length
60
+ results.take(length)
61
+ else
62
+ results
63
+ end
37
64
  end
38
65
  end
39
66
 
40
- def as_json
67
+ def to_indexed_json
41
68
  {
42
- :modifications => self.modifications,
43
- :changed_at => self.changed_at
44
- }
69
+ :klass => self.klass,
70
+ :oid => self.oid,
71
+ :modifications => self.modifications.to_json,
72
+ :modified_at => self.modified_at
73
+ }.to_json
45
74
  end
46
75
 
47
- def initialize(object, changes)
48
- # Remove updated_at field.
49
- changes.delete("updated_at")
50
-
51
- self.klass = object.class.to_s.underscore.pluralize
52
- self.object_id = object.id.to_s
53
- self.modifications = changes
76
+ def initialize(object)
77
+ if object.class == Hash
78
+ changes = JSON.parse(object['modifications'])
79
+ self.klass = object['klass']
80
+ self.oid = object['oid']
81
+ self.modifications = changes
54
82
 
55
- self.before, self.after = Logling.parse_changes(changes)
83
+ self.before, self.after = Logling.parse_changes(changes)
56
84
 
57
- if object.respond_to?(:updated_at)
58
- self.changed_at = object.updated_at
85
+ self.modified_at = DateTime.parse(object['modified_at'])
59
86
  else
60
- self.changed_at = Time.now
61
- end
62
- end
87
+ changes = object.changes
63
88
 
64
- def redis_key
65
- Logling.redis_key(self.klass, self.object_id)
66
- end
89
+ # Remove updated_at field.
90
+ changes.delete("updated_at")
67
91
 
68
- def save
69
- key = self.redis_key
70
- value = self.serialize
92
+ self.klass = Logling.klassify(object)
93
+ self.oid = object.id.to_s
94
+ self.modifications = changes
95
+
96
+ self.before, self.after = Logling.parse_changes(changes)
71
97
 
72
- Logling.redis.lpush(key, value)
98
+ if object.respond_to?(:updated_at)
99
+ self.modified_at = object.updated_at
100
+ else
101
+ self.modified_at = Time.now
102
+ end
103
+ end
73
104
  end
74
105
 
75
- def serialize
76
- self.as_json.to_json
106
+ def save
107
+ _run_save_callbacks {}
77
108
  end
78
109
  end
79
110
  end
@@ -5,8 +5,8 @@ module Changeling
5
5
  end
6
6
 
7
7
  def save_logling
8
- if changes = self.changes
9
- logling = Changeling::Models::Logling.create(self, changes)
8
+ if self.changes
9
+ logling = Changeling::Models::Logling.create(self)
10
10
  end
11
11
  end
12
12
  end
@@ -1,3 +1,3 @@
1
1
  module Changeling
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -13,68 +13,115 @@ describe Changeling::Models::Logling do
13
13
  @object = model.new(args[:options])
14
14
  @changes = args[:changes]
15
15
 
16
- @logling = @klass.new(@object, @changes)
16
+ @object.stub(:changes).and_return(@changes)
17
+ @logling = @klass.new(@object)
17
18
  end
18
19
 
19
20
  context "Class Methods" do
20
21
  describe ".create" do
21
22
  before(:each) do
22
- @object.stub(:changes).and_return(@changes)
23
23
 
24
- @klass.should_receive(:new).with(@object, @changes).and_return(@logling)
24
+ @klass.should_receive(:new).with(@object).and_return(@logling)
25
25
  end
26
26
 
27
27
  it "should call new with it's parameters then save the initialized logling" do
28
28
  @logling.should_receive(:save)
29
29
 
30
- @klass.create(@object, @changes)
30
+ @klass.create(@object)
31
31
  end
32
32
  end
33
33
 
34
34
  describe ".new" do
35
- before(:each) do
36
- @before, @after = @klass.parse_changes(@changes)
37
- end
35
+ context "when passed object is a ElasticSearch response hash" do
36
+ before(:each) do
37
+ @object = {
38
+ "klass"=>"blog_post",
39
+ "oid"=>"50b8355f7a93d04908000001",
40
+ "modifications"=>"{\"public\":[true,false]}",
41
+ "modified_at"=>"2012-11-29T20:26:07-08:00",
42
+ "id"=>"UU2YGr1WSbilNUlyM1ja8g",
43
+ "_score"=>nil,
44
+ "_type"=>"changeling/models/logling",
45
+ "_index"=>"changeling_test_changeling_models_loglings",
46
+ "_version"=>1,
47
+ "sort"=>[1354249567000],
48
+ "highlight"=>nil,
49
+ "_explanation"=>nil
50
+ }
51
+
52
+ @logling = @klass.new(@object)
53
+ @changes = JSON.parse(@object['modifications'])
54
+ @before, @after = @klass.parse_changes(@changes)
55
+ @modified_time = DateTime.parse(@object['modified_at'])
56
+ end
38
57
 
39
- it "should set klass as the pluralized version of the class name" do
40
- @logling.klass.should == @object.class.to_s.underscore.pluralize
41
- end
58
+ it "should set klass as the returned klass value" do
59
+ @logling.klass.should == @object['klass']
60
+ end
42
61
 
43
- it "should set object_id as the stringified object's ID" do
44
- @logling.object_id.should == @object.id.to_s
45
- end
62
+ it "should set oid as the returned oid value" do
63
+ @logling.oid.should == @object['oid']
64
+ end
46
65
 
47
- it "should set the modifications as the incoming changes parameter" do
48
- @logling.modifications.should == @changes
49
- end
66
+ it "should set the modifications as the incoming changes parameter" do
67
+ @logling.modifications.should == @changes
68
+ end
69
+
70
+ it "should set before and after based on .parse_changes" do
71
+ @logling.before.should == @before
72
+ @logling.after.should == @after
73
+ end
50
74
 
51
- it "should set before and after based on .parse_changes" do
52
- @logling.before.should == @before
53
- @logling.after.should == @after
75
+ it "should set modified_at as the parsed version of the returned modified_at value" do
76
+ @logling.modified_at.should == @modified_time
77
+ end
54
78
  end
55
79
 
56
- it "should set changed_at to the object's time of update if the object responds to the updated_at method" do
57
- @object.should_receive(:respond_to?).with(:updated_at).and_return(true)
80
+ context "when passed object is a real object" do
81
+ before(:each) do
82
+ @before, @after = @klass.parse_changes(@changes)
83
+ end
58
84
 
59
- # Setting up a variable to prevent test flakiness from passing time.
60
- time = Time.now
61
- @object.stub(:updated_at).and_return(time)
85
+ it "should set klass as the .klassify-ed value" do
86
+ @logling.klass.should == @klass.klassify(@object)
87
+ end
62
88
 
63
- # Create a new logling to trigger the initialize method
64
- @logling = @klass.new(@object, @changes)
65
- @logling.changed_at.should == @object.updated_at
66
- end
89
+ it "should set oid as the stringified object's ID" do
90
+ @logling.oid.should == @object.id.to_s
91
+ end
92
+
93
+ it "should set the modifications as the incoming changes parameter" do
94
+ @logling.modifications.should == @changes
95
+ end
96
+
97
+ it "should set before and after based on .parse_changes" do
98
+ @logling.before.should == @before
99
+ @logling.after.should == @after
100
+ end
101
+
102
+ it "should set modified_at to the object's time of update if the object responds to the updated_at method" do
103
+ @object.should_receive(:respond_to?).with(:updated_at).and_return(true)
104
+
105
+ # Setting up a variable to prevent test flakiness from passing time.
106
+ time = Time.now
107
+ @object.stub(:updated_at).and_return(time)
67
108
 
68
- it "should set changed_at to the current time if the object doesn't respond to updated_at" do
69
- @object.should_receive(:respond_to?).with(:updated_at).and_return(false)
109
+ # Create a new logling to trigger the initialize method
110
+ @logling = @klass.new(@object)
111
+ @logling.modified_at.should == @object.updated_at
112
+ end
113
+
114
+ it "should set modified_at to the current time if the object doesn't respond to updated_at" do
115
+ @object.should_receive(:respond_to?).with(:updated_at).and_return(false)
70
116
 
71
- # Setting up a variable to prevent test flakiness from passing time.
72
- time = Time.now
73
- Time.stub(:now).and_return(time)
117
+ # Setting up a variable to prevent test flakiness from passing time.
118
+ time = Time.now
119
+ Time.stub(:now).and_return(time)
74
120
 
75
- # Create a new logling to trigger the initialize method
76
- @logling = @klass.new(@object, @changes)
77
- @logling.changed_at.should == time
121
+ # Create a new logling to trigger the initialize method
122
+ @logling = @klass.new(@object)
123
+ @logling.modified_at.should == time
124
+ end
78
125
  end
79
126
  end
80
127
 
@@ -96,108 +143,76 @@ describe Changeling::Models::Logling do
96
143
  end
97
144
  end
98
145
 
99
- describe ".redis_key" do
100
- it "should consist of 3 parts, changeling::model_name::object_id" do
101
- @klass.redis_key(@logling.klass, @logling.object_id).should == "changeling::#{@object.class.to_s.underscore.pluralize}::#{@object.id.to_s}"
146
+ describe ".klassify" do
147
+ it "should return the underscored version of the objects class as a string" do
148
+ @klass.klassify(@object).should == @object.class.to_s.underscore
102
149
  end
103
150
  end
104
151
 
105
152
  describe ".records_for" do
106
153
  before(:each) do
107
- @klass.stub(:redis).and_return($redis)
154
+ @index = @klass.tire.index
155
+ @results = []
156
+ @klass.stub_chain(:tire, :index).and_return(@index)
157
+ @klass.stub_chain(:search, :results).and_return(@results)
108
158
  end
109
159
 
110
- it "should get a redis_key" do
111
- @key = @logling.redis_key
112
- @klass.should_receive(:redis_key).with(@logling.klass, @logling.object_id).and_return(@key)
160
+ it "should refresh the ElasticSearch index" do
161
+ @index.should_receive(:refresh)
113
162
  @klass.records_for(@object)
114
163
  end
115
164
 
116
- it "should find the length of the Redis list" do
117
- @key = @logling.redis_key
118
- @klass.stub(:redis_key).and_return(@key)
119
- $redis.should_receive(:llen).with(@key)
120
- @klass.records_for(@object)
121
- end
122
-
123
- it "should not find the length of the Redis list if length option is passed" do
124
- @key = @logling.redis_key
125
- @klass.stub(:redis_key).and_return(@key)
126
- $redis.should_not_receive(:llen).with(@key)
127
- @klass.records_for(@object, 10)
165
+ it "should only return the amount specified" do
166
+ num = 5
167
+ @results.should_receive(:take).with(num)
168
+ @klass.records_for(@object, 5)
128
169
  end
129
170
 
130
- it "should find all entries in the Redis list" do
131
- @key = @logling.redis_key
132
- @length = 100
133
- @klass.stub(:redis_key).and_return(@key)
134
- $redis.stub(:llen).and_return(@length)
135
- $redis.should_receive(:lrange).with(@key, 0, @length).and_return([])
171
+ it "should return all if no amount is specified" do
172
+ @results.should_not_receive(:take)
136
173
  @klass.records_for(@object)
137
174
  end
138
-
139
- it "should find the specified amount of entries in the Redis list if length option is passed" do
140
- @key = @logling.redis_key
141
- @klass.stub(:redis_key).and_return(@key)
142
- $redis.should_receive(:lrange).with(@key, 0, 5).and_return([])
143
- @klass.records_for(@object, 5)
144
- end
145
175
  end
146
176
  end
147
177
 
148
178
  context "Instance Methods" do
149
- describe ".as_json" do
150
- it "should include the object's modifications attribute" do
151
- @logling.should_receive(:modifications)
179
+ describe ".to_indexed_json" do
180
+ it "should include the object's klass attribute" do
181
+ @logling.should_receive(:klass)
152
182
  end
153
183
 
154
- it "should include the object's changed_at attribute" do
155
- @logling.should_receive(:changed_at)
156
- end
157
-
158
- after(:each) do
159
- @logling.as_json
184
+ it "should include the object's oid attribute" do
185
+ @logling.should_receive(:oid)
160
186
  end
161
- end
162
187
 
163
- describe ".redis_key" do
164
- it "should pass in it's klass and object_id" do
165
- @klass.should_receive(:redis_key).with(@logling.klass, @logling.object_id)
166
- @logling.redis_key
188
+ it "should include the object's modifications attribute" do
189
+ @logling.should_receive(:modifications)
167
190
  end
168
- end
169
191
 
170
- describe ".save" do
171
- before(:each) do
172
- @klass.stub(:redis).and_return($redis)
192
+ it "should convert the object's modifications attribute to JSON" do
193
+ mods = {}
194
+ @logling.should_receive(:modifications).and_return(mods)
195
+ mods.should_receive(:to_json)
173
196
  end
174
197
 
175
- it "should generate a key for storing in Redis" do
176
- @logling.should_receive(:redis_key)
198
+ it "should include the object's modified_at attribute" do
199
+ @logling.should_receive(:modified_at)
177
200
  end
178
201
 
179
- it "should serialize the logling" do
180
- @logling.should_receive(:serialize)
202
+ after(:each) do
203
+ @logling.to_indexed_json
181
204
  end
205
+ end
182
206
 
183
- it "should push the serialized object into Redis" do
184
- @key = 1
185
- @value = 2
186
- @logling.stub(:redis_key).and_return(@key)
187
- @logling.stub(:serialize).and_return(@value)
188
- $redis.should_receive(:lpush).with(@key, @value)
207
+ describe ".save" do
208
+ it "should update the ElasticSearch index" do
209
+ @logling.should_receive(:_run_save_callbacks)
189
210
  end
190
211
 
191
212
  after(:each) do
192
213
  @logling.save
193
214
  end
194
215
  end
195
-
196
- describe ".serialize" do
197
- it "should JSON-ify the as_json object" do
198
- @logling.serialize.should == @logling.as_json.to_json
199
- end
200
- end
201
216
  end
202
217
  end
203
218
  end
@@ -48,6 +48,11 @@ describe Changeling::Probeling do
48
48
  @object.history("5")
49
49
  end
50
50
 
51
+ it "should only return the amount of loglings requested" do
52
+ @object.all_history.count.should == 4
53
+ @object.history(2).count.should == 2
54
+ end
55
+
51
56
  it "should not error out if the record count desired is more than the total number of loglings" do
52
57
  @object.history(20).count.should == 4
53
58
  end
@@ -24,7 +24,7 @@ describe Changeling::Trackling do
24
24
  # Persist object to DB so we can update it.
25
25
  @object.save!
26
26
 
27
- @klass.should_receive(:create).with(@object, @changes)
27
+ @klass.should_receive(:create).with(@object)
28
28
 
29
29
  @changes.each_pair do |k, v|
30
30
  @object.send("#{k}=", v[1])
@@ -1,6 +1,5 @@
1
1
  require(File.expand_path('../../lib/changeling', __FILE__))
2
2
  require 'mongoid'
3
- require 'redis'
4
3
  require 'database_cleaner'
5
4
 
6
5
  # Fixtures
@@ -21,12 +20,12 @@ RSpec.configure do |config|
21
20
 
22
21
  config.before(:suite) do
23
22
  DatabaseCleaner[:mongoid].strategy = :truncation
24
- $redis = Redis.new(:db => 1)
23
+ Tire::Model::Search.index_prefix "changeling_test"
25
24
  end
26
25
 
27
26
  config.before(:each) do
28
- $redis.flushdb
29
27
  DatabaseCleaner.start
28
+ clear_tire_indexes
30
29
  end
31
30
 
32
31
  config.after(:each) do
@@ -34,6 +33,20 @@ RSpec.configure do |config|
34
33
  end
35
34
  end
36
35
 
36
+ # Inspiration from http://stackoverflow.com/questions/9676089/how-to-test-elasticsearch-in-a-rails-application-rspec
37
+ def clear_tire_indexes
38
+ [Changeling::Models::Logling].each do |model|
39
+ # Make sure that the current model is using Tire
40
+ if model.respond_to?(:tire)
41
+ # Delete the index for the model.
42
+ model.tire.index.delete
43
+
44
+ # Reload the model's index so that it can be used again.
45
+ model.tire.create_elasticsearch_index
46
+ end
47
+ end
48
+ end
49
+
37
50
  def models
38
51
  @models = {
39
52
  BlogPost => {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: changeling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-08 00:00:00.000000000 Z
12
+ date: 2012-11-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: redis
16
- requirement: &70287887029460 !ruby/object:Gem::Requirement
15
+ name: tire
16
+ requirement: &70134819579460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,21 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70287887029460
24
+ version_requirements: *70134819579460
25
+ - !ruby/object:Gem::Dependency
26
+ name: activemodel
27
+ requirement: &70134819577920 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70134819577920
25
36
  - !ruby/object:Gem::Dependency
26
37
  name: mongoid
27
- requirement: &70287887028580 !ruby/object:Gem::Requirement
38
+ requirement: &70134819577040 !ruby/object:Gem::Requirement
28
39
  none: false
29
40
  requirements:
30
41
  - - =
@@ -32,10 +43,10 @@ dependencies:
32
43
  version: 3.0.3
33
44
  type: :development
34
45
  prerelease: false
35
- version_requirements: *70287887028580
46
+ version_requirements: *70134819577040
36
47
  - !ruby/object:Gem::Dependency
37
48
  name: activerecord
38
- requirement: &70287887028040 !ruby/object:Gem::Requirement
49
+ requirement: &70134819575880 !ruby/object:Gem::Requirement
39
50
  none: false
40
51
  requirements:
41
52
  - - =
@@ -43,10 +54,21 @@ dependencies:
43
54
  version: 3.2.7
44
55
  type: :development
45
56
  prerelease: false
46
- version_requirements: *70287887028040
57
+ version_requirements: *70134819575880
58
+ - !ruby/object:Gem::Dependency
59
+ name: debugger
60
+ requirement: &70134819590880 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70134819590880
47
69
  - !ruby/object:Gem::Dependency
48
70
  name: rake
49
- requirement: &70287887027640 !ruby/object:Gem::Requirement
71
+ requirement: &70134819589240 !ruby/object:Gem::Requirement
50
72
  none: false
51
73
  requirements:
52
74
  - - ! '>='
@@ -54,10 +76,10 @@ dependencies:
54
76
  version: '0'
55
77
  type: :development
56
78
  prerelease: false
57
- version_requirements: *70287887027640
79
+ version_requirements: *70134819589240
58
80
  - !ruby/object:Gem::Dependency
59
81
  name: rspec
60
- requirement: &70287887027080 !ruby/object:Gem::Requirement
82
+ requirement: &70134819587220 !ruby/object:Gem::Requirement
61
83
  none: false
62
84
  requirements:
63
85
  - - ! '>='
@@ -65,10 +87,10 @@ dependencies:
65
87
  version: '0'
66
88
  type: :development
67
89
  prerelease: false
68
- version_requirements: *70287887027080
90
+ version_requirements: *70134819587220
69
91
  - !ruby/object:Gem::Dependency
70
92
  name: bson_ext
71
- requirement: &70287887026620 !ruby/object:Gem::Requirement
93
+ requirement: &70134819586580 !ruby/object:Gem::Requirement
72
94
  none: false
73
95
  requirements:
74
96
  - - ! '>='
@@ -76,10 +98,10 @@ dependencies:
76
98
  version: '0'
77
99
  type: :development
78
100
  prerelease: false
79
- version_requirements: *70287887026620
101
+ version_requirements: *70134819586580
80
102
  - !ruby/object:Gem::Dependency
81
103
  name: database_cleaner
82
- requirement: &70287887026120 !ruby/object:Gem::Requirement
104
+ requirement: &70134819585940 !ruby/object:Gem::Requirement
83
105
  none: false
84
106
  requirements:
85
107
  - - ! '>='
@@ -87,7 +109,7 @@ dependencies:
87
109
  version: '0'
88
110
  type: :development
89
111
  prerelease: false
90
- version_requirements: *70287887026120
112
+ version_requirements: *70134819585940
91
113
  description: A simple, yet flexible solution to tracking changes made to objects in
92
114
  your database.
93
115
  email:
@@ -97,6 +119,7 @@ extensions: []
97
119
  extra_rdoc_files: []
98
120
  files:
99
121
  - .gitignore
122
+ - .rspec
100
123
  - .rvmrc
101
124
  - .travis.yml
102
125
  - Gemfile