axtro-actionwebservice 2.3.5.1.20101118142125

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.
Files changed (85) hide show
  1. data/CHANGELOG +335 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +381 -0
  4. data/Rakefile +184 -0
  5. data/TODO +32 -0
  6. data/examples/googlesearch/README +143 -0
  7. data/examples/googlesearch/autoloading/google_search_api.rb +51 -0
  8. data/examples/googlesearch/autoloading/google_search_controller.rb +58 -0
  9. data/examples/googlesearch/delegated/google_search_service.rb +109 -0
  10. data/examples/googlesearch/delegated/search_controller.rb +8 -0
  11. data/examples/googlesearch/direct/google_search_api.rb +51 -0
  12. data/examples/googlesearch/direct/search_controller.rb +59 -0
  13. data/examples/metaWeblog/README +17 -0
  14. data/examples/metaWeblog/apis/blogger_api.rb +61 -0
  15. data/examples/metaWeblog/apis/blogger_service.rb +35 -0
  16. data/examples/metaWeblog/apis/meta_weblog_api.rb +68 -0
  17. data/examples/metaWeblog/apis/meta_weblog_service.rb +49 -0
  18. data/examples/metaWeblog/controllers/xmlrpc_controller.rb +17 -0
  19. data/generators/web_service/USAGE +28 -0
  20. data/generators/web_service/templates/api_definition.rb +6 -0
  21. data/generators/web_service/templates/controller.rb +9 -0
  22. data/generators/web_service/templates/functional_test.rb +20 -0
  23. data/generators/web_service/web_service_generator.rb +30 -0
  24. data/lib/action_web_service.rb +61 -0
  25. data/lib/action_web_service/acts_as_web_service.rb +26 -0
  26. data/lib/action_web_service/api.rb +298 -0
  27. data/lib/action_web_service/base.rb +39 -0
  28. data/lib/action_web_service/casting.rb +160 -0
  29. data/lib/action_web_service/client.rb +4 -0
  30. data/lib/action_web_service/client/base.rb +29 -0
  31. data/lib/action_web_service/client/soap_client.rb +114 -0
  32. data/lib/action_web_service/client/xmlrpc_client.rb +59 -0
  33. data/lib/action_web_service/container.rb +4 -0
  34. data/lib/action_web_service/container/action_controller_container.rb +94 -0
  35. data/lib/action_web_service/container/delegated_container.rb +87 -0
  36. data/lib/action_web_service/container/direct_container.rb +70 -0
  37. data/lib/action_web_service/dispatcher.rb +3 -0
  38. data/lib/action_web_service/dispatcher/abstract.rb +209 -0
  39. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +397 -0
  40. data/lib/action_web_service/invocation.rb +203 -0
  41. data/lib/action_web_service/protocol.rb +5 -0
  42. data/lib/action_web_service/protocol/abstract.rb +113 -0
  43. data/lib/action_web_service/protocol/discovery.rb +38 -0
  44. data/lib/action_web_service/protocol/soap_protocol.rb +177 -0
  45. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +243 -0
  46. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb~ +243 -0
  47. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +124 -0
  48. data/lib/action_web_service/scaffolding.rb +282 -0
  49. data/lib/action_web_service/simple.rb +54 -0
  50. data/lib/action_web_service/string_to_datetime_for_soap.rb +17 -0
  51. data/lib/action_web_service/struct.rb +69 -0
  52. data/lib/action_web_service/support/class_inheritable_options.rb +27 -0
  53. data/lib/action_web_service/support/signature_types.rb +262 -0
  54. data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
  55. data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
  56. data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
  57. data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
  58. data/lib/action_web_service/test_invoke.rb +111 -0
  59. data/lib/action_web_service/version.rb +11 -0
  60. data/lib/action_web_service/version.rb~ +10 -0
  61. data/lib/actionwebservice.rb +2 -0
  62. data/setup.rb +1380 -0
  63. data/test/abstract_client.rb +185 -0
  64. data/test/abstract_dispatcher.rb +550 -0
  65. data/test/abstract_unit.rb +44 -0
  66. data/test/api_test.rb +103 -0
  67. data/test/apis/auto_load_api.rb +4 -0
  68. data/test/apis/broken_auto_load_api.rb +3 -0
  69. data/test/base_test.rb +43 -0
  70. data/test/casting_test.rb +96 -0
  71. data/test/client_soap_test.rb +157 -0
  72. data/test/client_xmlrpc_test.rb +155 -0
  73. data/test/container_test.rb +76 -0
  74. data/test/dispatcher_action_controller_soap_test.rb +147 -0
  75. data/test/dispatcher_action_controller_xmlrpc_test.rb +60 -0
  76. data/test/fixtures/db_definitions/mysql.sql +8 -0
  77. data/test/fixtures/db_definitions/sqlite3.sql +8 -0
  78. data/test/fixtures/users.yml +12 -0
  79. data/test/gencov +3 -0
  80. data/test/invocation_test.rb +187 -0
  81. data/test/run +6 -0
  82. data/test/scaffolded_controller_test.rb +148 -0
  83. data/test/struct_test.rb +85 -0
  84. data/test/test_invoke_test.rb +114 -0
  85. metadata +167 -0
