activeset 0.5.8 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +2 -0
- data/lib/.DS_Store +0 -0
- data/lib/active_set.rb +24 -26
- data/lib/active_set/.DS_Store +0 -0
- data/lib/active_set/adapter_activerecord.rb +58 -0
- data/lib/active_set/adapter_base.rb +14 -0
- data/lib/active_set/instruction.rb +66 -0
- data/lib/active_set/instructions.rb +34 -0
- data/lib/active_set/processor_base.rb +28 -0
- data/lib/active_set/processor_filter.rb +21 -0
- data/lib/active_set/processor_filter/active_record_adapter.rb +50 -0
- data/lib/active_set/processor_filter/enumerable_adapter.rb +21 -0
- data/lib/active_set/processor_paginate.rb +35 -0
- data/lib/active_set/{processors/paginate → processor_paginate}/active_record_adapter.rb +11 -13
- data/lib/active_set/{processors/paginate → processor_paginate}/enumerable_adapter.rb +10 -12
- data/lib/active_set/processor_sort.rb +19 -0
- data/lib/active_set/processor_sort/active_record_adapter.rb +50 -0
- data/lib/active_set/processor_sort/enumerable_adapter.rb +58 -0
- data/lib/active_set/{processors/transform_processor.rb → processor_transform.rb} +6 -6
- data/lib/active_set/{processors/transform → processor_transform}/csv_adapter.rb +11 -14
- data/lib/active_set/version.rb +1 -1
- data/lib/helpers/throws.rb +19 -0
- metadata +21 -19
- data/lib/active_set/instructions/base.rb +0 -37
- data/lib/active_set/instructions/entry.rb +0 -27
- data/lib/active_set/instructions/entry/keypath.rb +0 -65
- data/lib/active_set/instructions/entry/value.rb +0 -15
- data/lib/active_set/processors/base_adapter.rb +0 -17
- data/lib/active_set/processors/base_processor.rb +0 -22
- data/lib/active_set/processors/filter/active_record_adapter.rb +0 -78
- data/lib/active_set/processors/filter/enumerable_adapter.rb +0 -27
- data/lib/active_set/processors/filter_processor.rb +0 -18
- data/lib/active_set/processors/paginate_processor.rb +0 -36
- data/lib/active_set/processors/sort/active_record_adapter.rb +0 -55
- data/lib/active_set/processors/sort/enumerable_adapter.rb +0 -41
- data/lib/active_set/processors/sort_processor.rb +0 -18
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/array/wrap'
|
4
|
-
require 'active_support/core_ext/object/try'
|
5
|
-
require 'active_support/core_ext/string/inflections'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class Instructions
|
9
|
-
class Entry
|
10
|
-
class KeyPath
|
11
|
-
attr_reader :path
|
12
|
-
|
13
|
-
def initialize(path)
|
14
|
-
# `path` can be an Array (e.g. [:parent, :child, :grandchild])
|
15
|
-
# or a String (e.g. 'parent.child.grandchild')
|
16
|
-
@path = Array.wrap(path).map(&:to_s).flat_map { |x| x.split('.') }
|
17
|
-
end
|
18
|
-
|
19
|
-
def attribute
|
20
|
-
attribute = @path.last
|
21
|
-
return attribute.sub(operator_regex, '') if attribute&.match operator_regex
|
22
|
-
attribute
|
23
|
-
end
|
24
|
-
|
25
|
-
def operator(default: '==')
|
26
|
-
attribute = @path.last
|
27
|
-
return attribute[operator_regex, 1] if attribute&.match operator_regex
|
28
|
-
default
|
29
|
-
end
|
30
|
-
|
31
|
-
def associations_array
|
32
|
-
return [] unless @path.any?
|
33
|
-
@path.slice(0, @path.length - 1)
|
34
|
-
end
|
35
|
-
|
36
|
-
def associations_hash
|
37
|
-
return {} unless @path.any?
|
38
|
-
associations_array.reverse.reduce({}) { |a, e| { e => a } }
|
39
|
-
end
|
40
|
-
|
41
|
-
def value_for(item:)
|
42
|
-
resource_for(item: item).send(attribute)
|
43
|
-
rescue
|
44
|
-
nil
|
45
|
-
end
|
46
|
-
|
47
|
-
def resource_for(item:)
|
48
|
-
associations_array.reduce(item, :try)
|
49
|
-
rescue
|
50
|
-
nil
|
51
|
-
end
|
52
|
-
|
53
|
-
def titleized
|
54
|
-
@path.map(&:titleize).join(' ')
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def operator_regex
|
60
|
-
/\((.*?)\)/
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveSet
|
4
|
-
class BaseAdapter
|
5
|
-
def initialize(set, instruction)
|
6
|
-
@set = set
|
7
|
-
@instruction = instruction
|
8
|
-
end
|
9
|
-
|
10
|
-
def return_set(set = nil)
|
11
|
-
{}.tap do |h|
|
12
|
-
h[:set] = set || @set
|
13
|
-
h[:processed] = set ? true : false
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'patches/core_ext/hash/flatten_keys'
|
4
|
-
require_relative '../instructions/base'
|
5
|
-
|
6
|
-
class ActiveSet
|
7
|
-
class BaseProcessor
|
8
|
-
def self.queue_adapter(adapter)
|
9
|
-
@adapters ||= []
|
10
|
-
@adapters |= [adapter]
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(set, instructions)
|
14
|
-
@set = set
|
15
|
-
@instructions = Instructions.new(instructions)
|
16
|
-
end
|
17
|
-
|
18
|
-
def adapters
|
19
|
-
self.class.instance_variable_get(:@adapters)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../base_adapter'
|
4
|
-
require_relative '../base_processor'
|
5
|
-
|
6
|
-
class ActiveSet
|
7
|
-
class FilterProcessor < BaseProcessor
|
8
|
-
class ActiveRecordAdapter < BaseAdapter
|
9
|
-
def process
|
10
|
-
return return_set unless @set.respond_to? :to_sql
|
11
|
-
return return_set(processed_query_set) if attribute_is_field?
|
12
|
-
return return_set(processed_scope_set) if attribute_is_class_method? && attribute_is_method_with_params?
|
13
|
-
|
14
|
-
return_set
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def processed_query_set
|
20
|
-
arel_eager_load_associations.where(arel_operation)
|
21
|
-
end
|
22
|
-
|
23
|
-
def processed_scope_set
|
24
|
-
tmp_results = attribute_model.public_send(@instruction.attribute, @instruction.value)
|
25
|
-
return @set unless tmp_results.is_a?(ActiveRecord::Relation)
|
26
|
-
arel_eager_load_associations.merge(tmp_results)
|
27
|
-
end
|
28
|
-
|
29
|
-
def attribute_is_field?
|
30
|
-
return false unless attribute_model
|
31
|
-
attribute_model.attribute_names
|
32
|
-
.include?(@instruction.attribute)
|
33
|
-
end
|
34
|
-
|
35
|
-
def attribute_is_class_method?
|
36
|
-
return false unless attribute_model
|
37
|
-
attribute_model.respond_to?(@instruction.attribute)
|
38
|
-
end
|
39
|
-
|
40
|
-
def attribute_is_method_with_params?
|
41
|
-
return false unless attribute_model
|
42
|
-
attribute_model.method(@instruction.attribute).arity != 0
|
43
|
-
end
|
44
|
-
|
45
|
-
def arel_operation
|
46
|
-
Arel::Nodes::InfixOperation.new(@instruction.operator(default: '='),
|
47
|
-
arel_column,
|
48
|
-
arel_value)
|
49
|
-
end
|
50
|
-
|
51
|
-
def attribute_model
|
52
|
-
tmp_model = @instruction.associations_array
|
53
|
-
.reduce(@set) do |obj, assoc|
|
54
|
-
obj.reflections[assoc.to_s]&.klass
|
55
|
-
end
|
56
|
-
return tmp_model.klass if tmp_model.is_a?(ActiveRecord::Relation)
|
57
|
-
tmp_model
|
58
|
-
end
|
59
|
-
|
60
|
-
def arel_eager_load_associations
|
61
|
-
@set.includes(@instruction.associations_hash)
|
62
|
-
.references(@instruction.associations_hash)
|
63
|
-
end
|
64
|
-
|
65
|
-
def arel_column
|
66
|
-
arel_table[@instruction.attribute]
|
67
|
-
end
|
68
|
-
|
69
|
-
def arel_value
|
70
|
-
Arel.sql(ActiveRecord::Base.connection.quote(@instruction.value))
|
71
|
-
end
|
72
|
-
|
73
|
-
def arel_table
|
74
|
-
Arel::Table.new(attribute_model.table_name)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../base_adapter'
|
4
|
-
|
5
|
-
class ActiveSet
|
6
|
-
class FilterProcessor < BaseProcessor
|
7
|
-
class EnumerableAdapter < BaseAdapter
|
8
|
-
def process
|
9
|
-
return_set(filtered_set)
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
def filtered_set
|
15
|
-
@set.select do |item|
|
16
|
-
select_comparison_for(item: item)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def select_comparison_for(item:)
|
21
|
-
@instruction.value_for(item: item)
|
22
|
-
.send(@instruction.operator,
|
23
|
-
@instruction.value)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './base_processor'
|
4
|
-
require_relative './filter/enumerable_adapter'
|
5
|
-
require_relative './filter/active_record_adapter'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class FilterProcessor < BaseProcessor
|
9
|
-
queue_adapter ActiveRecordAdapter
|
10
|
-
queue_adapter EnumerableAdapter
|
11
|
-
|
12
|
-
def process
|
13
|
-
adapters.reduce(@set) do |outer_set, adapter|
|
14
|
-
@instructions.process_adapter(set: outer_set, adapter: adapter)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './base_processor'
|
4
|
-
require_relative './paginate/enumerable_adapter'
|
5
|
-
require_relative './paginate/active_record_adapter'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class PaginateProcessor < BaseProcessor
|
9
|
-
queue_adapter ActiveRecordAdapter
|
10
|
-
queue_adapter EnumerableAdapter
|
11
|
-
|
12
|
-
def process
|
13
|
-
adapters.each do |adapter|
|
14
|
-
output = adapter.new(@set, instruction).process
|
15
|
-
|
16
|
-
return output[:set] if output[:processed]
|
17
|
-
end
|
18
|
-
|
19
|
-
@set
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def instruction
|
25
|
-
Instructions::Entry.new(page_number, page_size)
|
26
|
-
end
|
27
|
-
|
28
|
-
def page_number
|
29
|
-
@instructions.get(:page) || 1
|
30
|
-
end
|
31
|
-
|
32
|
-
def page_size
|
33
|
-
@instructions.get(:size) || 25
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../base_adapter'
|
4
|
-
require_relative '../base_processor'
|
5
|
-
|
6
|
-
class ActiveSet
|
7
|
-
class SortProcessor < BaseProcessor
|
8
|
-
class ActiveRecordAdapter < BaseAdapter
|
9
|
-
def process
|
10
|
-
return return_set unless @set.respond_to? :to_sql
|
11
|
-
return return_set unless attribute_is_field?
|
12
|
-
|
13
|
-
return_set(processed_set)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def attribute_is_field?
|
19
|
-
return false unless attribute_model
|
20
|
-
attribute_model.attribute_names
|
21
|
-
.include?(@instruction.attribute)
|
22
|
-
end
|
23
|
-
|
24
|
-
def processed_set
|
25
|
-
@set.includes(@instruction.associations_hash)
|
26
|
-
.references(@instruction.associations_hash)
|
27
|
-
.merge(arel_operation)
|
28
|
-
end
|
29
|
-
|
30
|
-
def arel_operation
|
31
|
-
column = case_insensitive? ? arel_column.lower : arel_column
|
32
|
-
attribute_model.order(column.send(@instruction.value))
|
33
|
-
end
|
34
|
-
|
35
|
-
def attribute_model
|
36
|
-
@instruction.associations_array
|
37
|
-
.reduce(@set.klass) do |obj, assoc|
|
38
|
-
obj.reflections[assoc.to_s]&.klass
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def arel_column
|
43
|
-
arel_table[@instruction.attribute]
|
44
|
-
end
|
45
|
-
|
46
|
-
def arel_table
|
47
|
-
Arel::Table.new(attribute_model.table_name)
|
48
|
-
end
|
49
|
-
|
50
|
-
def case_insensitive?
|
51
|
-
@instruction.operator.to_s == 'i'
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../base_adapter'
|
4
|
-
require_relative '../base_processor'
|
5
|
-
|
6
|
-
class ActiveSet
|
7
|
-
class SortProcessor < BaseProcessor
|
8
|
-
class EnumerableAdapter < BaseAdapter
|
9
|
-
def process
|
10
|
-
return_set(sorted_set)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def sorted_set
|
16
|
-
@set.sort_by { |item| sortable_attribute_for(item: item) }
|
17
|
-
.tap { |c| c.reverse! if descending? }
|
18
|
-
end
|
19
|
-
|
20
|
-
def sortable_attribute_for(item:)
|
21
|
-
attribute_value = @instruction.value_for(item: item)
|
22
|
-
case_insensitive?(attribute_value) ? insensify(attribute_value) : attribute_value
|
23
|
-
end
|
24
|
-
|
25
|
-
def case_insensitive?(value)
|
26
|
-
# Cannot sort pure Booleans or Nils, so we _must_ cast to Strings
|
27
|
-
return true if value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
28
|
-
return true if value.is_a?(NilClass)
|
29
|
-
@instruction.operator.to_s == 'i'
|
30
|
-
end
|
31
|
-
|
32
|
-
def insensify(value)
|
33
|
-
value.to_s.downcase
|
34
|
-
end
|
35
|
-
|
36
|
-
def descending?
|
37
|
-
@instruction.value.to_s == 'desc'
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './base_processor'
|
4
|
-
require_relative './sort/enumerable_adapter'
|
5
|
-
require_relative './sort/active_record_adapter'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class SortProcessor < BaseProcessor
|
9
|
-
queue_adapter ActiveRecordAdapter
|
10
|
-
queue_adapter EnumerableAdapter
|
11
|
-
|
12
|
-
def process
|
13
|
-
adapters.reduce(@set) do |outer_set, adapter|
|
14
|
-
@instructions.process_adapter(set: outer_set, adapter: adapter)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|