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.
- checksums.yaml +7 -0
- data/.index +62 -0
- data/Gemfile.lock +21 -0
- data/LICENSE.txt +23 -0
- data/README.md +112 -0
- data/lib/reusing.rb +25 -0
- data/test/example.rb +6 -0
- data/test/test_reusing.rb +23 -0
- metadata +128 -0
checksums.yaml
ADDED
@@ -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'
|
data/Gemfile.lock
ADDED
@@ -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
|
data/LICENSE.txt
ADDED
@@ -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
|
+
|
data/README.md
ADDED
@@ -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.
|
data/lib/reusing.rb
ADDED
@@ -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
|
+
|
data/test/example.rb
ADDED
@@ -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:
|