tantot 0.1.0
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 +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +45 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/tantot/changes.rb +65 -0
- data/lib/tantot/collector/base.rb +6 -0
- data/lib/tantot/collector/block.rb +78 -0
- data/lib/tantot/collector/watcher.rb +87 -0
- data/lib/tantot/collector.rb +76 -0
- data/lib/tantot/config.rb +17 -0
- data/lib/tantot/errors.rb +4 -0
- data/lib/tantot/extensions/chewy.rb +88 -0
- data/lib/tantot/extensions/grape/middleware.rb +17 -0
- data/lib/tantot/formatter/compact.rb +9 -0
- data/lib/tantot/formatter/detailed.rb +9 -0
- data/lib/tantot/formatter.rb +10 -0
- data/lib/tantot/observe.rb +84 -0
- data/lib/tantot/performer/bypass.rb +9 -0
- data/lib/tantot/performer/inline.rb +9 -0
- data/lib/tantot/performer/sidekiq.rb +19 -0
- data/lib/tantot/performer.rb +17 -0
- data/lib/tantot/railtie.rb +23 -0
- data/lib/tantot/registry.rb +11 -0
- data/lib/tantot/version.rb +3 -0
- data/lib/tantot/watcher.rb +16 -0
- data/lib/tantot.rb +62 -0
- data/spec/changes_spec.rb +60 -0
- data/spec/extensions/chewy_spec.rb +127 -0
- data/spec/sidekiq_spec.rb +100 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/tantot_spec.rb +299 -0
- data/tantot.gemspec +31 -0
- metadata +202 -0
data/spec/tantot_spec.rb
ADDED
@@ -0,0 +1,299 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tantot do
|
4
|
+
it "has a version number" do
|
5
|
+
expect(Tantot::VERSION).not_to be nil
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.derive_watcher' do
|
9
|
+
class TestWatcher
|
10
|
+
include Tantot::Watcher
|
11
|
+
end
|
12
|
+
|
13
|
+
class WrongWatcher
|
14
|
+
end
|
15
|
+
|
16
|
+
module Foo
|
17
|
+
class BarWatcher
|
18
|
+
include Tantot::Watcher
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
specify { expect { described_class.derive_watcher('foo') }.to raise_error(Tantot::UnderivableWatcher) }
|
23
|
+
specify { expect { described_class.derive_watcher(WrongWatcher) }.to raise_error(Tantot::UnderivableWatcher) }
|
24
|
+
specify { expect(described_class.derive_watcher(TestWatcher)).to eq(TestWatcher) }
|
25
|
+
specify { expect(described_class.derive_watcher(Foo::BarWatcher)).to eq(Foo::BarWatcher) }
|
26
|
+
specify { expect(described_class.derive_watcher('test')).to eq(TestWatcher) }
|
27
|
+
specify { expect(described_class.derive_watcher('foo/bar')).to eq(Foo::BarWatcher) }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.watch' do
|
31
|
+
|
32
|
+
let(:watcher_instance) { double }
|
33
|
+
|
34
|
+
before do
|
35
|
+
stub_class("TestWatcher") { include Tantot::Watcher }
|
36
|
+
allow(TestWatcher).to receive(:new).and_return(watcher_instance)
|
37
|
+
end
|
38
|
+
|
39
|
+
[true, false].each do |use_after_commit_callbacks|
|
40
|
+
context "using after_commit hooks: #{use_after_commit_callbacks}" do
|
41
|
+
before { allow(Tantot.config).to receive(:use_after_commit_callbacks).and_return(use_after_commit_callbacks) }
|
42
|
+
|
43
|
+
context "watching an attribute" do
|
44
|
+
before do
|
45
|
+
stub_model(:city) do
|
46
|
+
watch TestWatcher, :name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "doesn't call back when the attribute doesn't change" do
|
51
|
+
Tantot.collector.run do
|
52
|
+
City.create
|
53
|
+
expect(watcher_instance).not_to receive(:perform)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "calls back when the attribute changes (on creation)" do
|
58
|
+
Tantot.collector.run do
|
59
|
+
city = City.create name: 'foo'
|
60
|
+
expect(watcher_instance).to receive(:perform).with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => [nil, 'foo']}}}))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "calls back on model update" do
|
65
|
+
city = City.create!
|
66
|
+
city.reload
|
67
|
+
Tantot.collector.sweep(performer: :bypass)
|
68
|
+
|
69
|
+
expect(watcher_instance).to receive(:perform).with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => [nil, 'foo']}}}))
|
70
|
+
Tantot.collector.run do
|
71
|
+
city.name = "foo"
|
72
|
+
city.save
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "calls back on model destroy" do
|
77
|
+
city = City.create!(name: 'foo')
|
78
|
+
city.reload
|
79
|
+
Tantot.collector.sweep(performer: :bypass)
|
80
|
+
|
81
|
+
expect(watcher_instance).to receive(:perform).with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => ['foo']}}}))
|
82
|
+
Tantot.collector.run do
|
83
|
+
city.destroy
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "calls back once per model even when updated more than once" do
|
88
|
+
Tantot.collector.run do
|
89
|
+
city = City.create! name: 'foo'
|
90
|
+
city.name = 'bar'
|
91
|
+
city.save
|
92
|
+
city.name = 'baz'
|
93
|
+
city.save
|
94
|
+
expect(watcher_instance).to receive(:perform).once.with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => [nil, 'foo', 'bar', 'baz']}}}))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "allows to call a watcher mid-stream" do
|
99
|
+
Tantot.collector.run do
|
100
|
+
city = City.create name: 'foo'
|
101
|
+
expect(watcher_instance).to receive(:perform).with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => [nil, 'foo']}}}))
|
102
|
+
Tantot.collector.sweep(performer: :inline, watcher: TestWatcher)
|
103
|
+
city.name = 'bar'
|
104
|
+
city.save
|
105
|
+
expect(watcher_instance).to receive(:perform).with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => ['foo', 'bar']}}}))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "detailed format" do
|
113
|
+
let(:watcher_instance) { double }
|
114
|
+
before do
|
115
|
+
stub_class("DetailedTestWatcher") do
|
116
|
+
include Tantot::Watcher
|
117
|
+
|
118
|
+
watcher_options format: :detailed
|
119
|
+
end
|
120
|
+
allow(DetailedTestWatcher).to receive(:new).and_return(watcher_instance)
|
121
|
+
stub_model(:city) do
|
122
|
+
watch 'detailed_test', :name
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should output a detailed array of changes" do
|
127
|
+
Tantot.collector.run do
|
128
|
+
city = City.create! name: 'foo'
|
129
|
+
city.name = 'bar'
|
130
|
+
city.save
|
131
|
+
expect(watcher_instance).to receive(:perform).with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => [[nil, 'foo'], ['foo', 'bar']]}}}))
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context "on multiple models" do
|
137
|
+
before do
|
138
|
+
stub_model(:city) do
|
139
|
+
watch TestWatcher, :name, :country_id
|
140
|
+
end
|
141
|
+
stub_model(:country) do
|
142
|
+
watch TestWatcher, :country_code
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it "calls back once per watch when multiple watched models change" do
|
147
|
+
country = Country.create!(country_code: "CDN")
|
148
|
+
city = City.create!(name: "Quebec", country_id: country.id)
|
149
|
+
country.reload
|
150
|
+
city.reload
|
151
|
+
Tantot.collector.sweep(performer: :bypass)
|
152
|
+
|
153
|
+
expect(watcher_instance).to receive(:perform).once.with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => ['Quebec', 'foo', 'bar'], "country_id" => [country.id, nil]}}, Country => {country.id => {"country_code" => ['CDN', 'US']}}}))
|
154
|
+
Tantot.collector.run do
|
155
|
+
city.name = "foo"
|
156
|
+
city.save
|
157
|
+
city.name = "bar"
|
158
|
+
city.save
|
159
|
+
city.country_id = nil
|
160
|
+
city.save
|
161
|
+
country.country_code = 'US'
|
162
|
+
country.save
|
163
|
+
city.destroy
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "with multiple watchers" do
|
169
|
+
let(:watchA_instance) { double }
|
170
|
+
let(:watchB_instance) { double }
|
171
|
+
before do
|
172
|
+
stub_class("TestWatcherA") { include Tantot::Watcher }
|
173
|
+
stub_class("TestWatcherB") { include Tantot::Watcher }
|
174
|
+
allow(TestWatcherA).to receive(:new).and_return(watchA_instance)
|
175
|
+
allow(TestWatcherB).to receive(:new).and_return(watchB_instance)
|
176
|
+
stub_model(:city) do
|
177
|
+
watch TestWatcherA, :name, :country_id
|
178
|
+
watch TestWatcherB, :rating
|
179
|
+
end
|
180
|
+
stub_model(:country) do
|
181
|
+
watch TestWatcherA, :country_code
|
182
|
+
watch TestWatcherB, :name, :rating
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
it "calls each watcher once for multiple models" do
|
187
|
+
country = Country.create!(country_code: "CDN")
|
188
|
+
city = City.create!(name: "Quebec", country_id: country.id, rating: 12)
|
189
|
+
country.reload
|
190
|
+
city.reload
|
191
|
+
expect(watchA_instance).to receive(:perform).once.with(Tantot::Changes::ByModel.new({City => {city.id => {"name" => ['Quebec', 'foo', 'bar'], "country_id" => [country.id, nil]}}, Country => {country.id => {"country_code" => ['CDN', 'US']}}}))
|
192
|
+
# WatchB receives the last value of rating since it has been destroyed
|
193
|
+
expect(watchB_instance).to receive(:perform).once.with(Tantot::Changes::ByModel.new({City => {city.id => {"rating" => [12]}}}))
|
194
|
+
Tantot.collector.sweep(performer: :bypass)
|
195
|
+
|
196
|
+
Tantot.collector.run do
|
197
|
+
city.name = "foo"
|
198
|
+
city.save
|
199
|
+
city.name = "bar"
|
200
|
+
city.save
|
201
|
+
city.country_id = nil
|
202
|
+
city.save
|
203
|
+
country.country_code = 'US'
|
204
|
+
country.save
|
205
|
+
city.destroy
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'watching all attributes' do
|
211
|
+
before do
|
212
|
+
stub_model(:city) do
|
213
|
+
watch TestWatcher
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should watch all changes" do
|
218
|
+
Tantot.collector.run do
|
219
|
+
city = City.create name: 'foo'
|
220
|
+
expect(watcher_instance).to receive(:perform).with(Tantot::Changes::ByModel.new({City => {city.id => {"id" => [nil, city.id], "name" => [nil, "foo"]}}}))
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should also watch on destroy, but when watching all attributes, change hash is empty" do
|
225
|
+
city = City.create!(name: 'foo')
|
226
|
+
city.reload
|
227
|
+
Tantot.collector.sweep(performer: :bypass)
|
228
|
+
|
229
|
+
expect(watcher_instance).to receive(:perform).with(Tantot::Changes::ByModel.new({City => {city.id => {}}}))
|
230
|
+
Tantot.collector.run do
|
231
|
+
city.destroy
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context 'with an additional `if` statement' do
|
237
|
+
|
238
|
+
[:no, :some].each do |attribute_opt|
|
239
|
+
context "with #{attribute_opt.to_s} attributes" do
|
240
|
+
let(:condition) { double }
|
241
|
+
before do
|
242
|
+
c = condition
|
243
|
+
watch_params = [TestWatcher]
|
244
|
+
watch_params << :id if attribute_opt == :some
|
245
|
+
watch_params << {if: -> { c.passed? }}
|
246
|
+
stub_model(:city) do
|
247
|
+
watch(*watch_params)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
it "should fail if the condition is false" do
|
252
|
+
Tantot.collector.run do
|
253
|
+
expect(condition).to receive(:passed?).once.and_return(false)
|
254
|
+
City.create!
|
255
|
+
expect(watcher_instance).not_to receive(:perform)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should pass if the condition is true" do
|
260
|
+
Tantot.collector.run do
|
261
|
+
expect(condition).to receive(:passed?).once.and_return(true)
|
262
|
+
City.create!
|
263
|
+
expect(watcher_instance).to receive(:perform)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context 'using a block' do
|
271
|
+
let(:value) { {changes: 0} }
|
272
|
+
let(:changes) { {obj: nil} }
|
273
|
+
before do
|
274
|
+
v = value
|
275
|
+
c = changes
|
276
|
+
stub_model(:city) do
|
277
|
+
watch {|changes| v[:changes] += 1; c[:obj] = changes}
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should call the block" do
|
282
|
+
city = nil
|
283
|
+
Tantot.collector.run do
|
284
|
+
city = City.create!
|
285
|
+
end
|
286
|
+
expect(value[:changes]).to eq(1)
|
287
|
+
expect(changes[:obj]).to eq(Tantot::Changes::ById.new({city.id => {"id" => [nil, 1]}}))
|
288
|
+
end
|
289
|
+
|
290
|
+
it "call a single time if multiple changes occur" do
|
291
|
+
Tantot.collector.run do
|
292
|
+
3.times { City.create! }
|
293
|
+
end
|
294
|
+
expect(value[:changes]).to eq(1)
|
295
|
+
expect(changes[:obj]).to eq(Tantot::Changes::ById.new({1=>{"id"=>[nil, 1]}, 2=>{"id"=>[nil, 2]}, 3=>{"id"=>[nil, 3]}}))
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end # describe '.watch'
|
299
|
+
end
|
data/tantot.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tantot/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "tantot"
|
8
|
+
spec.version = Tantot::VERSION
|
9
|
+
spec.authors = ["François-Pierre Bouchard"]
|
10
|
+
spec.email = ["fpbouchard@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Delayed, grouped and compact ActiveRecord callbacks}
|
13
|
+
spec.description = %q{Centralize and delay changes to multiple ActiveRecord models to offload processing of complex calculations caused by model mutations.}
|
14
|
+
spec.homepage = "https://github.com/petalmd/tantot"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($RS)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
25
|
+
spec.add_development_dependency 'sqlite3'
|
26
|
+
spec.add_development_dependency 'database_cleaner'
|
27
|
+
|
28
|
+
spec.add_dependency 'activesupport', '>= 3.2'
|
29
|
+
spec.add_dependency 'activerecord', '>= 3.2'
|
30
|
+
spec.add_dependency 'cityhash', '>= 0.8'
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tantot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- François-Pierre Bouchard
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.13'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sqlite3
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: database_cleaner
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activesupport
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.2'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.2'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activerecord
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.2'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.2'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: cityhash
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.8'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.8'
|
125
|
+
description: Centralize and delay changes to multiple ActiveRecord models to offload
|
126
|
+
processing of complex calculations caused by model mutations.
|
127
|
+
email:
|
128
|
+
- fpbouchard@gmail.com
|
129
|
+
executables:
|
130
|
+
- console
|
131
|
+
- setup
|
132
|
+
extensions: []
|
133
|
+
extra_rdoc_files: []
|
134
|
+
files:
|
135
|
+
- ".gitignore"
|
136
|
+
- ".rspec"
|
137
|
+
- ".travis.yml"
|
138
|
+
- CODE_OF_CONDUCT.md
|
139
|
+
- Gemfile
|
140
|
+
- LICENSE.txt
|
141
|
+
- README.md
|
142
|
+
- Rakefile
|
143
|
+
- bin/console
|
144
|
+
- bin/setup
|
145
|
+
- lib/tantot.rb
|
146
|
+
- lib/tantot/changes.rb
|
147
|
+
- lib/tantot/collector.rb
|
148
|
+
- lib/tantot/collector/base.rb
|
149
|
+
- lib/tantot/collector/block.rb
|
150
|
+
- lib/tantot/collector/watcher.rb
|
151
|
+
- lib/tantot/config.rb
|
152
|
+
- lib/tantot/errors.rb
|
153
|
+
- lib/tantot/extensions/chewy.rb
|
154
|
+
- lib/tantot/extensions/grape/middleware.rb
|
155
|
+
- lib/tantot/formatter.rb
|
156
|
+
- lib/tantot/formatter/compact.rb
|
157
|
+
- lib/tantot/formatter/detailed.rb
|
158
|
+
- lib/tantot/observe.rb
|
159
|
+
- lib/tantot/performer.rb
|
160
|
+
- lib/tantot/performer/bypass.rb
|
161
|
+
- lib/tantot/performer/inline.rb
|
162
|
+
- lib/tantot/performer/sidekiq.rb
|
163
|
+
- lib/tantot/railtie.rb
|
164
|
+
- lib/tantot/registry.rb
|
165
|
+
- lib/tantot/version.rb
|
166
|
+
- lib/tantot/watcher.rb
|
167
|
+
- spec/changes_spec.rb
|
168
|
+
- spec/extensions/chewy_spec.rb
|
169
|
+
- spec/sidekiq_spec.rb
|
170
|
+
- spec/spec_helper.rb
|
171
|
+
- spec/tantot_spec.rb
|
172
|
+
- tantot.gemspec
|
173
|
+
homepage: https://github.com/petalmd/tantot
|
174
|
+
licenses:
|
175
|
+
- MIT
|
176
|
+
metadata: {}
|
177
|
+
post_install_message:
|
178
|
+
rdoc_options: []
|
179
|
+
require_paths:
|
180
|
+
- lib
|
181
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
187
|
+
requirements:
|
188
|
+
- - ">="
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '0'
|
191
|
+
requirements: []
|
192
|
+
rubyforge_project:
|
193
|
+
rubygems_version: 2.5.1
|
194
|
+
signing_key:
|
195
|
+
specification_version: 4
|
196
|
+
summary: Delayed, grouped and compact ActiveRecord callbacks
|
197
|
+
test_files:
|
198
|
+
- spec/changes_spec.rb
|
199
|
+
- spec/extensions/chewy_spec.rb
|
200
|
+
- spec/sidekiq_spec.rb
|
201
|
+
- spec/spec_helper.rb
|
202
|
+
- spec/tantot_spec.rb
|