changeling 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1,2 +1,2 @@
1
+ rvm use 1.9.3-p327@changeling --create
1
2
  rvm use 1.9.2-p290@changeling --create
2
- rvm use 1.9.3-p0@changeling --create
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Changeling [![Build Status][travis-image]][travis-link]
1
+ # Changeling [![Build Status][travis-image]][travis-link] [![Gem Version](https://badge.fury.io/rb/changeling.png)](http://badge.fury.io/rb/changeling)
2
2
 
3
3
  [travis-image]: https://secure.travis-ci.org/hahuang65/Changeling.png?branch=master
4
4
  [travis-link]: http://travis-ci.org/hahuang65/Changeling
@@ -49,7 +49,23 @@ class Post
49
49
  end
50
50
  ```
51
51
 
52
- That's it! Including the module will silently keep track of any changes made to objects of this class.
52
+ If you want to keep track of the user who made the changes:
53
+
54
+ ```ruby
55
+ # Doesn't have to be ApplicationController, perhaps you only want it in controllers for certain resources.
56
+ class ApplicationController < ActionController::Base
57
+ include Changeling::Blameling
58
+
59
+ # Changeling assumes your user is current_user, but if not, override the changeling_blame_user method like so:
60
+ def changeling_blame_user
61
+ current_account
62
+ end
63
+
64
+ # Controller logic here...
65
+ end
66
+ ```
67
+
68
+ That's it! Including the module(s) will silently keep track of any changes made to objects of this class.
53
69
  For example:
54
70
 
55
71
  ```ruby
@@ -122,6 +138,11 @@ log.before # what the before state of the object was.
122
138
  log.after # what the after state of the object is.
123
139
  => {"title" => "New Title"}
124
140
 
141
+ log.modified_by # ID of the user who made the changes to the object
142
+ # Note: this could be nil if the Blameling module was not set up in you controller, or if changes were made from a place without a user object, such as the Rails console.
143
+ # Note: integer type IDs will be integers. Non-integer types (such as Mongo's IDs) will be represented as a string.
144
+ => 33
145
+
125
146
  log.modifications # what changes were made to the object that this Logling recorded. Basically a roll up of the .before and .after methods.
126
147
  => {"title" => ["Old Title", "New Title"]}
127
148
 
@@ -129,7 +150,7 @@ log.modified_at # what time these changes were made.
129
150
  => Sat, 08 Sep 2012 10:21:46 UTC +00:00
130
151
 
131
152
  log.as_json # JSON representation of the changes.
