# frozen_string_literal: true module JsonbAccessor module QueryBuilder extend ActiveSupport::Concern included do scope(:jsonb_contains, lambda do |column_name, attributes| JsonbAccessor::QueryHelper.validate_column_name!(all, column_name) where("#{table_name}.#{column_name} @> (?)::jsonb", attributes.to_json) end) scope(:jsonb_excludes, lambda do |column_name, attributes| JsonbAccessor::QueryHelper.validate_column_name!(all, column_name) where.not("#{table_name}.#{column_name} @> (?)::jsonb", attributes.to_json) end) scope(:jsonb_number_where, lambda do |column_name, field_name, given_operator, value| JsonbAccessor::QueryHelper.validate_column_name!(all, column_name) operator = JsonbAccessor::QueryHelper::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s) where("(#{table_name}.#{column_name} ->> ?)::float #{operator} ?", field_name, value) end) scope(:jsonb_number_where_not, lambda do |column_name, field_name, given_operator, value| JsonbAccessor::QueryHelper.validate_column_name!(all, column_name) operator = JsonbAccessor::QueryHelper::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s) where.not("(#{table_name}.#{column_name} ->> ?)::float #{operator} ?", field_name, value) end) scope(:jsonb_time_where, lambda do |column_name, field_name, given_operator, value| JsonbAccessor::QueryHelper.validate_column_name!(all, column_name) operator = JsonbAccessor::QueryHelper::TIME_OPERATORS_MAP.fetch(given_operator.to_s) where("(#{table_name}.#{column_name} ->> ?)::timestamp #{operator} ?", field_name, value) end) scope(:jsonb_time_where_not, lambda do |column_name, field_name, given_operator, value| JsonbAccessor::QueryHelper.validate_column_name!(all, column_name) operator = JsonbAccessor::QueryHelper::TIME_OPERATORS_MAP.fetch(given_operator.to_s) where.not("(#{table_name}.#{column_name} ->> ?)::timestamp #{operator} ?", field_name, value) end) scope(:jsonb_where, lambda do |column_name, attributes| query = all contains_attributes = {} JsonbAccessor::QueryHelper.convert_ranges(attributes).each do |name, value| if JsonbAccessor::QueryHelper.number_query_arguments?(value) value.each { |operator, query_value| query = query.jsonb_number_where(column_name, name, operator, query_value) } elsif JsonbAccessor::QueryHelper.time_query_arguments?(value) value.each { |operator, query_value| query = query.jsonb_time_where(column_name, name, operator, query_value) } else contains_attributes[name] = value end end query.jsonb_contains(column_name, contains_attributes) end) scope(:jsonb_where_not, lambda do |column_name, attributes| query = all excludes_attributes = {} attributes.each do |name, value| if value.is_a?(Range) raise JsonbAccessor::QueryHelper::NotSupported, "`jsonb_where_not` scope does not accept ranges as arguments. Given `#{value}` for `#{name}` field" end if JsonbAccessor::QueryHelper.number_query_arguments?(value) value.each { |operator, query_value| query = query.jsonb_number_where_not(column_name, name, operator, query_value) } elsif JsonbAccessor::QueryHelper.time_query_arguments?(value) value.each { |operator, query_value| query = query.jsonb_time_where_not(column_name, name, operator, query_value) } else excludes_attributes[name] = value end end excludes_attributes.empty? ? query : query.jsonb_excludes(column_name, excludes_attributes) end) scope(:jsonb_order, lambda do |column_name, field_name, direction| JsonbAccessor::QueryHelper.validate_column_name!(all, column_name) JsonbAccessor::QueryHelper.validate_field_name!(all, column_name, field_name) JsonbAccessor::QueryHelper.validate_direction!(direction) order("(#{table_name}.#{column_name} -> '#{field_name}') #{direction}") end) end end end