implicitly 0.0.1
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.rdoc +50 -0
- data/Rakefile +9 -0
- data/lib/implicitly.rb +54 -0
- data/test/test_implicitly.rb +43 -0
- metadata +68 -0
data/README.rdoc
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= Synopsis
|
2
|
+
|
3
|
+
Implicits in Ruby, based on Scala. Works like:
|
4
|
+
|
5
|
+
implicitly.from(BaseClass).to(WrapperClass).via do |base_object|
|
6
|
+
WrapperClass.new(base_object)
|
7
|
+
end
|
8
|
+
|
9
|
+
= Example
|
10
|
+
|
11
|
+
For example, to extend Fixnum with #seconds, #minutes, and #hours:
|
12
|
+
|
13
|
+
class FixnumWithTime
|
14
|
+
def initialize(n)
|
15
|
+
@n = n
|
16
|
+
end
|
17
|
+
|
18
|
+
def minutes
|
19
|
+
seconds * 60
|
20
|
+
end
|
21
|
+
|
22
|
+
def hours
|
23
|
+
minutes * 60
|
24
|
+
end
|
25
|
+
|
26
|
+
def seconds
|
27
|
+
@n
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Person
|
32
|
+
implicitly.from(Fixnum).to(FixnumWithTime).via do |fixnum|
|
33
|
+
FixnumWithTime.new(fixnum)
|
34
|
+
end
|
35
|
+
|
36
|
+
def age_in_seconds
|
37
|
+
37.minutes
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
= Why
|
42
|
+
|
43
|
+
By using a wrapping class the extension can be tested independently of the base
|
44
|
+
class.
|
45
|
+
|
46
|
+
= Author
|
47
|
+
|
48
|
+
Mike Burns
|
49
|
+
mburns@thoughtbot.com
|
50
|
+
http://mike-burns.com/
|
data/Rakefile
ADDED
data/lib/implicitly.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class Module
|
2
|
+
# Set up the implicit handling. Use the #from #to and #via methods to specify
|
3
|
+
# the full transformation. For example:
|
4
|
+
#
|
5
|
+
# implicit.from(Fixnum).to(FixnumWithTime).via {|number| FixnumWithTime.new(number) }
|
6
|
+
#
|
7
|
+
# Nothing takes effect until all three (#from #to and #via) are set.
|
8
|
+
#
|
9
|
+
# The above implicit will transform a Fixnum instance into a FixnumWithTime
|
10
|
+
# wrapper, but only when you call a public instance method which is defined
|
11
|
+
# in FixnumWithTime.
|
12
|
+
def implicitly
|
13
|
+
Implicit.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Implicit
|
18
|
+
# Set the base of the implicit wrapping. This should be an existing class.
|
19
|
+
def from(starting_class)
|
20
|
+
@starting_class = starting_class
|
21
|
+
try_to_do_everything
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
# Set the wrapper class. This class must have a constructor which takes one
|
26
|
+
# argument, which is an instance of the base class.
|
27
|
+
def to(ending_class)
|
28
|
+
@ending_class = ending_class
|
29
|
+
try_to_do_everything
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set the transformer. This is a Proc which takes an instance of the base
|
34
|
+
# class and produces an instance of the wrapper class.
|
35
|
+
def via(&transformer)
|
36
|
+
@transformer = transformer
|
37
|
+
try_to_do_everything
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def try_to_do_everything
|
42
|
+
if !@starting_class.nil? && !@ending_class.nil? && !@transformer.nil?
|
43
|
+
transformer = @transformer
|
44
|
+
(@ending_class.instance_methods - Object.instance_methods).each do |meth_name|
|
45
|
+
@starting_class.class_eval do
|
46
|
+
define_method(meth_name) do |*args|
|
47
|
+
transformer.call(self).send(meth_name,*args)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
private :try_to_do_everything
|
54
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'implicitly'
|
3
|
+
|
4
|
+
class FixnumWithTime
|
5
|
+
def initialize(n)
|
6
|
+
@n = n
|
7
|
+
end
|
8
|
+
|
9
|
+
def minutes
|
10
|
+
seconds * 60
|
11
|
+
end
|
12
|
+
|
13
|
+
def hours
|
14
|
+
minutes * 60
|
15
|
+
end
|
16
|
+
|
17
|
+
def seconds
|
18
|
+
@n
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class ImplicitlyTest < Test::Unit::TestCase
|
23
|
+
implicitly.from(Fixnum).to(FixnumWithTime).via {|n| FixnumWithTime.new(n) }
|
24
|
+
|
25
|
+
def test_fixnum_with_time
|
26
|
+
assert_equal 120, 2.minutes
|
27
|
+
assert_equal 7200, 2.hours
|
28
|
+
assert_equal 2, 2.seconds
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_fixnum_with_time_delegation
|
32
|
+
assert !2.minutes.zero?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# TODO:
|
37
|
+
#class UnimplicitlyTest < Test::Unit::TestCase
|
38
|
+
# def test_fixnum_sans_time
|
39
|
+
# assert_raise(NoMethodError) do
|
40
|
+
# 2.minutes
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: implicitly
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Mike Burns
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-05-24 00:00:00 Z
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: A port of Scala's implicits, this is an alternative to open classes that allows for easier testing.
|
22
|
+
email: mburns@thoughtbot.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- README.rdoc
|
31
|
+
- Rakefile
|
32
|
+
- lib/implicitly.rb
|
33
|
+
- test/test_implicitly.rb
|
34
|
+
homepage: http://rubygems.org/gems/implicitly
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 3
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
version: "0"
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.7.2
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Wrap class instances implicitly
|
67
|
+
test_files:
|
68
|
+
- test/test_implicitly.rb
|