Forum: Ruby on Rails Problem w/ActionWebService and Inheritance in Service Params

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Jason F. (Guest)
on 2009-02-26 16:50
I have a service method that takes a PaymentMethod which can either be a
CreditCard or a PayPal account.  When I request the service and pass one
or the other it always comes over as a PaymentMethod; the service
doesn't seem to know that the parameter is really a CreditCard or
PayPal.  Here's some sample code that illustrates what I'm talking about
more concretely:

class PaymentsApi < ActionWebService::API::Base
 api_method(
   :create_payment,
   :expects => [
     { :payment_method => PaymentMethod }
   ],
   :returns => [ :payment_id => :string ]
 )
end

class PaymentMethod < ActionWebService::Struct
 # ...
end

class CreditCard < PaymentMethod
 # ...
end

class PayPal < PaymentMethod
 # ...
end

I see in the request XML that it knows that the payment_method is really
a CreditCard or Invoice (note the xsi:type).

<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <env:Body>
    <n1:CreatePayment xmlns:n1="urn:ActionWebService"
env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <payment_method
xmlns:n2="http://www.ruby-lang.org/xmlns/ruby/type/custom"
xsi:type="n2:CreditCard">
        ...
      </payment_method>
    </n1:CreatePayment>
  </env:Body>
</env:Envelope>

However, when I attempt to switch in the controller based on the type of
the payment_method it doesn't seem to remember that it knows this.  Is
it not possible to use this type of polymorphism in service parameters
or am I doing something wrong?

Any help would be much appreciated.

Thanks in advance,
Jason
Jason F. (Guest)
on 2009-02-26 19:17
Jason F. wrote:

> I have a service method that takes a PaymentMethod which can either be a
> CreditCard or a PayPal account.  When I request the service and pass one
> or the other it always comes over as a PaymentMethod; the service
> doesn't seem to know that the parameter is really a CreditCard or
> PayPal.

I tracked down the issue to the cast_to_structured_type method of
casting.rb. Essentially, a condition needs to be added that would
effectively cause the code to not attempt to "cast" the parameter if it
is derived from the type specified in the API declaration. Here's a
one-line modification:

  # lib/action_web_service/castings.rb - line 120
  obj = value if canonical_type(value.class) ==
canonical_type(signature_type.type)

And here's how it would read after the patch along with the next
unmodified line (121) for reference:

  obj = value if canonical_type(value.class) ==
canonical_type(signature_type.type) or
derived_from?(signature_type.type, value.class)
  obj ||= signature_type.type_class.new

I am going to look into submitting a patch. Can anyone think of why this
shouldn't work this way?  I am also asking the priest who resurrected
this code from the dead.

http://www.datanoise.com/articles/2008/7/2/actionw...

Jason
This topic is locked and can not be replied to.