132
- => {:class => Post, :oid => 1, :modifications=> { "title" => ["Old Title", "New Title"] }, :modified_at => Sat, 08 Sep 2012 10:21:46 UTC +00:00}
153
+ => {:class => Post, :oid => 1, :modified_by => 33, :modifications=> { "title" => ["Old Title", "New Title"] }, :modified_at => Sat, 08 Sep 2012 10:21:46 UTC +00:00}
133
154
  ```
134
155
 
135
156
  ## Testing
@@ -32,6 +32,9 @@ Gem::Specification.new do |gem|
32
32
  end
33
33
  gem.add_development_dependency "rake"
34
34
  gem.add_development_dependency "rspec"
35
+ gem.add_development_dependency "rspec-rails"
35
36
  gem.add_development_dependency "bson_ext"
36
37
  gem.add_development_dependency "database_cleaner"
38
+ gem.add_development_dependency "sqlite3"
39
+ gem.add_development_dependency "rails"
37
40
  end
@@ -7,8 +7,28 @@ module Changeling
7
7
 
8
8
  autoload :Trackling, 'changeling/trackling'
9
9
  autoload :Probeling, 'changeling/probeling'
10
+ autoload :Blameling, 'changeling/blameling'
10
11
 
11
12
  module Models
12
13
  autoload :Logling, 'changeling/models/logling'
13
14
  end
15
+
16
+ module Support
17
+ autoload :Search, 'changeling/support/search'
18
+ end
19
+
20
+ def self.blame_user
21
+ self.changeling_store[:blame_user]
22
+ end
23
+
24
+ def self.blame_user=(user)
25
+ self.changeling_store[:blame_user] = user
26
+ end
27
+
28
+ private
29
+ def self.changeling_store
30
+ Thread.current[:changeling] ||= {
31
+ :blame_user => nil
32
+ }
33
+ end
14
34
  end
@@ -0,0 +1,17 @@
1
+ module Changeling
2
+ module Blameling
3
+ def self.included(base)
4
+ base.before_filter :set_changeling_blame_user
5
+ end
6
+
7
+ protected
8
+ def changeling_blame_user
9
+ current_user rescue nil
10
+ end
11
+
12
+ private
13
+ def set_changeling_blame_user
14
+ Changeling.blame_user = changeling_blame_user
15
+ end
16
+ end
17
+ end
@@ -2,13 +2,15 @@ module Changeling
2
2
  module Models
3
3
  class Logling
4
4
  extend ActiveModel::Naming
5
- attr_accessor :klass, :oid, :modifications, :before, :after, :modified_at, :modified_fields
5
+ attr_accessor :klass, :oid, :modified_by, :modifications, :before, :after, :modified_at, :modified_fields
6
6
 
7
7
  include Tire::Model::Search
8
+ include Tire::Model::Callbacks
8
9
  include Tire::Model::Persistence
9
10
 
10
11
  property :klass, :type => 'string'
11
12
  property :oid, :type => 'string'
13
+ property :modified_by, :type => 'string'
12
14
  property :modifications, :type => 'string'
13
15
  property :modified_fields, :type => 'string', :analyzer => 'keyword'
14
16
  property :modified_at, :type => 'date'
@@ -16,6 +18,7 @@ module Changeling
16
18
  mapping do
17
19
  indexes :klass, :type => "string"
18
20
  indexes :oid, :type => "string"
21
+ indexes :modified_by, :type => "string"
19
22
  indexes :modifications, :type => 'string'
20
23
  indexes :modified_fields, :type => 'string', :analyzer => 'keyword'
21
24
  indexes :modified_at, :type => 'date'
@@ -40,59 +43,38 @@ module Changeling
40
43
  end
41
44
 
42
45
  def klassify(object)
43
- object.class
46
+ object.class.to_s.underscore
44
47
  end
45
48
 
46
- # TODO: Refactor me! More specs!
47
49
  def records_for(object, length = nil, field = nil)
48
- self.tire.index.refresh
49
-
50
- if field
51
- results = self.search do
52
- query do
53
- filtered do
54
- query { all }
55
- filter :terms, :klass => [Logling.klassify(object).to_s.underscore]
56
- filter :terms, :oid => [object.id.to_s]
57
- filter :terms, :modified_fields => [field]
58
- end
59
- end
60
-
61
- sort { by :modified_at, "desc" }
62
- end.results
63
- else
64
- results = self.search do
65
- query do
66
- filtered do
67
- query { all }
68
- filter :terms, :klass => [Logling.klassify(object).to_s.underscore]
69
- filter :terms, :oid => [object.id.to_s]
70
- end
71
- end
72
-
73
- sort { by :modified_at, "desc" }
74
- end.results
75
- end
50
+ filters = [
51
+ { :klass => Logling.klassify(object) },
52
+ { :oid => object.id.to_s }
53
+ ]
54
+
55
+ filters << { :modified_fields => field } if field
76
56
 
77
- results = results.take(length) if length
78
-
79
- # Some apps may return Tire::Results::Item objects in results instead of Changeling objects.
80
- results.map { |result|
81
- if result.class == Changeling::Models::Logling
82
- result
83
- elsif result.class == Tire::Results::Item
84
- Logling.new(JSON.parse(result.to_json))
85
- elsif result.class == Hash
86
- Logling.new(result)
87
- end
57
+ sort = {
58
+ :field => :modified_at,
59
+ :direction => :desc
88
60
  }
61
+
62
+ results = Changeling::Support::Search.find_by(:filters => filters, :sort => sort)
63
+
64
+ if length
65
+ results.take(length)
66
+ else
67
+ results
68
+ end
89
69
  end
90
70
  end
91
71
 
92
72
  def to_indexed_json
93
73
  {
74
+ :id => self.id,
94
75
  :klass => self.klass.to_s.underscore,
95
76
  :oid => self.oid.to_s,
77
+ :modified_by => self.modified_by,
96
78
  :modifications => self.modifications.to_json,
97
79
  :modified_at => self.modified_at,
98
80
  :modified_fields => self.modified_fields
@@ -103,16 +85,23 @@ module Changeling
103
85
  {
104
86
  :class => self.klass,
105
87
  :oid => self.oid,
88
+ :modified_by => self.modified_by,
106
89
  :modifications => self.modifications,
107
90
  :modified_at => self.modified_at
108
91
  }
109
92
  end
110
93
 
94
+ def id
95
+ # Make sure ElasticSearch creates new entries rather than update old entries.
96
+ Digest::MD5.hexdigest("#{self.klass}:#{self.oid}:#{self.modifications}")
97
+ end
98
+
111
99
  def initialize(object)
112
100
  if object.class == Hash
113
101
  changes = JSON.parse(object['modifications'])
114
102
  self.klass = object['klass'].camelize.constantize
115
103
  self.oid = object['oid'].to_i.to_s == object['oid'] ? object['oid'].to_i : object['oid']
104
+ self.modified_by = object['modified_by'].to_i.to_s == object['modified_by'] ? object['modified_by'].to_i : object['modified_by']
116
105
  self.modifications = changes
117
106
  self.modified_fields = self.modifications.keys
118
107
 
@@ -124,8 +113,9 @@ module Changeling
124
113
  # Remove updated_at field.
125
114
  changes.delete("updated_at")
126
115
 
127
- self.klass = Logling.klassify(object)
116
+ self.klass = object.class
128
117
  self.oid = object.id
118
+ self.modified_by = Changeling.blame_user.try(:id) || nil
129
119
  self.modifications = changes
130
120
  self.modified_fields = self.modifications.keys
131
121
 
@@ -141,7 +131,7 @@ module Changeling
141
131
 
142
132
  def save
143
133
  unless self.modifications.empty?
144
- _run_save_callbacks {}
134
+ self.update_index
145
135
  end
146
136
  end
147
137
  end
@@ -0,0 +1,40 @@
1
+ module Changeling
2
+ module Support
3
+ class Search
4
+ def self.find_by(args)
5
+ return [] unless args.kind_of?(Hash)
6
+
7
+ filters = args[:filters]
8
+ sort = args[:sort]
9
+ return [] unless filters || sort
10
+
11
+ @class = Changeling::Models::Logling
12
+ @class.tire.index.refresh
13
+
14
+ results = @class.search do
15
+ query do
16
+ filtered do
17
+ query { all }
18
+ filters.each do |f|
19
+ filter :terms, { f.first[0].to_sym => [f.first[1].to_s] }
20
+ end
21
+ end
22
+ end
23
+
24
+ sort { by sort[:field], sort[:direction].to_s }
25
+ end.results
26
+
27
+ # Some apps may return Tire::Results::Item objects in results instead of Changeling objects.
28
+ results.map { |result|
29
+ if result.class == @class
30
+ result
31
+ elsif result.class == Tire::Results::Item
32
+ @class.new(JSON.parse(result.to_json))
33
+ elsif result.class == Hash
34
+ @class.new(result)
35
+ end
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,3 @@
1
1
  module Changeling
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsApp do
4
+ controller(RailsApp::BlamelingController) do
5
+ extend(RSpec::Rails::ControllerExampleGroup::BypassRescue)
6
+ end
7
+
8
+ before(:each) do
9
+ # Request needs to be setup to avoid path setting error
10
+ @request = ActionController::TestRequest.new
11
+ end
12
+
13
+ it "should set current_user if Blameling is included" do
14
+ Thread.new {
15
+ post :create
16
+ # Look in application.rb for the User class and it's id method.
17
+ BlogPost.last.all_history.last.modified_by.should == 33
18
+ }.join
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsApp do
4
+ controller(RailsApp::BlogPostsController) do
5
+ extend(RSpec::Rails::ControllerExampleGroup::BypassRescue)
6
+ end
7
+
8
+ before(:each) do
9
+ # Request needs to be setup to avoid path setting error
10
+ @request = ActionController::TestRequest.new
11
+ end
12
+
13
+ it "should not set current_user if Blameling is not included" do
14
+ Thread.new {
15
+ post :create
16
+ # Look in application.rb for the User class and it's id method.
17
+ BlogPost.last.all_history.last.modified_by.should == nil
18
+ }.join
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsApp do
4
+ controller(RailsApp::CurrentAccountController) do
5
+ extend(RSpec::Rails::ControllerExampleGroup::BypassRescue)
6
+ end
7
+
8
+ before(:each) do
9
+ # Request needs to be setup to avoid path setting error
10
+ @request = ActionController::TestRequest.new
11
+ end
12
+
13
+ it "should not set current_user if current_user is not defined" do
14
+ Thread.new {
15
+ post :create
16
+ # Look in application.rb for the User class and it's id method.
17
+ BlogPost.last.all_history.last.modified_by.should == 88
18
+ }.join
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsApp do
4
+ controller(RailsApp::NoCurrentUserController) do
5
+ extend(RSpec::Rails::ControllerExampleGroup::BypassRescue)
6
+ end
7
+
8
+ before(:each) do
9
+ # Request needs to be setup to avoid path setting error
10
+ @request = ActionController::TestRequest.new
11
+ end
12
+
13
+ it "should not set current_user if current_user is not defined" do
14
+ Thread.new {
15
+ post :create
16
+ # Look in application.rb for the User class and it's id method.
17
+ BlogPost.last.all_history.last.modified_by.should == nil
18
+ }.join
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ module RailsApp
4
+ class Application < Rails::Application
5
+ # app config here
6
+ # config.secret_token = '572c86f5ede338bd8aba8dae0fd3a326aabababc98d1e6ce34b9f5'
7
+ # routes.draw do
8
+ # resources :blog_posts
9
+ # end
10
+ end
11
+
12
+ class ApplicationController < ActionController::Base
13
+ def render(*attributes)
14
+ # Override render so we don't have to deal with rendering in tests.
15
+ end
16
+
17
+ def current_user
18
+ User.new
19
+ end
20
+ end
21
+
22
+ class User
23
+ def id
24
+ 33
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ require (File.expand_path('../blog_posts_controller', __FILE__))
2
+
3
+ module RailsApp
4
+ class BlamelingController < BlogPostsController
5
+ include Changeling::Blameling
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module RailsApp
2
+ class BlogPostsController < ApplicationController
3
+ def create
4
+ @object = BlogPost.new(models[BlogPost][:options])
5
+ @object.save!
6
+
7
+ models[BlogPost][:changes].each do |field, values|
8
+ values.reverse.each do |value|
9
+ @object.send("#{field}=", value)
10
+ @object.save!
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require (File.expand_path('../no_current_user_controller', __FILE__))
2
+
3
+ module RailsApp
4
+ class CurrentAccountController < NoCurrentUserController
5
+ def changeling_blame_user
6
+ current_account
7
+ end
8
+
9
+ def current_account
10
+ Account.new
11
+ end
12
+ end
13
+
14
+ class Account
15
+ def id
16
+ 88
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ require (File.expand_path('../blameling_controller', __FILE__))
2
+
3
+ module RailsApp
4
+ class NoCurrentUserController < BlamelingController
5
+ undef :current_user
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ # Setup for the fields etc. happens in spec_helper.
2
+ class BlogPostActiveRecord < ActiveRecord::Base
3
+ include Changeling::Trackling
4
+ include Changeling::Probeling
5
+ end
@@ -1,4 +1,4 @@
1
- require (File.expand_path('../../../../spec_helper', __FILE__))
1
+ require 'spec_helper'
2
2
 
3
3
  describe Changeling::Models::Logling do
4
4
  before(:all) do
@@ -83,8 +83,8 @@ describe Changeling::Models::Logling do
83
83
  @before, @after = @klass.parse_changes(@changes)
84
84
  end
85
85
 
86
- it "should set klass as the .klassify-ed value" do
87
- @logling.klass.should == @klass.klassify(@object)
86
+ it "should set klass as the object's class" do
87
+ @logling.klass.should == @object.class
88
88
  end
89
89
 
90
90
  it "should set oid as the object's ID" do
@@ -161,39 +161,73 @@ describe Changeling::Models::Logling do
161
161
  end
162
162
 
163
163
  describe ".klassify" do
164
- it "should return the object's class" do
165
- @klass.klassify(@object).should == @object.class
164
+ it "should return the object's class as an underscored string" do
165
+ @klass.klassify(@object).should == @object.class.to_s.underscore
166
166
  end
167
167
  end
168
168
 
169
- # TODO: More specs!
170
169
  describe ".records_for" do
171
170
  before(:each) do
172
- @index = @klass.tire.index
171
+ @search = Changeling::Support::Search
173
172
  @results = []
174
- @klass.stub_chain(:tire, :index).and_return(@index)
175
- @klass.stub_chain(:search, :results).and_return(@results)
176
173
  end
177
174
 
178
- it "should refresh the ElasticSearch index" do
179
- @index.should_receive(:refresh)
175
+ context "length parameter" do
176
+ before(:each) do
177
+ @search.stub(:find_by).and_return(@results)
178
+ end
179
+
180
+ it "should only return the amount specified" do
181
+ num = 5
182
+ @results.should_receive(:take).with(num).and_return([])
183
+ @klass.records_for(@object, 5)
184
+ end
185
+
186
+ it "should return all if no amount is specified" do
187
+ @results.should_not_receive(:take)
188
+ @klass.records_for(@object)
189
+ end
190
+ end
191
+
192
+ it "should search with filters on the klass and oid" do
193
+ @search.should_receive(:find_by).with(hash_including({
194
+ :filters => [
195
+ { :klass => @klass.klassify(@object) },
196
+ { :oid => @object.id.to_s }
197
+ ]
198
+ })).and_return(@results)
180
199
  @klass.records_for(@object)
181
200
  end
182
201
 
183
- it "should only return the amount specified" do
184
- num = 5
185
- @results.should_receive(:take).with(num).and_return([])
186
- @klass.records_for(@object, 5)
202
+ it "should search with a filter on the field if one is passed in" do
203
+ @search.should_receive(:find_by).with(hash_including(
204
+ :filters => [
205
+ { :klass => @klass.klassify(@object) },
206
+ { :oid => @object.id.to_s },
207
+ { :modified_fields => "field" }
208
+ ]
209
+ )).and_return(@results)
210
+ @klass.records_for(@object, nil, "field")
187
211
  end
188
212
 
189
- it "should return all if no amount is specified" do
190
- @results.should_not_receive(:take)
191
- @klass.records_for(@object)
213
+ it "should sort by descending modified_at" do
214
+ @search.should_receive(:find_by).with(hash_including({
215
+ :sort => {
216
+ :field => :modified_at,
217
+ :direction => :desc
218
+ }
219
+ })).and_return(@results)
220
+ @klass.records_for(@object, nil)
192
221
  end
193
222
  end
194
223
  end
195
224
 
196
225
  context "Instance Methods" do
226
+ before(:each) do
227
+ # Stub :id so that it doesn't screw up these test's expectations.
228
+ @logling.stub(:id).and_return(1)
229
+ end
230
+
197
231
  describe ".to_indexed_json" do
198
232
  it "should include the object's klass attribute" do
199
233
  @logling.should_receive(:klass)
@@ -232,7 +266,7 @@ describe Changeling::Models::Logling do
232
266
  end
233
267
 
234
268
  it "should include the object's klass attribute" do
235
- @json[:class].should == @klass.klassify(@object)
269
+ @json[:class].should == @object.class
236
270
  end
237
271
 
238
272
  it "should include the object's oid attribute" do
@@ -254,7 +288,7 @@ describe Changeling::Models::Logling do
254
288
 
255
289
  describe ".save" do
256
290
  it "should update the ElasticSearch index" do
257
- @logling.should_receive(:_run_save_callbacks)
291
+ @logling.should_receive(:update_index)
258
292
  end
259
293
 
260
294
  it "should not update the index if there are no changes" do
@@ -1,4 +1,4 @@
1
- require (File.expand_path('../../../spec_helper', __FILE__))
1
+ require 'spec_helper'
2
2
 
3
3
  describe Changeling::Probeling do
4
4
  before(:all) do
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe Changeling::Support::Search do
4
+ before(:all) do
5
+ @klass = Changeling::Models::Logling
6
+ @search = Changeling::Support::Search
7
+ end
8
+
9
+ describe ".find_by" do
10
+ before(:each) do
11
+ @index = @klass.tire.index
12
+ @klass.stub_chain(:tire, :index).and_return(@index)
13
+
14
+ filters = [
15
+ { :klass => "blog_post" },
16
+ { :oid => "1" }
17
+ ]
18
+
19
+ sort = {
20
+ :field => :modified_at,
21
+ :direction => :desc
22
+ }
23
+
24
+ @options = { :filters => filters, :sort => sort }
25
+
26
+ @results = []
27
+
28
+ models.each_pair do |model, args|
29
+ object = model.new(args[:options])
30
+ changes = args[:changes]
31
+
32
+ object.stub(:changes).and_return(changes)
33
+ @results << @klass.new(object)
34
+ end
35
+
36
+ @klass.stub_chain(:search, :results).and_return(@results)
37
+ end
38
+
39
+ it "should return an empty array if options are not a hash" do
40
+ @search.find_by(nil).should == []
41
+ end
42
+
43
+ it "should return an empty array if options do not include filters or sort keys" do
44
+ @search.find_by({}).should == []
45
+ end
46
+
47
+ it "should refresh the ElasticSearch index" do
48
+ @index.should_receive(:refresh)
49
+ @search.find_by(@options)
50
+ end
51
+
52
+ context "results processing" do
53
+ it "should return objects as is if they are Logling objects" do
54
+ @search.find_by(@options).should == @results
55
+ end
56
+
57
+ it "should parse them and convert them into Logling objects if they are returned as Tire::Results::Item objects" do
58
+ @tire_object = Tire::Results::Item.new
59
+ @tire_json = "{}"
60
+ @hash = {}
61
+
62
+ @results = [@tire_object]
63
+ @klass.stub_chain(:search, :results).and_return(@results)
64
+
65
+ @tire_object.should_receive(:to_json).and_return(@tire_json)
66
+ JSON.should_receive(:parse).with(@tire_json).and_return(@hash)
67
+ @klass.should_receive(:new).with(@hash)
68
+
69
+ @search.find_by(@options)
70
+ end
71
+
72
+ it "should convert them into Logling objects if they are returned as Hash objects" do
73
+ @results = [{}, {}]
74
+ @klass.stub_chain(:search, :results).and_return(@results)
75
+
76
+ @results.each { |r| @klass.should_receive(:new).with(r) }
77
+ @search.find_by(@options)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,4 +1,4 @@
1
- require (File.expand_path('../../../spec_helper', __FILE__))
1
+ require 'spec_helper'
2
2
 
3
3
  describe Changeling::Trackling do
4
4
  before(:all) do
@@ -1,6 +1,9 @@
1
1
  require(File.expand_path('../../lib/changeling', __FILE__))
2
2
  require 'mongoid'
3
3
  require 'database_cleaner'
4
+ require 'rails/all'
5
+ require 'rspec/rails'
6
+ require 'action_controller/railtie' # allows ActionController::Base
4
7
 
5
8
  # Fixtures
6
9
  Dir[File.dirname(__FILE__) + "/fixtures/**/*.rb"].each { |file| require file }
@@ -15,10 +18,24 @@ else
15
18
  Mongoid.database = Mongo::Connection.new('localhost','27017').db('changeling_test')
16
19
  end
17
20
 
21
+ # ActiveRecord setup
22
+ ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ":memory:" )
23
+
24
+ ActiveRecord::Migration.verbose = false
25
+ ActiveRecord::Schema.define(:version => 1) do
26
+ # See the activerecord folder under spec/fixtures/models
27
+ create_table :blog_post_active_records do |t|
28
+ t.string :title
29
+ t.string :content
30
+ t.boolean :public
31
+ end
32
+ end
33
+
18
34
  RSpec.configure do |config|
19
35
  config.mock_with :rspec
20
36
 
21
37
  config.before(:suite) do
38
+ DatabaseCleaner[:active_record].strategy = :truncation
22
39
  DatabaseCleaner[:mongoid].strategy = :truncation
23
40
  Tire::Model::Search.index_prefix "changeling_test"
24
41
  end
@@ -48,29 +65,21 @@ def clear_tire_indexes
48
65
  end
49
66
 
50
67
  def models
51
- @models = {
52
- BlogPost => {
53
- :options => {
54
- :title => "Changeling",
55
- :content => "Something about Changeling",
56
- :public => false
57
- },
58
- :changes => {
59
- "public" => [false, true],
60
- "content" => ["Something about Changeling", "Content about Changeling"]
61
- }
68
+ hash = {
69
+ :options => {
70
+ :title => "Changeling",
71
+ :content => "Something about Changeling",
72
+ :public => false
62
73
  },
63
-
64
- BlogPostNoTimestamp => {
65
- :options => {
66
- :title => "Changeling",
67
- :content => "Something about Changeling",
68
- :public => false
69
- },
70
- :changes => {
71
- "public" => [false, true],
72
- "content" => ["Something about Changeling", "Content about Changeling"]
73
- }
74
+ :changes => {
75
+ "public" => [false, true],
76
+ "content" => ["Something about Changeling", "Content about Changeling"]
74
77
  }
75
78
  }
79
+
80
+ @models = {
81
+ BlogPost => hash,
82
+ BlogPostNoTimestamp => hash,
83
+ BlogPostActiveRecord => hash
84
+ }
76
85
  end
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.5
4
+ version: 0.0.6
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-12-10 00:00:00.000000000 Z
12
+ date: 2013-02-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tire
16
- requirement: &70170915769820 !ruby/object:Gem::Requirement
16
+ requirement: &70261420742240 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70170915769820
24
+ version_requirements: *70261420742240
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activemodel
27
- requirement: &70170915767980 !ruby/object:Gem::Requirement
27
+ requirement: &70261420741820 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,32 +32,32 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70170915767980
35
+ version_requirements: *70261420741820
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: mongoid
38
- requirement: &70170915766520 !ruby/object:Gem::Requirement
38
+ requirement: &70261420741320 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - =
42
42
  - !ruby/object:Gem::Version
43
- version: 3.0.3
43
+ version: 2.4.1
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70170915766520
46
+ version_requirements: *70261420741320
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: activerecord
49
- requirement: &70170915764360 !ruby/object:Gem::Requirement
49
+ requirement: &70261420740820 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - =
53
53
  - !ruby/object:Gem::Version
54
- version: 3.2.7
54
+ version: 3.1.3
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70170915764360
57
+ version_requirements: *70261420740820
58
58
  - !ruby/object:Gem::Dependency
59
- name: debugger
60
- requirement: &70170915763160 !ruby/object:Gem::Requirement
59
+ name: ruby-debug19
60
+ requirement: &70261420740440 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70170915763160
68
+ version_requirements: *70261420740440
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
- requirement: &70170915777700 !ruby/object:Gem::Requirement
71
+ requirement: &70261420739980 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70170915777700
79
+ version_requirements: *70261420739980
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rspec
82
- requirement: &70170915775660 !ruby/object:Gem::Requirement
82
+ requirement: &70261404212700 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,21 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70170915775660
90
+ version_requirements: *70261404212700
91
+ - !ruby/object:Gem::Dependency
92
+ name: rspec-rails
93
+ requirement: &70261404212280 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70261404212280
91
102
  - !ruby/object:Gem::Dependency
92
103
  name: bson_ext
93
- requirement: &70170915773840 !ruby/object:Gem::Requirement
104
+ requirement: &70261404211860 !ruby/object:Gem::Requirement
94
105
  none: false
95
106
  requirements:
96
107
  - - ! '>='
@@ -98,10 +109,32 @@ dependencies:
98
109
  version: '0'
99
110
  type: :development
100
111
  prerelease: false
101
- version_requirements: *70170915773840
112
+ version_requirements: *70261404211860
102
113
  - !ruby/object:Gem::Dependency
103
114
  name: database_cleaner
104
- requirement: &70170915771240 !ruby/object:Gem::Requirement
115
+ requirement: &70261404211440 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: *70261404211440
124
+ - !ruby/object:Gem::Dependency
125
+ name: sqlite3
126
+ requirement: &70261404211020 !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: *70261404211020
135
+ - !ruby/object:Gem::Dependency
136
+ name: rails
137
+ requirement: &70261404210600 !ruby/object:Gem::Requirement
105
138
  none: false
106
139
  requirements:
107
140
  - - ! '>='
@@ -109,7 +142,7 @@ dependencies:
109
142
  version: '0'
110
143
  type: :development
111
144
  prerelease: false
112
- version_requirements: *70170915771240
145
+ version_requirements: *70261404210600
113
146
  description: A simple, yet flexible solution to tracking changes made to objects in
114
147
  your database.
115
148
  email:
@@ -128,15 +161,28 @@ files:
128
161
  - Rakefile
129
162
  - changeling.gemspec
130
163
  - lib/changeling.rb
164
+ - lib/changeling/blameling.rb
131
165
  - lib/changeling/models/logling.rb
132
166
  - lib/changeling/probeling.rb
167
+ - lib/changeling/support/search.rb
133
168
  - lib/changeling/trackling.rb
134
169
  - lib/changeling/version.rb
135
170
  - spec/config/mongoid.yml
136
- - spec/fixtures/models/mongoid/blog_post.rb
137
- - spec/fixtures/models/mongoid/blog_post_no_timestamp.rb
171
+ - spec/controllers/blameling_controller_spec.rb
172
+ - spec/controllers/blog_posts_controller_spec.rb
173
+ - spec/controllers/current_account_controller_spec.rb
174
+ - spec/controllers/no_current_user_controller_spec.rb
175
+ - spec/fixtures/app/application.rb
176
+ - spec/fixtures/app/controllers/blameling_controller.rb
177
+ - spec/fixtures/app/controllers/blog_posts_controller.rb
178
+ - spec/fixtures/app/controllers/current_account_controller.rb
179
+ - spec/fixtures/app/controllers/no_current_user_controller.rb
180
+ - spec/fixtures/app/models/blog_post.rb
181
+ - spec/fixtures/app/models/blog_post_active_record.rb
182
+ - spec/fixtures/app/models/blog_post_no_timestamp.rb
138
183
  - spec/lib/changeling/models/logling_spec.rb
139
184
  - spec/lib/changeling/probeling_spec.rb
185
+ - spec/lib/changeling/support/search_spec.rb
140
186
  - spec/lib/changeling/trackling_spec.rb
141
187
  - spec/spec_helper.rb
142
188
  homepage: ''
@@ -159,15 +205,26 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
205
  version: '0'
160
206
  requirements: []
161
207
  rubyforge_project:
162
- rubygems_version: 1.8.6
208
+ rubygems_version: 1.8.15
163
209
  signing_key:
164
210
  specification_version: 3
165
211
  summary: Object change-logger
166
212
  test_files:
167
213
  - spec/config/mongoid.yml
168
- - spec/fixtures/models/mongoid/blog_post.rb
169
- - spec/fixtures/models/mongoid/blog_post_no_timestamp.rb
214
+ - spec/controllers/blameling_controller_spec.rb
215
+ - spec/controllers/blog_posts_controller_spec.rb
216
+ - spec/controllers/current_account_controller_spec.rb
217
+ - spec/controllers/no_current_user_controller_spec.rb
218
+ - spec/fixtures/app/application.rb
219
+ - spec/fixtures/app/controllers/blameling_controller.rb
220
+ - spec/fixtures/app/controllers/blog_posts_controller.rb
221
+ - spec/fixtures/app/controllers/current_account_controller.rb
222
+ - spec/fixtures/app/controllers/no_current_user_controller.rb
223
+ - spec/fixtures/app/models/blog_post.rb
224
+ - spec/fixtures/app/models/blog_post_active_record.rb
225
+ - spec/fixtures/app/models/blog_post_no_timestamp.rb
170
226
  - spec/lib/changeling/models/logling_spec.rb
171
227
  - spec/lib/changeling/probeling_spec.rb
228
+ - spec/lib/changeling/support/search_spec.rb
172
229
  - spec/lib/changeling/trackling_spec.rb
173
230
  - spec/spec_helper.rb