named_parameters 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2012 Marvin Ede
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README ADDED
@@ -0,0 +1,76 @@
1
+ = Named Parameters
2
+ Makes your methods callable with named parameters
3
+
4
+ == Get it
5
+ Surprisingly it is this easy:
6
+
7
+ gem install named_parameters
8
+
9
+ ---
10
+
11
+ == Use it
12
+ = First, include NamedParameters:
13
+ class AnyClass
14
+ include NamedParameters
15
+ end
16
+
17
+ = Second, call the macro:
18
+
19
+
20
+ class AnyClass
21
+ include NamedParameters
22
+
23
+ named_parameters
24
+ end
25
+
26
+
27
+ = Last, but not least, define your method:
28
+ class AnyClass
29
+ include NamedParameters
30
+
31
+ named_parameters
32
+ def some_method(a,b,c)
33
+ #... do something
34
+ end
35
+ end
36
+
37
+ == Call it
38
+ any_object = AnyClass.new
39
+ any_object.some_method(a: "here comes the 'a' parameter",
40
+ c: "this is for c"
41
+ b: 42)
42
+
43
+
44
+
45
+ ---
46
+ == Optional parameters
47
+ You may also define optional parameters with defaults values:
48
+ class AnyClass
49
+ named_parameters(a: "default a", b: "default b")
50
+ def some_method(a,b)
51
+ [a,b]
52
+ end
53
+ end
54
+ The call is just the same:
55
+ any_object.some_method(a: "actual a") # => ["actual a", "default b"]
56
+ any_object.some_method(b: "actual b") # => ["default a", "actual b"]
57
+ any_object.some_method # => ["default a", "default b"]
58
+
59
+ == Optional and mandatory parameters
60
+ You can have both optional and mandatory parameters for the same method.
61
+ All paramaters with no default value are mandatory:
62
+
63
+ class AnyClass
64
+ named_parameters(a: "default a")
65
+ def some_method(a,b,c)
66
+ [a,b,c]
67
+ end
68
+ end
69
+
70
+ any_object.some_method(b: "given",
71
+ c: nil) # => ["default a", "given", nil]
72
+
73
+ any_object.some_method(b: "given",
74
+ a: "overwritten") # => Error: Mandatory parameter 'c' not given
75
+
76
+
@@ -0,0 +1,94 @@
1
+ require_relative "../src/named_parameters"
2
+
3
+ class Book
4
+ include NamedParameters
5
+
6
+ attr_reader :author, :title, :year
7
+
8
+ named_parameters
9
+
10
+ def initialize author, title, year
11
+ @author = author
12
+ @title = title
13
+ @year = year
14
+ end
15
+
16
+ named_parameters
17
+
18
+ def foo bar, baz
19
+ [bar, baz]
20
+ end
21
+
22
+ named_parameters(foo: "foo", bar: "bar")
23
+
24
+ def method_with_defaults_only foo, bar
25
+ [foo, bar]
26
+ end
27
+
28
+ named_parameters(optional: "optional")
29
+
30
+ def method_with_defaults_and_mandatory optional, mandatory
31
+ [optional, mandatory]
32
+ end
33
+
34
+ end
35
+
36
+ describe Book do
37
+
38
+ attr_reader :book
39
+ before :each do
40
+ @book = Book.new(title: "Enders Game",
41
+ author: "Orson Scott Card",
42
+ year: 1992)
43
+ end
44
+
45
+
46
+ it "should be a book" do
47
+ book.should be_instance_of Book
48
+ end
49
+
50
+ it "attributes should be readable" do
51
+ book.title.should == "Enders Game"
52
+ book.author.should == "Orson Scott Card"
53
+ book.year.should == 1992
54
+ end
55
+
56
+ it "should accept a second method defined" do
57
+ book.foo(bar: "bar",
58
+ baz: "baz").should == ["bar", "baz"]
59
+ end
60
+
61
+ it "should raise an error on false parameters" do
62
+ -> { book.foo(bar: "bar") }.should raise_error(RuntimeError)
63
+ -> { book.foo(baz: "baz") }.should raise_error(RuntimeError)
64
+ -> { book.foo(bar: "bar",
65
+ baz: "baz",
66
+ other: "other") }.should raise_error(RuntimeError)
67
+ end
68
+
69
+ it "should accept a method with only optional parameters" do
70
+ #book.method_with_defaults_only.should == ["foo", "bar"]
71
+ book.method_with_defaults_only(foo: "FOO").should == ["FOO", "bar"]
72
+ end
73
+
74
+ it "should not accept inconsistent method definition" do
75
+ code = -> do
76
+ class Book
77
+ some_defaults(a: "a", b: "b")
78
+
79
+ def a_method a, c
80
+ #... do something
81
+ end
82
+ end
83
+ end
84
+ code.should raise_error(RuntimeError)
85
+ end
86
+
87
+ it "should accept a method with mixed parameters" do
88
+ book.method_with_defaults_and_mandatory(mandatory: "given").should == ["optional", "given"]
89
+ -> { book.method_with_defaults_and_mandatory(
90
+ optional: "only optional is given") }.should raise_error(RuntimeError)
91
+ end
92
+
93
+
94
+ end
@@ -0,0 +1,128 @@
1
+ module Kernel #:nodoc:
2
+ # @return [Class] the eigenclass / singletonclass / metaclass of self
3
+ def eigenclass
4
+ class << self
5
+ self
6
+ end
7
+ end
8
+ end
9
+
10
+ #
11
+ # Include this module to enable the named_parameters macro
12
+ #
13
+ module NamedParameters
14
+
15
+ # :nodoc:
16
+ # Makes all methods of this module to class or module methods of include
17
+ def self.included base
18
+ base.extend(self)
19
+ end
20
+
21
+ #noinspection RubyArgCount
22
+ self.class.class_eval do
23
+ alias :method_added_before_named_parameters :method_added #:nodoc:
24
+ private :method_added_before_named_parameters
25
+ end
26
+
27
+
28
+ # @param defaults [Hash] Containing defaults values for optional parameters.
29
+ # Parameters that are not listet here are mandatory.
30
+ def named_parameters defaults = { }
31
+ defaults.empty? ? all_required : some_defaults(defaults)
32
+ end
33
+
34
+ private
35
+
36
+ # [Symbol] is in [:nothing, :all_required, :defaults]
37
+ @@next_method_modifier = :nothing
38
+
39
+ def all_required
40
+ @@next_method_modifier = :all_required
41
+ end
42
+
43
+ def some_defaults defaults
44
+ @@next_method_modifier = :defaults
45
+ @@defaults = defaults
46
+ end
47
+
48
+
49
+ # @param method_name [Symbol]
50
+ def method_added(method_name)
51
+ if @@next_method_modifier == :all_required
52
+ @@next_method_modifier = :nothing
53
+ redefine_all_required_method(method_name)
54
+ elsif @@next_method_modifier == :defaults
55
+ @@next_method_modifier = :nothing
56
+ redefine_defaults_method(method_name, @@defaults)
57
+ @@defaults = nil
58
+ end
59
+ method_added_before_named_parameters method_name
60
+
61
+ end
62
+
63
+ # @param method_name [Symbol]
64
+ # @return [Object] Not important
65
+ def redefine_all_required_method(method_name)
66
+ method = instance_method method_name
67
+ parameter_definition = method.parameters.collect { |_, b| b }
68
+ old_name = (method_name.to_s+"_before_named_parameters").to_sym
69
+ alias_method old_name, method_name
70
+ module_eval do
71
+ define_method method_name do |options|
72
+ missing = parameter_definition-(options.keys)
73
+ unless missing.empty?
74
+ raise RuntimeError.new("Missing arguments: #{missing}")
75
+ end
76
+ unexpected = options.keys - parameter_definition
77
+ unless unexpected.empty?
78
+ raise RuntimeError.new("Unexpected arguments: #{unexpected}")
79
+ end
80
+ parameters = []
81
+ parameter_definition.each { |parameter| parameters << options[parameter] }
82
+ eval <<-STRING
83
+ obj = self
84
+ method.bind(obj).call *parameters
85
+ STRING
86
+ end
87
+ end
88
+ end
89
+
90
+ # @param method_name [Symbol]
91
+ # @param defaults [Hash]
92
+ # @return [Object] Not important
93
+ def redefine_defaults_method(method_name, defaults)
94
+ method = instance_method method_name
95
+ parameter_definition = method.parameters.collect { |_, b| b }
96
+
97
+ defaults.keys.each do |default_key|
98
+ raise RuntimeError.new("A default value for #{default_key} has been defined,
99
+ but it is not a parameter of #{method_name}") unless parameter_definition.include? default_key
100
+ end
101
+
102
+ old_name = (method_name.to_s+"_before_named_parameters").to_sym
103
+ alias_method old_name, method_name
104
+ module_eval do
105
+ define_method method_name do |options = { }|
106
+ unexpected = options.keys - parameter_definition
107
+ unless unexpected.empty?
108
+ raise RuntimeError.new("Unexpected arguments: #{unexpected}")
109
+ end
110
+
111
+ parameters = []
112
+ mandatory = parameter_definition-(defaults.keys)
113
+ parameter_definition.each do |parameter|
114
+ if mandatory.member? parameter
115
+ parameters << options.fetch(parameter) { raise RuntimeError.new("Mandatory parameter #{parameter} not
116
+ given") }
117
+ else
118
+ parameters << options.fetch(parameter, defaults[parameter])
119
+ end
120
+ end
121
+ eval <<-STRING
122
+ obj = self
123
+ method.bind(obj).call *parameters
124
+ STRING
125
+ end
126
+ end
127
+ end
128
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: named_parameters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marvin Ede
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &25860360 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.9.0
22
+ - - <
23
+ - !ruby/object:Gem::Version
24
+ version: 3.0.0
25
+ type: :development
26
+ prerelease: false
27
+ version_requirements: *25860360
28
+ description: ! 'By including the NamedParameters module into your class/module the
29
+ ''named_parameters'' macro is
30
+
31
+ available. Optional parameters with default values can be as easily defined as mandatory
32
+ parameters. Your actual
33
+
34
+ method definition does not change at all'
35
+ email: marvinede@gmx.net
36
+ executables: []
37
+ extensions: []
38
+ extra_rdoc_files:
39
+ - README
40
+ - LICENSE
41
+ files:
42
+ - src/named_parameters.rb
43
+ - README
44
+ - LICENSE
45
+ - spec/named_parameters_spec.rb
46
+ homepage: http://rubygems.org/gems/named_parameters
47
+ licenses:
48
+ - apache 2.0
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --title
52
+ - Named Parameters
53
+ - --main
54
+ - README
55
+ - --line_numbers
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: 1.9.0
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 1.8.17
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Makes your methods callable with named parameters
76
+ test_files:
77
+ - spec/named_parameters_spec.rb