@@ -0,0 +1,17 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # example controller implementing both blogger and metaWeblog APIs
4
+ # in a way that should be compatible with clients supporting both/either.
5
+ #
6
+ # test by pointing your client at http://URL/xmlrpc/api
7
+ #
8
+
9
+ require 'meta_weblog_service'
10
+ require 'blogger_service'
11
+
12
+ class XmlrpcController < ApplicationController
13
+ web_service_dispatching_mode :layered
14
+
15
+ web_service :metaWeblog, MetaWeblogService.new
16
+ web_service :blogger, BloggerService.new
17
+ end
@@ -0,0 +1,28 @@
1
+ Description:
2
+ The web service generator creates the controller and API definition for
3
+ a web service.
4
+
5
+ The generator takes a web service name and a list of API methods as arguments.
6
+ The web service name may be given in CamelCase or under_score and should
7
+ contain no extra suffixes. To create a web service within a
8
+ module, specify the web service name as 'module/webservice'.
9
+
10
+ The generator creates a controller class in app/controllers, an API definition
11
+ in app/apis, and a functional test suite in test/functional.
12
+
13
+ Example:
14
+ ./script/generate web_service User add edit list remove
15
+
16
+ User web service.
17
+ Controller: app/controllers/user_controller.rb
18
+ API: app/apis/user_api.rb
19
+ Test: test/functional/user_api_test.rb
20
+
21
+ Modules Example:
22
+ ./script/generate web_service 'api/registration' register renew
23
+
24
+ Registration web service.
25
+ Controller: app/controllers/api/registration_controller.rb
26
+ API: app/apis/api/registration_api.rb
27
+ Test: test/functional/api/registration_api_test.rb
28
+
@@ -0,0 +1,6 @@
1
+ # encoding: UTF-8
2
+ class <%= class_name %>Api < ActionWebService::API::Base
3
+ <% for method_name in args -%>
4
+ api_method :<%= method_name %>
5
+ <% end -%>
6
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: UTF-8
2
+ class <%= class_name %>Controller < ApplicationController
3
+ wsdl_service_name '<%= class_name %>'
4
+ <% for method_name in args -%>
5
+
6
+ def <%= method_name %>
7
+ end
8
+ <% end -%>
9
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
3
+ require '<%= file_path %>_controller'
4
+
5
+ class <%= class_name %>Controller; def rescue_action(e) raise e end; end
6
+
7
+ class <%= class_name %>ControllerApiTest < Test::Unit::TestCase
8
+ def setup
9
+ @controller = <%= class_name %>Controller.new
10
+ @request = ActionController::TestRequest.new
11
+ @response = ActionController::TestResponse.new
12
+ end
13
+ <% for method_name in args -%>
14
+
15
+ def test_<%= method_name %>
16
+ result = invoke :<%= method_name %>
17
+ assert_equal nil, result
18
+ end
19
+ <% end -%>
20
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+ class WebServiceGenerator < Rails::Generator::NamedBase
3
+ def manifest
4
+ record do |m|
5
+ # Check for class naming collisions.
6
+ m.class_collisions class_path, "#{class_name}Api", "#{class_name}Controller", "#{class_name}ApiTest"
7
+
8
+ # API and test directories.
9
+ m.directory File.join('app/services', class_path)
10
+ m.directory File.join('app/controllers', class_path)
11
+ m.directory File.join('test/functional', class_path)
12
+
13
+ # API definition, controller, and functional test.
14
+ m.template 'api_definition.rb',
15
+ File.join('app/services',
16
+ class_path,
17
+ "#{file_name}_api.rb")
18
+
19
+ m.template 'controller.rb',
20
+ File.join('app/controllers',
21
+ class_path,
22
+ "#{file_name}_controller.rb")
23
+
24
+ m.template 'functional_test.rb',
25
+ File.join('test/functional',
26
+ class_path,
27
+ "#{file_name}_api_test.rb")
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (C) 2005 Leon Breedt
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.
23
+ #++
24
+
25
+ begin
26
+ require 'active_support'
27
+ require 'action_controller'
28
+ require 'active_record'
29
+ rescue LoadError
30
+ require 'rubygems'
31
+ gem 'activesupport'
32
+ gem 'actionpack'
33
+ gem 'activerecord'
34
+ end
35
+
36
+ $:.unshift(File.dirname(__FILE__) + "/action_web_service/vendor/")
37
+
38
+ require 'action_web_service/string_to_datetime_for_soap'
39
+ require 'action_web_service/support/class_inheritable_options'
40
+ require 'action_web_service/support/signature_types'
41
+ require 'action_web_service/base'
42
+ require 'action_web_service/client'
43
+ require 'action_web_service/invocation'
44
+ require 'action_web_service/api'
45
+ require 'action_web_service/casting'
46
+ require 'action_web_service/simple'
47
+ require 'action_web_service/struct'
48
+ require 'action_web_service/container'
49
+ require 'action_web_service/protocol'
50
+ require 'action_web_service/dispatcher'
51
+ require 'action_web_service/scaffolding'
52
+ require 'action_web_service/acts_as_web_service'
53
+
54
+ ActionWebService::Base.class_eval do
55
+ include ActionWebService::Container::Direct
56
+ include ActionWebService::Invocation
57
+ end
58
+
59
+ ActionController::Base.class_eval do
60
+ include ActionWebService::ActsAsWebService
61
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: UTF-8
2
+ module ActionWebService
3
+ module ActsAsWebService
4
+
5
+ def self.included(base) # :nodoc:
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ # Add this to your controller to include all ActionWebservice
11
+ def acts_as_web_service
12
+ include ActionWebService::Protocol::Discovery
13
+ include ActionWebService::Protocol::Soap
14
+ include ActionWebService::Protocol::XmlRpc
15
+ include ActionWebService::Container::Direct
16
+ include ActionWebService::Container::Delegated
17
+ include ActionWebService::Container::ActionController
18
+ include ActionWebService::Invocation
19
+ include ActionWebService::Dispatcher
20
+ include ActionWebService::Dispatcher::ActionController
21
+ include ActionWebService::Dispatcher::ActionController::WsdlAction
22
+ include ActionWebService::Scaffolding
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,298 @@
1
+ # encoding: UTF-8
2
+ module ActionWebService # :nodoc:
3
+ module API # :nodoc:
4
+ # A web service API class specifies the methods that will be available for
5
+ # invocation for an API. It also contains metadata such as the method type
6
+ # signature hints.
7
+ #
8
+ # It is not intended to be instantiated.
9
+ #
10
+ # It is attached to web service implementation classes like
11
+ # ActionWebService::Base and ActionController::Base derivatives by using
12
+ # <tt>container.web_service_api</tt>, where <tt>container</tt> is an
13
+ # ActionController::Base or a ActionWebService::Base.
14
+ #
15
+ # See ActionWebService::Container::Direct::ClassMethods for an example
16
+ # of use.
17
+ class Base
18
+ # Whether to transform the public API method names into camel-cased names
19
+ class_inheritable_option :inflect_names, true
20
+
21
+ # By default only HTTP POST requests are processed
22
+ class_inheritable_option :allowed_http_methods, [ :post ]
23
+
24
+ # Whether to allow ActiveRecord::Base models in <tt>:expects</tt>.
25
+ # The default is +false+; you should be aware of the security implications
26
+ # of allowing this, and ensure that you don't allow remote callers to
27
+ # easily overwrite data they should not have access to.
28
+ class_inheritable_option :allow_active_record_expects, false
29
+
30
+ # If present, the name of a method to call when the remote caller
31
+ # tried to call a nonexistent method. Semantically equivalent to
32
+ # +method_missing+.
33
+ class_inheritable_option :default_api_method
34
+
35
+ # Disallow instantiation
36
+ private_class_method :new, :allocate
37
+
38
+ class << self
39
+ include ActionWebService::SignatureTypes
40
+
41
+ # API methods have a +name+, which must be the Ruby method name to use when
42
+ # performing the invocation on the web service object.
43
+ #
44
+ # The signatures for the method input parameters and return value can
45
+ # by specified in +options+.
46
+ #
47
+ # A signature is an array of one or more parameter specifiers.
48
+ # A parameter specifier can be one of the following:
49
+ #
50
+ # * A symbol or string representing one of the Action Web Service base types.
51
+ # See ActionWebService::SignatureTypes for a canonical list of the base types.
52
+ # * The Class object of the parameter type
53
+ # * A single-element Array containing one of the two preceding items. This
54
+ # will cause Action Web Service to treat the parameter at that position
55
+ # as an array containing only values of the given type.
56
+ # * A Hash containing as key the name of the parameter, and as value
57
+ # one of the three preceding items
58
+ #
59
+ # If no method input parameter or method return value signatures are given,
60
+ # the method is assumed to take no parameters and/or return no values of
61
+ # interest, and any values that are received by the server will be
62
+ # discarded and ignored.
63
+ #
64
+ # Valid options:
65
+ # [<tt>:expects</tt>] Signature for the method input parameters
66
+ # [<tt>:returns</tt>] Signature for the method return value
67
+ # [<tt>:expects_and_returns</tt>] Signature for both input parameters and return value
68
+ def api_method(name, options={})
69
+ unless options.is_a?(Hash)
70
+ raise(ActionWebServiceError, "Expected a Hash for options")
71
+ end
72
+ validate_options([:expects, :returns, :expects_and_returns], options.keys)
73
+ if options[:expects_and_returns]
74
+ expects = options[:expects_and_returns]
75
+ returns = options[:expects_and_returns]
76
+ else
77
+ expects = options[:expects]
78
+ returns = options[:returns]
79
+ end
80
+ expects = canonical_signature(expects)
81
+ returns = canonical_signature(returns)
82
+ if expects
83
+ expects.each do |type|
84
+ type = type.element_type if type.is_a?(ArrayType)
85
+ if type.type_class.ancestors.include?(ActiveRecord::Base) && !allow_active_record_expects
86
+ raise(ActionWebServiceError, "ActiveRecord model classes not allowed in :expects")
87
+ end
88
+ end
89
+ end
90
+ name = name.to_sym
91
+ public_name = public_api_method_name(name)
92
+ method = Method.new(name, public_name, expects, returns)
93
+ write_inheritable_hash("api_methods", name => method)
94
+ write_inheritable_hash("api_public_method_names", public_name => name)
95
+ end
96
+
97
+ # Whether the given method name is a service method on this API
98
+ #
99
+ # class ProjectsApi < ActionWebService::API::Base
100
+ # api_method :getCount, :returns => [:int]
101
+ # end
102
+ #
103
+ # ProjectsApi.has_api_method?('GetCount') #=> false
104
+ # ProjectsApi.has_api_method?(:getCount) #=> true
105
+ def has_api_method?(name)
106
+ api_methods.has_key?(name)
107
+ end
108
+
109
+ # Whether the given public method name has a corresponding service method
110
+ # on this API
111
+ #
112
+ # class ProjectsApi < ActionWebService::API::Base
113
+ # api_method :getCount, :returns => [:int]
114
+ # end
115
+ #
116
+ # ProjectsApi.has_api_method?(:getCount) #=> false
117
+ # ProjectsApi.has_api_method?('GetCount') #=> true
118
+ def has_public_api_method?(public_name)
119
+ api_public_method_names.has_key?(public_name)
120
+ end
121
+
122
+ # The corresponding public method name for the given service method name
123
+ #
124
+ # ProjectsApi.public_api_method_name('GetCount') #=> "GetCount"
125
+ # ProjectsApi.public_api_method_name(:getCount) #=> "GetCount"
126
+ def public_api_method_name(name)
127
+ if inflect_names
128
+ name.to_s.camelize
129
+ else
130
+ name.to_s
131
+ end
132
+ end
133
+
134
+ # The corresponding service method name for the given public method name
135
+ #
136
+ # class ProjectsApi < ActionWebService::API::Base
137
+ # api_method :getCount, :returns => [:int]
138
+ # end
139
+ #
140
+ # ProjectsApi.api_method_name('GetCount') #=> :getCount
141
+ def api_method_name(public_name)
142
+ api_public_method_names[public_name]
143
+ end
144
+
145
+ # A Hash containing all service methods on this API, and their
146
+ # associated metadata.
147
+ #
148
+ # class ProjectsApi < ActionWebService::API::Base
149
+ # api_method :getCount, :returns => [:int]
150
+ # api_method :getCompletedCount, :returns => [:int]
151
+ # end
152
+ #
153
+ # ProjectsApi.api_methods #=>
154
+ # {:getCount=>#<ActionWebService::API::Method:0x24379d8 ...>,
155
+ # :getCompletedCount=>#<ActionWebService::API::Method:0x2437794 ...>}
156
+ # ProjectsApi.api_methods[:getCount].public_name #=> "GetCount"
157
+ def api_methods
158
+ read_inheritable_attribute("api_methods") || {}
159
+ end
160
+
161
+ # The Method instance for the given public API method name, if any
162
+ #
163
+ # class ProjectsApi < ActionWebService::API::Base
164
+ # api_method :getCount, :returns => [:int]
165
+ # api_method :getCompletedCount, :returns => [:int]
166
+ # end
167
+ #
168
+ # ProjectsApi.public_api_method_instance('GetCount') #=> <#<ActionWebService::API::Method:0x24379d8 ...>
169
+ # ProjectsApi.public_api_method_instance(:getCount) #=> nil
170
+ def public_api_method_instance(public_method_name)
171
+ api_method_instance(api_method_name(public_method_name))
172
+ end
173
+
174
+ # The Method instance for the given API method name, if any
175
+ #
176
+ # class ProjectsApi < ActionWebService::API::Base
177
+ # api_method :getCount, :returns => [:int]
178
+ # api_method :getCompletedCount, :returns => [:int]
179
+ # end
180
+ #
181
+ # ProjectsApi.api_method_instance(:getCount) #=> <ActionWebService::API::Method:0x24379d8 ...>
182
+ # ProjectsApi.api_method_instance('GetCount') #=> <ActionWebService::API::Method:0x24379d8 ...>
183
+ def api_method_instance(method_name)
184
+ api_methods[method_name]
185
+ end
186
+
187
+ # The Method instance for the default API method, if any
188
+ def default_api_method_instance
189
+ return nil unless name = default_api_method
190
+ instance = read_inheritable_attribute("default_api_method_instance")
191
+ if instance && instance.name == name
192
+ return instance
193
+ end
194
+ instance = Method.new(name, public_api_method_name(name), nil, nil)
195
+ write_inheritable_attribute("default_api_method_instance", instance)
196
+ instance
197
+ end
198
+
199
+ private
200
+ def api_public_method_names
201
+ read_inheritable_attribute("api_public_method_names") || {}
202
+ end
203
+
204
+ def validate_options(valid_option_keys, supplied_option_keys)
205
+ unknown_option_keys = supplied_option_keys - valid_option_keys
206
+ unless unknown_option_keys.empty?
207
+ raise(ActionWebServiceError, "Unknown options: #{unknown_option_keys}")
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ # Represents an API method and its associated metadata, and provides functionality
214
+ # to assist in commonly performed API method tasks.
215
+ class Method
216
+ attr :name
217
+ attr :public_name
218
+ attr :expects
219
+ attr :returns
220
+
221
+ def initialize(name, public_name, expects, returns)
222
+ @name = name
223
+ @public_name = public_name
224
+ @expects = expects
225
+ @returns = returns
226
+ @caster = ActionWebService::Casting::BaseCaster.new(self)
227
+ end
228
+
229
+ # The list of parameter names for this method
230
+ def param_names
231
+ return [] unless @expects
232
+ @expects.map{ |type| type.name }
233
+ end
234
+
235
+ # Casts a set of Ruby values into the expected Ruby values
236
+ def cast_expects(params)
237
+ @caster.cast_expects(params)
238
+ end
239
+
240
+ # Cast a Ruby return value into the expected Ruby value
241
+ def cast_returns(return_value)
242
+ @caster.cast_returns(return_value)
243
+ end
244
+
245
+ # Returns the index of the first expected parameter
246
+ # with the given name
247
+ def expects_index_of(param_name)
248
+ return -1 if @expects.nil?
249
+ (0..(@expects.length-1)).each do |i|
250
+ return i if @expects[i].name.to_s == param_name.to_s
251
+ end
252
+ -1
253
+ end
254
+
255
+ # Returns a hash keyed by parameter name for the given
256
+ # parameter list
257
+ def expects_to_hash(params)
258
+ return {} if @expects.nil?
259
+ h = {}
260
+ @expects.zip(params){ |type, param| h[type.name] = param }
261
+ h
262
+ end
263
+
264
+ # Backwards compatibility with previous API
265
+ def [](sig_type)
266
+ case sig_type
267
+ when :expects
268
+ @expects.map{|x| compat_signature_entry(x)}
269
+ when :returns
270
+ @returns.map{|x| compat_signature_entry(x)}
271
+ end
272
+ end
273
+
274
+ # String representation of this method
275
+ def to_s
276
+ fqn = ""
277
+ fqn << (@returns ? (@returns[0].human_name(false) + " ") : "void ")
278
+ fqn << "#{@public_name}("
279
+ fqn << @expects.map{ |p| p.human_name }.join(", ") if @expects
280
+ fqn << ")"
281
+ fqn
282
+ end
283
+
284
+ private
285
+ def compat_signature_entry(entry)
286
+ if entry.array?
287
+ [compat_signature_entry(entry.element_type)]
288
+ else
289
+ if entry.spec.is_a?(Hash)
290
+ {entry.spec.keys.first => entry.type_class}
291
+ else
292
+ entry.type_class
293
+ end
294
+ end
295
+ end
296
+ end
297
+ end
298
+ end