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.
@@ -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/
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ t.test_files = FileList['test/test*.rb']
6
+ end
7
+
8
+ desc "Run tests"
9
+ task :default => :test
@@ -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