activehistory 0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +90 -0
- data/LICENSE +21 -0
- data/README.md +1 -0
- data/Rakefile +12 -0
- data/activehistory.gemspec +40 -0
- data/lib/activehistory.rb +39 -0
- data/lib/activehistory/action.rb +20 -0
- data/lib/activehistory/adapters/active_record.rb +202 -0
- data/lib/activehistory/connection.rb +121 -0
- data/lib/activehistory/event.rb +50 -0
- data/lib/activehistory/exceptions.rb +32 -0
- data/lib/activehistory/regard.rb +11 -0
- data/lib/activehistory/version.rb +3 -0
- data/test/active_record_adapter/association_test/belongs_to_association_test.rb +82 -0
- data/test/active_record_adapter/association_test/has_and_belongs_to_many_test.rb +224 -0
- data/test/active_record_adapter/association_test/has_many_association_test.rb +81 -0
- data/test/active_record_adapter/association_test/has_one_association_test.rb +141 -0
- data/test/active_record_adapter/create_test.rb +58 -0
- data/test/active_record_adapter/destroy_test.rb +38 -0
- data/test/active_record_adapter/event_test.rb +59 -0
- data/test/active_record_adapter/save_test.rb +67 -0
- data/test/factories.rb +36 -0
- data/test/models.rb +60 -0
- data/test/schema.rb +59 -0
- data/test/test_helper.rb +55 -0
- metadata +282 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class HasManyAssociationTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@time = (Time.now.utc + 2).change(usec: 0)
|
8
|
+
end
|
9
|
+
|
10
|
+
test '::create with has_many association' do
|
11
|
+
@property = create(:property)
|
12
|
+
WebMock::RequestRegistry.instance.reset!
|
13
|
+
|
14
|
+
@photo = travel_to(@time) { create(:photo, property: @property) }
|
15
|
+
|
16
|
+
assert_posted("/events") do |req|
|
17
|
+
req_data = JSON.parse(req.body)
|
18
|
+
assert_equal 2, req_data['actions'].size
|
19
|
+
|
20
|
+
assert_equal req_data['actions'][0], {
|
21
|
+
diff: {
|
22
|
+
id: [nil, @photo.id],
|
23
|
+
property_id: [nil, @property.id],
|
24
|
+
format: [nil, @photo.format]
|
25
|
+
},
|
26
|
+
subject: "Photo/#{@photo.id}",
|
27
|
+
timestamp: @time.iso8601(3),
|
28
|
+
type: 'create'
|
29
|
+
}.as_json
|
30
|
+
|
31
|
+
assert_equal req_data['actions'][1], {
|
32
|
+
timestamp: @time.iso8601(3),
|
33
|
+
type: 'update',
|
34
|
+
subject: "Property/#{@property.id}",
|
35
|
+
diff: {
|
36
|
+
photo_ids: [[], [@photo.id]]
|
37
|
+
}
|
38
|
+
}.as_json
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
test '::update with has_many association' do
|
43
|
+
@property = create(:property)
|
44
|
+
@photo = create(:photo, property: @property)
|
45
|
+
WebMock::RequestRegistry.instance.reset!
|
46
|
+
|
47
|
+
travel_to(@time) { @photo.update(property: nil) }
|
48
|
+
|
49
|
+
assert_posted("/events") do |req|
|
50
|
+
req_data = JSON.parse(req.body)
|
51
|
+
assert_equal 2, req_data['actions'].size
|
52
|
+
|
53
|
+
assert_equal req_data['actions'][0], {
|
54
|
+
diff: {
|
55
|
+
property_id: [@property.id, nil]
|
56
|
+
},
|
57
|
+
subject: "Photo/#{@photo.id}",
|
58
|
+
timestamp: @time.iso8601(3),
|
59
|
+
type: 'update'
|
60
|
+
}.as_json
|
61
|
+
|
62
|
+
assert_equal req_data['actions'][1], {
|
63
|
+
timestamp: @time.iso8601(3),
|
64
|
+
type: 'update',
|
65
|
+
subject: "Property/#{@property.id}",
|
66
|
+
diff: {
|
67
|
+
photo_ids: [[@photo.id], []]
|
68
|
+
}
|
69
|
+
}.as_json
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
test 'has_many <<'
|
74
|
+
test 'has_many.delete'
|
75
|
+
test 'has_many.destroy'
|
76
|
+
test 'has_many='
|
77
|
+
test 'has_many_ids='
|
78
|
+
test 'has_many.clear'
|
79
|
+
test 'has_many.create'
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class HasOneAssociationTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@time = (Time.now.utc + 2).change(usec: 0)
|
8
|
+
end
|
9
|
+
|
10
|
+
test '::create with has_one association' do
|
11
|
+
@email_address = create(:email_address)
|
12
|
+
WebMock::RequestRegistry.instance.reset!
|
13
|
+
|
14
|
+
@account = travel_to(@time) { create(:account, email_address: @email_address) }
|
15
|
+
|
16
|
+
assert_posted("/events") do |req|
|
17
|
+
req_data = JSON.parse(req.body)
|
18
|
+
assert_equal 2, req_data['actions'].size
|
19
|
+
|
20
|
+
assert_equal req_data['actions'][0], {
|
21
|
+
diff: {
|
22
|
+
id: [nil, @account.id],
|
23
|
+
name: [nil, @account.name],
|
24
|
+
photos_count: [nil, 0],
|
25
|
+
email_address_id: [nil, @email_address.id]
|
26
|
+
},
|
27
|
+
subject: "Account/#{@account.id}",
|
28
|
+
timestamp: @time.iso8601(3),
|
29
|
+
type: 'create'
|
30
|
+
}.as_json
|
31
|
+
|
32
|
+
assert_equal req_data['actions'][1], {
|
33
|
+
timestamp: @time.iso8601(3),
|
34
|
+
type: 'update',
|
35
|
+
subject: "EmailAddress/#{@email_address.id}",
|
36
|
+
diff: {
|
37
|
+
account_id: [nil, @account.id]
|
38
|
+
}
|
39
|
+
}.as_json
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
test '::create with belongs_to association' do
|
44
|
+
@account = create(:account)
|
45
|
+
WebMock::RequestRegistry.instance.reset!
|
46
|
+
|
47
|
+
@email_address = travel_to(@time) { create(:email_address, account: @account) }
|
48
|
+
|
49
|
+
assert_posted("/events") do |req|
|
50
|
+
req_data = JSON.parse(req.body)
|
51
|
+
assert_equal 2, req_data['actions'].size
|
52
|
+
|
53
|
+
assert_equal req_data['actions'][0], {
|
54
|
+
diff: {
|
55
|
+
id: [nil, @email_address.id],
|
56
|
+
address: [nil, @email_address.address],
|
57
|
+
account_id: [nil, @account.id]
|
58
|
+
},
|
59
|
+
subject: "EmailAddress/#{@email_address.id}",
|
60
|
+
timestamp: @time.iso8601(3),
|
61
|
+
type: 'create'
|
62
|
+
}.as_json
|
63
|
+
|
64
|
+
assert_equal req_data['actions'][1], {
|
65
|
+
timestamp: @time.iso8601(3),
|
66
|
+
type: 'update',
|
67
|
+
subject: "Account/#{@account.id}",
|
68
|
+
diff: {
|
69
|
+
email_address_id: [nil, @email_address.id]
|
70
|
+
}
|
71
|
+
}.as_json
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
test '::create with has_one association 2' do
|
76
|
+
@account = travel_to(@time) { create(:account, email_address: build(:email_address)) }
|
77
|
+
|
78
|
+
assert_posted("/events") do |req|
|
79
|
+
req_data = JSON.parse(req.body)
|
80
|
+
assert_equal 2, req_data['actions'].size
|
81
|
+
|
82
|
+
assert_equal req_data['actions'][0], {
|
83
|
+
diff: {
|
84
|
+
id: [nil, @account.id],
|
85
|
+
name: [nil, @account.name],
|
86
|
+
photos_count: [nil, 0],
|
87
|
+
email_address_id: [nil, @account.email_address.id]
|
88
|
+
},
|
89
|
+
subject: "Account/#{@account.id}",
|
90
|
+
timestamp: @time.iso8601(3),
|
91
|
+
type: 'create'
|
92
|
+
}.as_json
|
93
|
+
|
94
|
+
assert_equal req_data['actions'][1], {
|
95
|
+
timestamp: @time.iso8601(3),
|
96
|
+
type: 'create',
|
97
|
+
subject: "EmailAddress/#{@account.email_address.id}",
|
98
|
+
diff: {
|
99
|
+
id: [nil, @account.email_address.id],
|
100
|
+
address: [nil, @account.email_address.address],
|
101
|
+
account_id: [nil, @account.id]
|
102
|
+
}
|
103
|
+
}.as_json
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
test '::update removes has_one association' do
|
108
|
+
@account = create(:account, email_address: build(:email_address))
|
109
|
+
WebMock::RequestRegistry.instance.reset!
|
110
|
+
|
111
|
+
@email_address = @account.email_address
|
112
|
+
travel_to(@time) { @account.update(email_address: nil) }
|
113
|
+
|
114
|
+
assert_posted("/events") do |req|
|
115
|
+
req_data = JSON.parse(req.body)
|
116
|
+
assert_equal 2, req_data['actions'].size
|
117
|
+
|
118
|
+
assert_equal req_data['actions'][0], {
|
119
|
+
diff: {
|
120
|
+
account_id: [@account.id, nil]
|
121
|
+
},
|
122
|
+
subject: "EmailAddress/#{@email_address.id}",
|
123
|
+
timestamp: @time.iso8601(3),
|
124
|
+
type: 'update'
|
125
|
+
}.as_json
|
126
|
+
|
127
|
+
assert_equal req_data['actions'][1], {
|
128
|
+
timestamp: @time.iso8601(3),
|
129
|
+
type: 'update',
|
130
|
+
subject: "Account/#{@account.id}",
|
131
|
+
diff: {
|
132
|
+
email_address_id: [@email_address.id, nil]
|
133
|
+
}
|
134
|
+
}.as_json
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
test '::destroy removes has_one association with dependent: :nullify'
|
139
|
+
test '::destroy removes has_one association with dependent: :delete'
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CreateTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@time = Time.now.utc.change(usec: 0)
|
8
|
+
end
|
9
|
+
|
10
|
+
test '::create creates an Action' do
|
11
|
+
@property = travel_to(@time) { create(:property) }
|
12
|
+
|
13
|
+
assert_posted("/events") do |req|
|
14
|
+
req_data = JSON.parse(req.body)
|
15
|
+
assert_equal 1, req_data['actions'].size
|
16
|
+
|
17
|
+
assert_equal req_data['actions'][0], {
|
18
|
+
diff: {
|
19
|
+
id: [nil, @property.id],
|
20
|
+
name: [nil, @property.name],
|
21
|
+
aliases: [nil, []],
|
22
|
+
description: [nil, @property.description],
|
23
|
+
constructed: [nil, @property.constructed],
|
24
|
+
size: [nil, @property.size],
|
25
|
+
active: [nil, @property.active],
|
26
|
+
created_at: [nil, @property.created_at]
|
27
|
+
},
|
28
|
+
subject: "Property/#{@property.id}",
|
29
|
+
timestamp: @time.iso8601(3),
|
30
|
+
type: 'create'
|
31
|
+
}.as_json
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
test "::create creates an Action without :excluded attributes" do
|
36
|
+
@comment = travel_to(@time) { create(:comment) }
|
37
|
+
|
38
|
+
assert_posted("/events") do |req|
|
39
|
+
req_data = JSON.parse(req.body)
|
40
|
+
assert_equal 1, req_data['actions'].size
|
41
|
+
|
42
|
+
assert_equal req_data['actions'][0], {
|
43
|
+
diff: {
|
44
|
+
id: [nil, @comment.id],
|
45
|
+
# No Title
|
46
|
+
body: [nil, @comment.body]
|
47
|
+
},
|
48
|
+
subject: "Comment/#{@comment.id}",
|
49
|
+
timestamp: @time.iso8601(3),
|
50
|
+
type: 'create'
|
51
|
+
}.as_json
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DestroyTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@time = (Time.now.utc + 2).change(usec: 0)
|
8
|
+
end
|
9
|
+
|
10
|
+
test '::destroy creates an Action' do
|
11
|
+
@property = create(:property)
|
12
|
+
WebMock::RequestRegistry.instance.reset!
|
13
|
+
|
14
|
+
travel_to(@time) { @property.destroy }
|
15
|
+
|
16
|
+
assert_posted("/events") do |req|
|
17
|
+
req_data = JSON.parse(req.body)
|
18
|
+
assert_equal 1, req_data['actions'].size
|
19
|
+
|
20
|
+
assert_equal req_data['actions'][0], {
|
21
|
+
timestamp: @time.iso8601(3),
|
22
|
+
type: 'destroy',
|
23
|
+
subject: "Property/#{@property.id}",
|
24
|
+
diff: {
|
25
|
+
id: [@property.id, nil],
|
26
|
+
name: [@property.name, nil],
|
27
|
+
aliases: [[], nil],
|
28
|
+
description: [@property.description, nil],
|
29
|
+
constructed: [@property.constructed, nil],
|
30
|
+
size: [@property.size, nil],
|
31
|
+
created_at: [@property.created_at, nil],
|
32
|
+
active: [@property.active, nil]
|
33
|
+
}
|
34
|
+
}.as_json
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class EventTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@time = Time.now.utc.change(usec: 0)
|
8
|
+
end
|
9
|
+
|
10
|
+
test 'Data captured from Event encalpsulation' do
|
11
|
+
data = {
|
12
|
+
ip: '127.0.0.1',
|
13
|
+
user_agent: 'user-agent',
|
14
|
+
session_id: 'session-id',
|
15
|
+
account: 'model/id',
|
16
|
+
api_key: 'api-key',
|
17
|
+
metadata: {random: 'stuff'},
|
18
|
+
timestamp: Time.now
|
19
|
+
}
|
20
|
+
|
21
|
+
# TODO: timestamp: @attrs[:timestamp].iso8601(3),
|
22
|
+
ActiveHistory.encapsulate(data) do
|
23
|
+
create(:property)
|
24
|
+
create(:property)
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_requested(:post, "http://activehistory.com/events", times: 1) do |req|
|
28
|
+
req_data = JSON.parse(req.body)
|
29
|
+
data.each do |k, v|
|
30
|
+
assert_equal v.is_a?(Time) ? v.utc.iso8601(3) : v.as_json, req_data[k.to_s]
|
31
|
+
end
|
32
|
+
|
33
|
+
assert_equal 2, req_data['actions'].size
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
test 'Timestamp gets sent with Event' do
|
38
|
+
travel_to @time do
|
39
|
+
ActiveHistory.encapsulate { create(:property) }
|
40
|
+
end
|
41
|
+
|
42
|
+
assert_requested(:post, "http://activehistory.com/events", times: 1) do |req|
|
43
|
+
assert_equal @time.iso8601(3), JSON.parse(req.body)['timestamp']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
test 'Event not captured it no actions taken' do
|
48
|
+
ActiveHistory.encapsulate { 1 + 1 }
|
49
|
+
|
50
|
+
assert_not_requested :any, /^http:\/\/activehistory.com\/.*/
|
51
|
+
end
|
52
|
+
|
53
|
+
test 'Nothing sent on a model not being tracked' do
|
54
|
+
ActiveHistory.encapsulate { create(:unobserved_model) }
|
55
|
+
|
56
|
+
assert_not_requested :any, /^http:\/\/activehistory.com\/.*/
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SaveTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@time = (Time.now.utc + 2).change(usec: 0)
|
8
|
+
end
|
9
|
+
|
10
|
+
test '::save creates an Action' do
|
11
|
+
@property = create(:property, name: 'unkown')
|
12
|
+
WebMock::RequestRegistry.instance.reset!
|
13
|
+
|
14
|
+
@property.name = 'Empire State Building'
|
15
|
+
travel_to(@time) { @property.save }
|
16
|
+
|
17
|
+
assert_posted("/events") do |req|
|
18
|
+
req_data = JSON.parse(req.body)
|
19
|
+
assert_equal 1, req_data['actions'].size
|
20
|
+
|
21
|
+
assert_equal req_data['actions'][0], {
|
22
|
+
timestamp: @time.iso8601(3),
|
23
|
+
type: 'update',
|
24
|
+
subject: "Property/#{@property.id}",
|
25
|
+
diff: {
|
26
|
+
name: ['unkown', 'Empire State Building']
|
27
|
+
}
|
28
|
+
}.as_json
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
test '::save creates an Action, excluding any :excluded attributes' do
|
33
|
+
@comment = create(:comment, title: 'title', body: 'body')
|
34
|
+
WebMock::RequestRegistry.instance.reset!
|
35
|
+
|
36
|
+
@comment.title = 'new title'
|
37
|
+
@comment.body = 'new body'
|
38
|
+
travel_to(@time) { @comment.save }
|
39
|
+
|
40
|
+
assert_posted("/events") do |req|
|
41
|
+
req_data = JSON.parse(req.body)
|
42
|
+
assert_equal 1, req_data['actions'].size
|
43
|
+
|
44
|
+
assert_equal req_data['actions'][0], {
|
45
|
+
timestamp: @time.iso8601(3),
|
46
|
+
type: 'update',
|
47
|
+
subject: "Comment/#{@comment.id}",
|
48
|
+
diff: {
|
49
|
+
body: ['body', 'new body']
|
50
|
+
}
|
51
|
+
}.as_json
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
test "::save doesn't create an Action if just changing :excluded attributes" do
|
56
|
+
@comment = create(:comment, title: 'title', body: 'body')
|
57
|
+
WebMock::RequestRegistry.instance.reset!
|
58
|
+
|
59
|
+
@comment.title = 'new title'
|
60
|
+
travel_to(@time) { @comment.save }
|
61
|
+
|
62
|
+
assert_not_posted("/events")
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|