absorb 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/lib/absorb.rb +53 -0
  3. data/test/test_absorb.rb +91 -0
  4. metadata +46 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 638cbacbd4bc5b6f49a180bc22b742da1a6533cb
4
+ data.tar.gz: 5e36bd4eb9356a917126a707ed5813aee09a6bbf
5
+ SHA512:
6
+ metadata.gz: 832a9df3c37fccccac55f0bd28fda4906df5172ac070437fab5258cd2dc56315215efafc483feca62814edc011a822ffb267019585e115184dfbd536a6335fcd
7
+ data.tar.gz: b55edee932d4c53ef673ba95e0d2b3c83545f75a319edd51fa43e6df33dcb0057e3656bfe8da8b7b54abc4b83113953f29a3ba92aeb588464cfdc04219f5f31b
@@ -0,0 +1,53 @@
1
+ # Pickup -- The Object extension that gives us pickups
2
+ class Object
3
+ @@local_extensions = []
4
+
5
+ def method_missing(name, *args, &block)
6
+ klass = self
7
+ @@local_extensions.each { |mod|
8
+ if mod.instance_methods.include? name
9
+ return mod
10
+ .instance_method(name)
11
+ .bind(klass)
12
+ .call(*args, &block)
13
+ end
14
+ }
15
+
16
+ super
17
+ end
18
+
19
+ def respond_to?(method_name, include_all=false)
20
+ klass = self
21
+ result = super method_name, include_all
22
+
23
+ if result then return result end
24
+
25
+ @@local_extensions.each { |mod|
26
+ if mod.instance_methods.include? method_name
27
+ result = true
28
+ return result
29
+ end
30
+ }
31
+
32
+ result
33
+ end
34
+
35
+ # Absorb lets you locally extend a class with a module
36
+ #
37
+ # Example:
38
+ # >> Array.absorb(MyArrayExtension) do
39
+ # >> [1,2,3].nowHasThisMethodFromModule #=> Works!
40
+ # >> end
41
+ # >> [1,2,3].nowHasThisMethodFromModule #=> NoMethodError
42
+ #
43
+ # Arguments:
44
+ # module_name: (String)
45
+ # block: (Block)
46
+ #
47
+ def absorb(name, &block)
48
+ @@local_extensions.push(name)
49
+ result = block.call
50
+ @@local_extensions.pop
51
+ result
52
+ end
53
+ end
@@ -0,0 +1,91 @@
1
+ require 'test/unit'
2
+ require 'absorb'
3
+
4
+ # we'll be testing these two modules
5
+
6
+ module ArrayPowerups
7
+ # return an array of only the even elements
8
+ def even
9
+ select { |x| x.even? }
10
+ end
11
+
12
+ # return an array of elements strictly between
13
+ # the two numbers passed as arguments
14
+ def between(a, b)
15
+ select { |x| x > a and x < b }
16
+ end
17
+ end
18
+
19
+ module NumberPowerups
20
+ # return the number squared
21
+ def powerup
22
+ self * self
23
+ end
24
+ end
25
+
26
+ class PickupTest < Test::Unit::TestCase
27
+ def test_one_module_pickup
28
+ Array.absorb(ArrayPowerups) do
29
+ assert_equal [1,2,3,4,5].even(), [2,4]
30
+ end
31
+ end
32
+
33
+ def test_nested_module_pickup
34
+ Array.absorb(ArrayPowerups) do
35
+ Numeric.absorb(NumberPowerups) do
36
+ even_nums = [1,2,3,4,5].even().map { |x| x.powerup }
37
+ assert_equal even_nums.length, 2
38
+ assert_equal even_nums[0], 4
39
+ assert_equal even_nums[1], 16
40
+ end
41
+ end
42
+ end
43
+
44
+ def test_respond_to_works_correctly
45
+ mock = [1,2,3,4]
46
+ assert_equal mock.respond_to?(:even), false
47
+ assert_equal mock.respond_to?(:between), false
48
+ Array.absorb(ArrayPowerups) do
49
+ assert_respond_to mock, :even
50
+ assert_respond_to mock, :between
51
+ end
52
+ assert_equal mock.respond_to?(:even), false
53
+ assert_equal mock.respond_to?(:between), false
54
+ end
55
+
56
+ def test_method_is_missing_outside_pickup
57
+ mock = [1,2,3,4]
58
+ assert_raise NoMethodError do
59
+ mock.even
60
+ end
61
+
62
+ assert_raise NoMethodError do
63
+ mock.between(1, 3)
64
+ end
65
+
66
+ Array.absorb(ArrayPowerups) do
67
+ assert_nothing_raised NoMethodError do
68
+ assert_equal mock.even, [2,4]
69
+ assert_equal mock.between(1, 3), [2]
70
+ end
71
+
72
+ assert_raise NoMethodError do
73
+ mock.even[0].powerup
74
+ end
75
+
76
+ Numeric.absorb(NumberPowerups) do
77
+ assert_nothing_raised NoMethodError do
78
+ assert_equal mock.even[0].powerup, 4
79
+ end
80
+ end
81
+ end
82
+
83
+ assert_raise NoMethodError do
84
+ mock.even
85
+ end
86
+
87
+ assert_raise NoMethodError do
88
+ mock.between(1, 3)
89
+ end
90
+ end
91
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: absorb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Miroslav Gavrilov
8
+ - Igor Sarcevic
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-29 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Use this module to enable local, in-method class extensions.
15
+ email: gavrilov.miroslav@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/absorb.rb
21
+ - test/test_absorb.rb
22
+ homepage: http://www.pixelablaze.com
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: '2.0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 2.0.14
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: Locally pick up and extend a class with a module.
46
+ test_files: []