named_parameters 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.
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