Sometimes you have one endpoint that accepts different payloads with some type
identifier. While you can pass Resource
, Serializer
and Deserializer
to the Operation
, the Operation
tries to infer Resource
class from its name.
There are two ways to solve this:
You create Operation
for specific endpoint and dummy Resource
with Serializer
and Deserializer
. Then you create Resource
, Serializer
and Deserializer
for each type
you have and you pass these into the Operation
.
resource = MyResource.new(name: 'Test')
serializer = MyResource::Serializer.new
deserializer = MyResource::Deserializer.new
operation = MainOperation.new(client: client, resource: resource, serializer: serializer, deserializer: deserializer)
operation.perform
This should be enough, but afaik it wasnt. I don't remember why.
In above step you need to define Resource
, Serializer
and Deserializer
for each type. From this it is not that far to simply define Operation
for each type. All of these operations will be hitting same endpoint, just using different type
from serializer.
This illustrates 2nd approach. (bit simplified)
module Rainforest
class Product < Rainforest::Resource
attribute :asin, type: LedgerSync::Type::String
attribute :amazon_domain, type: LedgerSync::Type::String
attribute :title, type: LedgerSync::Type::String
# ...
end
end
module Rainforest
class ProductDataApi < Rainforest::Resource
attribute :amazon_domain, type: LedgerSync::Type::String
references_one :product, to: Product
# ...
end
end
module Rainforest
class ProductOffersApi < Rainforest::Resource
attribute :amazon_domain, type: LedgerSync::Type::String
attribute :page, type: LedgerSync::Type::Integer
references_one :product, to: Product
# ...
end
end
module Rainforest
class ProductDataApi
class Serializer < LedgerSync::Serializer
attribute :asin, resource_attribute: :ledger_id
attribute :amazon_domain
attribute :type do
'product'
end
end
end
end
module Rainforest
class ProductDataApi
class Deserializer < LedgerSync::Deserializer
references_one :product, deserializer: Rainforest::Product::Deserializer
# ...
end
end
end
module Rainforest
class ProductDataApi
module Operations
class Find < Rainforest::Operation::Find
private
def operate
return failure('Rainforest api request failed') if response.failure?
success(
resource: deserializer.deserialize(hash: response.body, resource: resource),
response: response.body
)
end
def response
@response ||= client.get(
path: '/request',
params: serializer.serialize(resource: resource)
)
end
end
end
end
end
module Rainforest
class ProductOffersApi
class Serializer < LedgerSync::Serializer
attribute :asin, resource_attribute: :ledger_id
attribute :amazon_domain
attribute :page
attribute :type do
'offers'
end
end
end
end
module Rainforest
class ProductOffersApi
class Deserializer < LedgerSync::Deserializer
references_one :product, deserializer: Rainforest::Product::Deserializer
# ...
end
end
end
module Rainforest
class ProductOffersApi
module Operations
class Find < Rainforest::Operation::Find
private
def operate
return failure('Rainforest api request failed') if response.failure?
success(
resource: deserializer.deserialize(hash: response.body, resource: resource),
response: response.body
)
end
def response
@response ||= client.get(
path: '/request',
params: serializer.serialize(resource: resource)
)
end
end
end
end
end