force_bind 0.1.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.
- data/README +34 -0
- data/Rakefile +18 -0
- data/ext/extconf.rb +5 -0
- data/ext/force_bind.c +29 -0
- data/test/test_force_bind.rb +25 -0
- metadata +59 -0
data/README
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
= force_bind
|
2
|
+
|
3
|
+
Adds UnboundMethod#force_bind to bind an unbound method to class (or any object of any type).
|
4
|
+
It basically bypasses the argument type checking that #bind has.
|
5
|
+
|
6
|
+
== Example
|
7
|
+
|
8
|
+
Bind an instance method to its class (making it act like a class method):
|
9
|
+
|
10
|
+
class Foo
|
11
|
+
def bar
|
12
|
+
puts "I'm inside #{self}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Foo.new.bar
|
17
|
+
#=> "I'm inside #<Foo:0x123456>"
|
18
|
+
|
19
|
+
meth = Foo.instance_method(:bar).force_bind(Foo)
|
20
|
+
meth.call
|
21
|
+
#=> "I'm inside Foo"
|
22
|
+
|
23
|
+
You can also use this to rebind the instance method of any object to any
|
24
|
+
other object:
|
25
|
+
|
26
|
+
class A
|
27
|
+
def foo; self end
|
28
|
+
end
|
29
|
+
|
30
|
+
class B; end
|
31
|
+
|
32
|
+
meth = A.instance_method(:foo).force_bind(B.new)
|
33
|
+
meth.call
|
34
|
+
#=> #<B:0x123456>
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
WINDOWS = (PLATFORM =~ /win32|cygwin/ ? true : false) rescue false
|
5
|
+
SUDO = WINDOWS ? '' : 'sudo'
|
6
|
+
|
7
|
+
load 'force_bind.gemspec'
|
8
|
+
Rake::GemPackageTask.new(SPEC) do |pkg|
|
9
|
+
pkg.gem_spec = SPEC
|
10
|
+
pkg.need_zip = true
|
11
|
+
pkg.need_tar = true
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Install the gem locally"
|
15
|
+
task :install => :package do
|
16
|
+
sh "#{SUDO} gem install pkg/#{SPEC.name}-#{SPEC.version}.gem --local"
|
17
|
+
sh "rm -rf pkg/#{SPEC.name}-#{SPEC.version}" unless ENV['KEEP_FILES']
|
18
|
+
end
|
data/ext/extconf.rb
ADDED
data/ext/force_bind.c
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
struct METHOD {
|
4
|
+
VALUE oclass;
|
5
|
+
VALUE rclass;
|
6
|
+
VALUE recv;
|
7
|
+
ID id, oid;
|
8
|
+
struct RNode *body;
|
9
|
+
};
|
10
|
+
|
11
|
+
static VALUE
|
12
|
+
umethod_force_bind(VALUE method, VALUE recv)
|
13
|
+
{
|
14
|
+
struct METHOD *data, *bound;
|
15
|
+
|
16
|
+
Data_Get_Struct(method, struct METHOD, data);
|
17
|
+
method = Data_Make_Struct(rb_cMethod, struct METHOD, free, -1, bound);
|
18
|
+
*bound = *data;
|
19
|
+
bound->recv = recv;
|
20
|
+
bound->rclass = TYPE(recv) == T_CLASS ? RCLASS(recv) : CLASS_OF(recv);
|
21
|
+
|
22
|
+
return method;
|
23
|
+
}
|
24
|
+
|
25
|
+
void
|
26
|
+
Init_force_bind()
|
27
|
+
{
|
28
|
+
rb_define_method(rb_cUnboundMethod, "force_bind", umethod_force_bind, 1);
|
29
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../force_bind'
|
3
|
+
|
4
|
+
class Mock
|
5
|
+
def the_method; self end
|
6
|
+
end
|
7
|
+
|
8
|
+
class TestForceBind < Test::Unit::TestCase
|
9
|
+
def test_force_bind_class
|
10
|
+
proc = Mock.instance_method(:the_method).force_bind(Mock)
|
11
|
+
assert_equal Mock, proc.call
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_force_bind_object
|
15
|
+
mock = Mock.new
|
16
|
+
proc = Mock.instance_method(:the_method).force_bind(mock)
|
17
|
+
assert_equal mock, proc.call
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_force_bind_object_from_other_class
|
21
|
+
arr = Array.new
|
22
|
+
proc = Mock.instance_method(:the_method).force_bind(arr)
|
23
|
+
assert_equal arr, proc.call
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: force_bind
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Loren Segal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-15 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: lsegal@soen.ca
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions:
|
21
|
+
- ext/extconf.rb
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- Rakefile
|
26
|
+
- README
|
27
|
+
- ext/force_bind.c
|
28
|
+
- ext/extconf.rb
|
29
|
+
- test/test_force_bind.rb
|
30
|
+
has_rdoc: false
|
31
|
+
homepage: http://github.com/lsegal/force_bind
|
32
|
+
licenses: []
|
33
|
+
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
requirements: []
|
52
|
+
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.3.5
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Adds UnboundMethod#force_bind to bind an unbound method to class (or any object of any type)
|
58
|
+
test_files: []
|
59
|
+
|