actionwebservice 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/CHANGELOG +21 -0
  2. data/README +50 -6
  3. data/Rakefile +9 -9
  4. data/TODO +6 -6
  5. data/lib/action_web_service.rb +4 -3
  6. data/lib/action_web_service/api.rb +248 -1
  7. data/lib/action_web_service/casting.rb +111 -0
  8. data/lib/action_web_service/client/soap_client.rb +17 -33
  9. data/lib/action_web_service/client/xmlrpc_client.rb +10 -34
  10. data/lib/action_web_service/container/delegated_container.rb +1 -1
  11. data/lib/action_web_service/dispatcher/abstract.rb +52 -72
  12. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +71 -55
  13. data/lib/action_web_service/protocol/abstract.rb +82 -3
  14. data/lib/action_web_service/protocol/discovery.rb +2 -2
  15. data/lib/action_web_service/protocol/soap_protocol.rb +95 -22
  16. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +197 -0
  17. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +56 -24
  18. data/lib/action_web_service/scaffolding.rb +237 -0
  19. data/lib/action_web_service/struct.rb +17 -4
  20. data/lib/action_web_service/support/signature_types.rb +194 -0
  21. data/lib/action_web_service/templates/scaffolds/layout.rhtml +65 -0
  22. data/lib/action_web_service/templates/scaffolds/methods.rhtml +6 -0
  23. data/lib/action_web_service/templates/scaffolds/parameters.rhtml +28 -0
  24. data/lib/action_web_service/templates/scaffolds/result.rhtml +30 -0
  25. data/lib/action_web_service/test_invoke.rb +23 -42
  26. data/test/abstract_dispatcher.rb +102 -48
  27. data/test/abstract_unit.rb +1 -1
  28. data/test/api_test.rb +40 -7
  29. data/test/casting_test.rb +82 -0
  30. data/test/client_soap_test.rb +3 -0
  31. data/test/client_xmlrpc_test.rb +5 -1
  32. data/test/dispatcher_action_controller_soap_test.rb +9 -12
  33. data/test/dispatcher_action_controller_xmlrpc_test.rb +1 -11
  34. data/test/run +1 -0
  35. data/test/scaffolded_controller_test.rb +67 -0
  36. data/test/struct_test.rb +33 -21
  37. data/test/test_invoke_test.rb +1 -1
  38. metadata +18 -31
  39. data/lib/action_web_service/api/base.rb +0 -135
  40. data/lib/action_web_service/vendor/ws.rb +0 -4
  41. data/lib/action_web_service/vendor/ws/common.rb +0 -8
  42. data/lib/action_web_service/vendor/ws/encoding.rb +0 -3
  43. data/lib/action_web_service/vendor/ws/encoding/abstract.rb +0 -26
  44. data/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb +0 -90
  45. data/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb +0 -53
  46. data/lib/action_web_service/vendor/ws/marshaling.rb +0 -3
  47. data/lib/action_web_service/vendor/ws/marshaling/abstract.rb +0 -17
  48. data/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb +0 -277
  49. data/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb +0 -116
  50. data/lib/action_web_service/vendor/ws/types.rb +0 -165
  51. data/test/ws/abstract_encoding.rb +0 -68
  52. data/test/ws/abstract_unit.rb +0 -13
  53. data/test/ws/gencov +0 -3
  54. data/test/ws/run +0 -5
  55. data/test/ws/soap_marshaling_test.rb +0 -91
  56. data/test/ws/soap_rpc_encoding_test.rb +0 -47
  57. data/test/ws/types_test.rb +0 -43
  58. data/test/ws/xmlrpc_encoding_test.rb +0 -34
