Module: ActiveRecordExtended::ArrayAndJsonbQueryMethods

Defined in:
lib/active_record_extended/array_and_jsonb_query_methods.rb

Instance Method Summary collapse

Instance Method Details

#any_of(*conditions) ⇒ Object

WHERE (cond_a) OR (cond_b) OR ... -- each condition is a Hash of
attribute filters or an existing Relation. Mirrors the gem's
where.any_of(...) API so call sites stay readable.

Branches are built FROM @scope (not from @scope.klass) so any
joins/references already on the chain carry into each OR branch.
Otherwise Model.joins(:assoc).where.any_of(...) would build OR
branches without the join context and produce invalid SQL.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/active_record_extended/array_and_jsonb_query_methods.rb', line 68

def any_of(*conditions)
  return @scope if conditions.empty?

  relations = conditions.map do |cond|
    case cond
    when ActiveRecord::Relation then @scope.merge(cond)
    when Hash                   then @scope.where(cond)
    else
      raise ArgumentError, "where.any_of expects Hash or Relation; got #{cond.class}"
    end
  end

  relations.reduce { |memo, rel| memo.or(rel) }
end

#contains(opts) ⇒ Object

column @> value -- jsonb (Hash) or array (Array) containment.
Same element-type-cast discipline as overlap for the array branch.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/active_record_extended/array_and_jsonb_query_methods.rb', line 42

def contains(opts)
  scope = @scope
  opts.each do |column, value|
    qualified = qualify_column(scope, column)
    scope =
      case value
      when Hash
        scope.where("#{qualified} @> ?", value.to_json)
      when Array
        cast = pg_array_cast(scope, column)
        scope.where("#{qualified} @> ARRAY[?]#{cast}", value)
      else
        raise ArgumentError, "where.contains expects Hash (jsonb) or Array; got #{value.class}"
      end
  end
  scope
end

#overlap(opts) ⇒ Object

column && ARRAY[...] -- true when any element overlaps. Empty input
short-circuits to none (overlap with empty array is always false).

PG requires matching array element types for &&. We discover the
column's element type from AR column metadata and cast the RHS literal
accordingly — otherwise varchar[] && ARRAY['x'] (which defaults to
text[]) errors with "operator does not exist: character varying[] && text[]".



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/active_record_extended/array_and_jsonb_query_methods.rb', line 27

def overlap(opts)
  scope = @scope
  opts.each do |column, values|
    values = Array(values)
    return scope.none if values.empty?

    qualified = qualify_column(scope, column)
    cast = pg_array_cast(scope, column)
    scope = scope.where("#{qualified} && ARRAY[?]#{cast}", values)
  end
  scope
end