reusing 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: