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.
- data/CHANGELOG +335 -0
- data/MIT-LICENSE +21 -0
- data/README +381 -0
- data/Rakefile +184 -0
- data/TODO +32 -0
- data/examples/googlesearch/README +143 -0
- data/examples/googlesearch/autoloading/google_search_api.rb +51 -0
- data/examples/googlesearch/autoloading/google_search_controller.rb +58 -0
- data/examples/googlesearch/delegated/google_search_service.rb +109 -0
- data/examples/googlesearch/delegated/search_controller.rb +8 -0
- data/examples/googlesearch/direct/google_search_api.rb +51 -0
- data/examples/googlesearch/direct/search_controller.rb +59 -0
- data/examples/metaWeblog/README +17 -0
- data/examples/metaWeblog/apis/blogger_api.rb +61 -0
- data/examples/metaWeblog/apis/blogger_service.rb +35 -0
- data/examples/metaWeblog/apis/meta_weblog_api.rb +68 -0
- data/examples/metaWeblog/apis/meta_weblog_service.rb +49 -0
- data/examples/metaWeblog/controllers/xmlrpc_controller.rb +17 -0
- data/generators/web_service/USAGE +28 -0
- data/generators/web_service/templates/api_definition.rb +6 -0
- data/generators/web_service/templates/controller.rb +9 -0
- data/generators/web_service/templates/functional_test.rb +20 -0
- data/generators/web_service/web_service_generator.rb +30 -0
- data/lib/action_web_service.rb +61 -0
- data/lib/action_web_service/acts_as_web_service.rb +26 -0
- data/lib/action_web_service/api.rb +298 -0
- data/lib/action_web_service/base.rb +39 -0
- data/lib/action_web_service/casting.rb +160 -0
- data/lib/action_web_service/client.rb +4 -0
- data/lib/action_web_service/client/base.rb +29 -0
- data/lib/action_web_service/client/soap_client.rb +114 -0
- data/lib/action_web_service/client/xmlrpc_client.rb +59 -0
- data/lib/action_web_service/container.rb +4 -0
- data/lib/action_web_service/container/action_controller_container.rb +94 -0
- data/lib/action_web_service/container/delegated_container.rb +87 -0
- data/lib/action_web_service/container/direct_container.rb +70 -0
- data/lib/action_web_service/dispatcher.rb +3 -0
- data/lib/action_web_service/dispatcher/abstract.rb +209 -0
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +397 -0
- data/lib/action_web_service/invocation.rb +203 -0
- data/lib/action_web_service/protocol.rb +5 -0
- data/lib/action_web_service/protocol/abstract.rb +113 -0
- data/lib/action_web_service/protocol/discovery.rb +38 -0
- data/lib/action_web_service/protocol/soap_protocol.rb +177 -0
- data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +243 -0
- data/lib/action_web_service/protocol/soap_protocol/marshaler.rb~ +243 -0
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +124 -0
- data/lib/action_web_service/scaffolding.rb +282 -0
- data/lib/action_web_service/simple.rb +54 -0
- data/lib/action_web_service/string_to_datetime_for_soap.rb +17 -0
- data/lib/action_web_service/struct.rb +69 -0
- data/lib/action_web_service/support/class_inheritable_options.rb +27 -0
- data/lib/action_web_service/support/signature_types.rb +262 -0
- data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
- data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
- data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
- data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
- data/lib/action_web_service/test_invoke.rb +111 -0
- data/lib/action_web_service/version.rb +11 -0
- data/lib/action_web_service/version.rb~ +10 -0
- data/lib/actionwebservice.rb +2 -0
- data/setup.rb +1380 -0
- data/test/abstract_client.rb +185 -0
- data/test/abstract_dispatcher.rb +550 -0
- data/test/abstract_unit.rb +44 -0
- data/test/api_test.rb +103 -0
- data/test/apis/auto_load_api.rb +4 -0
- data/test/apis/broken_auto_load_api.rb +3 -0
- data/test/base_test.rb +43 -0
- data/test/casting_test.rb +96 -0
- data/test/client_soap_test.rb +157 -0
- data/test/client_xmlrpc_test.rb +155 -0
- data/test/container_test.rb +76 -0
- data/test/dispatcher_action_controller_soap_test.rb +147 -0
- data/test/dispatcher_action_controller_xmlrpc_test.rb +60 -0
- data/test/fixtures/db_definitions/mysql.sql +8 -0
- data/test/fixtures/db_definitions/sqlite3.sql +8 -0
- data/test/fixtures/users.yml +12 -0
- data/test/gencov +3 -0
- data/test/invocation_test.rb +187 -0
- data/test/run +6 -0
- data/test/scaffolded_controller_test.rb +148 -0
- data/test/struct_test.rb +85 -0
- data/test/test_invoke_test.rb +114 -0
- metadata +167 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'xmlrpc/marshal'
|
3
|
+
require 'action_web_service/client/xmlrpc_client'
|
4
|
+
|
5
|
+
module XMLRPC # :nodoc:
|
6
|
+
class FaultException # :nodoc:
|
7
|
+
alias :message :faultString
|
8
|
+
end
|
9
|
+
|
10
|
+
class Create
|
11
|
+
def wrong_type(value)
|
12
|
+
if BigDecimal === value
|
13
|
+
[true, value.to_f]
|
14
|
+
else
|
15
|
+
false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ActionWebService # :nodoc:
|
22
|
+
module API # :nodoc:
|
23
|
+
class Base # :nodoc:
|
24
|
+
def self.xmlrpc_client(endpoint_uri, options={})
|
25
|
+
ActionWebService::Client::XmlRpc.new self, endpoint_uri, options
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Protocol # :nodoc:
|
31
|
+
module XmlRpc # :nodoc:
|
32
|
+
def self.included(base)
|
33
|
+
base.register_protocol(XmlRpcProtocol)
|
34
|
+
end
|
35
|
+
|
36
|
+
class XmlRpcProtocol < AbstractProtocol # :nodoc:
|
37
|
+
def self.create(controller)
|
38
|
+
XmlRpcProtocol.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def decode_action_pack_request(action_pack_request)
|
42
|
+
service_name = action_pack_request.parameters['action']
|
43
|
+
decode_request(action_pack_request.raw_post, service_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def decode_request(raw_request, service_name)
|
47
|
+
method_name, params = XMLRPC::Marshal.load_call(raw_request)
|
48
|
+
Request.new(self, method_name, params, service_name)
|
49
|
+
rescue
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def encode_request(method_name, params, param_types)
|
54
|
+
if param_types
|
55
|
+
params = params.dup
|
56
|
+
param_types.each_with_index{ |type, i| params[i] = value_to_xmlrpc_wire_format(params[i], type) }
|
57
|
+
end
|
58
|
+
XMLRPC::Marshal.dump_call(method_name, *params)
|
59
|
+
end
|
60
|
+
|
61
|
+
def decode_response(raw_response)
|
62
|
+
[nil, XMLRPC::Marshal.load_response(raw_response)]
|
63
|
+
end
|
64
|
+
|
65
|
+
def encode_response(method_name, return_value, return_type, protocol_options={})
|
66
|
+
if return_value && return_type
|
67
|
+
return_value = value_to_xmlrpc_wire_format(return_value, return_type)
|
68
|
+
end
|
69
|
+
return_value = false if return_value.nil?
|
70
|
+
raw_response = XMLRPC::Marshal.dump_response(return_value)
|
71
|
+
Response.new(raw_response, 'text/xml', return_value)
|
72
|
+
end
|
73
|
+
|
74
|
+
def encode_multicall_response(responses, protocol_options={})
|
75
|
+
result = responses.map do |return_value, return_type|
|
76
|
+
if return_value && return_type
|
77
|
+
return_value = value_to_xmlrpc_wire_format(return_value, return_type)
|
78
|
+
return_value = [return_value] unless return_value.nil?
|
79
|
+
end
|
80
|
+
return_value = false if return_value.nil?
|
81
|
+
return_value
|
82
|
+
end
|
83
|
+
raw_response = XMLRPC::Marshal.dump_response(result)
|
84
|
+
Response.new(raw_response, 'text/xml', result)
|
85
|
+
end
|
86
|
+
|
87
|
+
def protocol_client(api, protocol_name, endpoint_uri, options={})
|
88
|
+
return nil unless protocol_name == :xmlrpc
|
89
|
+
ActionWebService::Client::XmlRpc.new(api, endpoint_uri, options)
|
90
|
+
end
|
91
|
+
|
92
|
+
def value_to_xmlrpc_wire_format(value, value_type)
|
93
|
+
if value_type.array?
|
94
|
+
value.map{ |val| value_to_xmlrpc_wire_format(val, value_type.element_type) }
|
95
|
+
else
|
96
|
+
if value.is_a?(ActionWebService::Struct)
|
97
|
+
struct = {}
|
98
|
+
value.class.members.each do |name, type_options|
|
99
|
+
type, options = type_options
|
100
|
+
member_value = value[name]
|
101
|
+
next if member_value.nil?
|
102
|
+
struct[name.to_s] = value_to_xmlrpc_wire_format(member_value, type)
|
103
|
+
end
|
104
|
+
struct
|
105
|
+
elsif value.is_a?(ActiveRecord::Base)
|
106
|
+
struct = {}
|
107
|
+
value.attributes.each do |key, member_value|
|
108
|
+
next if member_value.nil?
|
109
|
+
struct[key.to_s] = member_value
|
110
|
+
end
|
111
|
+
struct
|
112
|
+
elsif value.is_a?(ActionWebService::Base64)
|
113
|
+
XMLRPC::Base64.new(value)
|
114
|
+
elsif value.is_a?(Exception) && !value.is_a?(XMLRPC::FaultException)
|
115
|
+
XMLRPC::FaultException.new(2, value.message)
|
116
|
+
else
|
117
|
+
value
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'benchmark'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module ActionWebService
|
6
|
+
module Scaffolding # :nodoc:
|
7
|
+
class ScaffoldingError < ActionWebServiceError # :nodoc:
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.extend(ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Web service invocation scaffolding provides a way to quickly invoke web service methods in a controller. The
|
15
|
+
# generated scaffold actions have default views to let you enter the method parameters and view the
|
16
|
+
# results.
|
17
|
+
#
|
18
|
+
# Example:
|
19
|
+
#
|
20
|
+
# class ApiController < ActionController
|
21
|
+
# web_service_scaffold :invoke
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# This example generates an +invoke+ action in the +ApiController+ that you can navigate to from
|
25
|
+
# your browser, select the API method, enter its parameters, and perform the invocation.
|
26
|
+
#
|
27
|
+
# If you want to customize the default views, create the following views in "app/views":
|
28
|
+
#
|
29
|
+
# * <tt>action_name/methods.html.erb</tt>
|
30
|
+
# * <tt>action_name/parameters.html.erb</tt>
|
31
|
+
# * <tt>action_name/result.html.erb</tt>
|
32
|
+
# * <tt>action_name/layout.html.erb</tt>
|
33
|
+
#
|
34
|
+
# Where <tt>action_name</tt> is the name of the action you gave to ClassMethods#web_service_scaffold.
|
35
|
+
#
|
36
|
+
# You can use the default views in <tt>RAILS_DIR/lib/action_web_service/templates/scaffolds</tt> as
|
37
|
+
# a guide.
|
38
|
+
module ClassMethods
|
39
|
+
# Generates web service invocation scaffolding for the current controller. The given action name
|
40
|
+
# can then be used as the entry point for invoking API methods from a web browser.
|
41
|
+
def web_service_scaffold(action_name)
|
42
|
+
add_template_helper(Helpers)
|
43
|
+
module_eval <<-"end_eval", __FILE__, __LINE__ + 1
|
44
|
+
def #{action_name}
|
45
|
+
if request.method == :get
|
46
|
+
setup_invocation_assigns
|
47
|
+
render_invocation_scaffold 'methods'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def #{action_name}_method_params
|
52
|
+
if request.method == :get
|
53
|
+
setup_invocation_assigns
|
54
|
+
render_invocation_scaffold 'parameters'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def #{action_name}_submit
|
59
|
+
if request.method == :post
|
60
|
+
setup_invocation_assigns
|
61
|
+
protocol_name = params['protocol'] ? params['protocol'].to_sym : :soap
|
62
|
+
case protocol_name
|
63
|
+
when :soap
|
64
|
+
@protocol = Protocol::Soap::SoapProtocol.create(self)
|
65
|
+
when :xmlrpc
|
66
|
+
@protocol = Protocol::XmlRpc::XmlRpcProtocol.create(self)
|
67
|
+
end
|
68
|
+
bm = Benchmark.measure do
|
69
|
+
@protocol.register_api(@scaffold_service.api)
|
70
|
+
post_params = params['method_params'] ? params['method_params'].dup : nil
|
71
|
+
params = []
|
72
|
+
@scaffold_method.expects.each_with_index do |spec, i|
|
73
|
+
params << post_params[i.to_s]
|
74
|
+
end if @scaffold_method.expects
|
75
|
+
params = @scaffold_method.cast_expects(params)
|
76
|
+
method_name = public_method_name(@scaffold_service.name, @scaffold_method.public_name)
|
77
|
+
@method_request_xml = @protocol.encode_request(method_name, params, @scaffold_method.expects)
|
78
|
+
new_request = @protocol.encode_action_pack_request(@scaffold_service.name, @scaffold_method.public_name, @method_request_xml)
|
79
|
+
prepare_request(new_request, @scaffold_service.name, @scaffold_method.public_name)
|
80
|
+
self.request = new_request
|
81
|
+
if @scaffold_container.dispatching_mode != :direct
|
82
|
+
request.parameters['action'] = @scaffold_service.name
|
83
|
+
end
|
84
|
+
dispatch_web_service_request
|
85
|
+
@method_response_xml = response.body
|
86
|
+
method_name, obj = @protocol.decode_response(@method_response_xml)
|
87
|
+
return if handle_invocation_exception(obj)
|
88
|
+
@method_return_value = @scaffold_method.cast_returns(obj)
|
89
|
+
end
|
90
|
+
@method_elapsed = bm.real
|
91
|
+
reset_invocation_response
|
92
|
+
render_invocation_scaffold 'result'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def setup_invocation_assigns
|
98
|
+
@scaffold_class = self.class
|
99
|
+
@scaffold_action_name = "#{action_name}"
|
100
|
+
@scaffold_container = WebServiceModel::Container.new(self)
|
101
|
+
if params['service'] && params['method']
|
102
|
+
@scaffold_service = @scaffold_container.services.find{ |x| x.name == params['service'] }
|
103
|
+
@scaffold_method = @scaffold_service.api_methods[params['method']]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def render_invocation_scaffold(action)
|
108
|
+
customized_template = "\#{self.class.controller_path}/#{action_name}/\#{action}"
|
109
|
+
default_template = scaffold_path(action)
|
110
|
+
begin
|
111
|
+
content = @template.render(:file => customized_template)
|
112
|
+
rescue ActionView::MissingTemplate
|
113
|
+
content = @template.render(:file => default_template)
|
114
|
+
end
|
115
|
+
@template.instance_variable_set("@content_for_layout", content)
|
116
|
+
if self.active_layout.nil?
|
117
|
+
render :file => scaffold_path("layout")
|
118
|
+
else
|
119
|
+
render :file => self.active_layout, :use_full_path => true
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def scaffold_path(template_name)
|
124
|
+
File.dirname(__FILE__) + "/templates/scaffolds/" + template_name + ".html.erb"
|
125
|
+
end
|
126
|
+
|
127
|
+
def reset_invocation_response
|
128
|
+
erase_render_results
|
129
|
+
response.instance_variable_set :@header, Rack::Utils::HeaderHash.new(::ActionController::Response::DEFAULT_HEADERS.merge("cookie" => []))
|
130
|
+
end
|
131
|
+
|
132
|
+
def public_method_name(service_name, method_name)
|
133
|
+
if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::XmlRpc::XmlRpcProtocol)
|
134
|
+
service_name + '.' + method_name
|
135
|
+
else
|
136
|
+
method_name
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def prepare_request(new_request, service_name, method_name)
|
141
|
+
new_request.parameters.update(request.parameters)
|
142
|
+
request.env.each{ |k, v| new_request.env[k] = v unless new_request.env.has_key?(k) }
|
143
|
+
if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::Soap::SoapProtocol)
|
144
|
+
new_request.env['HTTP_SOAPACTION'] = "/\#{controller_name()}/\#{service_name}/\#{method_name}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def handle_invocation_exception(obj)
|
149
|
+
exception = nil
|
150
|
+
if obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && obj.detail.cause.is_a?(Exception)
|
151
|
+
exception = obj.detail.cause
|
152
|
+
elsif obj.is_a?(XMLRPC::FaultException)
|
153
|
+
exception = obj
|
154
|
+
end
|
155
|
+
return unless exception
|
156
|
+
reset_invocation_response
|
157
|
+
rescue_action(exception)
|
158
|
+
true
|
159
|
+
end
|
160
|
+
end_eval
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
module Helpers # :nodoc:
|
165
|
+
def method_parameter_input_fields(method, type, field_name_base, idx, was_structured=false)
|
166
|
+
if type.array?
|
167
|
+
return content_tag('em', "Typed array input fields not supported yet (#{type.name})")
|
168
|
+
end
|
169
|
+
if type.structured?
|
170
|
+
return content_tag('em', "Nested structural types not supported yet (#{type.name})") if was_structured
|
171
|
+
parameters = ""
|
172
|
+
type.each_member do |member_name, member_type|
|
173
|
+
label = method_parameter_label(member_name, member_type)
|
174
|
+
nested_content = method_parameter_input_fields(
|
175
|
+
method,
|
176
|
+
member_type,
|
177
|
+
"#{field_name_base}[#{idx}][#{member_name}]",
|
178
|
+
idx,
|
179
|
+
true)
|
180
|
+
if member_type.custom?
|
181
|
+
parameters << content_tag('li', label)
|
182
|
+
parameters << content_tag('ul', nested_content)
|
183
|
+
else
|
184
|
+
parameters << content_tag('li', label + ' ' + nested_content)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
content_tag('ul', parameters)
|
188
|
+
else
|
189
|
+
# If the data source was structured previously we already have the index set
|
190
|
+
field_name_base = "#{field_name_base}[#{idx}]" unless was_structured
|
191
|
+
|
192
|
+
case type.type
|
193
|
+
when :int
|
194
|
+
text_field_tag "#{field_name_base}"
|
195
|
+
when :string
|
196
|
+
text_field_tag "#{field_name_base}"
|
197
|
+
when :base64
|
198
|
+
text_area_tag "#{field_name_base}", nil, :size => "40x5"
|
199
|
+
when :bool
|
200
|
+
radio_button_tag("#{field_name_base}", "true") + " True" +
|
201
|
+
radio_button_tag("#{field_name_base}", "false") + "False"
|
202
|
+
when :float
|
203
|
+
text_field_tag "#{field_name_base}"
|
204
|
+
when :time, :datetime
|
205
|
+
time = Time.now
|
206
|
+
i = 0
|
207
|
+
%w|year month day hour minute second|.map do |name|
|
208
|
+
i += 1
|
209
|
+
send("select_#{name}", time, :prefix => "#{field_name_base}[#{i}]", :discard_type => true)
|
210
|
+
end.join
|
211
|
+
when :date
|
212
|
+
date = Date.today
|
213
|
+
i = 0
|
214
|
+
%w|year month day|.map do |name|
|
215
|
+
i += 1
|
216
|
+
send("select_#{name}", date, :prefix => "#{field_name_base}[#{i}]", :discard_type => true)
|
217
|
+
end.join
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def method_parameter_label(name, type)
|
223
|
+
name.to_s.capitalize + ' (' + type.human_name(false) + ')'
|
224
|
+
end
|
225
|
+
|
226
|
+
def service_method_list(service)
|
227
|
+
action = @scaffold_action_name + '_method_params'
|
228
|
+
methods = service.api_methods_full.sort {|a, b| a[1] <=> b[1]}.map do |desc, name|
|
229
|
+
content_tag("li", link_to(name, :action => action, :service => service.name, :method => name))
|
230
|
+
end
|
231
|
+
content_tag("ul", methods.join("\n"))
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
module WebServiceModel # :nodoc:
|
236
|
+
class Container # :nodoc:
|
237
|
+
attr :services
|
238
|
+
attr :dispatching_mode
|
239
|
+
|
240
|
+
def initialize(real_container)
|
241
|
+
@real_container = real_container
|
242
|
+
@dispatching_mode = @real_container.class.web_service_dispatching_mode
|
243
|
+
@services = []
|
244
|
+
if @dispatching_mode == :direct
|
245
|
+
@services << Service.new(@real_container.controller_name, @real_container)
|
246
|
+
else
|
247
|
+
@real_container.class.web_services.each do |name, obj|
|
248
|
+
@services << Service.new(name, @real_container.instance_eval{ web_service_object(name) })
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class Service # :nodoc:
|
255
|
+
attr :name
|
256
|
+
attr :object
|
257
|
+
attr :api
|
258
|
+
attr :api_methods
|
259
|
+
attr :api_methods_full
|
260
|
+
|
261
|
+
def initialize(name, real_service)
|
262
|
+
@name = name.to_s
|
263
|
+
@object = real_service
|
264
|
+
@api = @object.class.web_service_api
|
265
|
+
if @api.nil?
|
266
|
+
raise ScaffoldingError, "No web service API attached to #{object.class}"
|
267
|
+
end
|
268
|
+
@api_methods = {}
|
269
|
+
@api_methods_full = []
|
270
|
+
@api.api_methods.each do |name, method|
|
271
|
+
@api_methods[method.public_name.to_s] = method
|
272
|
+
@api_methods_full << [method.to_s, method.public_name.to_s]
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def to_s
|
277
|
+
self.name.camelize
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module ActionWebService
|
3
|
+
# To send simple types across the wire, derive from ActionWebService::Simple,
|
4
|
+
# and use +base+ to declare the base type for it restriction and,
|
5
|
+
# use +restriction+ to declare valid W3C restriction element for SimpleType.
|
6
|
+
#
|
7
|
+
# ActionWebService::Simple should be used when you want to declare valid custom simple type
|
8
|
+
# to be used inside expects, returns and structured types
|
9
|
+
#
|
10
|
+
#
|
11
|
+
# There plenty documentation available at W3C Archives
|
12
|
+
# http://www.w3.org/TR/xmlschema-2/
|
13
|
+
#
|
14
|
+
# === Example
|
15
|
+
#
|
16
|
+
# class Gender < ActionWebService::Simple
|
17
|
+
# base :string
|
18
|
+
# restriction :enumeration, "male|female"
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
#
|
22
|
+
class Simple
|
23
|
+
|
24
|
+
def initialize(value)
|
25
|
+
@value = value
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
def base(type)
|
30
|
+
type = type.to_s.camelize(:lower)
|
31
|
+
write_inheritable_attribute("xml_base", type)
|
32
|
+
class_eval <<-END
|
33
|
+
def xml_base; "#{type}"; end
|
34
|
+
END
|
35
|
+
end
|
36
|
+
|
37
|
+
def restriction_base
|
38
|
+
read_inheritable_attribute("xml_base") || ""
|
39
|
+
end
|
40
|
+
|
41
|
+
def restriction(type, value)
|
42
|
+
type = type.to_s.camelize(:lower)
|
43
|
+
write_inheritable_hash("simple_restrictions", type => value)
|
44
|
+
end
|
45
|
+
|
46
|
+
def restrictions
|
47
|
+
read_inheritable_attribute("simple_restrictions") || {}
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|