attach_function 0.1.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|