multidispatch_dsl 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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +110 -0
- data/Rakefile +7 -0
- data/lib/multidispatch_dsl/dsl.rb +28 -0
- data/lib/multidispatch_dsl/generator.rb +32 -0
- data/lib/multidispatch_dsl/missing_declaration_error.rb +6 -0
- data/lib/multidispatch_dsl/version.rb +3 -0
- data/lib/multidispatch_dsl.rb +7 -0
- data/multidispatch_dsl.gemspec +24 -0
- data/spec/lib/multidispatch_dsl_generator_spec.rb +23 -0
- data/spec/lib/multidispatch_dsl_spec.rb +19 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/test_class.rb +35 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1c188815e5ebea95a603b6756349b233ae3deba0
|
4
|
+
data.tar.gz: 4002fc2dfb32cc96e86cad69dafb88a727a09f88
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: de7e6fabc8c9cfd0de466917c036e1990a44684371b0710a7b37b603b75d869797cc0c3b92da9f1b05b9759c2bdb1c097d85158f540f6c19dcdb0d21d3a5124a
|
7
|
+
data.tar.gz: 0f51bc346dcc8120c7a7cf3db4812abf204f6cc9ec876b09a5592bbd6c3d108becbd453a3cd4adb4f27bde5b6aa8bd342a5ff9da5baa299614624bd85b6d23c9
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Sergey Pchelincev
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
= MultidispatchDSL
|
2
|
+
|
3
|
+
If you worked with other languages you probably know multi dispatch feature - define variants of same method with
|
4
|
+
different number of arguments of different types. In Ruby with it's duck typing you cannot do it from out of box. This
|
5
|
+
gem will allow you to do it.
|
6
|
+
|
7
|
+
{<img src="https://codeclimate.com/github/jalkoby/multidispatch_dsl.png" />}[https://codeclimate.com/github/jalkoby/multidispatch_dsl]
|
8
|
+
{<img src="https://travis-ci.org/jalkoby/uni_sender_gem.png?branch=master" alt="Build Status" />}[https://travis-ci.org/jalkoby/uni_sender_gem]
|
9
|
+
|
10
|
+
== Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'multidispatch_dsl'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install multidispatch_dsl
|
23
|
+
|
24
|
+
== Usage
|
25
|
+
|
26
|
+
Just include MultidispatchDSL into your class and your will get `mdef` class method. For example
|
27
|
+
|
28
|
+
class TestClass
|
29
|
+
include MultidispatchDSL
|
30
|
+
|
31
|
+
# hello method with one integer argument
|
32
|
+
mdef(:hello, Fixnum) do |i|
|
33
|
+
"Fixnum version with number #{ i }"
|
34
|
+
end
|
35
|
+
|
36
|
+
# hello method with one string argument
|
37
|
+
mdef(:hello, String) do |str|
|
38
|
+
"String version with string #{ str }"
|
39
|
+
end
|
40
|
+
|
41
|
+
# hello method with fixnum and string arguments
|
42
|
+
mdef(:hello, Fixnum, String) do |i, str|
|
43
|
+
"Fixnum String version with #{ i } & #{ str }"
|
44
|
+
end
|
45
|
+
|
46
|
+
# hello method with string and fixnum arguments
|
47
|
+
mdef(:hello, String, Fixnum) do |str, i|
|
48
|
+
"String Fixnum version with #{ str } & #{ i }"
|
49
|
+
end
|
50
|
+
|
51
|
+
# hello method without arguments
|
52
|
+
mdef(:hello) do
|
53
|
+
"Version without args"
|
54
|
+
end
|
55
|
+
|
56
|
+
# hello method with symbol argument
|
57
|
+
mdef(:hello, Symbol) do |symbol|
|
58
|
+
"Symbol version with :#{ symbol } & :#{ internal_method }"
|
59
|
+
end
|
60
|
+
|
61
|
+
# hello method with 2 string argument and nested block
|
62
|
+
mdef(:hello, String, String) do |str_one, str_two, &block|
|
63
|
+
instance_exec(str_one.upcase, str_two.downcase, &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def internal_method
|
67
|
+
:internal_method
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
test_instance = TestClass.new
|
72
|
+
|
73
|
+
test_instance.hello
|
74
|
+
#=> "Version without args"
|
75
|
+
|
76
|
+
test_instance.hello(1)
|
77
|
+
#=> "Fixnum version with number 1"
|
78
|
+
|
79
|
+
test_instance.hello(:foo)
|
80
|
+
#=> "Symbol version with :foo & :internal_method"
|
81
|
+
|
82
|
+
test_instance.hello(1, "string")
|
83
|
+
#=> "Fixnum String version with 1 & string"
|
84
|
+
|
85
|
+
test_instance.hello("string", 1)
|
86
|
+
#=> "String Fixnum version with string & 1"
|
87
|
+
|
88
|
+
test_instance.hello(:not, :defined)
|
89
|
+
#=> raise error MultidispatchDSL::MissingDeclarationError
|
90
|
+
|
91
|
+
test_instance.hello('One', 'Two') { |str_one, str_two| "#{str_one} #{ str_two } #{ internal_method }" }
|
92
|
+
#=> "ONE two internal_method"
|
93
|
+
|
94
|
+
As you can see defining version of method with *yield* is little bit tricky. That because defining method from block add extra scope. More details about it here http://www.andylindeman.com/2011/01/08/defining-methods-using-blocks-in-ruby.html
|
95
|
+
|
96
|
+
If you desire add this functionality to all classes just include MultidispatchDSL to Object class:
|
97
|
+
|
98
|
+
Object.send(:include, MultidispatchDSL)
|
99
|
+
|
100
|
+
== Requirements
|
101
|
+
|
102
|
+
Ruby >= 1.9.2 and other ruby implementations with 1.9 mode
|
103
|
+
|
104
|
+
== Contributing
|
105
|
+
|
106
|
+
1. Fork it
|
107
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
108
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
109
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
110
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'multidispatch_dsl/generator'
|
2
|
+
require 'multidispatch_dsl/missing_declaration_error'
|
3
|
+
|
4
|
+
module MultidispatchDSL::DSL
|
5
|
+
def self.included(klass)
|
6
|
+
klass.extend(::MultidispatchDSL::DSL::ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def mdef(method_name, *declaration, &block)
|
11
|
+
real_method_name = ::MultidispatchDSL::Generator.method_name_from_declaration(method_name, declaration)
|
12
|
+
define_method(real_method_name, &block)
|
13
|
+
|
14
|
+
unless method_defined?(method_name)
|
15
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
16
|
+
def #{ method_name }(*args, &block)
|
17
|
+
real_method_name = ::MultidispatchDSL::Generator.method_name_from_args(__callee__, args)
|
18
|
+
if respond_to?(real_method_name)
|
19
|
+
send(real_method_name, *args, &block)
|
20
|
+
else
|
21
|
+
raise ::MultidispatchDSL::MissingDeclarationError.new(__callee__, args)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MultidispatchDSL::Generator
|
2
|
+
module_function
|
3
|
+
|
4
|
+
def method_name_from_declaration(base, declaration)
|
5
|
+
if declaration.empty?
|
6
|
+
"#{ base }_empty"
|
7
|
+
else
|
8
|
+
prefix = declaration.map { |klass| underscore(klass) }.join('_')
|
9
|
+
"#{ base }_#{ prefix }"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_name_from_args(base, args)
|
14
|
+
method_name_from_declaration(base, args.map(&:class))
|
15
|
+
end
|
16
|
+
|
17
|
+
def declaration_from_args(args)
|
18
|
+
list = args.join(', ') { |item| item.class.to_s }
|
19
|
+
"(#{ list })"
|
20
|
+
end
|
21
|
+
|
22
|
+
# source code was taken from activesupport library
|
23
|
+
def underscore(klass)
|
24
|
+
word = klass.to_s.dup
|
25
|
+
word.gsub!(/::/, '_')
|
26
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
27
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
28
|
+
word.tr!("-", "_")
|
29
|
+
word.downcase!
|
30
|
+
word
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'multidispatch_dsl/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "multidispatch_dsl"
|
8
|
+
spec.version = MultidispatchDSL::VERSION
|
9
|
+
spec.authors = ["Sergey Pchelincev"]
|
10
|
+
spec.email = ["jalkoby91@gmail.com"]
|
11
|
+
spec.description = %q{Add mutlti dispatch functionality to Ruby}
|
12
|
+
spec.summary = spec.description
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec", ">= 2.0.0"
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MultidispatchDSL::Generator do
|
4
|
+
context '.method_name_from_declaration' do
|
5
|
+
specify { should == "execute_empty" }
|
6
|
+
specify { subject(Fixnum).should == "execute_fixnum" }
|
7
|
+
specify { subject(Fixnum, String).should == "execute_fixnum_string" }
|
8
|
+
specify { subject(described_class).should == "execute_multidispatch_dsl_generator" }
|
9
|
+
|
10
|
+
def subject(*declaration)
|
11
|
+
described_class.method_name_from_declaration("execute", declaration)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context '.declaration_from_args' do
|
16
|
+
specify { should = "()" }
|
17
|
+
specify { subject(Fixnum, String).should == "(Fixnum, String)" }
|
18
|
+
|
19
|
+
def subject(*args)
|
20
|
+
described_class.declaration_from_args(args)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MultidispatchDSL do
|
4
|
+
subject { TestClass.new }
|
5
|
+
|
6
|
+
specify { subject.hello.should == "Version without args" }
|
7
|
+
specify { subject.hello(1).should == "Fixnum version with number 1" }
|
8
|
+
specify { subject.hello(:foo).should == "Symbol version with :foo & :internal_method" }
|
9
|
+
specify { subject.hello(1, "string").should == "Fixnum String version with 1 & string" }
|
10
|
+
specify { subject.hello("string", 1).should == "String Fixnum version with string & 1" }
|
11
|
+
specify { expect { subject.fooo }.to raise_error(NameError) }
|
12
|
+
specify { expect { subject.hello(:not, :defined).to raise_error(MultidispatchDSL::MissingDeclarationError) } }
|
13
|
+
|
14
|
+
it 'allow yield in methods' do
|
15
|
+
subject.hello('One', 'Two') do |str_one, str_two|
|
16
|
+
"#{str_one} #{ str_two } #{ internal_method }"
|
17
|
+
end.should == "ONE two internal_method"
|
18
|
+
end
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
class TestClass
|
2
|
+
include MultidispatchDSL
|
3
|
+
|
4
|
+
mdef(:hello, Fixnum) do |i|
|
5
|
+
"Fixnum version with number #{ i }"
|
6
|
+
end
|
7
|
+
|
8
|
+
mdef(:hello, String) do |str|
|
9
|
+
"String version with string #{ str }"
|
10
|
+
end
|
11
|
+
|
12
|
+
mdef(:hello, Fixnum, String) do |i, str|
|
13
|
+
"Fixnum String version with #{ i } & #{ str }"
|
14
|
+
end
|
15
|
+
|
16
|
+
mdef(:hello, String, Fixnum) do |str, i|
|
17
|
+
"String Fixnum version with #{ str } & #{ i }"
|
18
|
+
end
|
19
|
+
|
20
|
+
mdef(:hello) do
|
21
|
+
"Version without args"
|
22
|
+
end
|
23
|
+
|
24
|
+
mdef(:hello, Symbol) do |symbol|
|
25
|
+
"Symbol version with :#{ symbol } & :#{ internal_method }"
|
26
|
+
end
|
27
|
+
|
28
|
+
mdef(:hello, String, String) do |str_one, str_two, &block|
|
29
|
+
instance_exec(str_one.upcase, str_two.downcase, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def internal_method
|
33
|
+
:internal_method
|
34
|
+
end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multidispatch_dsl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergey Pchelincev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-28 00:00:00.000000000 Z
|
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.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.0.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.0.0
|
55
|
+
description: Add mutlti dispatch functionality to Ruby
|
56
|
+
email:
|
57
|
+
- jalkoby91@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- .travis.yml
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.rdoc
|
67
|
+
- Rakefile
|
68
|
+
- lib/multidispatch_dsl.rb
|
69
|
+
- lib/multidispatch_dsl/dsl.rb
|
70
|
+
- lib/multidispatch_dsl/generator.rb
|
71
|
+
- lib/multidispatch_dsl/missing_declaration_error.rb
|
72
|
+
- lib/multidispatch_dsl/version.rb
|
73
|
+
- multidispatch_dsl.gemspec
|
74
|
+
- spec/lib/multidispatch_dsl_generator_spec.rb
|
75
|
+
- spec/lib/multidispatch_dsl_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
- spec/support/test_class.rb
|
78
|
+
homepage: ''
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 2.0.3
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: Add mutlti dispatch functionality to Ruby
|
102
|
+
test_files:
|
103
|
+
- spec/lib/multidispatch_dsl_generator_spec.rb
|
104
|
+
- spec/lib/multidispatch_dsl_spec.rb
|
105
|
+
- spec/spec_helper.rb
|
106
|
+
- spec/support/test_class.rb
|