pelle-actionwebservice 2.3.3

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 (79) hide show
  1. data/CHANGELOG +320 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +381 -0
  4. data/Rakefile +173 -0
  5. data/TODO +32 -0
  6. data/examples/googlesearch/README +143 -0
  7. data/examples/googlesearch/autoloading/google_search_api.rb +50 -0
  8. data/examples/googlesearch/autoloading/google_search_controller.rb +57 -0
  9. data/examples/googlesearch/delegated/google_search_service.rb +108 -0
  10. data/examples/googlesearch/delegated/search_controller.rb +7 -0
  11. data/examples/googlesearch/direct/google_search_api.rb +50 -0
  12. data/examples/googlesearch/direct/search_controller.rb +58 -0
  13. data/examples/metaWeblog/README +17 -0
  14. data/examples/metaWeblog/apis/blogger_api.rb +60 -0
  15. data/examples/metaWeblog/apis/blogger_service.rb +34 -0
  16. data/examples/metaWeblog/apis/meta_weblog_api.rb +67 -0
  17. data/examples/metaWeblog/apis/meta_weblog_service.rb +48 -0
  18. data/examples/metaWeblog/controllers/xmlrpc_controller.rb +16 -0
  19. data/generators/web_service/USAGE +28 -0
  20. data/generators/web_service/templates/api_definition.rb +5 -0
  21. data/generators/web_service/templates/controller.rb +8 -0
  22. data/generators/web_service/templates/functional_test.rb +19 -0
  23. data/generators/web_service/web_service_generator.rb +29 -0
  24. data/lib/action_web_service/api.rb +297 -0
  25. data/lib/action_web_service/base.rb +38 -0
  26. data/lib/action_web_service/casting.rb +149 -0
  27. data/lib/action_web_service/client/base.rb +28 -0
  28. data/lib/action_web_service/client/soap_client.rb +113 -0
  29. data/lib/action_web_service/client/xmlrpc_client.rb +58 -0
  30. data/lib/action_web_service/client.rb +3 -0
  31. data/lib/action_web_service/container/action_controller_container.rb +93 -0
  32. data/lib/action_web_service/container/delegated_container.rb +86 -0
  33. data/lib/action_web_service/container/direct_container.rb +69 -0
  34. data/lib/action_web_service/container.rb +3 -0
  35. data/lib/action_web_service/dispatcher/abstract.rb +207 -0
  36. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +379 -0
  37. data/lib/action_web_service/dispatcher.rb +2 -0
  38. data/lib/action_web_service/invocation.rb +202 -0
  39. data/lib/action_web_service/protocol/abstract.rb +112 -0
  40. data/lib/action_web_service/protocol/discovery.rb +37 -0
  41. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +242 -0
  42. data/lib/action_web_service/protocol/soap_protocol.rb +176 -0
  43. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +122 -0
  44. data/lib/action_web_service/protocol.rb +4 -0
  45. data/lib/action_web_service/scaffolding.rb +281 -0
  46. data/lib/action_web_service/struct.rb +64 -0
  47. data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
  48. data/lib/action_web_service/support/signature_types.rb +226 -0
  49. data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
  50. data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
  51. data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
  52. data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
  53. data/lib/action_web_service/test_invoke.rb +110 -0
  54. data/lib/action_web_service/version.rb +9 -0
  55. data/lib/action_web_service.rb +66 -0
  56. data/lib/actionwebservice.rb +1 -0
  57. data/setup.rb +1379 -0
  58. data/test/abstract_client.rb +183 -0
  59. data/test/abstract_dispatcher.rb +548 -0
  60. data/test/abstract_unit.rb +39 -0
  61. data/test/api_test.rb +102 -0
  62. data/test/apis/auto_load_api.rb +3 -0
  63. data/test/apis/broken_auto_load_api.rb +2 -0
  64. data/test/base_test.rb +42 -0
  65. data/test/casting_test.rb +94 -0
  66. data/test/client_soap_test.rb +155 -0
  67. data/test/client_xmlrpc_test.rb +153 -0
  68. data/test/container_test.rb +73 -0
  69. data/test/dispatcher_action_controller_soap_test.rb +138 -0
  70. data/test/dispatcher_action_controller_xmlrpc_test.rb +59 -0
  71. data/test/fixtures/db_definitions/mysql.sql +8 -0
  72. data/test/fixtures/users.yml +12 -0
  73. data/test/gencov +3 -0
  74. data/test/invocation_test.rb +185 -0
  75. data/test/run +6 -0
  76. data/test/scaffolded_controller_test.rb +146 -0
  77. data/test/struct_test.rb +52 -0
  78. data/test/test_invoke_test.rb +112 -0
  79. metadata +171 -0
