changeling 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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