# frozen_string_literal: true require_relative 'context' require_relative 'finder_methods' require_relative 'pagination_methods' require_relative 'persistence' require_relative 'query_methods' module ErpIntegration module Fulfil class ApiResource include Context include Enumerable include FinderMethods include PaginationMethods include Persistence include QueryMethods attr_accessor :resource_klass delegate :client, :model_name, to: 'self.class' def initialize(resource_klass) @resource_klass = resource_klass end # The `client` exposes the `ErpIntegration::Fulfil::Client` to the class. # @return [ErpIntegration::Fulfil::Client] The HTTP client for Fulfil. def self.client Client.new( api_key: config.fulfil_api_key, merchant_id: config.fulfil_merchant_id, logger: config.logger ) end # The `config` exposes the gem's configuration to the `ApiResource`. # @return [ErpIntegration::Configuration] The gem's configuration object. def self.config ErpIntegration.config end # Fulfil doesn't use logical naming conventions. However, we do need # the name of a model to build the resource URI. # # By manually setting the model name, we allow the `Fulfil::Connection` # module to connect to the correct API endpoint. # # @param name [String] The logical path name in Fulfil. # @return [String] The model name def self.model_name=(name) instance_variable_set(:@model_name, name) end def self.model_name instance_variable_get(:@model_name) end # The `where` and `includes` methods lazyly build a search/read query # for Fulfil. By calling `all`, the prepared search/read query will actually # be executed and the results will be fetched. # @return [Array] An enumerable collection object with all API results. def all return @results if defined?(@results) @results = client.put( api_resource_path, Query.new( fields: selected_fields, filters: where_clauses, alternative_filters: or_clauses, offset: offset_clause, limit: limit_clause ) ).map { |item| resource_klass.new(item) } end # As with the `all` method, the `query methods` lazyly build a search/read # or search/count query for Fulfil. # By calling `count`, the prepared search/count will actually be executed and # the result will be fetched # @return [Integer] The count of records that match with the query in Fulfil def count return @count if defined?(@count) @count = client.put( "model/#{model_name}/search_count", Query.new( fields: nil, filters: where_clauses, alternative_filters: or_clauses ).to_h.except(:fields, :offset, :limit) ) end # The `each` method turns the `ApiResource` instance into an enumerable object. # For more information, see https://ruby-doc.org/core-3.0.2/Enumerable.html def each(&block) all.each(&block) end private # Builds the relative resource path and adds the context if needed. # # @return [String] def api_resource_path base_path = "model/#{model_name}/search_read" return base_path unless context? "#{base_path}?context=#{context.to_json}" end end end end