# frozen_string_literal: true module IronBank # A query builder helps buidling a syntaxically correct query using ZOQL. # class QueryBuilder private_class_method :new def self.zoql(object, fields, conditions = {}) new(object, fields, conditions).zoql end def zoql query = "select #{query_fields} from #{object}" conditions.empty? ? query : "#{query} where #{query_conditions}" end private attr_reader :object, :fields, :conditions def initialize(object, fields, conditions) @object = object @fields = fields @conditions = conditions end def query_fields fields.join(',') end def query_conditions ensure_range_single_condition case conditions when Hash hash_query_conditions end end def range_query_builder(field, value) value.each.with_object([]) do |option, range_query| range_query << "#{field}='#{option}'" end.join(' OR ') end def hash_query_conditions conditions.each.with_object([]) do |(field, value), filters| # TODO: sanitize the value field = IronBank::Utils.camelize(field) filters << current_filter(field, value) end.join(' AND ') end def current_filter(field, value) if value.is_a?(Array) range_query_builder(field, value) elsif [true, false].include? value "#{field}=#{value}" else "#{field}='#{value}'" end end def ensure_range_single_condition return if conditions.count <= 1 return unless conditions.values.any? { |value| value.is_a?(Array) } raise 'Filter ranges must be used in isolation.' end end end