# frozen_string_literal: true require_relative 'query' require_relative 'where_clause' require_relative 'or_clause' module ErpIntegration module Fulfil module QueryMethods attr_accessor :selected_fields, :where_clauses, :or_clauses # The `QueryMethods#select` works in two unique ways # # First, it takes a block to allow it to function like a regular `Enumerable#select`. # # @example # $ ErpIntegration::SalesOrder.select { |sales_order| sales_order.id > 100 } # # => [, ] # # Secondly, it allows us to select specific fields to be returned by Fulfil. # # Fulfil only returns an ID by default when one would query their API. However, # the ID is seldom the only value one will need. The `select` method allows # selecting multiple fields at once. # # @example # $ ErpIntegration::SalesOrder.select(:id, :name, 'product.name') # # => # # When one calls the `all` method, it will fetch all the resources from Fulfil # and it will return all the given fields (if available). # # @example # $ ErpIntegration::SalesOrder.select(:id, :name, 'product.name').all # # => [, ] # # Both a list of Strings, Symbols or a combination of these can be passed # to the `select` method. def select(*fields) if block_given? raise ArgumentError, "'select' with block doesn't take arguments." if fields.any? return super() end clone.select!(*fields) end def select!(*fields) self.selected_fields = (selected_fields || []).concat(fields) self end # Fulfil has a very powerful query syntax. However, that query syntax is rather # complicated and it's really specific to Fulfil. # # The `where` method introduces a well-known interface (e.g. ActiveRecord::Relation) # to query resources in Fulfil. # # @example # $ ErpIntegration::SalesOrder.where(id: 100).all # # => ] /> # # If one adds the `comparison_operator` key to the arguments, it will use # that comparison operator to build the query to Fulfil. # # All the other `where_` methods use this technique to provide logic for all # the different comparison operators. def where(*args) clone.where!(*args) end def where!(args) comparison_operator = args.delete(:comparison_operator) args.each_pair do |key, value| self.where_clauses = (where_clauses || []) << WhereClause.new( key: key, value: value, comparison_operator: comparison_operator ) end self end # The `or` method introduces an interface to query resources in Fulfil # Is quite similar to the `where` method but with one big difference. # The `or` method allows us to use the OR operator with several conditions # # @example # $ ErpIntegration::SalesOrder.or(id: 100, carrier: 12).all # # => # ] /> # # @example # $ ErpIntegration::SalesOrder.or(id: [100, 200]).all # # => # ] /> # # Now we are just accepting the last 'or' method so if we have multiple # we are only accepting the last one. def or(*args) clone.or!(*args) end def or!(args) where_clauses = [] args.each_pair do |key, value_or_values| [*value_or_values].each do |value| where_clauses << WhereClause.new( key: key, value: value ) end end self.or_clauses = [ OrClause.new( where_clauses: where_clauses ) ] self end def where_ilike(args) where(args.merge(comparison_operator: 'ilike')) end def where_in(args) where(args.merge(comparison_operator: 'in')) end def where_less_than(args) where(args.merge(comparison_operator: '<')) end def where_less_or_equal_to(args) where(args.merge(comparison_operator: '<=')) end def where_like(args) where(args.merge(comparison_operator: 'like')) end def where_more_than(args) where(args.merge(comparison_operator: '>')) end def where_more_or_equal_to(args) where(args.merge(comparison_operator: '>=')) end def where_not(args) where(args.merge(comparison_operator: '!=')) end def where_not_in(args) where(args.merge(comparison_operator: 'not in')) end end end end