reusing 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a0a624b8d21979282d101db2474ea7ad3d1cce00
4
+ data.tar.gz: cb0419a8e426ba527840d769edf72683f57ac7c7
5
+ SHA512:
6
+ metadata.gz: 7e3e03c9452c15c5295f7ed7ec5616ab05a5be5971527a10de376ab2c9b7189503f51ca28d5dd2eb14e0c0db19b76b618bfab70ccc7df6a33d9206b6ea1bfb44
7
+ data.tar.gz: c27da6f4e1853666c162681a26d997ba077110c2da0cf57d64c72e9a166f5603a88545fa6301571a2bc00b6feadc81a92d440dfdca3598dff2a4bc72bca5f4d6
data/.index ADDED
@@ -0,0 +1,62 @@
1
+ ---
2
+ revision: 2013
3
+ type: ruby
4
+ sources:
5
+ - Indexfile
6
+ - Gemfile
7
+ authors:
8
+ - name: Thomas Sawyer
9
+ email: transfire@gmail.com
10
+ organizations:
11
+ - name: Rubyworks
12
+ requirements:
13
+ - version: '>= 0'
14
+ name: finder
15
+ - groups:
16
+ - test
17
+ version: '>= 0'
18
+ name: rubytest
19
+ - groups:
20
+ - test
21
+ version: '>= 0'
22
+ name: rubytest-cli
23
+ - groups:
24
+ - test
25
+ version: '>= 0'
26
+ name: microtest
27
+ - groups:
28
+ - build
29
+ version: '>= 0'
30
+ name: indexer
31
+ conflicts: []
32
+ alternatives: []
33
+ resources:
34
+ - type: home
35
+ uri: http://rubyworks.github.com/reusing
36
+ label: Homepage
37
+ - type: code
38
+ uri: http://github.com/rubyworks/reusing
39
+ label: Source Code
40
+ repositories:
41
+ - name: upstream
42
+ scm: git
43
+ uri: git@github.com:rubyworks/reusing.git
44
+ categories: []
45
+ copyrights:
46
+ - holder: Rubyworks
47
+ year: '2014'
48
+ license: BSD-2-Clause
49
+ customs: []
50
+ paths:
51
+ load:
52
+ - lib
53
+ name: reusing
54
+ title: Reusing
55
+ version: 1.0.0
56
+ summary: Use `using` with extension files.
57
+ description: Reusing makes it possible to use refinements without all the boiler plate
58
+ normally necessary in their creation. Instead extension scripts can be loaded directly
59
+ as refinements.
60
+ scm_uri: https://github.com/rubyworks/reusing/tree/master
61
+ created: '2014-04-16'
62
+ date: '2014-04-22'
@@ -0,0 +1,21 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ ansi (1.4.3)
5
+ finder (0.4.0)
6
+ microtest (0.2.1)
7
+ rubytest
8
+ rubytest (0.7.0)
9
+ ansi
10
+ rubytest-cli (0.1.0)
11
+ ansi
12
+ rubytest (>= 0.7.0)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ finder
19
+ microtest
20
+ rubytest
21
+ rubytest-cli
@@ -0,0 +1,23 @@
1
+ BSD-2-Clause License (http://spdx.org/licenses/BSD-2-Clause)
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are
4
+ permitted provided that the following conditions are met:
5
+
6
+ 1. Redistributions of source code must retain the above copyright notice, this list of
7
+ conditions and the following disclaimer.
8
+
9
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
10
+ of conditions and the following disclaimer in the documentation and/or other materials
11
+ provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS OR IMPLIED
14
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
15
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
16
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
21
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
+
23
+
@@ -0,0 +1,112 @@
1
+ # Reusing
2
+
3
+ ## Short Story
4
+
5
+ Reusing allows one to use refinements directly from an extension file.
6
+
7
+ ```ruby
8
+ require 'reusing'
9
+
10
+ using 'some_extension_script'
11
+ ```
12
+
13
+ ## Long Story
14
+
15
+ Ruby introduced refinements in version 2.0. Refinements are essentially
16
+ a safe alternative to monkey-patching. Unfortunately, a serious problem
17
+ with the syntax of refinements is the degree to which they differ from
18
+ writing tradition class extensions. Traditionally, if you want to add
19
+ a method to the String class, for instance, you simply open the class
20
+ and define them method.
21
+
22
+ ```ruby
23
+ class String
24
+ def some_method
25
+ ...
26
+ end
27
+ end
28
+ ```
29
+
30
+ And that's it. You could put that code in a file and require as needed.
31
+ Refinements, on the other hand, hand much more *boiler-plate*. The
32
+ above would have to be written:
33
+
34
+ ```ruby
35
+ module SomeModule
36
+ refine String do
37
+ def some_method
38
+ ...
39
+ end
40
+ end
41
+ end
42
+
43
+ using SomeModule
44
+ ```
45
+
46
+ This can be put in a file too, but the `using SomeModule` will have to
47
+ be reissued in every file the refinement is needed.
48
+
49
+ For a one off use, this isn't a big deal. But for a method library such as
50
+ Ruby Facets, this has huge implications. In fact, Facets does not yet support
51
+ refinements precisely b/c of this issue. To do so would require maintaining
52
+ a second copy of every method in refinement format. While doable, it is obviously
53
+ not DRY, and quite simply a pain in the ass.
54
+
55
+ So the idea of overriding the `using` method to accept a library file name was
56
+ hatched. With it, most extension scripts can be readily used as-is, without all
57
+ the boiler-plate. Usage is pretty simple. Let's say the example given
58
+ above is in a library file called `some_method.rb`, then we can do:
59
+
60
+ ```ruby
61
+ require 'reusing'
62
+
63
+ using 'some_method'
64
+ ```
65
+
66
+ The refinement method will find the file, read it in, perform a transformation
67
+ converting `class String` into `refine String do` and wrap it all in a module
68
+ which it then passes to the original `using` method, which has been aliased, btw,
69
+ as `reusing` (hence the name of this library).
70
+
71
+
72
+ ## Caveats
73
+
74
+ Unfortunately the implementation of Reusing is necessarily a bit hackish. Although
75
+ it works fine for basic extensions scripts there are complications if, for instance,
76
+ the script requires another extension script. While the scripts extensions will become
77
+ refinements, the further requirements will not.
78
+
79
+
80
+ ## Thoughts
81
+
82
+ Probably the ideal solution would be if refinement syntax could use normal `class` and
83
+ `module` keywords, instead of the special `refine` clause.
84
+
85
+ ```ruby
86
+ module M
87
+ class String
88
+ def important!
89
+ self + "!"
90
+ end
91
+ end
92
+ end
93
+
94
+ # refinement
95
+ using M::*
96
+ ```
97
+
98
+ In conjunction with this is should be possible to monkey patch with the same code as well.
99
+
100
+ ```ruby
101
+ # core extension
102
+ patch M::*
103
+ ```
104
+
105
+ In this way the both techniques could be used via the same code, while still being modular.
106
+
107
+
108
+ ## Copyrights
109
+
110
+ Copyright (c) 2014 Rubyworks (BSD-2 License)
111
+
112
+ See LICENSE.txt for details.
@@ -0,0 +1,25 @@
1
+ require 'finder'
2
+
3
+ class << self
4
+ alias :reusing :using
5
+
6
+ define_method :using do |feature|
7
+ if String === feature
8
+ file = Find.feature(feature, :absolute=>true).first
9
+
10
+ raise LoadError, "LoadError: cannot load such file -- #{file}" unless file
11
+
12
+ text = File.read(file)
13
+
14
+ text = text.gsub(/^\s*class\s*([A-Z]\w*)\s*$/, 'refine \1 do')
15
+ text = "m = Module.new do\n" + text + "\nend\nreusing m\n"
16
+
17
+ eval(text, TOPLEVEL_BINDING)
18
+ else
19
+ text = "reusing #{feature}"
20
+
21
+ eval(text, TOPLEVEL_BINDING)
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,6 @@
1
+ class String
2
+ def example
3
+ self + " example"
4
+ end
5
+ end
6
+
@@ -0,0 +1,23 @@
1
+ require 'reusing'
2
+
3
+ $LOAD_PATH.unshift(__dir__)
4
+
5
+ using 'example'
6
+
7
+ module M
8
+ refine String do
9
+ def important
10
+ self + "!"
11
+ end
12
+ end
13
+ end
14
+
15
+ using M
16
+
17
+ result = "this".example
18
+ raise unless result == "this example"
19
+
20
+ result = "this".important
21
+ raise unless result == "this!"
22
+
23
+
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reusing
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Sawyer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: finder
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubytest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubytest-cli
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: microtest
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: indexer
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
+ description: Reusing makes it possible to use refinements without all the boiler plate
84
+ normally necessary in their creation. Instead extension scripts can be loaded directly
85
+ as refinements.
86
+ email:
87
+ - transfire@gmail.com
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files:
91
+ - LICENSE.txt
92
+ - README.md
93
+ files:
94
+ - .index
95
+ - lib/reusing.rb
96
+ - test/test_reusing.rb
97
+ - test/example.rb
98
+ - Gemfile.lock
99
+ - README.md
100
+ - LICENSE.txt
101
+ homepage: http://rubyworks.github.com/reusing
102
+ licenses:
103
+ - BSD-2-Clause
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.0.3
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Use `using` with extension files.
125
+ test_files:
126
+ - test/test_reusing.rb
127
+ - test/example.rb
128
+ has_rdoc: