attach_function 0.1.1 → 0.2.2
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 +4 -4
- data/README.md +25 -1
- data/Rakefile +0 -1
- data/VERSIONING.md +22 -0
- data/attach_function-0.1.2.gem +0 -0
- data/attach_function.gemspec +6 -2
- data/lib/attach_function/version.rb +2 -1
- data/lib/attach_function.rb +38 -24
- data/spec/attach_function_spec.rb +15 -0
- metadata +5 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11e67fe07ac303c8f2c3fc3ca1ca130185dc91ac
|
4
|
+
data.tar.gz: 45b2be4c31976b5e5fccf18b49485a4ea06dad91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b752860396416ac322fce4b49ba243a3ad778d316bb046d79d8392b3a1dca2aa697fb7870be5c2aa6dd43e91187154dcc5e75af79f4f4b3590f019786b203b7b
|
7
|
+
data.tar.gz: 74ee96c15175952138ee4cef1ad71a7726058be0b01e2c8e64ca2004a47562b0019332126f817c50bc7861dffe64e4d7ea9dd4e889e1e5a50db343c3249bcc9d
|
data/README.md
CHANGED
@@ -31,15 +31,39 @@ Numeric.include(Math::MethodVersions)
|
|
31
31
|
p "3.14.sin = #{3.14.sin}"
|
32
32
|
p "10.log = #{10.log10}"
|
33
33
|
p "4.sqrt = #{4.sqrt}"
|
34
|
-
```
|
35
34
|
|
36
35
|
#The functionality that has been added to Numeric in this way is contained in the Math::MethodVersions mixin.
|
37
36
|
#I consider this much nicer than rudely monkepatching methods right onto a core class.
|
38
37
|
#This way, library users can see (in pry, for example, or via introspection) where a certain added method came from, and possibly filter it out.
|
39
38
|
#(Ruby doesn't currently support unmixing).
|
40
39
|
|
40
|
+
```
|
41
|
+
|
41
42
|
|
42
43
|
See the specs and the example folder for more examples.
|
44
|
+
|
45
|
+
## Versioning
|
46
|
+
|
47
|
+
### Version number for machines
|
48
|
+
|
49
|
+
This gem uses a slightly modified version of the **SemVer** specification, namely:
|
50
|
+
```ruby
|
51
|
+
spec.version = "BREAKING.PATCHES.NONBREAKING"
|
52
|
+
```
|
53
|
+
You can use this versioning with your dependency tools, only you have a somewhat stronger guarantees that your
|
54
|
+
code won't break if you limit yourself to the third number, but you need to allow second level updates in order to
|
55
|
+
get (security and other) patches.
|
56
|
+
|
57
|
+
### Version number for humans
|
58
|
+
Since the above-described type of versioning doesn't tell you anything about the functional state of the gem (you can go from a "hello world" to a full blown operating system
|
59
|
+
without making a breaking change, as long as your operating system prints "hello world" to the screen) (SemVer, when used correctly, doesn't tell anything about the functional state of a software package either)
|
60
|
+
A second human-friendly version number can be found in `spec.metadata[:human_version]`.
|
61
|
+
|
62
|
+
The magnitude of this version number shall be made to correspond to actual functional changes in the software.
|
63
|
+
If I've worked a lot on the package, I'll make it move a lot, but unless I've made breaking changes, I'll stick to only moving the third number in the `spec.version` version.
|
64
|
+
This number is for you. If you see it increase a lot, it probably means much more new goodies, but is less strictly defined then the version number for the machine. (I reserve the right to later change the way I change this number).
|
65
|
+
|
66
|
+
|
43
67
|
## Installation
|
44
68
|
|
45
69
|
Add this line to your application's Gemfile:
|
data/Rakefile
CHANGED
data/VERSIONING.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Versioning
|
2
|
+
|
3
|
+
## Version number for machines
|
4
|
+
|
5
|
+
This gem uses a slightly modified version of the **SemVer** specification, namely:
|
6
|
+
```ruby
|
7
|
+
spec.version = "BREAKING.PATCHES.NONBREAKING"
|
8
|
+
```
|
9
|
+
You can use this versioning with your dependency tools, only you have a somewhat stronger guarantees that your
|
10
|
+
code won't break if you limit yourself to the third number, but you need to allow second level updates in order to
|
11
|
+
get (security and other) patches.
|
12
|
+
|
13
|
+
## Version number for humans
|
14
|
+
Since the above-described type of versioning doesn't tell you anything about the functional state of the gem (you can go from a "hello world" to a full blown operating system
|
15
|
+
without making a breaking change, as long as your operating system prints "hello world" to the screen) (SemVer, when used correctly, doesn't tell anything about the functional state of a software package either)
|
16
|
+
A second human-friendly version number can be found in `spec.metadata[:human_version]`.
|
17
|
+
|
18
|
+
The magnitude of this version number shall be made to correspond to actual functional changes in the software.
|
19
|
+
If I've worked a lot on the package, I'll make it move a lot, but unless I've made breaking changes, I'll stick to only moving the third number in the `spec.version` version.
|
20
|
+
This number is for you. If you see it increase a lot, it probably means much more new goodies, but is less strictly defined then the version number for the machine. (I reserve the right to later change the way I change this number).
|
21
|
+
|
22
|
+
|
Binary file
|
data/attach_function.gemspec
CHANGED
@@ -5,7 +5,8 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'ostruct'
|
6
6
|
|
7
7
|
gem = OpenStruct.new
|
8
|
-
gem.name = File.basename(File.dirname(__FILE__))
|
8
|
+
gem.name = File.basename(File.expand_path(File.dirname(__FILE__)))
|
9
|
+
|
9
10
|
require "#{gem.name}/version"
|
10
11
|
gem.module = AttachFunction
|
11
12
|
|
@@ -13,6 +14,7 @@ Gem::Specification.new do |spec|
|
|
13
14
|
|
14
15
|
spec.name = gem.name
|
15
16
|
spec.version = (gem.module)::VERSION
|
17
|
+
#spec.metadata[:human_version] = (gem.module)::HUMAN_VERSION
|
16
18
|
spec.summary = %q{Macro to attach a module function to an object by fixing its first argument to self}
|
17
19
|
spec.description = %q{Macro to attach a module function to an object by fixing its first argument to self}
|
18
20
|
|
@@ -26,10 +28,12 @@ Gem::Specification.new do |spec|
|
|
26
28
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
27
29
|
spec.require_paths = ["lib"]
|
28
30
|
|
29
|
-
spec.add_development_dependency "bundler", "~> 1.7"
|
31
|
+
#spec.add_development_dependency "bundler", "~> 1.7"
|
30
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
31
33
|
spec.add_development_dependency "rspec"
|
32
34
|
spec.add_development_dependency "guard", "2.12"
|
33
35
|
spec.add_development_dependency "guard-rspec"
|
36
|
+
#spec.add_development_dependency "listen"
|
37
|
+
#spec.add_development_dependency "highline"
|
34
38
|
spec.add_development_dependency "guard-bundler"
|
35
39
|
end
|
data/lib/attach_function.rb
CHANGED
@@ -1,27 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# -*- coding: utf-8 -*-
|
3
3
|
module AttachFunction
|
4
|
-
#
|
5
|
-
#attach_function defines new methods that are partial applications of a target function where the first argument to the target function gets fixed to self.
|
6
|
-
#
|
7
|
-
#The name of the newly defined method will be the basename of the target function (the module path gets stripped) or a user-specified name.
|
8
|
-
#The receiver of relatively specified parameter functions will be the current module, if a user-specified name is given and
|
9
|
-
#the user-specified name is not the same as the basename of the target function, or the enclosing module, if no-user specified name is provided or
|
10
|
-
#if the user-specified name is the same as the basename of the parameter.
|
11
|
-
#
|
12
|
-
#Usage:
|
13
|
-
#
|
14
|
-
#module MyModule
|
15
|
-
# def function_method1(arg1, arg2); end
|
16
|
-
# def function_method2(arg1); end
|
17
|
-
#
|
18
|
-
# module MethodVersions
|
19
|
-
# extend Attachmethod
|
20
|
-
# attach_function :function_method1
|
21
|
-
# attach_function :function_method2
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
#See the specs and the example folder for more examples.
|
25
4
|
|
26
5
|
def _receiver_and_message(method_name, function_symbol)
|
27
6
|
#Parse the function symbol to get the receiver and the function's basename
|
@@ -36,15 +15,41 @@ module AttachFunction
|
|
36
15
|
#Can't send to self if method_name == function_method (or it will recurse and crash):
|
37
16
|
# send it to the outer module/class, if there's no outer module, send it to Object
|
38
17
|
if (method_name ||= function_method) == function_method
|
39
|
-
receiver =
|
40
|
-
outer_module = receiver.rpartition('::').first
|
41
|
-
receiver = outer_module == "" ? Object : eval(outer_module)
|
18
|
+
receiver = Object.const_get(outer_module_name(name))
|
42
19
|
end
|
43
20
|
end
|
44
21
|
|
45
22
|
return [ receiver, function_method ]
|
46
23
|
end
|
47
24
|
|
25
|
+
#Give a fully qualified name of the outer module for a name assumed to be fully qualified
|
26
|
+
#(:: is prepended unless it's already there)
|
27
|
+
def outer_module_name(name)
|
28
|
+
outer_module = name.rpartition('::').first
|
29
|
+
outer_module.sub!(/^::/,'')
|
30
|
+
return outer_module == "" ? '::Object' : ('::'+outer_module)
|
31
|
+
end
|
32
|
+
|
33
|
+
#attach_function defines new methods that are partial applications of a target function where the first argument to the target function gets fixed to self.
|
34
|
+
#
|
35
|
+
#The name of the newly defined method will be the basename of the target function (the module path gets stripped) or a user-specified name.
|
36
|
+
#The receiver of relatively specified parameter functions will be the current module, if a user-specified name is given and
|
37
|
+
#the user-specified name is not the same as the basename of the target function, or the enclosing module, if no-user specified name is provided or
|
38
|
+
#if the user-specified name is the same as the basename of the parameter.
|
39
|
+
#
|
40
|
+
#Usage:
|
41
|
+
#
|
42
|
+
#module MyModule
|
43
|
+
# def function_method1(arg1, arg2); end
|
44
|
+
# def function_method2(arg1); end
|
45
|
+
#
|
46
|
+
# module MethodVersions
|
47
|
+
# extend Attachmethod
|
48
|
+
# attach_function :function_method1
|
49
|
+
# attach_function :function_method2
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
#See the specs and the example folder for more examples.
|
48
53
|
def attach_function(method_name = nil, function_symbol)
|
49
54
|
receiver, message = _receiver_and_message(method_name, function_symbol)
|
50
55
|
|
@@ -56,4 +61,13 @@ module AttachFunction
|
|
56
61
|
receiver.send(message, self, *args)
|
57
62
|
end
|
58
63
|
end
|
64
|
+
|
65
|
+
#Attaches all uninherited (by default, pass true to change that) public class methods
|
66
|
+
#of the enclosing module or of Object
|
67
|
+
def attach_outer_class_methods(inherited = false)
|
68
|
+
outer_module = Object.const_get(outer_module_name(name))
|
69
|
+
outer_module.methods(inherited).each do |m|
|
70
|
+
attach_function m
|
71
|
+
end
|
72
|
+
end
|
59
73
|
end
|
@@ -27,6 +27,21 @@ describe AttachFunction do
|
|
27
27
|
it 'has a version number' do
|
28
28
|
expect(AttachFunction::VERSION).not_to be nil
|
29
29
|
end
|
30
|
+
describe "#_outer_module_name" do
|
31
|
+
extend AttachFunction
|
32
|
+
{
|
33
|
+
'::A::M' => "::A",
|
34
|
+
'A::m' => "::A",
|
35
|
+
'::A::B::M' => "::A::B",
|
36
|
+
'::A' => "::Object",
|
37
|
+
'A' => "::Object"
|
38
|
+
}.each_pair do |k,answers|
|
39
|
+
it "should resolve #{k} to #{answers.inspect}" do
|
40
|
+
extend AttachFunction
|
41
|
+
expect(outer_module_name(k)).to eq(answers)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
30
45
|
it "should define an instance method named 'attach_function'" do
|
31
46
|
expect(subject.instance_methods(false)).to include(:attach_function)
|
32
47
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attach_function
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Petr Skocik
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.7'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.7'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rake
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,6 +95,8 @@ files:
|
|
109
95
|
- Guardfile
|
110
96
|
- README.md
|
111
97
|
- Rakefile
|
98
|
+
- VERSIONING.md
|
99
|
+
- attach_function-0.1.2.gem
|
112
100
|
- attach_function.gemspec
|
113
101
|
- examples/enclosing_scope.rb
|
114
102
|
- lib/attach_function.rb
|
@@ -135,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
123
|
version: '0'
|
136
124
|
requirements: []
|
137
125
|
rubyforge_project:
|
138
|
-
rubygems_version: 2.2.
|
126
|
+
rubygems_version: 2.2.2
|
139
127
|
signing_key:
|
140
128
|
specification_version: 4
|
141
129
|
summary: Macro to attach a module function to an object by fixing its first argument
|