Class: ActionBlocks::FilterEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/action_blocks/data_engine/filter_engine.rb

Overview

Data Engine

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root_klass, user: nil, filter_reqs: []) ⇒ FilterEngine

Returns a new instance of FilterEngine.



7
8
9
10
11
12
13
14
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 7

def initialize(root_klass, user: nil, filter_reqs: [])
  @root_klass = root_klass
  @filter_reqs = filter_reqs
  @tables = {}
  @joins = {}
  @wheres = []
  @froms = []
end

Instance Attribute Details

#filter_reqsObject

Returns the value of attribute filter_reqs.



4
5
6
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 4

def filter_reqs
  @filter_reqs
end

#fromsObject

Returns the value of attribute froms.



4
5
6
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 4

def froms
  @froms
end

#joinsObject

Returns the value of attribute joins.



4
5
6
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 4

def joins
  @joins
end

#root_keyObject

Returns the value of attribute root_key.



4
5
6
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 4

def root_key
  @root_key
end

#root_klassObject

Returns the value of attribute root_klass.



4
5
6
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 4

def root_klass
  @root_klass
end

#selectsObject

Returns the value of attribute selects.



4
5
6
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 4

def selects
  @selects
end

#tablesObject

Returns the value of attribute tables.



4
5
6
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 4

def tables
  @tables
end

#wheresObject

Returns the value of attribute wheres.



4
5
6
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 4

def wheres
  @wheres
end

Instance Method Details

#ordered_joinsObject



73
74
75
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 73

def ordered_joins
  @joins.values
end

#processObject



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
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 16

def process
  @root_table = @root_klass.arel_table
  @root_key = @root_klass.to_s.underscore.to_sym

  # Add base table to tables
  @tables[@root_key.to_sym] = @root_table

  [@filter_reqs].flatten.each do |matchreq|
    node, *rest = matchreq[:path1]
    # puts "base node: #{node} rest #{rest}"
    base_expression = walk_filter_path(@root_klass, node, @root_key, rest)

    node, *rest = matchreq[:path2]
    # puts "related node: #{node} rest #{rest}"
    related_expression = walk_filter_path(@root_klass, node, @root_key, rest)

    if base_expression.class.ancestors.include?(Arel::Attributes::Attribute)
      where = base_expression.send(matchreq[:predicate], related_expression)
    else
      where = related_expression.send(matchreq[:predicate], base_expression)
    end
    @wheres << where

  end

end

#queryObject



81
82
83
84
85
86
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 81

def query
  @root_klass
    .from(froms)
    .joins(ordered_joins)
    .where(wheres)
end

#walk_filter_path(klass, node, parent_key, col_path) ⇒ Object



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
# File 'lib/action_blocks/data_engine/filter_engine.rb', line 43

def walk_filter_path(klass, node, parent_key, col_path)
  key = [parent_key, node].compact.join('_').to_sym
  if node.class != Symbol
    return node
  end
  if !col_path.empty?
    # Create Arel Table Alias
    relation = klass.reflections[node.to_s]
    klass = relation.klass
    @tables[key] = klass.arel_table.alias(key) unless @tables[key]
    # Create Join
    fk = relation.join_foreign_key
    pk = relation.join_primary_key
    join_on = @tables[key].create_on(@tables[parent_key][fk].eq(@tables[key][pk]))
    @joins[key] = @tables[parent_key].create_join(@tables[key], join_on, Arel::Nodes::OuterJoin)
    # Recurse
    next_node, *rest = col_path
    return walk_filter_path(klass, next_node, key, rest)
  else
    # Return expression
    # puts "parent_key: #{node.to_sym}"
    # puts "node: #{node.to_sym}"
    return @tables[parent_key][node.to_sym]
  end
end