@@ -1,135 +0,0 @@
1
- module ActionWebService # :nodoc:
2
- module API # :nodoc:
3
- # A web service API class specifies the methods that will be available for
4
- # invocation for an API. It also contains metadata such as the method type
5
- # signature hints.
6
- #
7
- # It is not intended to be instantiated.
8
- #
9
- # It is attached to web service implementation classes like
10
- # ActionWebService::Base and ActionController::Base derivatives by using
11
- # ClassMethods#web_service_api.
12
- class Base
13
- # Whether to transform the public API method names into camel-cased names
14
- class_inheritable_option :inflect_names, true
15
-
16
- # Whether to allow ActiveRecord::Base models in <tt>:expects</tt>.
17
- # The default is +false+, you should be aware of the security implications
18
- # of allowing this, and ensure that you don't allow remote callers to
19
- # easily overwrite data they should not have access to.
20
- class_inheritable_option :allow_active_record_expects, false
21
-
22
- # If present, the name of a method to call when the remote caller
23
- # tried to call a nonexistent method. Semantically equivalent to
24
- # +method_missing+.
25
- class_inheritable_option :default_api_method
26
-
27
- # Disallow instantiation
28
- private_class_method :new, :allocate
29
-
30
- class << self
31
- # API methods have a +name+, which must be the Ruby method name to use when
32
- # performing the invocation on the web service object.
33
- #
34
- # The signatures for the method input parameters and return value can
35
- # by specified in +options+.
36
- #
37
- # A signature is an array of one or more parameter specifiers.
38
- # A parameter specifier can be one of the following:
39
- #
40
- # * A symbol or string of representing one of the Action Web Service base types.
41
- # See ActionWebService::Signature for a canonical list of the base types.
42
- # * The Class object of the parameter type
43
- # * A single-element Array containing one of the two preceding items. This
44
- # will cause Action Web Service to treat the parameter at that position
45
- # as an array containing only values of the given type.
46
- # * A Hash containing as key the name of the parameter, and as value
47
- # one of the three preceding items
48
- #
49
- # If no method input parameter or method return value signatures are given,
50
- # the method is assumed to take no parameters and/or return no values of
51
- # interest, and any values that are received by the server will be
52
- # discarded and ignored.
53
- #
54
- # Valid options:
55
- # [<tt>:expects</tt>] Signature for the method input parameters
56
- # [<tt>:returns</tt>] Signature for the method return value
57
- # [<tt>:expects_and_returns</tt>] Signature for both input parameters and return value
58
- def api_method(name, options={})
59
- validate_options([:expects, :returns, :expects_and_returns], options.keys)
60
- if options[:expects_and_returns]
61
- expects = options[:expects_and_returns]
62
- returns = options[:expects_and_returns]
63
- else
64
- expects = options[:expects]
65
- returns = options[:returns]
66
- end
67
- expects = canonical_signature(expects)
68
- returns = canonical_signature(returns)
69
- if expects
70
- expects.each do |param|
71
- klass = WS::BaseTypes.canonical_param_type_class(param)
72
- klass = klass[0] if klass.is_a?(Array)
73
- if klass.ancestors.include?(ActiveRecord::Base) && !allow_active_record_expects
74
- raise(ActionWebServiceError, "ActiveRecord model classes not allowed in :expects")
75
- end
76
- end
77
- end
78
- name = name.to_sym
79
- public_name = public_api_method_name(name)
80
- info = { :expects => expects, :returns => returns }
81
- write_inheritable_hash("api_methods", name => info)
82
- write_inheritable_hash("api_public_method_names", public_name => name)
83
- end
84
-
85
- # Whether the given method name is a service method on this API
86
- def has_api_method?(name)
87
- api_methods.has_key?(name)
88
- end
89
-
90
- # Whether the given public method name has a corresponding service method
91
- # on this API
92
- def has_public_api_method?(public_name)
93
- api_public_method_names.has_key?(public_name)
94
- end
95
-
96
- # The corresponding public method name for the given service method name
97
- def public_api_method_name(name)
98
- if inflect_names
99
- name.to_s.camelize
100
- else
101
- name.to_s
102
- end
103
- end
104
-
105
- # The corresponding service method name for the given public method name
106
- def api_method_name(public_name)
107
- api_public_method_names[public_name]
108
- end
109
-
110
- # A Hash containing all service methods on this API, and their
111
- # associated metadata.
112
- def api_methods
113
- read_inheritable_attribute("api_methods") || {}
114
- end
115
-
116
- private
117
- def api_public_method_names
118
- read_inheritable_attribute("api_public_method_names") || {}
119
- end
120
-
121
- def validate_options(valid_option_keys, supplied_option_keys)
122
- unknown_option_keys = supplied_option_keys - valid_option_keys
123
- unless unknown_option_keys.empty?
124
- raise(ActionWebServiceError, "Unknown options: #{unknown_option_keys}")
125
- end
126
- end
127
-
128
- def canonical_signature(signature)
129
- return nil if signature.nil?
130
- signature.map{|spec| WS::BaseTypes.canonical_param_type_spec(spec)}
131
- end
132
- end
133
- end
134
- end
135
- end
@@ -1,4 +0,0 @@
1
- require 'ws/common'
2
- require 'ws/types'
3
- require 'ws/marshaling'
4
- require 'ws/encoding'
@@ -1,8 +0,0 @@
1
- module WS
2
- class WSError < StandardError
3
- end
4
-
5
- def self.derived_from?(ancestor, child)
6
- child.ancestors.include?(ancestor)
7
- end
8
- end
@@ -1,3 +0,0 @@
1
- require 'ws/encoding/abstract'
2
- require 'ws/encoding/soap_rpc_encoding'
3
- require 'ws/encoding/xmlrpc_encoding'
@@ -1,26 +0,0 @@
1
- module WS
2
- module Encoding
3
- # Encoders operate on _foreign_ objects. That is, Ruby object
4
- # instances that are the _marshaling format specific_ representation
5
- # of objects. In other words, objects that have not yet been marshaled, but
6
- # are in protocol-specific form (such as an AST or DOM element), and not
7
- # native Ruby form.
8
- class AbstractEncoding
9
- def encode_rpc_call(method_name, params)
10
- raise NotImplementedError
11
- end
12
-
13
- def decode_rpc_call(obj)
14
- raise NotImplementedError
15
- end
16
-
17
- def encode_rpc_response(method_name, return_value)
18
- raise NotImplementedError
19
- end
20
-
21
- def decode_rpc_response(obj)
22
- raise NotImplementedError
23
- end
24
- end
25
- end
26
- end
@@ -1,90 +0,0 @@
1
- require 'soap/processor'
2
- require 'soap/mapping'
3
- require 'soap/rpc/element'
4
-
5
- module WS
6
- module Encoding
7
- class SoapRpcError < WSError
8
- end
9
-
10
- class SoapRpcEncoding < AbstractEncoding
11
- attr_accessor :method_namespace
12
-
13
- def initialize(method_namespace='')
14
- @method_namespace = method_namespace
15
- end
16
-
17
- def encode_rpc_call(method_name, foreign_params)
18
- qname = create_method_qname(method_name)
19
- param_def = []
20
- params = foreign_params.map do |p|
21
- param_def << ['in', p.param.info.name, p.param.info.data.mapping]
22
- [p.param.info.name, p.soap_object]
23
- end
24
- request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
25
- request.set_param(params)
26
- envelope = create_soap_envelope(request)
27
- SOAP::Processor.marshal(envelope)
28
- end
29
-
30
- def decode_rpc_call(obj)
31
- envelope = SOAP::Processor.unmarshal(obj)
32
- unless envelope
33
- raise(SoapRpcError, "Malformed SOAP request")
34
- end
35
- request = envelope.body.request
36
- method_name = request.elename.name
37
- params = request.collect do |key, value|
38
- info = ParamInfo.new(key, nil, nil)
39
- param = Param.new(nil, info)
40
- Marshaling::SoapForeignObject.new(param, request[key])
41
- end
42
- [method_name, params]
43
- end
44
-
45
- def encode_rpc_response(method_name, return_value)
46
- response = nil
47
- qname = create_method_qname(method_name)
48
- if return_value.nil?
49
- response = SOAP::RPC::SOAPMethodResponse.new(qname, nil)
50
- else
51
- param = return_value.param
52
- soap_object = return_value.soap_object
53
- param_def = [['retval', 'return', param.info.data.mapping]]
54
- if soap_object.is_a?(SOAP::SOAPFault)
55
- response = soap_object
56
- else
57
- response = SOAP::RPC::SOAPMethodResponse.new(qname, param_def)
58
- response.retval = soap_object
59
- end
60
- end
61
- envelope = create_soap_envelope(response)
62
- SOAP::Processor.marshal(envelope)
63
- end
64
-
65
- def decode_rpc_response(obj)
66
- envelope = SOAP::Processor.unmarshal(obj)
67
- unless envelope
68
- raise(SoapRpcError, "Malformed SOAP response")
69
- end
70
- method_name = envelope.body.request.elename.name
71
- return_value = envelope.body.response
72
- info = ParamInfo.new('return', nil, nil)
73
- param = Param.new(nil, info)
74
- return_value = Marshaling::SoapForeignObject.new(param, return_value)
75
- [method_name, return_value]
76
- end
77
-
78
- private
79
- def create_soap_envelope(body)
80
- header = SOAP::SOAPHeader.new
81
- body = SOAP::SOAPBody.new(body)
82
- SOAP::SOAPEnvelope.new(header, body)
83
- end
84
-
85
- def create_method_qname(method_name)
86
- XSD::QName.new(@method_namespace, method_name)
87
- end
88
- end
89
- end
90
- end
@@ -1,53 +0,0 @@
1
- require 'xmlrpc/marshal'
2
-
3
- module WS
4
- module Encoding
5
- class XmlRpcError < WSError
6
- end
7
-
8
- class XmlRpcEncoding < AbstractEncoding
9
- def encode_rpc_call(method_name, params)
10
- XMLRPC::Marshal.dump_call(method_name, *params)
11
- end
12
-
13
- def decode_rpc_call(obj)
14
- method_name, params = XMLRPC::Marshal.load_call(obj) rescue nil
15
- unless method_name && params
16
- raise(XmlRpcError, "Malformed XML-RPC request")
17
- end
18
- i = 0
19
- params = params.map do |value|
20
- param = XmlRpcDecodedParam.new("param#{i}", value)
21
- i += 1
22
- param
23
- end
24
- [method_name, params]
25
- end
26
-
27
- def encode_rpc_response(method_name, return_value)
28
- if return_value.nil?
29
- XMLRPC::Marshal.dump_response(true)
30
- else
31
- XMLRPC::Marshal.dump_response(return_value)
32
- end
33
- end
34
-
35
- def decode_rpc_response(obj)
36
- return_value = XMLRPC::Marshal.load_response(obj) rescue nil
37
- if return_value.nil?
38
- raise(XmlRpcError, "Malformed XML-RPC response")
39
- end
40
- [nil, XmlRpcDecodedParam.new('return', return_value)]
41
- end
42
- end
43
-
44
- class XmlRpcDecodedParam
45
- attr :param
46
-
47
- def initialize(name, value)
48
- info = ParamInfo.new(name, value.class)
49
- @param = Param.new(value, info)
50
- end
51
- end
52
- end
53
- end
@@ -1,3 +0,0 @@
1
- require 'ws/marshaling/abstract'
2
- require 'ws/marshaling/soap_marshaling'
3
- require 'ws/marshaling/xmlrpc_marshaling'
@@ -1,17 +0,0 @@
1
- module WS
2
- module Marshaling
3
- class AbstractMarshaler
4
- def marshal(param)
5
- raise NotImplementedError
6
- end
7
-
8
- def unmarshal(param)
9
- raise NotImplementedError
10
- end
11
-
12
- def register_type(type)
13
- nil
14
- end
15
- end
16
- end
17
- end
@@ -1,277 +0,0 @@
1
- require 'soap/mapping'
2
- require 'xsd/ns'
3
-
4
- module WS
5
- module Marshaling
6
- SoapEncodingNS = 'http://schemas.xmlsoap.org/soap/encoding/'
7
-
8
- class SoapError < WSError
9
- end
10
-
11
- class SoapMarshaler < AbstractMarshaler
12
- attr :registry
13
- attr_accessor :type_namespace
14
-
15
- def initialize(type_namespace='')
16
- @type_namespace = type_namespace
17
- @registry = SOAP::Mapping::Registry.new
18
- @spec2binding = {}
19
- end
20
-
21
- def marshal(param)
22
- annotate_arrays(param.info.data, param.value)
23
- if param.value.is_a?(Exception)
24
- detail = SOAP::Mapping::SOAPException.new(param.value)
25
- soap_obj = SOAP::SOAPFault.new(
26
- SOAP::SOAPQName.new('%s:%s' % [SOAP::SOAPNamespaceTag, 'Server']),
27
- SOAP::SOAPString.new(param.value.to_s),
28
- SOAP::SOAPString.new(self.class.name),
29
- SOAP::Mapping.obj2soap(detail))
30
- else
31
- soap_obj = SOAP::Mapping.obj2soap(param.value, @registry)
32
- end
33
- SoapForeignObject.new(param, soap_obj)
34
- end
35
-
36
- def unmarshal(obj)
37
- param = obj.param
38
- soap_object = obj.soap_object
39
- soap_type = soap_object ? soap_object.type : nil
40
- value = soap_object ? SOAP::Mapping.soap2obj(soap_object, @registry) : nil
41
- param.value = value
42
- param.info.type = value.class
43
- mapping = @registry.find_mapped_soap_class(param.info.type) rescue nil
44
- if soap_type && soap_type.name == 'Array' && soap_type.namespace == SoapEncodingNS
45
- param.info.data = SoapBinding.new(self, soap_object.arytype, Array, mapping)
46
- else
47
- param.info.data = SoapBinding.new(self, soap_type, value.class, mapping)
48
- end
49
- param
50
- end
51
-
52
- def register_type(spec)
53
- if @spec2binding.has_key?(spec)
54
- return @spec2binding[spec]
55
- end
56
-
57
- klass = BaseTypes.canonical_param_type_class(spec)
58
- if klass.is_a?(Array)
59
- type_class = klass[0]
60
- else
61
- type_class = klass
62
- end
63
-
64
- type_binding = nil
65
- if (mapping = @registry.find_mapped_soap_class(type_class) rescue nil)
66
- qname = mapping[2] ? mapping[2][:type] : nil
67
- qname ||= soap_base_type_name(mapping[0])
68
- type_binding = SoapBinding.new(self, qname, type_class, mapping)
69
- else
70
- qname = XSD::QName.new(@type_namespace, soap_type_name(type_class.name))
71
- @registry.add(type_class,
72
- SOAP::SOAPStruct,
73
- typed_struct_factory(type_class),
74
- { :type => qname })
75
- mapping = @registry.find_mapped_soap_class(type_class)
76
- type_binding = SoapBinding.new(self, qname, type_class, mapping)
77
- end
78
-
79
- array_binding = nil
80
- if klass.is_a?(Array)
81
- array_mapping = @registry.find_mapped_soap_class(Array) rescue nil
82
- if (array_mapping && !array_mapping[1].is_a?(SoapTypedArrayFactory)) || array_mapping.nil?
83
- @registry.set(Array,
84
- SOAP::SOAPArray,
85
- SoapTypedArrayFactory.new)
86
- array_mapping = @registry.find_mapped_soap_class(Array)
87
- end
88
- qname = XSD::QName.new(@type_namespace, soap_type_name(type_class.name) + 'Array')
89
- array_binding = SoapBinding.new(self, qname, Array, array_mapping, type_binding)
90
- end
91
-
92
- @spec2binding[spec] = array_binding ? array_binding : type_binding
93
- @spec2binding[spec]
94
- end
95
-
96
- protected
97
- def annotate_arrays(binding, value)
98
- if binding.is_typed_array?
99
- mark_typed_array(value, binding.element_binding.qname)
100
- if binding.element_binding.is_custom_type?
101
- value.each do |element|
102
- annotate_arrays(register_type(element.class), element)
103
- end
104
- end
105
- elsif binding.is_typed_struct?
106
- if binding.type_class.respond_to?(:members)
107
- binding.type_class.members.each do |name, spec|
108
- member_binding = register_type(spec)
109
- member_value = value.send(name)
110
- if member_binding.is_custom_type?
111
- annotate_arrays(member_binding, member_value)
112
- end
113
- end
114
- end
115
- end
116
- end
117
-
118
- def mark_typed_array(array, qname)
119
- (class << array; self; end).class_eval do
120
- define_method(:arytype) do
121
- qname
122
- end
123
- end
124
- end
125
-
126
- def typed_struct_factory(type_class)
127
- if Object.const_defined?('ActiveRecord')
128
- if WS.derived_from?(ActiveRecord::Base, type_class)
129
- qname = XSD::QName.new(@type_namespace, soap_type_name(type_class.name))
130
- type_class.instance_variable_set('@qname', qname)
131
- return SoapActiveRecordStructFactory.new
132
- end
133
- end
134
- SOAP::Mapping::Registry::TypedStructFactory
135
- end
136
-
137
- def soap_type_name(type_name)
138
- type_name.gsub(/::/, '..')
139
- end
140
-
141
- def soap_base_type_name(type)
142
- xsd_type = type.ancestors.find{|c| c.const_defined? 'Type'}
143
- xsd_type ? xsd_type.const_get('Type') : XSD::XSDAnySimpleType::Type
144
- end
145
- end
146
-
147
- class SoapForeignObject
148
- attr_accessor :param
149
- attr_accessor :soap_object
150
-
151
- def initialize(param, soap_object)
152
- @param = param
153
- @soap_object = soap_object
154
- end
155
- end
156
-
157
- class SoapBinding
158
- attr :qname
159
- attr :type_class
160
- attr :mapping
161
- attr :element_binding
162
-
163
- def initialize(marshaler, qname, type_class, mapping, element_binding=nil)
164
- @marshaler = marshaler
165
- @qname = qname
166
- @type_class = type_class
167
- @mapping = mapping
168
- @element_binding = element_binding
169
- end
170
-
171
- def is_custom_type?
172
- is_typed_array? || is_typed_struct?
173
- end
174
-
175
- def is_typed_array?
176
- @mapping[1].is_a?(WS::Marshaling::SoapTypedArrayFactory)
177
- end
178
-
179
- def is_typed_struct?
180
- @mapping[1] == SOAP::Mapping::Registry::TypedStructFactory || \
181
- @mapping[1].is_a?(WS::Marshaling::SoapActiveRecordStructFactory)
182
- end
183
-
184
- def each_member(&block)
185
- if is_typed_struct?
186
- if @mapping[1] == SOAP::Mapping::Registry::TypedStructFactory
187
- if @type_class.respond_to?(:members)
188
- @type_class.members.each do |name, spec|
189
- yield name, spec
190
- end
191
- end
192
- elsif @mapping[1].is_a?(WS::Marshaling::SoapActiveRecordStructFactory)
193
- @type_class.columns.each do |column|
194
- yield column.name, column.klass
195
- end
196
- end
197
- end
198
- end
199
-
200
- def type_name
201
- is_custom_type? ? @qname.name : nil
202
- end
203
-
204
- def qualified_type_name(ns=nil)
205
- if is_custom_type?
206
- "#{ns ? ns : @qname.namespace}:#{@qname.name}"
207
- else
208
- ns = XSD::NS.new
209
- ns.assign(XSD::Namespace, SOAP::XSDNamespaceTag)
210
- xsd_klass = mapping[0].ancestors.find{|c| c.const_defined?('Type')}
211
- return ns.name(XSD::AnyTypeName) unless xsd_klass
212
- ns.name(xsd_klass.const_get('Type'))
213
- end
214
- end
215
- end
216
-
217
- class SoapActiveRecordStructFactory < SOAP::Mapping::Factory
218
- def obj2soap(soap_class, obj, info, map)
219
- unless obj.is_a?(ActiveRecord::Base)
220
- return nil
221
- end
222
- soap_obj = soap_class.new(obj.class.instance_variable_get('@qname'))
223
- obj.class.columns.each do |column|
224
- key = column.name.to_s
225
- value = obj.send(key)
226
- soap_obj[key] = SOAP::Mapping._obj2soap(value, map)
227
- end
228
- soap_obj
229
- end
230
-
231
- def soap2obj(obj_class, node, info, map)
232
- unless node.type == obj_class.instance_variable_get('@qname')
233
- return false
234
- end
235
- obj = obj_class.new
236
- node.each do |key, value|
237
- obj[key] = value.data
238
- end
239
- obj.instance_variable_set('@new_record', false)
240
- return true, obj
241
- end
242
- end
243
-
244
- class SoapTypedArrayFactory < SOAP::Mapping::Factory
245
- def obj2soap(soap_class, obj, info, map)
246
- unless obj.respond_to?(:arytype)
247
- return nil
248
- end
249
- soap_obj = soap_class.new(SOAP::ValueArrayName, 1, obj.arytype)
250
- mark_marshalled_obj(obj, soap_obj)
251
- obj.each do |item|
252
- child = SOAP::Mapping._obj2soap(item, map)
253
- soap_obj.add(child)
254
- end
255
- soap_obj
256
- end
257
-
258
- def soap2obj(obj_class, node, info, map)
259
- return false
260
- end
261
- end
262
-
263
- module ActiveRecordSoapMarshallable
264
- def allocate
265
- obj = super
266
- attrs = {}
267
- self.columns.each{|c| attrs[c.name.to_s] = c.default}
268
- obj.instance_variable_set('@attributes', attrs)
269
- obj
270
- end
271
- end
272
-
273
- if Object.const_defined?('ActiveRecord')
274
- ActiveRecord::Base.extend(ActiveRecordSoapMarshallable)
275
- end
276
- end
277
- end