File: query_builder.rb

package info (click to toggle)
ruby-jsonb-accessor 1.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 204 kB
  • sloc: ruby: 371; makefile: 10; sh: 5
file content (86 lines) | stat: -rw-r--r-- 4,199 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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|
          raise JsonbAccessor::QueryHelper::NotSupported, "`jsonb_where_not` scope does not accept ranges as arguments. Given `#{value}` for `#{name}` field" if value.is_a?(Range)

          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(Arel.sql("(#{table_name}.#{column_name} -> '#{field_name}') #{direction}"))
      end)
    end
  end
end