actionwebservice 0.5.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/ChangeLog +47 -0
- data/MIT-LICENSE +21 -0
- data/README +238 -0
- data/Rakefile +144 -0
- data/TODO +13 -0
- data/examples/googlesearch/README +143 -0
- data/examples/googlesearch/autoloading/google_search_api.rb +50 -0
- data/examples/googlesearch/autoloading/google_search_controller.rb +57 -0
- data/examples/googlesearch/delegated/google_search_service.rb +108 -0
- data/examples/googlesearch/delegated/search_controller.rb +7 -0
- data/examples/googlesearch/direct/google_search_api.rb +50 -0
- data/examples/googlesearch/direct/search_controller.rb +58 -0
- data/examples/metaWeblog/README +16 -0
- data/examples/metaWeblog/blog_controller.rb +127 -0
- data/lib/action_web_service.rb +60 -0
- data/lib/action_web_service/api.rb +2 -0
- data/lib/action_web_service/api/abstract.rb +192 -0
- data/lib/action_web_service/api/action_controller.rb +92 -0
- data/lib/action_web_service/base.rb +41 -0
- data/lib/action_web_service/client.rb +3 -0
- data/lib/action_web_service/client/base.rb +39 -0
- data/lib/action_web_service/client/soap_client.rb +88 -0
- data/lib/action_web_service/client/xmlrpc_client.rb +77 -0
- data/lib/action_web_service/container.rb +85 -0
- data/lib/action_web_service/dispatcher.rb +2 -0
- data/lib/action_web_service/dispatcher/abstract.rb +150 -0
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +299 -0
- data/lib/action_web_service/invocation.rb +205 -0
- data/lib/action_web_service/protocol.rb +4 -0
- data/lib/action_web_service/protocol/abstract.rb +128 -0
- data/lib/action_web_service/protocol/registry.rb +55 -0
- data/lib/action_web_service/protocol/soap_protocol.rb +484 -0
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +168 -0
- data/lib/action_web_service/struct.rb +55 -0
- data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
- data/lib/action_web_service/support/signature.rb +100 -0
- data/setup.rb +1360 -0
- data/test/abstract_client.rb +131 -0
- data/test/abstract_soap.rb +58 -0
- data/test/abstract_unit.rb +9 -0
- data/test/api_test.rb +52 -0
- data/test/base_test.rb +42 -0
- data/test/client_soap_test.rb +93 -0
- data/test/client_xmlrpc_test.rb +92 -0
- data/test/container_test.rb +53 -0
- data/test/dispatcher_action_controller_test.rb +186 -0
- data/test/gencov +3 -0
- data/test/invocation_test.rb +149 -0
- data/test/protocol_registry_test.rb +53 -0
- data/test/protocol_soap_test.rb +252 -0
- data/test/protocol_xmlrpc_test.rb +147 -0
- data/test/run +5 -0
- data/test/struct_test.rb +40 -0
- metadata +131 -0
@@ -0,0 +1,131 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
require 'webrick'
|
3
|
+
require 'webrick/log'
|
4
|
+
require 'singleton'
|
5
|
+
|
6
|
+
module ClientTest
|
7
|
+
class Person < ActionWebService::Struct
|
8
|
+
member :firstnames, [:string]
|
9
|
+
member :lastname, :string
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
firstnames == other.firstnames && lastname == other.lastname
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class API < ActionWebService::API::Base
|
17
|
+
api_method :void
|
18
|
+
api_method :normal, :expects => [:int, :int], :returns => [:int]
|
19
|
+
api_method :array_return, :returns => [[Person]]
|
20
|
+
api_method :struct_pass, :expects => [[Person]], :returns => [:bool]
|
21
|
+
api_method :client_container, :returns => [:int]
|
22
|
+
api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}]
|
23
|
+
end
|
24
|
+
|
25
|
+
class NullLogOut
|
26
|
+
def <<(*args); end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Container < ActionController::Base
|
30
|
+
web_service_api API
|
31
|
+
|
32
|
+
attr :value_void
|
33
|
+
attr :value_normal
|
34
|
+
attr :value_array_return
|
35
|
+
attr :value_struct_pass
|
36
|
+
attr :value_named_parameters
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
@session = @assigns = {}
|
40
|
+
@value_void = nil
|
41
|
+
@value_normal = nil
|
42
|
+
@value_array_return = nil
|
43
|
+
@value_struct_pass = nil
|
44
|
+
@value_named_parameters = nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def void
|
48
|
+
@value_void = @method_params
|
49
|
+
end
|
50
|
+
|
51
|
+
def normal
|
52
|
+
@value_normal = @method_params
|
53
|
+
5
|
54
|
+
end
|
55
|
+
|
56
|
+
def array_return
|
57
|
+
person = Person.new
|
58
|
+
person.firstnames = ["one", "two"]
|
59
|
+
person.lastname = "last"
|
60
|
+
@value_array_return = [person]
|
61
|
+
end
|
62
|
+
|
63
|
+
def struct_pass
|
64
|
+
@value_struct_pass = @method_params
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
def client_container
|
69
|
+
50
|
70
|
+
end
|
71
|
+
|
72
|
+
def named_parameters
|
73
|
+
@value_named_parameters = @method_params
|
74
|
+
end
|
75
|
+
|
76
|
+
def protocol_request(request)
|
77
|
+
probe_request_protocol(request)
|
78
|
+
end
|
79
|
+
|
80
|
+
def dispatch_request(protocol_request)
|
81
|
+
dispatch_protocol_request(protocol_request)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class AbstractClientLet < WEBrick::HTTPServlet::AbstractServlet
|
86
|
+
def initialize(controller)
|
87
|
+
@controller = controller
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_instance(*args)
|
91
|
+
self
|
92
|
+
end
|
93
|
+
|
94
|
+
def require_path_info?
|
95
|
+
false
|
96
|
+
end
|
97
|
+
|
98
|
+
def do_GET(req, res)
|
99
|
+
raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed."
|
100
|
+
end
|
101
|
+
|
102
|
+
def do_POST(req, res)
|
103
|
+
raise NotImplementedError
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class AbstractServer
|
108
|
+
include ClientTest
|
109
|
+
include Singleton
|
110
|
+
attr :container
|
111
|
+
def initialize
|
112
|
+
@container = Container.new
|
113
|
+
@clientlet = create_clientlet(@container)
|
114
|
+
log = WEBrick::BasicLog.new(NullLogOut.new)
|
115
|
+
@server = WEBrick::HTTPServer.new(:Port => server_port, :Logger => log, :AccessLog => log)
|
116
|
+
@server.mount('/', @clientlet)
|
117
|
+
@thr = Thread.new { @server.start }
|
118
|
+
until @server.status == :Running; end
|
119
|
+
at_exit { @server.stop; @thr.join }
|
120
|
+
end
|
121
|
+
|
122
|
+
protected
|
123
|
+
def create_clientlet
|
124
|
+
raise NotImplementedError
|
125
|
+
end
|
126
|
+
|
127
|
+
def server_port
|
128
|
+
raise NotImplementedError
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
require 'soap/rpc/element'
|
3
|
+
|
4
|
+
class SoapTestError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
class AbstractSoapTest < Test::Unit::TestCase
|
8
|
+
def default_test
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
def service_name
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def do_soap_call(public_method_name, *args)
|
17
|
+
mapper = @container.class.soap_mapper
|
18
|
+
param_def = []
|
19
|
+
i = 1
|
20
|
+
args.each do |arg|
|
21
|
+
mapping = mapper.lookup(arg.class)
|
22
|
+
param_def << ["in", "param#{i}", mapping.registry_mapping]
|
23
|
+
i += 1
|
24
|
+
end
|
25
|
+
qname = XSD::QName.new('urn:ActionWebService', public_method_name)
|
26
|
+
request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
|
27
|
+
soap_args = []
|
28
|
+
i = 1
|
29
|
+
args.each do |arg|
|
30
|
+
soap_args << ["param#{i}", SOAP::Mapping.obj2soap(arg)]
|
31
|
+
i += 1
|
32
|
+
end
|
33
|
+
request.set_param(soap_args)
|
34
|
+
header = SOAP::SOAPHeader.new
|
35
|
+
body = SOAP::SOAPBody.new(request)
|
36
|
+
envelope = SOAP::SOAPEnvelope.new(header, body)
|
37
|
+
raw_request = SOAP::Processor.marshal(envelope)
|
38
|
+
test_request = ActionController::TestRequest.new
|
39
|
+
test_request.request_parameters['action'] = service_name
|
40
|
+
test_request.env['REQUEST_METHOD'] = "POST"
|
41
|
+
test_request.env['HTTP_CONTENTTYPE'] = 'text/xml'
|
42
|
+
test_request.env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{public_method_name}"
|
43
|
+
test_request.env['RAW_POST_DATA'] = raw_request
|
44
|
+
test_response = ActionController::TestResponse.new
|
45
|
+
response = yield test_request, test_response
|
46
|
+
raw_body = response.respond_to?(:body) ? response.body : response.raw_body
|
47
|
+
envelope = SOAP::Processor.unmarshal(raw_body)
|
48
|
+
if envelope
|
49
|
+
if envelope.body.response
|
50
|
+
SOAP::Mapping.soap2obj(envelope.body.response)
|
51
|
+
else
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
else
|
55
|
+
raise(SoapTestError, "empty/invalid body from server")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'action_web_service'
|
5
|
+
require 'action_controller'
|
6
|
+
require 'action_controller/test_process'
|
7
|
+
|
8
|
+
ActionController::Base.logger = nil
|
9
|
+
ActionController::Base.ignore_missing_templates = true
|
data/test/api_test.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
|
3
|
+
module APITest
|
4
|
+
class API < ActionWebService::API::Base
|
5
|
+
api_method :void
|
6
|
+
api_method :expects_and_returns, :expects_and_returns => [:string]
|
7
|
+
api_method :expects, :expects => [:int, :bool]
|
8
|
+
api_method :returns, :returns => [:int, [:string]]
|
9
|
+
api_method :named_signature, :expects => [{:appkey=>:int}, {:publish=>:bool}]
|
10
|
+
api_method :string_types, :expects => ['int', 'string', 'bool']
|
11
|
+
api_method :class_types, :expects => [TrueClass, Bignum, String]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TC_API < Test::Unit::TestCase
|
16
|
+
API = APITest::API
|
17
|
+
|
18
|
+
def test_api_method_declaration
|
19
|
+
%w(
|
20
|
+
void
|
21
|
+
expects_and_returns
|
22
|
+
expects
|
23
|
+
returns
|
24
|
+
named_signature
|
25
|
+
string_types
|
26
|
+
class_types
|
27
|
+
).each do |name|
|
28
|
+
name = name.to_sym
|
29
|
+
public_name = API.public_api_method_name(name)
|
30
|
+
assert(API.has_api_method?(name))
|
31
|
+
assert(API.has_public_api_method?(public_name))
|
32
|
+
assert(API.api_method_name(public_name) == name)
|
33
|
+
assert(API.api_methods.has_key?(name))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_signature_canonicalization
|
38
|
+
assert_equal({:expects=>nil, :returns=>nil}, API.api_methods[:void])
|
39
|
+
assert_equal({:expects=>[String], :returns=>[String]}, API.api_methods[:expects_and_returns])
|
40
|
+
assert_equal({:expects=>[Integer, TrueClass], :returns=>nil}, API.api_methods[:expects])
|
41
|
+
assert_equal({:expects=>nil, :returns=>[Integer, [String]]}, API.api_methods[:returns])
|
42
|
+
assert_equal({:expects=>[{:appkey=>Integer}, {:publish=>TrueClass}], :returns=>nil}, API.api_methods[:named_signature])
|
43
|
+
assert_equal({:expects=>[Integer, String, TrueClass], :returns=>nil}, API.api_methods[:string_types])
|
44
|
+
assert_equal({:expects=>[TrueClass, Bignum, String], :returns=>nil}, API.api_methods[:class_types])
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_not_instantiable
|
48
|
+
assert_raises(NoMethodError) do
|
49
|
+
API.new
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
+
|
3
|
+
module BaseTest
|
4
|
+
class API < ActionWebService::API::Base
|
5
|
+
api_method :add, :expects => [:int, :int], :returns => [:int]
|
6
|
+
api_method :void
|
7
|
+
end
|
8
|
+
|
9
|
+
class PristineAPI < ActionWebService::API::Base
|
10
|
+
inflect_names false
|
11
|
+
|
12
|
+
api_method :add
|
13
|
+
api_method :under_score
|
14
|
+
end
|
15
|
+
|
16
|
+
class Service < ActionWebService::Base
|
17
|
+
web_service_api API
|
18
|
+
|
19
|
+
def add(a, b)
|
20
|
+
end
|
21
|
+
|
22
|
+
def void
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class PristineService < ActionWebService::Base
|
27
|
+
web_service_api PristineAPI
|
28
|
+
|
29
|
+
def add
|
30
|
+
end
|
31
|
+
|
32
|
+
def under_score
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class TC_Base < Test::Unit::TestCase
|
38
|
+
def test_options
|
39
|
+
assert(BaseTest::PristineService.web_service_api.inflect_names == false)
|
40
|
+
assert(BaseTest::Service.web_service_api.inflect_names == true)
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_client'
|
2
|
+
|
3
|
+
|
4
|
+
module ClientSoapTest
|
5
|
+
PORT = 8998
|
6
|
+
|
7
|
+
class SoapClientLet < ClientTest::AbstractClientLet
|
8
|
+
def do_POST(req, res)
|
9
|
+
test_request = ActionController::TestRequest.new
|
10
|
+
test_request.request_parameters['action'] = req.path.gsub(/^\//, '').split(/\//)[1]
|
11
|
+
test_request.env['REQUEST_METHOD'] = "POST"
|
12
|
+
test_request.env['HTTP_CONTENTTYPE'] = 'text/xml'
|
13
|
+
test_request.env['HTTP_SOAPACTION'] = req.header['soapaction'][0]
|
14
|
+
test_request.env['RAW_POST_DATA'] = req.body
|
15
|
+
protocol_request = @controller.protocol_request(test_request)
|
16
|
+
response = @controller.dispatch_request(protocol_request)
|
17
|
+
res.header['content-type'] = 'text/xml'
|
18
|
+
res.body = response.raw_body
|
19
|
+
rescue Exception => e
|
20
|
+
$stderr.puts e.message
|
21
|
+
$stderr.puts e.backtrace.join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ClientContainer < ActionController::Base
|
26
|
+
web_client_api :client, :soap, "http://localhost:#{PORT}/client/api", :api => ClientTest::API
|
27
|
+
|
28
|
+
def get_client
|
29
|
+
client
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class SoapServer < ClientTest::AbstractServer
|
34
|
+
def create_clientlet(controller)
|
35
|
+
SoapClientLet.new(controller)
|
36
|
+
end
|
37
|
+
|
38
|
+
def server_port
|
39
|
+
PORT
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class TC_ClientSoap < Test::Unit::TestCase
|
45
|
+
include ClientTest
|
46
|
+
include ClientSoapTest
|
47
|
+
|
48
|
+
def setup
|
49
|
+
@server = SoapServer.instance
|
50
|
+
@container = @server.container
|
51
|
+
@client = ActionWebService::Client::Soap.new(API, "http://localhost:#{@server.server_port}/client/api")
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_void
|
55
|
+
assert(@container.value_void.nil?)
|
56
|
+
@client.void
|
57
|
+
assert(!@container.value_void.nil?)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_normal
|
61
|
+
assert(@container.value_normal.nil?)
|
62
|
+
assert_equal(5, @client.normal(5, 6))
|
63
|
+
assert_equal([5, 6], @container.value_normal)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_array_return
|
67
|
+
assert(@container.value_array_return.nil?)
|
68
|
+
new_person = Person.new
|
69
|
+
new_person.firstnames = ["one", "two"]
|
70
|
+
new_person.lastname = "last"
|
71
|
+
assert_equal([new_person], @client.array_return)
|
72
|
+
assert_equal([new_person], @container.value_array_return)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_struct_pass
|
76
|
+
assert(@container.value_struct_pass.nil?)
|
77
|
+
new_person = Person.new
|
78
|
+
new_person.firstnames = ["one", "two"]
|
79
|
+
new_person.lastname = "last"
|
80
|
+
assert_equal(true, @client.struct_pass([new_person]))
|
81
|
+
assert_equal([[new_person]], @container.value_struct_pass)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_client_container
|
85
|
+
assert_equal(50, ClientContainer.new.get_client.client_container)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_named_parameters
|
89
|
+
assert(@container.value_named_parameters.nil?)
|
90
|
+
assert(@client.named_parameters("key", 5).nil?)
|
91
|
+
assert_equal(["key", 5], @container.value_named_parameters)
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/abstract_client'
|
2
|
+
|
3
|
+
|
4
|
+
module ClientXmlRpcTest
|
5
|
+
PORT = 8999
|
6
|
+
|
7
|
+
class XmlRpcClientLet < ClientTest::AbstractClientLet
|
8
|
+
def do_POST(req, res)
|
9
|
+
test_request = ActionController::TestRequest.new
|
10
|
+
test_request.request_parameters['action'] = req.path.gsub(/^\//, '').split(/\//)[1]
|
11
|
+
test_request.env['REQUEST_METHOD'] = "POST"
|
12
|
+
test_request.env['HTTP_CONTENTTYPE'] = 'text/xml'
|
13
|
+
test_request.env['RAW_POST_DATA'] = req.body
|
14
|
+
protocol_request = @controller.protocol_request(test_request)
|
15
|
+
response = @controller.dispatch_request(protocol_request)
|
16
|
+
res.header['content-type'] = 'text/xml'
|
17
|
+
res.body = response.raw_body
|
18
|
+
rescue Exception => e
|
19
|
+
$stderr.puts e.message
|
20
|
+
$stderr.puts e.backtrace.join("\n")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class ClientContainer < ActionController::Base
|
25
|
+
web_client_api :client, :xmlrpc, "http://localhost:#{PORT}/client/api", :api => ClientTest::API
|
26
|
+
|
27
|
+
def get_client
|
28
|
+
client
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class XmlRpcServer < ClientTest::AbstractServer
|
33
|
+
def create_clientlet(controller)
|
34
|
+
XmlRpcClientLet.new(controller)
|
35
|
+
end
|
36
|
+
|
37
|
+
def server_port
|
38
|
+
PORT
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class TC_ClientXmlRpc < Test::Unit::TestCase
|
44
|
+
include ClientTest
|
45
|
+
include ClientXmlRpcTest
|
46
|
+
|
47
|
+
def setup
|
48
|
+
@server = XmlRpcServer.instance
|
49
|
+
@container = @server.container
|
50
|
+
@client = ActionWebService::Client::XmlRpc.new(API, "http://localhost:#{@server.server_port}/client/api")
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_void
|
54
|
+
assert(@container.value_void.nil?)
|
55
|
+
@client.void
|
56
|
+
assert(!@container.value_void.nil?)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_normal
|
60
|
+
assert(@container.value_normal.nil?)
|
61
|
+
assert_equal(5, @client.normal(5, 6))
|
62
|
+
assert_equal([5, 6], @container.value_normal)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_array_return
|
66
|
+
assert(@container.value_array_return.nil?)
|
67
|
+
new_person = Person.new
|
68
|
+
new_person.firstnames = ["one", "two"]
|
69
|
+
new_person.lastname = "last"
|
70
|
+
assert_equal([new_person], @client.array_return)
|
71
|
+
assert_equal([new_person], @container.value_array_return)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_struct_pass
|
75
|
+
assert(@container.value_struct_pass.nil?)
|
76
|
+
new_person = Person.new
|
77
|
+
new_person.firstnames = ["one", "two"]
|
78
|
+
new_person.lastname = "last"
|
79
|
+
assert_equal(true, @client.struct_pass([new_person]))
|
80
|
+
assert_equal([[new_person]], @container.value_struct_pass)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_client_container
|
84
|
+
assert_equal(50, ClientContainer.new.get_client.client_container)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_named_parameters
|
88
|
+
assert(@container.value_named_parameters.nil?)
|
89
|
+
assert_equal(true, @client.named_parameters("xxx", 7))
|
90
|
+
assert_equal(["xxx", 7], @container.value_named_parameters)
|
91
|
+
end
|
92
|
+
end
|