mtrack 0.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 +16 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +190 -0
- data/Rakefile +10 -0
- data/lib/mtrack.rb +4 -0
- data/lib/mtrack/core.rb +79 -0
- data/lib/mtrack/module_mixin.rb +52 -0
- data/lib/mtrack/state.rb +113 -0
- data/lib/mtrack/state/group.rb +55 -0
- data/lib/mtrack/version.rb +24 -0
- data/mtrack.gemspec +32 -0
- data/spec/lib/mtrack/core_spec.rb +377 -0
- data/spec/lib/mtrack/state/group_spec.rb +38 -0
- data/spec/lib/mtrack/state_spec.rb +135 -0
- data/spec/lib/mtrack/version_spec.rb +5 -0
- data/spec/spec_helper.rb +21 -0
- data/tasks/console.rb +13 -0
- data/tasks/coverage.rb +9 -0
- metadata +157 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
module MTrack
|
4
|
+
class State
|
5
|
+
|
6
|
+
##
|
7
|
+
# Handles method information for each group in MTrack::State#groups.
|
8
|
+
class Group
|
9
|
+
|
10
|
+
##
|
11
|
+
# call-seq:
|
12
|
+
# new() => new_group
|
13
|
+
#
|
14
|
+
# Creates a new Group instance.
|
15
|
+
def initialize
|
16
|
+
self.tracked = Set.new
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# call-seq:
|
21
|
+
# delete_tracked(name) => name
|
22
|
+
#
|
23
|
+
# Removes method +name+ from tracked methods.
|
24
|
+
def delete_tracked(name)
|
25
|
+
@tracked.delete name
|
26
|
+
name
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# call-seq:
|
31
|
+
# merge_tracked(names) => names
|
32
|
+
#
|
33
|
+
# Adds method +names+ to tracked methods.
|
34
|
+
def merge_tracked(names)
|
35
|
+
@tracked.merge names
|
36
|
+
names
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# call-seq:
|
41
|
+
# tracked() => new_set
|
42
|
+
#
|
43
|
+
# Returns a new set containing the methods currently being tracked.
|
44
|
+
def tracked
|
45
|
+
@tracked.dup
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
##
|
51
|
+
# A set containing the method names currently being tracked.
|
52
|
+
attr_writer :tracked
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
##
|
2
|
+
# MTrack extends the functionality of Modules and Classes and enables them to
|
3
|
+
# define public methods within groups. These methods can then be queried back
|
4
|
+
# even through a hierarchy of inclusion and/or inheritance.
|
5
|
+
#
|
6
|
+
# module M
|
7
|
+
# track_methods { def method_1; end }
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# class C
|
11
|
+
# include M
|
12
|
+
# track_methods { def method_2; end }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# class D < C
|
16
|
+
# track_methods { def method_3; end }
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# D.tracked_methods #=> #<Set: {:method_1, :method_2, :method_3}>
|
20
|
+
module MTrack
|
21
|
+
|
22
|
+
# Current version of MTrack.
|
23
|
+
VERSION = "0.0.1"
|
24
|
+
end
|
data/mtrack.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "mtrack/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mtrack"
|
8
|
+
spec.version = MTrack::VERSION
|
9
|
+
spec.authors = ["Gabriel de Oliveira"]
|
10
|
+
spec.email = ["deoliveira.gab@gmail.com"]
|
11
|
+
spec.summary = %q{Group and track methods on classes and modules.}
|
12
|
+
spec.description = <<-EOS.strip.gsub(/\n/, "").gsub(/\s{2,}/, " ")
|
13
|
+
MTrack extends the functionality of modules and
|
14
|
+
classes and enables them to define public methods
|
15
|
+
within groups. These methods can then be queried back
|
16
|
+
even through a hierarchy of inclusion and/or
|
17
|
+
inheritance.
|
18
|
+
EOS
|
19
|
+
spec.homepage = "https://github.com/gdeoliveira/mtrack"
|
20
|
+
spec.license = "MIT"
|
21
|
+
|
22
|
+
spec.files = `git ls-files -z`.split("\x0")
|
23
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler"
|
27
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
28
|
+
spec.add_development_dependency "pry"
|
29
|
+
spec.add_development_dependency "rake"
|
30
|
+
spec.add_development_dependency "rspec"
|
31
|
+
spec.add_development_dependency "simplecov"
|
32
|
+
end
|
@@ -0,0 +1,377 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
METHOD_DEFINITION = proc {}
|
4
|
+
|
5
|
+
describe MTrack::Core do
|
6
|
+
let(:base_module_1) do
|
7
|
+
Module.new.tap do |m|
|
8
|
+
m.module_eval do
|
9
|
+
define_method :unt_1, METHOD_DEFINITION
|
10
|
+
track_methods { define_method :meth, METHOD_DEFINITION }
|
11
|
+
track_methods :numbers do
|
12
|
+
track_methods(:odd) { define_method :one, METHOD_DEFINITION }
|
13
|
+
track_methods(:even) { define_method :two, METHOD_DEFINITION }
|
14
|
+
end
|
15
|
+
define_method :unt_2, METHOD_DEFINITION
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:base_module_2) do
|
21
|
+
Module.new.tap do |m|
|
22
|
+
m.module_eval do
|
23
|
+
define_method :unt_2, METHOD_DEFINITION
|
24
|
+
track_methods { define_method :meth, METHOD_DEFINITION }
|
25
|
+
track_methods :numbers do
|
26
|
+
track_methods(:even) { define_method :two, METHOD_DEFINITION }
|
27
|
+
track_methods(:odd) { define_method :three, METHOD_DEFINITION }
|
28
|
+
end
|
29
|
+
define_method :unt_3, METHOD_DEFINITION
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:base_module_3) do
|
35
|
+
Module.new.tap do |m|
|
36
|
+
m.module_eval do
|
37
|
+
define_method :unt_3, METHOD_DEFINITION
|
38
|
+
track_methods { define_method :meth, METHOD_DEFINITION }
|
39
|
+
track_methods :numbers do
|
40
|
+
track_methods(:odd) { define_method :three, METHOD_DEFINITION }
|
41
|
+
track_methods(:even) { define_method :four, METHOD_DEFINITION }
|
42
|
+
end
|
43
|
+
define_method :unt_4, METHOD_DEFINITION
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
let(:sub_module_1) do
|
49
|
+
bm_1 = base_module_1
|
50
|
+
bm_2 = base_module_2
|
51
|
+
Module.new.tap do |m|
|
52
|
+
m.module_eval do
|
53
|
+
include bm_1
|
54
|
+
define_method :unt_4, METHOD_DEFINITION
|
55
|
+
track_methods { define_method :meth, METHOD_DEFINITION }
|
56
|
+
track_methods :numbers do
|
57
|
+
track_methods(:even) { define_method :four, METHOD_DEFINITION }
|
58
|
+
track_methods(:odd) { define_method :five, METHOD_DEFINITION }
|
59
|
+
end
|
60
|
+
define_method :unt_5, METHOD_DEFINITION
|
61
|
+
include bm_2
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:sub_module_2) do
|
67
|
+
bm_3 = base_module_3
|
68
|
+
Module.new.tap do |m|
|
69
|
+
m.module_eval do
|
70
|
+
define_method :unt_5, METHOD_DEFINITION
|
71
|
+
track_methods { define_method :meth, METHOD_DEFINITION }
|
72
|
+
include bm_3
|
73
|
+
track_methods :numbers do
|
74
|
+
track_methods(:odd) { define_method :five, METHOD_DEFINITION }
|
75
|
+
track_methods(:even) { define_method :six, METHOD_DEFINITION }
|
76
|
+
end
|
77
|
+
define_method :unt_6, METHOD_DEFINITION
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
let(:super_class) do
|
83
|
+
sm_1 = sub_module_1
|
84
|
+
Class.new.tap do |c|
|
85
|
+
c.class_eval do
|
86
|
+
include sm_1
|
87
|
+
define_method :unt_6, METHOD_DEFINITION
|
88
|
+
track_methods { define_method :meth, METHOD_DEFINITION }
|
89
|
+
track_methods :numbers do
|
90
|
+
track_methods(:even) { define_method :six, METHOD_DEFINITION }
|
91
|
+
track_methods(:odd) { define_method :seven, METHOD_DEFINITION }
|
92
|
+
end
|
93
|
+
define_method :unt_7, METHOD_DEFINITION
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
let(:sub_class) do
|
99
|
+
sm_2 = sub_module_2
|
100
|
+
sc = super_class
|
101
|
+
Class.new(sc).tap do |c|
|
102
|
+
c.class_eval do
|
103
|
+
define_method :unt_7, METHOD_DEFINITION
|
104
|
+
track_methods { define_method :meth, METHOD_DEFINITION }
|
105
|
+
track_methods :numbers do
|
106
|
+
track_methods(:odd) { define_method :seven, METHOD_DEFINITION }
|
107
|
+
track_methods(:even) { define_method :eight, METHOD_DEFINITION }
|
108
|
+
end
|
109
|
+
define_method :unt_8, METHOD_DEFINITION
|
110
|
+
include sm_2
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "base module 1" do
|
116
|
+
subject { base_module_1 }
|
117
|
+
|
118
|
+
it "tracks methods" do
|
119
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
120
|
+
expect(subject.tracked_methods(:numbers)).to match_array([:one, :two])
|
121
|
+
expect(subject.tracked_methods(:odd)).to match_array([:one])
|
122
|
+
expect(subject.tracked_methods(:even)).to match_array([:two])
|
123
|
+
end
|
124
|
+
|
125
|
+
it "untracks removed methods" do
|
126
|
+
subject.module_eval { remove_method :meth }
|
127
|
+
expect(subject.tracked_methods).to be_empty
|
128
|
+
end
|
129
|
+
|
130
|
+
it "untracks undefined methods" do
|
131
|
+
subject.module_eval { undef_method :meth }
|
132
|
+
expect(subject.tracked_methods).to be_empty
|
133
|
+
|
134
|
+
subject.module_eval { define_method :meth, METHOD_DEFINITION }
|
135
|
+
expect(subject.tracked_methods).to be_empty
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "base module 2" do
|
140
|
+
subject { base_module_2 }
|
141
|
+
|
142
|
+
it "tracks methods" do
|
143
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
144
|
+
expect(subject.tracked_methods(:numbers)).to match_array([:two, :three])
|
145
|
+
expect(subject.tracked_methods(:even)).to match_array([:two])
|
146
|
+
expect(subject.tracked_methods(:odd)).to match_array([:three])
|
147
|
+
end
|
148
|
+
|
149
|
+
it "untracks removed methods" do
|
150
|
+
subject.module_eval { remove_method :meth }
|
151
|
+
expect(subject.tracked_methods).to be_empty
|
152
|
+
end
|
153
|
+
|
154
|
+
it "untracks undefined methods" do
|
155
|
+
subject.module_eval { undef_method :meth }
|
156
|
+
expect(subject.tracked_methods).to be_empty
|
157
|
+
|
158
|
+
subject.module_eval { define_method :meth, METHOD_DEFINITION }
|
159
|
+
expect(subject.tracked_methods).to be_empty
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "base module 3" do
|
164
|
+
subject { base_module_3 }
|
165
|
+
|
166
|
+
it "tracks methods" do
|
167
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
168
|
+
expect(subject.tracked_methods(:numbers)).to match_array([:three, :four])
|
169
|
+
expect(subject.tracked_methods(:odd)).to match_array([:three])
|
170
|
+
expect(subject.tracked_methods(:even)).to match_array([:four])
|
171
|
+
end
|
172
|
+
|
173
|
+
it "untracks removed methods" do
|
174
|
+
subject.module_eval { remove_method :meth }
|
175
|
+
expect(subject.tracked_methods).to be_empty
|
176
|
+
end
|
177
|
+
|
178
|
+
it "untracks undefined methods" do
|
179
|
+
subject.module_eval { undef_method :meth }
|
180
|
+
expect(subject.tracked_methods).to be_empty
|
181
|
+
|
182
|
+
subject.module_eval { define_method :meth, METHOD_DEFINITION }
|
183
|
+
expect(subject.tracked_methods).to be_empty
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "sub module 1" do
|
188
|
+
subject { sub_module_1 }
|
189
|
+
|
190
|
+
it "tracks methods" do
|
191
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
192
|
+
expect(subject.tracked_methods(:numbers)).to match_array([:one, :two, :three, :four, :five])
|
193
|
+
expect(subject.tracked_methods(:odd)).to match_array([:one, :three, :five])
|
194
|
+
expect(subject.tracked_methods(:even)).to match_array([:two, :four])
|
195
|
+
end
|
196
|
+
|
197
|
+
it "untracks removed methods" do
|
198
|
+
subject.module_eval { remove_method :meth }
|
199
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
200
|
+
|
201
|
+
base_module_1.module_eval { remove_method :meth }
|
202
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
203
|
+
|
204
|
+
base_module_2.module_eval { remove_method :meth }
|
205
|
+
expect(subject.tracked_methods).to be_empty
|
206
|
+
end
|
207
|
+
|
208
|
+
it "untracks undefined methods" do
|
209
|
+
subject.module_eval { undef_method :meth }
|
210
|
+
expect(subject.tracked_methods).to be_empty
|
211
|
+
|
212
|
+
subject.module_eval { define_method :meth, METHOD_DEFINITION }
|
213
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context "sub module 2" do
|
218
|
+
subject { sub_module_2 }
|
219
|
+
|
220
|
+
it "tracks methods" do
|
221
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
222
|
+
expect(subject.tracked_methods(:numbers)).to match_array([:three, :four, :five, :six])
|
223
|
+
expect(subject.tracked_methods(:odd)).to match_array([:three, :five])
|
224
|
+
expect(subject.tracked_methods(:even)).to match_array([:four, :six])
|
225
|
+
end
|
226
|
+
|
227
|
+
it "untracks removed methods" do
|
228
|
+
base_module_3.module_eval { remove_method :meth }
|
229
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
230
|
+
|
231
|
+
subject.module_eval { remove_method :meth }
|
232
|
+
expect(subject.tracked_methods).to be_empty
|
233
|
+
end
|
234
|
+
|
235
|
+
it "untracks undefined methods" do
|
236
|
+
subject.module_eval { undef_method :meth }
|
237
|
+
expect(subject.tracked_methods).to be_empty
|
238
|
+
|
239
|
+
subject.module_eval { define_method :meth, METHOD_DEFINITION }
|
240
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
context "super class" do
|
245
|
+
subject { super_class }
|
246
|
+
|
247
|
+
it "tracks methods" do
|
248
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
249
|
+
expect(subject.tracked_methods(:numbers)).to match_array([:one, :two, :three, :four, :five, :six, :seven])
|
250
|
+
expect(subject.tracked_methods(:odd)).to match_array([:one, :three, :five, :seven])
|
251
|
+
expect(subject.tracked_methods(:even)).to match_array([:two, :four, :six])
|
252
|
+
end
|
253
|
+
|
254
|
+
it "untracks removed methods" do
|
255
|
+
subject.class_eval { remove_method :meth }
|
256
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
257
|
+
|
258
|
+
sub_module_1.module_eval { remove_method :meth }
|
259
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
260
|
+
|
261
|
+
base_module_2.module_eval { remove_method :meth }
|
262
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
263
|
+
|
264
|
+
base_module_1.module_eval { remove_method :meth }
|
265
|
+
expect(subject.tracked_methods).to be_empty
|
266
|
+
end
|
267
|
+
|
268
|
+
it "untracks undefined methods" do
|
269
|
+
subject.module_eval { undef_method :meth }
|
270
|
+
expect(subject.tracked_methods).to be_empty
|
271
|
+
|
272
|
+
subject.module_eval { define_method :meth, METHOD_DEFINITION }
|
273
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
context "sub class" do
|
278
|
+
subject { sub_class }
|
279
|
+
|
280
|
+
it "tracks methods" do
|
281
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
282
|
+
expect(subject.tracked_methods(:numbers)).to match_array([:one, :two, :three, :four, :five, :six, :seven, :eight])
|
283
|
+
expect(subject.tracked_methods(:odd)).to match_array([:one, :three, :five, :seven])
|
284
|
+
expect(subject.tracked_methods(:even)).to match_array([:two, :four, :six, :eight])
|
285
|
+
end
|
286
|
+
|
287
|
+
it "untracks removed methods" do
|
288
|
+
base_module_1.module_eval { remove_method :meth }
|
289
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
290
|
+
|
291
|
+
base_module_2.module_eval { remove_method :meth }
|
292
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
293
|
+
|
294
|
+
base_module_3.module_eval { remove_method :meth }
|
295
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
296
|
+
|
297
|
+
sub_module_1.module_eval { remove_method :meth }
|
298
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
299
|
+
|
300
|
+
sub_module_2.module_eval { remove_method :meth }
|
301
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
302
|
+
|
303
|
+
super_class.class_eval { remove_method :meth }
|
304
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
305
|
+
|
306
|
+
subject.class_eval { remove_method :meth }
|
307
|
+
expect(subject.tracked_methods).to be_empty
|
308
|
+
end
|
309
|
+
|
310
|
+
it "untracks undefined methods" do
|
311
|
+
subject.module_eval { undef_method :meth }
|
312
|
+
expect(subject.tracked_methods).to be_empty
|
313
|
+
|
314
|
+
subject.module_eval { define_method :meth, METHOD_DEFINITION }
|
315
|
+
expect(subject.tracked_methods).to match_array([:meth])
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
context "partially defined" do
|
320
|
+
context "module" do
|
321
|
+
it "tracks methods" do
|
322
|
+
m = ::Module.new
|
323
|
+
|
324
|
+
expect do
|
325
|
+
m.module_eval do
|
326
|
+
track_methods do
|
327
|
+
define_method :meth_1, METHOD_DEFINITION
|
328
|
+
define_method :meth_2, METHOD_DEFINITION
|
329
|
+
raise "Unexpected error"
|
330
|
+
define_method :meth_3, METHOD_DEFINITION
|
331
|
+
define_method :meth_4, METHOD_DEFINITION
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end.to raise_error(RuntimeError, "Unexpected error")
|
335
|
+
|
336
|
+
expect(m.public_instance_methods(false).map(&:to_sym)).to match_array([:meth_1, :meth_2])
|
337
|
+
expect(m.tracked_methods).to match_array([:meth_1, :meth_2])
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
context "class" do
|
342
|
+
it "tracks methods" do
|
343
|
+
c = ::Class.new
|
344
|
+
|
345
|
+
expect do
|
346
|
+
c.class_eval do
|
347
|
+
track_methods do
|
348
|
+
define_method :meth_1, METHOD_DEFINITION
|
349
|
+
define_method :meth_2, METHOD_DEFINITION
|
350
|
+
raise "Unexpected error"
|
351
|
+
define_method :meth_3, METHOD_DEFINITION
|
352
|
+
define_method :meth_4, METHOD_DEFINITION
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end.to raise_error(RuntimeError, "Unexpected error")
|
356
|
+
|
357
|
+
expect(c.public_instance_methods(false).map(&:to_sym)).to match_array([:meth_1, :meth_2])
|
358
|
+
expect(c.tracked_methods).to match_array([:meth_1, :meth_2])
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
context "inclusion" do
|
364
|
+
it "adds #{described_class} to submodule" do
|
365
|
+
bm_1 = base_module_1
|
366
|
+
m = ::Module.new.module_eval { include bm_1 }
|
367
|
+
expect(m.tracked_methods).to match_array([:meth])
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
context "inheritance" do
|
372
|
+
it "adds #{described_class} to subclass" do
|
373
|
+
c = ::Class.new(super_class)
|
374
|
+
expect(c.tracked_methods).to match_array([:meth])
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|