multidispatch_dsl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rspec
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - jruby-19mode # JRuby in 1.9 mode
7
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in multidispatch_dsl.gemspec
4
+ gemspec
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,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ desc "Run all specs"
7
+ task :default => :spec
@@ -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,6 @@
1
+ class MultidispatchDSL::MissingDeclarationError < StandardError
2
+
3
+ def initialize(method_name, args)
4
+ super "#{ MultidispatchDSL::Generator.declaration_from_args(args) } for #{ method_name }"
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module MultidispatchDSL
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,7 @@
1
+ module MultidispatchDSL
2
+ autoload :DSL, 'multidispatch_dsl/dsl'
3
+
4
+ def self.included(klass)
5
+ klass.send(:include, ::MultidispatchDSL::DSL)
6
+ end
7
+ 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
@@ -0,0 +1,3 @@
1
+ require 'bundler/setup'
2
+ Bundler.require(:default)
3
+ Dir["#{ File.dirname(__FILE__) }/support/**/*.rb"].each { |f| require f }
@@ -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