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.performThis 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
endmodule 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
endmodule 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