@@ -0,0 +1,281 @@
1
+ require 'benchmark'
2
+ require 'pathname'
3
+
4
+ module ActionWebService
5
+ module Scaffolding # :nodoc:
6
+ class ScaffoldingError < ActionWebServiceError # :nodoc:
7
+ end
8
+
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+
13
+ # Web service invocation scaffolding provides a way to quickly invoke web service methods in a controller. The
14
+ # generated scaffold actions have default views to let you enter the method parameters and view the
15
+ # results.
16
+ #
17
+ # Example:
18
+ #
19
+ # class ApiController < ActionController
20
+ # web_service_scaffold :invoke
21
+ # end
22
+ #
23
+ # This example generates an +invoke+ action in the +ApiController+ that you can navigate to from
24
+ # your browser, select the API method, enter its parameters, and perform the invocation.
25
+ #
26
+ # If you want to customize the default views, create the following views in "app/views":
27
+ #
28
+ # * <tt>action_name/methods.html.erb</tt>
29
+ # * <tt>action_name/parameters.html.erb</tt>
30
+ # * <tt>action_name/result.html.erb</tt>
31
+ # * <tt>action_name/layout.html.erb</tt>
32
+ #
33
+ # Where <tt>action_name</tt> is the name of the action you gave to ClassMethods#web_service_scaffold.
34
+ #
35
+ # You can use the default views in <tt>RAILS_DIR/lib/action_web_service/templates/scaffolds</tt> as
36
+ # a guide.
37
+ module ClassMethods
38
+ # Generates web service invocation scaffolding for the current controller. The given action name
39
+ # can then be used as the entry point for invoking API methods from a web browser.
40
+ def web_service_scaffold(action_name)
41
+ add_template_helper(Helpers)
42
+ module_eval <<-"end_eval", __FILE__, __LINE__ + 1
43
+ def #{action_name}
44
+ if request.method == :get
45
+ setup_invocation_assigns
46
+ render_invocation_scaffold 'methods'
47
+ end
48
+ end
49
+
50
+ def #{action_name}_method_params
51
+ if request.method == :get
52
+ setup_invocation_assigns
53
+ render_invocation_scaffold 'parameters'
54
+ end
55
+ end
56
+
57
+ def #{action_name}_submit
58
+ if request.method == :post
59
+ setup_invocation_assigns
60
+ protocol_name = params['protocol'] ? params['protocol'].to_sym : :soap
61
+ case protocol_name
62
+ when :soap
63
+ @protocol = Protocol::Soap::SoapProtocol.create(self)
64
+ when :xmlrpc
65
+ @protocol = Protocol::XmlRpc::XmlRpcProtocol.create(self)
66
+ end
67
+ bm = Benchmark.measure do
68
+ @protocol.register_api(@scaffold_service.api)
69
+ post_params = params['method_params'] ? params['method_params'].dup : nil
70
+ params = []
71
+ @scaffold_method.expects.each_with_index do |spec, i|
72
+ params << post_params[i.to_s]
73
+ end if @scaffold_method.expects
74
+ params = @scaffold_method.cast_expects(params)
75
+ method_name = public_method_name(@scaffold_service.name, @scaffold_method.public_name)
76
+ @method_request_xml = @protocol.encode_request(method_name, params, @scaffold_method.expects)
77
+ new_request = @protocol.encode_action_pack_request(@scaffold_service.name, @scaffold_method.public_name, @method_request_xml)
78
+ prepare_request(new_request, @scaffold_service.name, @scaffold_method.public_name)
79
+ self.request = new_request
80
+ if @scaffold_container.dispatching_mode != :direct
81
+ request.parameters['action'] = @scaffold_service.name
82
+ end
83
+ dispatch_web_service_request
84
+ @method_response_xml = response.body
85
+ method_name, obj = @protocol.decode_response(@method_response_xml)
86
+ return if handle_invocation_exception(obj)
87
+ @method_return_value = @scaffold_method.cast_returns(obj)
88
+ end
89
+ @method_elapsed = bm.real
90
+ reset_invocation_response
91
+ render_invocation_scaffold 'result'
92
+ end
93
+ end
94
+
95
+ private
96
+ def setup_invocation_assigns
97
+ @scaffold_class = self.class
98
+ @scaffold_action_name = "#{action_name}"
99
+ @scaffold_container = WebServiceModel::Container.new(self)
100
+ if params['service'] && params['method']
101
+ @scaffold_service = @scaffold_container.services.find{ |x| x.name == params['service'] }
102
+ @scaffold_method = @scaffold_service.api_methods[params['method']]
103
+ end
104
+ end
105
+
106
+ def render_invocation_scaffold(action)
107
+ customized_template = "\#{self.class.controller_path}/#{action_name}/\#{action}"
108
+ default_template = scaffold_path(action)
109
+ begin
110
+ content = @template.render(:file => customized_template)
111
+ rescue ActionView::MissingTemplate
112
+ content = @template.render(:file => default_template)
113
+ end
114
+ @template.instance_variable_set("@content_for_layout", content)
115
+ if self.active_layout.nil?
116
+ render :file => scaffold_path("layout")
117
+ else
118
+ render :file => self.active_layout, :use_full_path => true
119
+ end
120
+ end
121
+
122
+ def scaffold_path(template_name)
123
+ File.dirname(__FILE__) + "/templates/scaffolds/" + template_name + ".html.erb"
124
+ end
125
+
126
+ def reset_invocation_response
127
+ erase_render_results
128
+ response.instance_variable_set :@header, Rack::Utils::HeaderHash.new(::ActionController::Response::DEFAULT_HEADERS.merge("cookie" => []))
129
+ end
130
+
131
+ def public_method_name(service_name, method_name)
132
+ if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::XmlRpc::XmlRpcProtocol)
133
+ service_name + '.' + method_name
134
+ else
135
+ method_name
136
+ end
137
+ end
138
+
139
+ def prepare_request(new_request, service_name, method_name)
140
+ new_request.parameters.update(request.parameters)
141
+ request.env.each{ |k, v| new_request.env[k] = v unless new_request.env.has_key?(k) }
142
+ if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::Soap::SoapProtocol)
143
+ new_request.env['HTTP_SOAPACTION'] = "/\#{controller_name()}/\#{service_name}/\#{method_name}"
144
+ end
145
+ end
146
+
147
+ def handle_invocation_exception(obj)
148
+ exception = nil
149
+ if obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && obj.detail.cause.is_a?(Exception)
150
+ exception = obj.detail.cause
151
+ elsif obj.is_a?(XMLRPC::FaultException)
152
+ exception = obj
153
+ end
154
+ return unless exception
155
+ reset_invocation_response
156
+ rescue_action(exception)
157
+ true
158
+ end
159
+ end_eval
160
+ end
161
+ end
162
+
163
+ module Helpers # :nodoc:
164
+ def method_parameter_input_fields(method, type, field_name_base, idx, was_structured=false)
165
+ if type.array?
166
+ return content_tag('em', "Typed array input fields not supported yet (#{type.name})")
167
+ end
168
+ if type.structured?
169
+ return content_tag('em', "Nested structural types not supported yet (#{type.name})") if was_structured
170
+ parameters = ""
171
+ type.each_member do |member_name, member_type|
172
+ label = method_parameter_label(member_name, member_type)
173
+ nested_content = method_parameter_input_fields(
174
+ method,
175
+ member_type,
176
+ "#{field_name_base}[#{idx}][#{member_name}]",
177
+ idx,
178
+ true)
179
+ if member_type.custom?
180
+ parameters << content_tag('li', label)
181
+ parameters << content_tag('ul', nested_content)
182
+ else
183
+ parameters << content_tag('li', label + ' ' + nested_content)
184
+ end
185
+ end
186
+ content_tag('ul', parameters)
187
+ else
188
+ # If the data source was structured previously we already have the index set
189
+ field_name_base = "#{field_name_base}[#{idx}]" unless was_structured
190
+
191
+ case type.type
192
+ when :int
193
+ text_field_tag "#{field_name_base}"
194
+ when :string
195
+ text_field_tag "#{field_name_base}"
196
+ when :base64
197
+ text_area_tag "#{field_name_base}", nil, :size => "40x5"
198
+ when :bool
199
+ radio_button_tag("#{field_name_base}", "true") + " True" +
200
+ radio_button_tag("#{field_name_base}", "false") + "False"
201
+ when :float
202
+ text_field_tag "#{field_name_base}"
203
+ when :time, :datetime
204
+ time = Time.now
205
+ i = 0
206
+ %w|year month day hour minute second|.map do |name|
207
+ i += 1
208
+ send("select_#{name}", time, :prefix => "#{field_name_base}[#{i}]", :discard_type => true)
209
+ end.join
210
+ when :date
211
+ date = Date.today
212
+ i = 0
213
+ %w|year month day|.map do |name|
214
+ i += 1
215
+ send("select_#{name}", date, :prefix => "#{field_name_base}[#{i}]", :discard_type => true)
216
+ end.join
217
+ end
218
+ end
219
+ end
220
+
221
+ def method_parameter_label(name, type)
222
+ name.to_s.capitalize + ' (' + type.human_name(false) + ')'
223
+ end
224
+
225
+ def service_method_list(service)
226
+ action = @scaffold_action_name + '_method_params'
227
+ methods = service.api_methods_full.map do |desc, name|
228
+ content_tag("li", link_to(desc, :action => action, :service => service.name, :method => name))
229
+ end
230
+ content_tag("ul", methods.join("\n"))
231
+ end
232
+ end
233
+
234
+ module WebServiceModel # :nodoc:
235
+ class Container # :nodoc:
236
+ attr :services
237
+ attr :dispatching_mode
238
+
239
+ def initialize(real_container)
240
+ @real_container = real_container
241
+ @dispatching_mode = @real_container.class.web_service_dispatching_mode
242
+ @services = []
243
+ if @dispatching_mode == :direct
244
+ @services << Service.new(@real_container.controller_name, @real_container)
245
+ else
246
+ @real_container.class.web_services.each do |name, obj|
247
+ @services << Service.new(name, @real_container.instance_eval{ web_service_object(name) })
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ class Service # :nodoc:
254
+ attr :name
255
+ attr :object
256
+ attr :api
257
+ attr :api_methods
258
+ attr :api_methods_full
259
+
260
+ def initialize(name, real_service)
261
+ @name = name.to_s
262
+ @object = real_service
263
+ @api = @object.class.web_service_api
264
+ if @api.nil?
265
+ raise ScaffoldingError, "No web service API attached to #{object.class}"
266
+ end
267
+ @api_methods = {}
268
+ @api_methods_full = []
269
+ @api.api_methods.each do |name, method|
270
+ @api_methods[method.public_name.to_s] = method
271
+ @api_methods_full << [method.to_s, method.public_name.to_s]
272
+ end
273
+ end
274
+
275
+ def to_s
276
+ self.name.camelize
277
+ end
278
+ end
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,64 @@
1
+ module ActionWebService
2
+ # To send structured types across the wire, derive from ActionWebService::Struct,
3
+ # and use +member+ to declare structure members.
4
+ #
5
+ # ActionWebService::Struct should be used in method signatures when you want to accept or return
6
+ # structured types that have no Active Record model class representations, or you don't
7
+ # want to expose your entire Active Record model to remote callers.
8
+ #
9
+ # === Example
10
+ #
11
+ # class Person < ActionWebService::Struct
12
+ # member :id, :int
13
+ # member :firstnames, [:string]
14
+ # member :lastname, :string
15
+ # member :email, :string
16
+ # end
17
+ # person = Person.new(:id => 5, :firstname => 'john', :lastname => 'doe')
18
+ #
19
+ # Active Record model classes are already implicitly supported in method
20
+ # signatures.
21
+ class Struct
22
+ # If a Hash is given as argument to an ActionWebService::Struct constructor,
23
+ # it can contain initial values for the structure member.
24
+ def initialize(values={})
25
+ if values.is_a?(Hash)
26
+ values.map{|k,v| __send__('%s=' % k.to_s, v)}
27
+ end
28
+ end
29
+
30
+ # The member with the given name
31
+ def [](name)
32
+ send(name.to_s)
33
+ end
34
+
35
+ # Iterates through each member
36
+ def each_pair(&block)
37
+ self.class.members.each do |name, type|
38
+ yield name, self.__send__(name)
39
+ end
40
+ end
41
+
42
+ class << self
43
+ # Creates a structure member with the specified +name+ and +type+. Generates
44
+ # accessor methods for reading and writing the member value.
45
+ def member(name, type)
46
+ name = name.to_sym
47
+ type = ActionWebService::SignatureTypes.canonical_signature_entry({ name => type }, 0)
48
+ write_inheritable_hash("struct_members", name => type)
49
+ class_eval <<-END
50
+ def #{name}; @#{name}; end
51
+ def #{name}=(value); @#{name} = value; end
52
+ END
53
+ end
54
+
55
+ def members # :nodoc:
56
+ read_inheritable_attribute("struct_members") || {}
57
+ end
58
+
59
+ def member_type(name) # :nodoc:
60
+ members[name.to_sym]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,26 @@
1
+ class Class # :nodoc:
2
+ def class_inheritable_option(sym, default_value=nil)
3
+ write_inheritable_attribute sym, default_value
4
+ class_eval <<-EOS
5
+ def self.#{sym}(value=nil)
6
+ if !value.nil?
7
+ write_inheritable_attribute(:#{sym}, value)
8
+ else
9
+ read_inheritable_attribute(:#{sym})
10
+ end
11
+ end
12
+
13
+ def self.#{sym}=(value)
14
+ write_inheritable_attribute(:#{sym}, value)
15
+ end
16
+
17
+ def #{sym}
18
+ self.class.#{sym}
19
+ end
20
+
21
+ def #{sym}=(value)
22
+ self.class.#{sym} = value
23
+ end
24
+ EOS
25
+ end
26
+ end
@@ -0,0 +1,226 @@
1
+ module ActionWebService # :nodoc:
2
+ # Action Web Service supports the following base types in a signature:
3
+ #
4
+ # [<tt>:int</tt>] Represents an integer value, will be cast to an integer using <tt>Integer(value)</tt>
5
+ # [<tt>:string</tt>] Represents a string value, will be cast to an string using the <tt>to_s</tt> method on an object
6
+ # [<tt>:base64</tt>] Represents a Base 64 value, will contain the binary bytes of a Base 64 value sent by the caller
7
+ # [<tt>:bool</tt>] Represents a boolean value, whatever is passed will be cast to boolean (<tt>true</tt>, '1', 'true', 'y', 'yes' are taken to represent true; <tt>false</tt>, '0', 'false', 'n', 'no' and <tt>nil</tt> represent false)
8
+ # [<tt>:float</tt>] Represents a floating point value, will be cast to a float using <tt>Float(value)</tt>
9
+ # [<tt>:time</tt>] Represents a timestamp, will be cast to a <tt>Time</tt> object
10
+ # [<tt>:datetime</tt>] Represents a timestamp, will be cast to a <tt>DateTime</tt> object
11
+ # [<tt>:date</tt>] Represents a date, will be cast to a <tt>Date</tt> object
12
+ #
13
+ # For structured types, you'll need to pass in the Class objects of
14
+ # ActionWebService::Struct and ActiveRecord::Base derivatives.
15
+ module SignatureTypes
16
+ def canonical_signature(signature) # :nodoc:
17
+ return nil if signature.nil?
18
+ unless signature.is_a?(Array)
19
+ raise(ActionWebServiceError, "Expected signature to be an Array")
20
+ end
21
+ i = -1
22
+ signature.map{ |spec| canonical_signature_entry(spec, i += 1) }
23
+ end
24
+
25
+ def canonical_signature_entry(spec, i) # :nodoc:
26
+ orig_spec = spec
27
+ name = "param#{i}"
28
+ if spec.is_a?(Hash)
29
+ name, spec = spec.keys.first, spec.values.first
30
+ end
31
+ type = spec
32
+ if spec.is_a?(Array)
33
+ ArrayType.new(orig_spec, canonical_signature_entry(spec[0], 0), name)
34
+ else
35
+ type = canonical_type(type)
36
+ if type.is_a?(Symbol)
37
+ BaseType.new(orig_spec, type, name)
38
+ else
39
+ StructuredType.new(orig_spec, type, name)
40
+ end
41
+ end
42
+ end
43
+
44
+ def canonical_type(type) # :nodoc:
45
+ type_name = symbol_name(type) || class_to_type_name(type)
46
+ type = type_name || type
47
+ return canonical_type_name(type) if type.is_a?(Symbol)
48
+ type
49
+ end
50
+
51
+ def canonical_type_name(name) # :nodoc:
52
+ name = name.to_sym
53
+ case name
54
+ when :int, :integer, :fixnum, :bignum
55
+ :int
56
+ when :string, :text
57
+ :string
58
+ when :base64, :binary
59
+ :base64
60
+ when :bool, :boolean
61
+ :bool
62
+ when :float, :double
63
+ :float
64
+ when :decimal
65
+ :decimal
66
+ when :time, :timestamp
67
+ :time
68
+ when :datetime
69
+ :datetime
70
+ when :date
71
+ :date
72
+ else
73
+ raise(TypeError, "#{name} is not a valid base type")
74
+ end
75
+ end
76
+
77
+ def canonical_type_class(type) # :nodoc:
78
+ type = canonical_type(type)
79
+ type.is_a?(Symbol) ? type_name_to_class(type) : type
80
+ end
81
+
82
+ def symbol_name(name) # :nodoc:
83
+ return name.to_sym if name.is_a?(Symbol) || name.is_a?(String)
84
+ nil
85
+ end
86
+
87
+ def class_to_type_name(klass) # :nodoc:
88
+ klass = klass.class unless klass.is_a?(Class)
89
+ if derived_from?(Integer, klass) || derived_from?(Fixnum, klass) || derived_from?(Bignum, klass)
90
+ :int
91
+ elsif klass == String
92
+ :string
93
+ elsif klass == Base64
94
+ :base64
95
+ elsif klass == TrueClass || klass == FalseClass
96
+ :bool
97
+ elsif derived_from?(Float, klass) || derived_from?(Precision, klass) || derived_from?(Numeric, klass)
98
+ :float
99
+ elsif klass == Time
100
+ :time
101
+ elsif klass == DateTime
102
+ :datetime
103
+ elsif klass == Date
104
+ :date
105
+ else
106
+ nil
107
+ end
108
+ end
109
+
110
+ def type_name_to_class(name) # :nodoc:
111
+ case canonical_type_name(name)
112
+ when :int
113
+ Integer
114
+ when :string
115
+ String
116
+ when :base64
117
+ Base64
118
+ when :bool
119
+ TrueClass
120
+ when :float
121
+ Float
122
+ when :decimal
123
+ BigDecimal
124
+ when :time
125
+ Time
126
+ when :date
127
+ Date
128
+ when :datetime
129
+ DateTime
130
+ else
131
+ nil
132
+ end
133
+ end
134
+
135
+ def derived_from?(ancestor, child) # :nodoc:
136
+ child.ancestors.include?(ancestor)
137
+ end
138
+
139
+ module_function :type_name_to_class
140
+ module_function :class_to_type_name
141
+ module_function :symbol_name
142
+ module_function :canonical_type_class
143
+ module_function :canonical_type_name
144
+ module_function :canonical_type
145
+ module_function :canonical_signature_entry
146
+ module_function :canonical_signature
147
+ module_function :derived_from?
148
+ end
149
+
150
+ class BaseType # :nodoc:
151
+ include SignatureTypes
152
+
153
+ attr :spec
154
+ attr :type
155
+ attr :type_class
156
+ attr :name
157
+
158
+ def initialize(spec, type, name)
159
+ @spec = spec
160
+ @type = canonical_type(type)
161
+ @type_class = canonical_type_class(@type)
162
+ @name = name
163
+ end
164
+
165
+ def custom?
166
+ false
167
+ end
168
+
169
+ def array?
170
+ false
171
+ end
172
+
173
+ def structured?
174
+ false
175
+ end
176
+
177
+ def human_name(show_name=true)
178
+ type_type = array? ? element_type.type.to_s : self.type.to_s
179
+ str = array? ? (type_type + '[]') : type_type
180
+ show_name ? (str + " " + name.to_s) : str
181
+ end
182
+ end
183
+
184
+ class ArrayType < BaseType # :nodoc:
185
+ attr :element_type
186
+
187
+ def initialize(spec, element_type, name)
188
+ super(spec, Array, name)
189
+ @element_type = element_type
190
+ end
191
+
192
+ def custom?
193
+ true
194
+ end
195
+
196
+ def array?
197
+ true
198
+ end
199
+ end
200
+
201
+ class StructuredType < BaseType # :nodoc:
202
+ def each_member
203
+ if @type_class.respond_to?(:members)
204
+ @type_class.members.each do |name, type|
205
+ yield name, type
206
+ end
207
+ elsif @type_class.respond_to?(:columns)
208
+ i = -1
209
+ @type_class.columns.each do |column|
210
+ yield column.name, canonical_signature_entry(column.type, i += 1)
211
+ end
212
+ end
213
+ end
214
+
215
+ def custom?
216
+ true
217
+ end
218
+
219
+ def structured?
220
+ true
221
+ end
222
+ end
223
+
224
+ class Base64 < String # :nodoc:
225
+ end
226
+ end
@@ -0,0 +1,65 @@
1
+ <html>
2
+ <head>
3
+ <title><%= @scaffold_class.wsdl_service_name %> Web Service</title>
4
+ <style>
5
+ body { background-color: #fff; color: #333; }
6
+
7
+ body, p, ol, ul, td {
8
+ font-family: verdana, arial, helvetica, sans-serif;
9
+ font-size: 13px;
10
+ line-height: 18px;
11
+ }
12
+
13
+ pre {
14
+ background-color: #eee;
15
+ padding: 10px;
16
+ font-size: 11px;
17
+ }
18
+
19
+ a { color: #000; }
20
+ a:visited { color: #666; }
21
+ a:hover { color: #fff; background-color:#000; }
22
+
23
+ .fieldWithErrors {
24
+ padding: 2px;
25
+ background-color: red;
26
+ display: table;
27
+ }
28
+
29
+ #errorExplanation {
30
+ width: 400px;
31
+ border: 2px solid red;
32
+ padding: 7px;
33
+ padding-bottom: 12px;
34
+ margin-bottom: 20px;
35
+ background-color: #f0f0f0;
36
+ }
37
+
38
+ #errorExplanation h2 {
39
+ text-align: left;
40
+ font-weight: bold;
41
+ padding: 5px 5px 5px 15px;
42
+ font-size: 12px;
43
+ margin: -7px;
44
+ background-color: #c00;
45
+ color: #fff;
46
+ }
47
+
48
+ #errorExplanation p {
49
+ color: #333;
50
+ margin-bottom: 0;
51
+ padding: 5px;
52
+ }
53
+
54
+ #errorExplanation ul li {
55
+ font-size: 12px;
56
+ list-style: square;
57
+ }
58
+ </style>
59
+ </head>
60
+ <body>
61
+
62
+ <%= @content_for_layout %>
63
+
64
+ </body>
65
+ </html>
@@ -0,0 +1,6 @@
1
+ <% @scaffold_container.services.each do |service| %>
2
+
3
+ <h4>API Methods for <%= service %></h4>
4
+ <%= service_method_list(service) %>
5
+
6
+ <% end %>
@@ -0,0 +1,29 @@
1
+ <h4>Method Invocation Details for <em><%= @scaffold_service %>#<%= @scaffold_method.public_name %></em></h4>
2
+
3
+ <% form_tag(:action => @scaffold_action_name + '_submit') do -%>
4
+ <%= hidden_field_tag "service", @scaffold_service.name %>
5
+ <%= hidden_field_tag "method", @scaffold_method.public_name %>
6
+
7
+ <p>
8
+ <label for="protocol">Protocol:</label><br />
9
+ <%= select_tag 'protocol', options_for_select([['SOAP', 'soap'], ['XML-RPC', 'xmlrpc']], params['protocol']) %>
10
+ </p>
11
+
12
+ <% if @scaffold_method.expects %>
13
+
14
+ <strong>Method Parameters:</strong><br />
15
+ <% @scaffold_method.expects.each_with_index do |type, i| %>
16
+ <p>
17
+ <label for="method_params[<%= i %>]"><%= method_parameter_label(type.name, type) %> </label><br />
18
+ <%= method_parameter_input_fields(@scaffold_method, type, "method_params", i) %>
19
+ </p>
20
+ <% end %>
21
+
22
+ <% end %>
23
+
24
+ <%= submit_tag "Invoke" %>
25
+ <% end -%>
26
+
27
+ <p>
28
+ <%= link_to "Back", :action => @scaffold_action_name %>
29
+ </p>