simple-service 0.1.1 → 0.1.6
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 +4 -4
- data/.gitignore +2 -2
- data/.rubocop.yml +7 -0
- data/.tm_properties +1 -1
- data/Makefile +8 -0
- data/README.md +68 -1
- data/TODO.txt +3 -0
- data/VERSION +1 -1
- data/doc/Simple.html +117 -0
- data/doc/Simple/Service.html +865 -0
- data/doc/Simple/Service/Action.html +923 -0
- data/doc/Simple/Service/Action/Comment.html +451 -0
- data/doc/Simple/Service/Action/Comment/Extractor.html +347 -0
- data/doc/Simple/Service/Action/MethodReflection.html +285 -0
- data/doc/Simple/Service/Action/Parameter.html +816 -0
- data/doc/Simple/Service/ArgumentError.html +128 -0
- data/doc/Simple/Service/ClassMethods.html +187 -0
- data/doc/Simple/Service/Context.html +379 -0
- data/doc/Simple/Service/ContextMissingError.html +124 -0
- data/doc/Simple/Service/ContextReadOnlyError.html +206 -0
- data/doc/Simple/Service/ExtraArguments.html +428 -0
- data/doc/Simple/Service/GemHelper.html +190 -0
- data/doc/Simple/Service/MissingArguments.html +426 -0
- data/doc/Simple/Service/NoSuchAction.html +433 -0
- data/doc/_index.html +274 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +496 -0
- data/doc/file.README.html +146 -0
- data/doc/file.TODO.html +70 -0
- data/doc/file_list.html +61 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +146 -0
- data/doc/js/app.js +303 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +483 -0
- data/doc/top-level-namespace.html +110 -0
- data/lib/simple/service.rb +161 -56
- data/lib/simple/service/action.rb +104 -107
- data/lib/simple/service/action/comment.rb +3 -1
- data/lib/simple/service/action/method_reflection.rb +3 -3
- data/lib/simple/service/action/parameter.rb +3 -7
- data/lib/simple/service/context.rb +69 -27
- data/lib/simple/service/errors.rb +54 -0
- data/lib/simple/service/version.rb +7 -2
- data/scripts/stats +2 -1
- data/spec/simple/service/action_invoke3_spec.rb +266 -0
- data/spec/simple/service/action_invoke_spec.rb +237 -0
- data/spec/simple/service/action_spec.rb +51 -0
- data/spec/simple/service/context_spec.rb +39 -7
- data/spec/simple/service/service_spec.rb +158 -0
- data/spec/simple/service/version_spec.rb +7 -0
- data/spec/spec_helper.rb +15 -2
- data/spec/support/spec_services.rb +58 -0
- metadata +48 -6
- data/lib/simple.rb +0 -2
- data/spec/support/004_simplecov.rb +0 -13
@@ -1,6 +1,6 @@
|
|
1
1
|
# rubocop:disable Metrics/AbcSize
|
2
2
|
|
3
|
-
module ::Simple::Service::Action::MethodReflection #
|
3
|
+
module ::Simple::Service::Action::MethodReflection # @private
|
4
4
|
extend self
|
5
5
|
|
6
6
|
#
|
@@ -16,7 +16,7 @@ module ::Simple::Service::Action::MethodReflection # :nodoc:
|
|
16
16
|
method = service.instance_method(method_id)
|
17
17
|
parameters = method.parameters
|
18
18
|
|
19
|
-
# method parameters with a :key mode are optional
|
19
|
+
# method parameters with a :key mode are optional named arguments. We only
|
20
20
|
# support defaults for those - if there are none we abort here already.
|
21
21
|
keys = parameters.map { |mode, name| name if mode == :key }.compact
|
22
22
|
return parameters if keys.empty?
|
@@ -59,7 +59,7 @@ module ::Simple::Service::Action::MethodReflection # :nodoc:
|
|
59
59
|
# values for these arguments doesn't matter at all.
|
60
60
|
args = method.parameters.select { |mode, _name| mode == :req }
|
61
61
|
|
62
|
-
# Add a hash with all required
|
62
|
+
# Add a hash with all required named arguments
|
63
63
|
required_keyword_args = method.parameters.each_with_object({}) do |(mode, name), hsh|
|
64
64
|
hsh[name] = :anything if mode == :keyreq
|
65
65
|
end
|
@@ -7,10 +7,10 @@ class ::Simple::Service::Action::Parameter
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def keyword?
|
10
|
-
[:
|
10
|
+
[:keyreq, :key].include? @kind
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
13
|
+
def positional?
|
14
14
|
[:req, :opt].include? @kind
|
15
15
|
end
|
16
16
|
|
@@ -22,10 +22,6 @@ class ::Simple::Service::Action::Parameter
|
|
22
22
|
@kind == :rest
|
23
23
|
end
|
24
24
|
|
25
|
-
def optional?
|
26
|
-
!required?
|
27
|
-
end
|
28
|
-
|
29
25
|
attr_reader :name
|
30
26
|
attr_reader :kind
|
31
27
|
|
@@ -40,7 +36,7 @@ class ::Simple::Service::Action::Parameter
|
|
40
36
|
expect! default_value.length => [0, 1]
|
41
37
|
|
42
38
|
@kind = kind
|
43
|
-
@name = name
|
39
|
+
@name = name.to_s
|
44
40
|
@default_value = default_value[0]
|
45
41
|
end
|
46
42
|
end
|
@@ -1,39 +1,65 @@
|
|
1
1
|
module Simple::Service
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
7
|
-
end
|
2
|
+
# Returns the current context.
|
3
|
+
def self.context
|
4
|
+
Thread.current[:"Simple::Service.context"]
|
5
|
+
end
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
# yields a block with a given context, and restores the previous context
|
8
|
+
# object afterwards.
|
9
|
+
def self.with_context(ctx = nil, &block)
|
10
|
+
old_ctx = Thread.current[:"Simple::Service.context"]
|
11
|
+
new_ctx = old_ctx ? old_ctx.merge(ctx) : Context.new(ctx)
|
12
12
|
|
13
|
-
|
13
|
+
Thread.current[:"Simple::Service.context"] = new_ctx
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
block.call
|
16
|
+
ensure
|
17
|
+
Thread.current[:"Simple::Service.context"] = old_ctx
|
18
|
+
end
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
+
module Simple::Service
|
22
|
+
# A context object
|
23
|
+
#
|
24
|
+
# Each service executes with a current context. The system manages a stack of
|
25
|
+
# contexts; whenever a service execution is done the current context is reverted
|
26
|
+
# to its previous value.
|
27
|
+
#
|
28
|
+
# A context object can store a large number of values; the only way to set or
|
29
|
+
# access a value is via getters and setters. These are implemented via
|
30
|
+
# +method_missing(..)+.
|
31
|
+
#
|
32
|
+
# Also, once a value is set in the context it is not possible to change or
|
33
|
+
# unset it.
|
34
|
+
class Context
|
35
|
+
def initialize(hsh = nil) # @private
|
36
|
+
@hsh = hsh || {}
|
37
|
+
end
|
21
38
|
|
22
|
-
|
23
|
-
|
24
|
-
|
39
|
+
# returns a new Context object, which merges the values in the +overlay+
|
40
|
+
# argument (which must be a Hash or nil) with the values in this context.
|
41
|
+
#
|
42
|
+
# The overlay is allowed to change values in the current context.
|
43
|
+
#
|
44
|
+
# It does not change this context.
|
45
|
+
def merge(overlay)
|
46
|
+
expect! overlay => [Hash, nil]
|
25
47
|
|
26
|
-
|
48
|
+
overlay ||= {}
|
49
|
+
new_context_hsh = @hsh.merge(overlay)
|
50
|
+
::Simple::Service::Context.new(new_context_hsh)
|
27
51
|
end
|
28
52
|
|
29
|
-
|
30
|
-
|
31
|
-
|
53
|
+
private
|
54
|
+
|
55
|
+
IDENTIFIER_PATTERN = "[a-z][a-z0-9_]*" # @private
|
56
|
+
IDENTIFIER_REGEXP = Regexp.compile("\\A#{IDENTIFIER_PATTERN}\\z") # @private
|
57
|
+
ASSIGNMENT_REGEXP = Regexp.compile("\\A(#{IDENTIFIER_PATTERN})=\\z") # @private
|
32
58
|
|
33
59
|
def method_missing(sym, *args, &block)
|
34
|
-
if block
|
35
|
-
|
36
|
-
|
60
|
+
raise ArgumentError, "Block given" if block
|
61
|
+
|
62
|
+
if args.count == 0 && sym =~ IDENTIFIER_REGEXP
|
37
63
|
self[sym]
|
38
64
|
elsif args.count == 1 && sym =~ ASSIGNMENT_REGEXP
|
39
65
|
self[$1.to_sym] = args.first
|
@@ -43,10 +69,26 @@ module Simple::Service
|
|
43
69
|
end
|
44
70
|
|
45
71
|
def respond_to_missing?(sym, include_private = false)
|
46
|
-
|
47
|
-
return true if
|
72
|
+
# :nocov:
|
73
|
+
return true if IDENTIFIER_REGEXP.match?(sym)
|
74
|
+
return true if ASSIGNMENT_REGEXP.match?(sym)
|
48
75
|
|
49
76
|
super
|
77
|
+
# :nocov:
|
78
|
+
end
|
79
|
+
|
80
|
+
def [](key)
|
81
|
+
@hsh[key]
|
82
|
+
end
|
83
|
+
|
84
|
+
def []=(key, value)
|
85
|
+
existing_value = @hsh[key]
|
86
|
+
|
87
|
+
unless existing_value.nil? || existing_value == value
|
88
|
+
raise ::Simple::Service::ContextReadOnlyError, key
|
89
|
+
end
|
90
|
+
|
91
|
+
@hsh[key] = value
|
50
92
|
end
|
51
93
|
end
|
52
94
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Simple::Service
|
2
|
+
# Will be raised by ::Simple::Service.action.
|
3
|
+
class NoSuchAction < ::ArgumentError
|
4
|
+
attr_reader :service, :name
|
5
|
+
def initialize(service, name)
|
6
|
+
@service, @name = service, name
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
action_names = ::Simple::Service.actions(service).keys.sort
|
11
|
+
informal = "service #{service} has these actions: #{action_names.map(&:inspect).join(", ")}"
|
12
|
+
"No such action #{name.inspect}; #{informal}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class ArgumentError < ::ArgumentError
|
17
|
+
end
|
18
|
+
|
19
|
+
class MissingArguments < ArgumentError
|
20
|
+
attr_reader :action
|
21
|
+
attr_reader :parameters
|
22
|
+
|
23
|
+
def initialize(action, parameters)
|
24
|
+
@action, @parameters = action, parameters
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"#{action}: missing argument(s): #{parameters.map(&:to_s).join(", ")}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class ExtraArguments < ArgumentError
|
33
|
+
attr_reader :action
|
34
|
+
attr_reader :arguments
|
35
|
+
|
36
|
+
def initialize(action, arguments)
|
37
|
+
@action, @arguments = action, arguments
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
str = @arguments.map(&:inspect).join(", ")
|
42
|
+
"#{action}: extra argument(s) #{str}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class ContextMissingError < ::StandardError
|
47
|
+
end
|
48
|
+
|
49
|
+
class ContextReadOnlyError < ::StandardError
|
50
|
+
def initialize(key)
|
51
|
+
super "Cannot overwrite existing context setting #{key.inspect}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -1,5 +1,8 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Simple # @private
|
2
|
+
end
|
3
|
+
|
4
|
+
module Simple::Service
|
5
|
+
module GemHelper # @private
|
3
6
|
extend self
|
4
7
|
|
5
8
|
def version(name)
|
@@ -14,9 +17,11 @@ class Simple::Service
|
|
14
17
|
def unreleased?(spec)
|
15
18
|
return false unless defined?(Bundler::Source::Gemspec)
|
16
19
|
return true if spec.source.is_a?(::Bundler::Source::Gemspec)
|
20
|
+
# :nocov:
|
17
21
|
return true if spec.source.is_a?(::Bundler::Source::Path)
|
18
22
|
|
19
23
|
false
|
24
|
+
# :nocov:
|
20
25
|
end
|
21
26
|
end
|
22
27
|
|
data/scripts/stats
CHANGED
@@ -0,0 +1,266 @@
|
|
1
|
+
# rubocop:disable Style/WordArray
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe "Simple::Service.invoke3" do
|
6
|
+
# the context to use in the around hook below. By default this is nil -
|
7
|
+
# which gives us an empty context.
|
8
|
+
let(:context) { nil }
|
9
|
+
|
10
|
+
around do |example|
|
11
|
+
::Simple::Service.with_context(context) { example.run }
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:service) { InvokeTestService }
|
15
|
+
let(:action) { nil }
|
16
|
+
|
17
|
+
# a shortcut
|
18
|
+
def invoke3!(*args, **keywords)
|
19
|
+
@actual = ::Simple::Service.invoke3(service, action, *args, **keywords)
|
20
|
+
# rescue ::StandardError => e
|
21
|
+
rescue ::Simple::Service::ArgumentError => e
|
22
|
+
@actual = e
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :actual
|
26
|
+
|
27
|
+
# when calling #invoke3 using positional arguments they will be matched against
|
28
|
+
# positional arguments of the invoke3d method - but they will not be matched
|
29
|
+
# against named arguments.
|
30
|
+
#
|
31
|
+
# When there are not enough positional arguments to match the number of required
|
32
|
+
# positional arguments of the method we raise an ArgumentError.
|
33
|
+
#
|
34
|
+
# When there are more positional arguments provided than the number accepted
|
35
|
+
# by the method we raise an ArgumentError.
|
36
|
+
|
37
|
+
context "calling an action w/o parameters" do
|
38
|
+
# reminder: this is the definition of no_params
|
39
|
+
#
|
40
|
+
# def no_params
|
41
|
+
# "service2 return"
|
42
|
+
# end
|
43
|
+
|
44
|
+
let(:action) { :no_params }
|
45
|
+
|
46
|
+
context "calling without args" do
|
47
|
+
it "runs the action" do
|
48
|
+
invoke3!
|
49
|
+
expect(actual).to eq("service2 return")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "calling with extra positional args" do
|
54
|
+
it "raises ExtraArguments" do
|
55
|
+
invoke3!("foo", "bar")
|
56
|
+
expect(actual).to be_a(::Simple::Service::ExtraArguments)
|
57
|
+
expect(actual.to_s).to match(/"foo", "bar"/)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "calling with extra named args" do
|
62
|
+
it "ignores extra args" do
|
63
|
+
invoke3!(foo: "foo", bar: "bar")
|
64
|
+
expect(actual).to eq("service2 return")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "calling with an additional hash arg" do
|
69
|
+
xit "ignores extra args" do
|
70
|
+
args = []
|
71
|
+
args.push foo: "foo", bar: "bar"
|
72
|
+
invoke3!(*args)
|
73
|
+
|
74
|
+
expect(actual).to be_a(::Simple::Service::ExtraArguments)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "calling an action w/positional parameters" do
|
80
|
+
# reminder: this is the definition of positional_params
|
81
|
+
#
|
82
|
+
# def positional_params(a, b, c = "speed-of-light", e = 2.781)
|
83
|
+
# [a, b, c, e]
|
84
|
+
# end
|
85
|
+
|
86
|
+
let(:action) { :positional_params }
|
87
|
+
|
88
|
+
context "without args" do
|
89
|
+
it "raises MissingArguments" do
|
90
|
+
invoke3!
|
91
|
+
expect(actual).to be_a(::Simple::Service::MissingArguments)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "with the required number of args" do
|
96
|
+
it "runs" do
|
97
|
+
invoke3!("foo", "bar")
|
98
|
+
expect(actual).to eq(["foo", "bar", "speed-of-light", 2.781])
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "with the allowed number of args" do
|
103
|
+
it "runs" do
|
104
|
+
invoke3!("foo", "bar", "baz", "number4")
|
105
|
+
expect(actual).to eq(%w[foo bar baz number4])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "with more than the allowed number of args" do
|
110
|
+
it "raises ExtraArguments" do
|
111
|
+
invoke3!("foo", "bar", "baz", "number4", "extra")
|
112
|
+
expect(actual).to be_a(::Simple::Service::ExtraArguments)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "calling with extra named args" do
|
117
|
+
it "ignores extra args" do
|
118
|
+
invoke3!("foo", "bar", "baz", extra3: 3)
|
119
|
+
expect(actual).to eq(["foo", "bar", "baz", 2.781])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "calling with an additional hash arg" do
|
124
|
+
xit "raises ExtraArguments" do
|
125
|
+
args = ["foo", "bar", "baz", extra3: 3]
|
126
|
+
invoke3!(*args)
|
127
|
+
expect(actual).to be_a(::Simple::Service::ExtraArguments)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "calling an action w/named parameters" do
|
133
|
+
# reminder: this is the definition of named_params
|
134
|
+
#
|
135
|
+
# def named_params(a:, b:, c: "speed-of-light", e: 2.781)
|
136
|
+
# [a, b, c, e]
|
137
|
+
# end
|
138
|
+
|
139
|
+
let(:action) { :named_params }
|
140
|
+
|
141
|
+
context "without args" do
|
142
|
+
it "raises MissingArguments" do
|
143
|
+
invoke3!
|
144
|
+
expect(actual).to be_a(::Simple::Service::MissingArguments)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "with the required number of args" do
|
149
|
+
it "runs" do
|
150
|
+
invoke3!(a: "foo", b: "bar")
|
151
|
+
expect(actual).to eq(["foo", "bar", "speed-of-light", 2.781])
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "with the allowed number of args" do
|
156
|
+
it "runs" do
|
157
|
+
invoke3!(a: "foo", b: "bar", c: "baz", e: "number4")
|
158
|
+
expect(actual).to eq(%w[foo bar baz number4])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "with more than the allowed number of args" do
|
163
|
+
it "runs" do
|
164
|
+
invoke3!("foo", "bar", "baz", "number4", "extra")
|
165
|
+
expect(actual).to be_a(::Simple::Service::ExtraArguments)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "with extra named args" do
|
170
|
+
it "ignores extra args" do
|
171
|
+
invoke3!(a: "foo", b: "bar", c: "baz", extra3: 3)
|
172
|
+
expect(actual).to eq(["foo", "bar", "baz", 2.781])
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "calling an action w/mixed and optional parameters" do
|
178
|
+
# reminder: this is the definition of named_params
|
179
|
+
#
|
180
|
+
# def mixed_optional_params(a, b = "default-b", c = "speed-of-light", e: 2.781)
|
181
|
+
# [a, b, c, e]
|
182
|
+
# end
|
183
|
+
|
184
|
+
let(:action) { :mixed_optional_params }
|
185
|
+
|
186
|
+
context "without args" do
|
187
|
+
it "raises MissingArguments" do
|
188
|
+
invoke3!
|
189
|
+
expect(actual).to be_a(::Simple::Service::MissingArguments)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context "with the required number of args" do
|
194
|
+
it "runs" do
|
195
|
+
invoke3!("foo")
|
196
|
+
expect(actual).to eq(["foo", "default-b", "speed-of-light", 2.781])
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context "with the allowed number of args" do
|
201
|
+
it "runs" do
|
202
|
+
invoke3!("foo", "bar", "baz", e: "number4")
|
203
|
+
expect(actual).to eq(%w[foo bar baz number4])
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "with more than the allowed number of args" do
|
208
|
+
it "runs" do
|
209
|
+
invoke3!("foo", "bar", "baz", "extra", e: "number4")
|
210
|
+
expect(actual).to be_a(::Simple::Service::ExtraArguments)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
context "with extra named args" do
|
215
|
+
it "ignores extra args" do
|
216
|
+
invoke3!("foo", "bar", "baz", e: "number4", extra3: 3)
|
217
|
+
expect(actual).to eq(["foo", "bar", "baz", "number4"])
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context "calling an action w/mixed and variadic parameters" do
|
223
|
+
# reminder: this is the definition of variadic_params
|
224
|
+
#
|
225
|
+
# def variadic_params(a, b = "queen bee", *args, e: 2.781)
|
226
|
+
# [a, b, args, e]
|
227
|
+
# end
|
228
|
+
|
229
|
+
let(:action) { :variadic_params }
|
230
|
+
|
231
|
+
context "without args" do
|
232
|
+
it "raises MissingArguments" do
|
233
|
+
invoke3!
|
234
|
+
expect(actual).to be_a(::Simple::Service::MissingArguments)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
context "with the required number of args" do
|
239
|
+
it "runs" do
|
240
|
+
invoke3!("foo")
|
241
|
+
expect(actual).to eq(["foo", "queen bee", [], 2.781])
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context "with the allowed number of args" do
|
246
|
+
it "runs" do
|
247
|
+
invoke3!("foo", "bar", "baz", e: "number4")
|
248
|
+
expect(actual).to eq(["foo", "bar", ["baz"], "number4"])
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
context "with more than the allowed number of args" do
|
253
|
+
it "runs" do
|
254
|
+
invoke3!("foo", "bar", "baz", "extra", e: "number4")
|
255
|
+
expect(actual).to eq(["foo", "bar", ["baz", "extra"], "number4"])
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context "with extra named args" do
|
260
|
+
it "ignores extra args" do
|
261
|
+
invoke3!("foo", "bar", "baz", e: "number4", extra3: 3)
|
262
|
+
expect(actual).to eq(["foo", "bar", ["baz"], "number4"])
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|