Class: Praxis::Extensions::SequelFilterQueryBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query:, model:) ⇒ SequelFilterQueryBuilder

Base query to build upon table is necessary when use the strin queries, when the query has multiple tables involved (to disambiguate)



30
31
32
33
# File 'lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb', line 30

def initialize(query:, model: )
  @query = query
  @root = model.table_name
end

Instance Attribute Details

#queryObject (readonly)

Returns the value of attribute query.



6
7
8
# File 'lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb', line 6

def query
  @query
end

#rootObject (readonly)

Returns the value of attribute root.



6
7
8
# File 'lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb', line 6

def root
  @root
end

Class Method Details

.for(definition) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb', line 10

def for(definition)
  Class.new(self) do
    @filters_map = case definition
                      when Hash
                        definition
                      when Array
                        definition.each_with_object({}) { |item, hash| hash[item.to_sym] = item }
                      else
                        raise "Cannot use FilterQueryBuilder.of without passing an array or a hash (Got: #{definition.class.name})"
                      end
    class << self
      attr_reader :filters_map
    end
  end
end

Instance Method Details

#_mapped_filter(name) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb', line 72

def _mapped_filter(name)
  target = self.class.filters_map[name]
  unless target
    if @model.attribute_names.include?(name.to_s)
      # Cache it in the filters mapping (to avoid later lookups), and return it.
      self.class.filters_map[name] = name
      target = name
    end
  end
  return target
end

#expand_binding(column_name:, op:, value:) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb', line 59

def expand_binding(column_name:,op:,value:)
  assoc_or_field, *rest = column_name.to_s.split('.')
  if rest.empty?
    column_name = Sequel.qualify(root,column_name)
  else
    puts "Adding eager graph for #{assoc_or_field} due to being used in filter"
    # Ensure the joined table is aliased properly (to the association name) so we can add the condition appropriately
    @query = query.eager_graph(Sequel.as(assoc_or_field.to_sym, assoc_or_field.to_sym) )
    column_name = Sequel.qualify(assoc_or_field, rest.first)
  end
  add_clause(attr: column_name, op: op, value: value)
end

#generate(filters) ⇒ Object

By default we’ll simply use the incoming op and value, and will map the attribute based on what’s on the ‘filters_map` definition



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb', line 37

def generate(filters)
  raise "Not refactored yet!"
  seen_associations = Set.new
  filters.each do |(attr, spec)|
    column_name = _mapped_filter(attr)
    unless column_name
      msg = "Filtering by #{attr} is not allowed. No implementation mapping defined for it has been found \
        and there is not a model attribute with this name either.\n" \
        "Please add a mapping for #{attr} in the `filters_mapping` method of the appropriate Resource class"
      raise msg
    end          
    if column_name.is_a?(Proc)
      bindings = column_name.call(spec)
      # A hash of bindings, consisting of a key with column name and a value to the query value
      bindings.each{|col,val| expand_binding(column_name: col, op: spec[:op], value: val )}
    else
      expand_binding(column_name: column_name, **spec)
    end
  end
  query
end

#get_like_value(value) ⇒ Object

Returns nil if the value was not a fuzzzy pattern



127
128
129
130
131
132
133
134
# File 'lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb', line 127

def get_like_value(value)
  if value.is_a?(String) && (value[-1] == '*' || value[0] == '*')
    likeval = value.dup
    likeval[-1] = '%' if value[-1] == '*'
    likeval[0] = '%' if value[0] == '*'
    likeval
  end
end