diff options
author | Leon Breedt <bitserf@gmail.com> | 2005-04-02 21:03:36 +0000 |
---|---|---|
committer | Leon Breedt <bitserf@gmail.com> | 2005-04-02 21:03:36 +0000 |
commit | aaea48fe9826b9e5d2d5b92795a297b8f238c58d (patch) | |
tree | e7c01c7f95d467f837c1f96d58dac74c3c902610 /actionwebservice/lib/action_web_service/api | |
parent | aa09c770e9b5400683be11952673017295246de7 (diff) | |
download | rails-aaea48fe9826b9e5d2d5b92795a297b8f238c58d.tar.gz rails-aaea48fe9826b9e5d2d5b92795a297b8f238c58d.tar.bz2 rails-aaea48fe9826b9e5d2d5b92795a297b8f238c58d.zip |
* collapse 'ws' back into protocols, it just added complexity and indirection, and was hard to extend.
* extract casting into seperate support file
* ensure casting always does the right thing for return values, should fix interoperability issues with Ecto and possibly other XML-RPC clients
* add functional unit tests for scaffolding
* represent signature items with classes instead of symbols/Class objects, much more flexible
* tweak logging to always show casted versions of parameters and return values, if possible.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1072 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice/lib/action_web_service/api')
-rw-r--r-- | actionwebservice/lib/action_web_service/api/base.rb | 146 |
1 files changed, 18 insertions, 128 deletions
diff --git a/actionwebservice/lib/action_web_service/api/base.rb b/actionwebservice/lib/action_web_service/api/base.rb index 03e406cfc3..c9fb9f967f 100644 --- a/actionwebservice/lib/action_web_service/api/base.rb +++ b/actionwebservice/lib/action_web_service/api/base.rb @@ -1,8 +1,5 @@ module ActionWebService # :nodoc: module API # :nodoc: - class CastingError < ActionWebService::ActionWebServiceError - end - # A web service API class specifies the methods that will be available for # invocation for an API. It also contains metadata such as the method type # signature hints. @@ -31,6 +28,8 @@ module ActionWebService # :nodoc: private_class_method :new, :allocate class << self + include ActionWebService::SignatureTypes + # API methods have a +name+, which must be the Ruby method name to use when # performing the invocation on the web service object. # @@ -70,10 +69,9 @@ module ActionWebService # :nodoc: expects = canonical_signature(expects) returns = canonical_signature(returns) if expects - expects.each do |param| - klass = WS::BaseTypes.canonical_param_type_class(param) - klass = klass[0] if klass.is_a?(Array) - if klass.ancestors.include?(ActiveRecord::Base) && !allow_active_record_expects + expects.each do |type| + type = type.element_type if type.is_a?(ArrayType) + if type.type_class.ancestors.include?(ActiveRecord::Base) && !allow_active_record_expects raise(ActionWebServiceError, "ActiveRecord model classes not allowed in :expects") end end @@ -138,16 +136,6 @@ module ActionWebService # :nodoc: instance end - # Creates a dummy API Method instance for the given public method name - def dummy_public_api_method_instance(public_method_name) - Method.new(public_method_name.underscore.to_sym, public_method_name, nil, nil) - end - - # Creates a dummy API Method instance for the given method name - def dummy_api_method_instance(method_name) - Method.new(method_name, public_api_method_name(method_name), nil, nil) - end - private def api_public_method_names read_inheritable_attribute("api_public_method_names") || {} @@ -159,11 +147,6 @@ module ActionWebService # :nodoc: raise(ActionWebServiceError, "Unknown options: #{unknown_option_keys}") end end - - def canonical_signature(signature) - return nil if signature.nil? - signature.map{|spec| WS::BaseTypes.canonical_param_type_spec(spec)} - end end end @@ -180,134 +163,41 @@ module ActionWebService # :nodoc: @public_name = public_name @expects = expects @returns = returns + @caster = ActionWebService::Casting::BaseCaster.new(self) end # The list of parameter names for this method def param_names return [] unless @expects - i = 0 - @expects.map{ |spec| param_name(spec, i += 1) } - end - - # The name for the given parameter - def param_name(spec, i=1) - spec.is_a?(Hash) ? spec.keys.first.to_s : "p#{i}" - end - - # The type of the parameter declared in +spec+. Is either - # the Class of the parameter, or its canonical name (if its a - # base type). Typed array specifications will return the type of - # their elements. - def param_type(spec) - spec = spec.values.first if spec.is_a?(Hash) - param_type = spec.is_a?(Array) ? spec[0] : spec - WS::BaseTypes::class_to_type_name(param_type) rescue param_type - end - - # The Class of the parameter declared in +spec+. - def param_class(spec) - type = param_type(spec) - type.is_a?(Symbol) ? WS::BaseTypes.type_name_to_class(type) : type - end - - # Registers all types known to this method with the given marshaler - def register_types(marshaler) - @expects.each{ |x| marshaler.register_type(x) } if @expects - @returns.each{ |x| marshaler.register_type(x) } if @returns + @expects.map{ |type| type.name } end - # Encodes an RPC call for this method. Casting is performed if - # the <tt>:strict</tt> option is given. - def encode_rpc_call(marshaler, encoder, params, options={}) - name = options[:method_name] || @public_name - expects = @expects || [] - returns = @returns || [] - (expects + returns).each { |spec| marshaler.register_type spec } - (0..(params.length-1)).each do |i| - spec = expects[i] || params[i].class - type_binding = marshaler.lookup_type(spec) - param_info = WS::ParamInfo.create(spec, type_binding, i) - if options[:strict] - value = marshaler.cast_outbound_recursive(params[i], spec) - else - value = params[i] - end - param = WS::Param.new(value, param_info) - params[i] = marshaler.marshal(param) - end - encoder.encode_rpc_call(name, params) - end - - # Encodes an RPC response for this method. Casting is performed if - # the <tt>:strict</tt> option is given. - def encode_rpc_response(marshaler, encoder, return_value, options={}) - if !return_value.nil? && @returns - return_type = @returns[0] - type_binding = marshaler.register_type(return_type) - param_info = WS::ParamInfo.create(return_type, type_binding, 0) - if options[:strict] - return_value = marshaler.cast_inbound_recursive(return_value, return_type) - end - return_value = marshaler.marshal(WS::Param.new(return_value, param_info)) - else - return_value = nil - end - encoder.encode_rpc_response(response_name(encoder), return_value) - end - - # Casts a set of WS::Param values into the appropriate - # Ruby values - def cast_expects_ws2ruby(marshaler, params) - return [] if @expects.nil? - i = 0 - @expects.map do |spec| - value = marshaler.cast_inbound_recursive(params[i].value, spec) - i += 1 - value - end - end - # Casts a set of Ruby values into the expected Ruby values - def cast_expects(marshaler, params) - return [] if @expects.nil? - i = 0 - @expects.map do |spec| - value = marshaler.cast_outbound_recursive(params[i], spec) - i += 1 - value - end + def cast_expects(params) + @caster.cast_expects(params) end # Cast a Ruby return value into the expected Ruby value - def cast_returns(marshaler, return_value) - return nil if @returns.nil? - marshaler.cast_inbound_recursive(return_value, @returns[0]) + def cast_returns(return_value) + @caster.cast_returns(return_value) end # String representation of this method def to_s fqn = "" - fqn << (@returns ? (friendly_param(@returns[0], nil) + " ") : "void ") + fqn << (@returns ? (friendly_param(@returns[0], false) + " ") : "void ") fqn << "#{@public_name}(" - if @expects - i = 0 - fqn << @expects.map{ |p| friendly_param(p, i+= 1) }.join(", ") - end + fqn << @expects.map{ |p| friendly_param(p) }.join(", ") if @expects fqn << ")" fqn end private - def response_name(encoder) - encoder.is_a?(WS::Encoding::SoapRpcEncoding) ? (@public_name + "Response") : @public_name - end - - def friendly_param(spec, i) - name = param_name(spec, i) - type = param_type(spec) - spec = spec.values.first if spec.is_a?(Hash) - type = spec.is_a?(Array) ? (type.to_s + "[]") : type.to_s - i ? (type + " " + name) : type + def friendly_param(type, show_name=true) + name = type.name.to_s + type_type = type.type.to_s + str = type.array?? (type_type + '[]') : type_type + show_name ? (str + " " + name) : str end end end |