Class: ForestAdminDatasourceToolkit::Components::Query::ConditionTree::ConditionTreeFactory
- Inherits:
-
Object
- Object
- ForestAdminDatasourceToolkit::Components::Query::ConditionTree::ConditionTreeFactory
- Includes:
- Nodes, Exceptions
- Defined in:
- lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb
Class Method Summary collapse
- .branch?(tree) ⇒ Boolean
- .from_plain_object(json) ⇒ Object
- .group(aggregator, trees = nil) ⇒ Object
- .intersect(trees = nil) ⇒ Object
- .leaf?(tree) ⇒ Boolean
- .match_fields(fields, values) ⇒ Object
- .match_ids(collection, ids) ⇒ Object
- .match_none ⇒ Object
- .match_records(collection, records) ⇒ Object
- .union(trees) ⇒ Object
Class Method Details
.branch?(tree) ⇒ Boolean
122 123 124 125 126 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 122 def self.branch?(tree) return false unless tree.is_a?(Hash) tree.key?(:aggregator) && tree.key?(:conditions) end |
.from_plain_object(json) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 53 def self.from_plain_object(json) return nil if json.nil? if leaf?(json) ConditionTreeLeaf.new(json[:field], json[:operator], json[:value]) elsif branch?(json) branch = ConditionTreeBranch.new( json[:aggregator], json[:conditions].map { |sub_tree| from_plain_object(sub_tree) } ) branch.conditions.length == 1 ? branch.conditions[0] : branch else raise ForestException, 'Failed to instantiate condition tree from json' end end |
.group(aggregator, trees = nil) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 70 def self.group(aggregator, trees = nil) return nil if trees.nil? || trees.empty? conditions = trees .compact .reduce([]) do |current_conditions, tree| if tree.is_a?(ConditionTreeBranch) && tree.aggregator == aggregator current_conditions + tree.conditions else current_conditions + [tree] end end conditions.length == 1 ? conditions[0] : ConditionTreeBranch.new(aggregator, conditions) end |
.intersect(trees = nil) ⇒ Object
42 43 44 45 46 47 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 42 def self.intersect(trees = nil) result = group('And', trees) is_empty_and = result.is_a?(ConditionTreeBranch) && result.aggregator == 'And' && result.conditions.empty? is_empty_and ? nil : result end |
.leaf?(tree) ⇒ Boolean
116 117 118 119 120 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 116 def self.leaf?(tree) return false unless tree.is_a?(Hash) tree.key?(:field) && tree.key?(:operator) && (tree[:operator] == 'Present' || tree.key?(:value)) end |
.match_fields(fields, values) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 86 def self.match_fields(fields, values) return ConditionTreeFactory.match_none if values.empty? if fields.length == 1 field_values = values.map { |tuple| tuple[0] } return field_values.length > 1 ? ConditionTreeLeaf.new(fields[0], 'In', field_values) : ConditionTreeLeaf.new(fields[0], 'Equal', field_values[0]) end first_field, *other_fields = fields groups = {} values.each do |first_value, *other_values| if groups.key?(first_value) groups[first_value].push(other_values) else groups[first_value] = [other_values] end end ConditionTreeFactory.union( groups.map do |first_value, sub_values| ConditionTreeFactory.intersect([ ConditionTreeFactory.match_fields([first_field], [[first_value]]), ConditionTreeFactory.match_fields(other_fields, sub_values) ]) end ) end |
.match_ids(collection, ids) ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 19 def self.match_ids(collection, ids) primary_key_names = ForestAdminDatasourceToolkit::Utils::Schema.primary_keys(collection) raise ForestException, 'Collection must have at least one primary key' if primary_key_names.empty? primary_key_names.each do |name| operators = collection.schema[:fields][name].filter_operators unless operators.include?(Operators::EQUAL) || operators.include?(Operators::IN) raise ForestException, "Field '#{name}' must support operators: ['Equal', 'In']" end end normalized_ids = ids.map do |id| if id.is_a?(Hash) primary_key_names.map { |pk_name| id[pk_name] } else id end end match_fields(primary_key_names, normalized_ids) end |
.match_none ⇒ Object
9 10 11 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 9 def self.match_none ConditionTreeBranch.new('Or', []) end |
.match_records(collection, records) ⇒ Object
13 14 15 16 17 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 13 def self.match_records(collection, records) ids = records.map { |record| ForestAdminDatasourceToolkit::Utils::Record.primary_keys(collection, record) } match_ids(collection, ids) end |
.union(trees) ⇒ Object
49 50 51 |
# File 'lib/forest_admin_datasource_toolkit/components/query/condition_tree/condition_tree_factory.rb', line 49 def self.union(trees) group('Or', trees) end |