require 'uri' module SpreeClient module API class V1 class Resources # Spree API client instance. # @return [SpreeClient::API::V1] attr_reader :api # Every method caches the response so it can be inspected afterwards. # @return [HTTParty::Response] The API response attr_reader :response # @return [Hash] attr_reader :default_args # Initialize # # @param [SpreeClient::API::V1] :api An API client instance def initialize(**args) @api = args.delete :api @default_args = args end # Initialize a new resource # # @param [Hash] Attributes # @return [Struct] def new(**args) resource_class.new **args end # Gets all products or filter with params # # Filters: # # ids: comma-separated list of IDs # q: Ransack search params (mutually exclusive with ids) # # Pagination: # # page: page number # per_page: results per page # # @param [Hash] Query params def index(**q) @response = api.class.get endpoint(q), query: q.slice(:ids, :q, :page, :per_page), headers: api.headers response.ok? end # Get a single product by ID def show(resource) @response = api.class.get endpoint(resource), headers: api.headers response.ok? end # Creates a resource # # @see SpreeClient::API::V1#headers # @param [Struct,Hash] Model instance # @return [Boolean] def create(resource) resource = new **resource unless resource.is_a? resource_class @response = api.class.post endpoint(resource), body: params(resource), headers: api.headers response.created? end # Updates a resource # # @see SpreeClient::API::V1#headers # @param [Struct,Hash] # @return [Boolean] def update(resource) resource = new resource unless resource.is_a? resource_class @response = api.class.patch endpoint(resource), body: params(resource), headers: api.headers response.ok? end # Deletes a resource # # @see SpreeClient::API::V1#headers # @param [Struct,Hash] # @return [Boolean] def delete(resource) @response = spree.class.delete endpoint(resource), headers: api.headers response.no_content? end private # Strong parameters # # @see SpreeClient#authenticity_token # @param [Struct,Nil] # @return [Hash] def params(resource = nil) { resource_name => default_args.merge(resource.to_h.compact) }.to_json end # Backend endpoint # # @param [Struct] # @return [String] def endpoint(resource = {}) endpoint = self.class::ENDPOINT + (resource.dig(:id) ? '/:id' : '') parameterize_with endpoint, resource end # Generates a URL with :parameter replaced with values # # @param [String] # @param [Struct,Hash] def parameterize_with(endpoint, resource = {}) default_args.merge(resource.to_h.compact).inject(endpoint) do |e, pair| e.gsub ':' + pair.first.to_s, pair.last.to_s end + '.json' end def resource_class self.class::RESOURCE end def resource_name self.class::NAME end end end end end