Module: ActiveRecordExtended::LtreeQueryMethods

Defined in:
lib/active_record_extended/ltree_query_methods.rb

Instance Method Summary collapse

Instance Method Details

#ltree_contains(column, ids, array: true) ⇒ Object

ltree contains check - does the path contain a specific subpath anywhere?
Uses the index() function which has no simple Arel equivalent.

Example:
ProductLine.where.ltree_contains(:ltree_path_ids, '102', array: false)
ViewProductCatalog.where.ltree_contains(:all_pl_paths_ids, [1, 2])
CatalogItem.with_item.where.ltree_contains('items.all_pl_paths_ids', [58, 59])

Parameters:

  • column (Symbol, String)

    The ltree or ltree[] column (can include table: 'items.all_pl_paths_ids')

  • ids (String, Integer, Array)

    The ID(s) to find in the path

  • array (Boolean) (defaults to: true)

    Whether the column is an ltree[] (default: true)



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/active_record_extended/ltree_query_methods.rb', line 72

def ltree_contains(column, ids, array: true)
  ids = [ids].flatten.compact.map { |id| Integer(id, exception: false) }.compact
  return none_query if ids.empty?

  col = column.to_s.include?('.') ? column.to_s : "#{table_name}.#{column}"

  if array
    @scope.where(
      "EXISTS (SELECT 1 FROM unnest(#{col}) AS p, unnest(ARRAY[?]::ltree[]) AS id WHERE index(p, id) >= 0)",
      ids.map(&:to_s)
    )
  else
    @scope.where(
      "EXISTS (SELECT 1 FROM unnest(ARRAY[?]::ltree[]) AS id WHERE index(#{col}, id) >= 0)",
      ids.map(&:to_s)
    )
  end
end

#ltree_depth(column, depth, operator = :eq) ⇒ Object

ltree depth check using nlevel()

Example:
ProductCategory.where.ltree_depth(:ltree_path_ids, 2) # depth = 2
ProductCategory.where.ltree_depth(:ltree_path_ids, 2, :gt) # depth > 2

Parameters:

  • column (Symbol)

    The ltree column

  • depth (Integer)

    The depth to check

  • operator (Symbol) (defaults to: :eq)

    Comparison operator (:eq, :gt, :gte, :lt, :lte)



101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/active_record_extended/ltree_query_methods.rb', line 101

def ltree_depth(column, depth, operator = :eq)
  op = case operator
       when :eq then '='
       when :gt then '>'
       when :gte then '>='
       when :lt then '<'
       when :lte then '<='
       else raise ArgumentError, "Invalid operator: #{operator}. Use :eq, :gt, :gte, :lt, :lte"
       end

  @scope.where("nlevel(#{table_name}.#{column}) #{op} ?", depth)
end