activeset 0.6.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +0 -6
- data/CHANGELOG +5 -0
- data/README.md +58 -6
- data/activeset.gemspec +8 -8
- data/bin/console +14 -0
- data/lib/.DS_Store +0 -0
- data/lib/active_set.rb +28 -21
- data/lib/active_set/{instruction.rb → attribute_instruction.rb} +12 -8
- data/lib/active_set/column_instruction.rb +44 -0
- data/lib/active_set/exporting/operation.rb +66 -0
- data/lib/active_set/filtering/operation.rb +190 -0
- data/lib/active_set/paginating/operation.rb +102 -0
- data/lib/active_set/sorting/operation.rb +144 -0
- data/lib/helpers/throws.rb +2 -2
- data/lib/helpers/transform_to_sortable_numeric.rb +36 -0
- data/lib/patches/core_ext/hash/flatten_keys.rb +43 -14
- metadata +55 -39
- data/lib/active_set/.DS_Store +0 -0
- data/lib/active_set/adapter_activerecord.rb +0 -58
- data/lib/active_set/adapter_base.rb +0 -14
- data/lib/active_set/instructions.rb +0 -42
- data/lib/active_set/processor_base.rb +0 -28
- data/lib/active_set/processor_filter.rb +0 -21
- data/lib/active_set/processor_filter/active_record_adapter.rb +0 -50
- data/lib/active_set/processor_filter/enumerable_adapter.rb +0 -21
- data/lib/active_set/processor_paginate.rb +0 -35
- data/lib/active_set/processor_paginate/active_record_adapter.rb +0 -37
- data/lib/active_set/processor_paginate/enumerable_adapter.rb +0 -39
- data/lib/active_set/processor_sort.rb +0 -19
- data/lib/active_set/processor_sort/active_record_adapter.rb +0 -27
- data/lib/active_set/processor_sort/active_record_operation.rb +0 -55
- data/lib/active_set/processor_sort/enumerable_adapter.rb +0 -58
- data/lib/active_set/processor_transform.rb +0 -30
- data/lib/active_set/processor_transform/csv_adapter.rb +0 -77
- data/lib/active_set/version.rb +0 -5
data/lib/active_set/.DS_Store
DELETED
Binary file
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './adapter_base'
|
4
|
-
|
5
|
-
class ActiveSet
|
6
|
-
class Adapter::ActiveRecord < Adapter::Base
|
7
|
-
private
|
8
|
-
|
9
|
-
def can_query_with_active_record?
|
10
|
-
attribute_is_field?
|
11
|
-
end
|
12
|
-
|
13
|
-
def can_merge_with_active_record?
|
14
|
-
attribute_is_class_method? &&
|
15
|
-
attribute_is_method_with_params?
|
16
|
-
end
|
17
|
-
|
18
|
-
def arel_eager_load_associations
|
19
|
-
@set.eager_load(instruction.associations_hash)
|
20
|
-
end
|
21
|
-
|
22
|
-
def arel_column
|
23
|
-
arel_table[instruction.attribute]
|
24
|
-
end
|
25
|
-
|
26
|
-
def arel_table
|
27
|
-
Arel::Table.new(attribute_model.table_name)
|
28
|
-
end
|
29
|
-
|
30
|
-
def attribute_is_field?
|
31
|
-
return false unless attribute_model
|
32
|
-
|
33
|
-
attribute_model.attribute_names
|
34
|
-
.include?(instruction.attribute)
|
35
|
-
end
|
36
|
-
|
37
|
-
def attribute_is_class_method?
|
38
|
-
return false unless attribute_model
|
39
|
-
|
40
|
-
attribute_model.respond_to?(instruction.attribute)
|
41
|
-
end
|
42
|
-
|
43
|
-
def attribute_is_method_with_params?
|
44
|
-
return false unless attribute_model
|
45
|
-
|
46
|
-
attribute_model.method(instruction.attribute).arity != 0
|
47
|
-
end
|
48
|
-
|
49
|
-
def attribute_model
|
50
|
-
tmp_model = instruction.associations_array
|
51
|
-
.reduce(@set) do |obj, assoc|
|
52
|
-
obj.reflections[assoc.to_s]&.klass
|
53
|
-
end
|
54
|
-
return tmp_model.klass if tmp_model.is_a?(ActiveRecord::Relation)
|
55
|
-
tmp_model
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../patches/core_ext/hash/flatten_keys'
|
4
|
-
require_relative './instruction'
|
5
|
-
|
6
|
-
class ActiveSet
|
7
|
-
class Instructions
|
8
|
-
include Enumerable
|
9
|
-
|
10
|
-
def initialize(hash)
|
11
|
-
@instructions = hash.flatten_keys.map do |keypath, value|
|
12
|
-
Instruction.new(keypath, value)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def each(&block)
|
17
|
-
@instructions.each(&block)
|
18
|
-
end
|
19
|
-
|
20
|
-
# :nocov:
|
21
|
-
def method_missing(method_name, *args, &block)
|
22
|
-
@instructions.send(method_name, *args, &block) || super
|
23
|
-
end
|
24
|
-
# :nocov:
|
25
|
-
|
26
|
-
# :nocov:
|
27
|
-
def respond_to_missing?(method_name, include_private = false)
|
28
|
-
@instructions.respond_to?(method_name) || super
|
29
|
-
end
|
30
|
-
# :nocov:
|
31
|
-
|
32
|
-
def associations_hash
|
33
|
-
@instructions.reduce({}) { |h, i| h.merge(i.associations_hash) }
|
34
|
-
end
|
35
|
-
|
36
|
-
def get(key)
|
37
|
-
@instructions.find do |instruction|
|
38
|
-
instruction.attribute.to_s == key.to_s
|
39
|
-
end&.value
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './instructions'
|
4
|
-
|
5
|
-
class ActiveSet
|
6
|
-
module Processor
|
7
|
-
class Base
|
8
|
-
attr_reader :set, :instructions, :adapters
|
9
|
-
|
10
|
-
def self.register_adapter(adapter, precedence = 0)
|
11
|
-
@adapters ||= []
|
12
|
-
@adapters.insert(precedence, adapter)
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(set, instructions)
|
16
|
-
@set = set
|
17
|
-
@instructions = Instructions.new(validate_instructions(instructions))
|
18
|
-
@adapters = self.class.instance_variable_get(:@adapters)
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def validate_instructions(instructions)
|
24
|
-
instructions
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './processor_base'
|
4
|
-
require_relative './processor_filter/enumerable_adapter'
|
5
|
-
require_relative './processor_filter/active_record_adapter'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class Processor::Filter < Processor::Base
|
9
|
-
def process
|
10
|
-
@instructions.reduce(@set) do |set, instruction|
|
11
|
-
adapters.each do |adapter|
|
12
|
-
result = adapter.new(set, [instruction]).process
|
13
|
-
break(result) if result
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
register_adapter(EnumerableAdapter)
|
19
|
-
register_adapter(ActiveRecordAdapter)
|
20
|
-
end
|
21
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../adapter_activerecord'
|
4
|
-
require_relative '../processor_base'
|
5
|
-
require_relative '../../helpers/throws'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class Processor::Filter < Processor::Base
|
9
|
-
class ActiveRecordAdapter < Adapter::ActiveRecord
|
10
|
-
def process
|
11
|
-
return false unless @set.respond_to?(:to_sql)
|
12
|
-
|
13
|
-
if can_query_with_active_record?
|
14
|
-
statement = arel_eager_load_associations
|
15
|
-
.where(arel_operation)
|
16
|
-
elsif can_merge_with_active_record?
|
17
|
-
statement = arel_eager_load_associations
|
18
|
-
.merge(attribute_model.public_send(instruction.attribute,
|
19
|
-
instruction.value))
|
20
|
-
else
|
21
|
-
return false
|
22
|
-
end
|
23
|
-
|
24
|
-
return false if throws?(ActiveRecord::StatementInvalid) { statement.load }
|
25
|
-
|
26
|
-
statement
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def instruction
|
32
|
-
@instructions.first
|
33
|
-
end
|
34
|
-
|
35
|
-
def arel_operation
|
36
|
-
Arel::Nodes::InfixOperation.new(arel_operator,
|
37
|
-
arel_column,
|
38
|
-
arel_value)
|
39
|
-
end
|
40
|
-
|
41
|
-
def arel_value
|
42
|
-
Arel.sql(ActiveRecord::Base.connection.quote(instruction.value))
|
43
|
-
end
|
44
|
-
|
45
|
-
def arel_operator
|
46
|
-
instruction.operator(default: '=')
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../adapter_base'
|
4
|
-
|
5
|
-
class ActiveSet
|
6
|
-
class Processor::Filter < Processor::Base
|
7
|
-
class EnumerableAdapter < Adapter::Base
|
8
|
-
def process
|
9
|
-
return false unless @set.respond_to? :select
|
10
|
-
|
11
|
-
@instructions.reduce(@set) do |set, instruction|
|
12
|
-
set.select do |item|
|
13
|
-
instruction.value_for(item: item)
|
14
|
-
.send(instruction.operator,
|
15
|
-
instruction.value)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './processor_base'
|
4
|
-
require_relative './processor_paginate/enumerable_adapter'
|
5
|
-
require_relative './processor_paginate/active_record_adapter'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class Processor::Paginate < Processor::Base
|
9
|
-
def process
|
10
|
-
adapters.each do |adapter|
|
11
|
-
result = adapter.new(@set, @instructions).process
|
12
|
-
break(result) if result
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def validate_instructions(instructions)
|
19
|
-
{
|
20
|
-
page: (instructions[:page] ||
|
21
|
-
instructions['page'] ||
|
22
|
-
1).to_i,
|
23
|
-
size: (instructions[:size] ||
|
24
|
-
instructions['size'] ||
|
25
|
-
25).to_i,
|
26
|
-
outset: (instructions[:outset] ||
|
27
|
-
instructions['outset'] ||
|
28
|
-
0).to_i
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
register_adapter(EnumerableAdapter)
|
33
|
-
register_adapter(ActiveRecordAdapter)
|
34
|
-
end
|
35
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../adapter_base'
|
4
|
-
require_relative '../processor_base'
|
5
|
-
|
6
|
-
class ActiveSet
|
7
|
-
class Processor::Paginate < Processor::Base
|
8
|
-
class ActiveRecordAdapter < Adapter::Base
|
9
|
-
def process
|
10
|
-
return false unless @set.respond_to? :to_sql
|
11
|
-
return @set.none if @set.length <= page_size && page_number > 1
|
12
|
-
|
13
|
-
@set.limit(page_size).offset(page_offset)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def page_offset
|
19
|
-
return 0 if page_number == 1
|
20
|
-
|
21
|
-
page_size * (page_number - 1)
|
22
|
-
end
|
23
|
-
|
24
|
-
def page_size
|
25
|
-
@instructions.get('size').to_i
|
26
|
-
end
|
27
|
-
|
28
|
-
def page_number
|
29
|
-
num = @instructions.get('page').to_i
|
30
|
-
return 1 if (num - 1).negative?
|
31
|
-
return 1 if (num - 1).zero?
|
32
|
-
|
33
|
-
num
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../adapter_base'
|
4
|
-
require_relative '../processor_base'
|
5
|
-
|
6
|
-
class ActiveSet
|
7
|
-
class Processor::Paginate < Processor::Base
|
8
|
-
class EnumerableAdapter < Adapter::Base
|
9
|
-
def process
|
10
|
-
return [] if @set.count <= page_size && page_number > 1
|
11
|
-
|
12
|
-
@set[page_start..page_end] || []
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def page_start
|
18
|
-
return 0 if page_number == 1
|
19
|
-
|
20
|
-
page_size * (page_number - 1)
|
21
|
-
end
|
22
|
-
|
23
|
-
def page_end
|
24
|
-
return page_start if page_size == 1
|
25
|
-
|
26
|
-
page_start + page_size - 1
|
27
|
-
end
|
28
|
-
|
29
|
-
def page_size
|
30
|
-
@instructions.get('size').to_i
|
31
|
-
end
|
32
|
-
|
33
|
-
def page_number
|
34
|
-
num = @instructions.get('page').to_i
|
35
|
-
(num.to_i - 1).negative? ? 0 : num
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './processor_base'
|
4
|
-
require_relative './processor_sort/enumerable_adapter'
|
5
|
-
require_relative './processor_sort/active_record_adapter'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class Processor::Sort < Processor::Base
|
9
|
-
def process
|
10
|
-
adapters.each do |adapter|
|
11
|
-
result = adapter.new(@set, @instructions).process
|
12
|
-
break(result) if result
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
register_adapter(EnumerableAdapter)
|
17
|
-
register_adapter(ActiveRecordAdapter)
|
18
|
-
end
|
19
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../adapter_activerecord'
|
4
|
-
require_relative '../processor_base'
|
5
|
-
require_relative '../../helpers/throws'
|
6
|
-
require_relative './active_record_operation'
|
7
|
-
|
8
|
-
class ActiveSet
|
9
|
-
class Processor::Sort < Processor::Base
|
10
|
-
class ActiveRecordAdapter < Adapter::ActiveRecord
|
11
|
-
def process
|
12
|
-
return false unless @set.respond_to?(:to_sql)
|
13
|
-
|
14
|
-
@instructions.reduce(@set.eager_load(@instructions.associations_hash)) do |set, instruction|
|
15
|
-
ar_operation = ActiveRecordOperation.new(instruction, @set.klass)
|
16
|
-
return false unless ar_operation.attribute_is_field?
|
17
|
-
|
18
|
-
statement = set.merge(ar_operation.operation)
|
19
|
-
|
20
|
-
return false if throws?(ActiveRecord::StatementInvalid) { statement.load }
|
21
|
-
|
22
|
-
statement
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../adapter_activerecord'
|
4
|
-
require_relative '../processor_base'
|
5
|
-
require_relative '../../helpers/throws'
|
6
|
-
|
7
|
-
class ActiveSet
|
8
|
-
class Processor::Sort < Processor::Base
|
9
|
-
class ActiveRecordOperation
|
10
|
-
def initialize(instruction, klass)
|
11
|
-
@instruction = instruction
|
12
|
-
@klass = klass
|
13
|
-
end
|
14
|
-
|
15
|
-
def operation
|
16
|
-
attribute_model.order(column.send(validate_direction(@instruction.value)))
|
17
|
-
end
|
18
|
-
|
19
|
-
def attribute_is_field?
|
20
|
-
return false unless attribute_model
|
21
|
-
|
22
|
-
attribute_model.attribute_names
|
23
|
-
.include?(@instruction.attribute)
|
24
|
-
end
|
25
|
-
|
26
|
-
def case_insensitive?
|
27
|
-
@instruction.operator.to_s.downcase == 'i'
|
28
|
-
end
|
29
|
-
|
30
|
-
def column
|
31
|
-
column = table[@instruction.attribute]
|
32
|
-
case_insensitive? ? column.lower : column
|
33
|
-
end
|
34
|
-
|
35
|
-
def table
|
36
|
-
Arel::Table.new(attribute_model.table_name)
|
37
|
-
end
|
38
|
-
|
39
|
-
def validate_direction(direction)
|
40
|
-
return 'desc' if direction.to_s.downcase.start_with? 'desc'
|
41
|
-
|
42
|
-
'asc'
|
43
|
-
end
|
44
|
-
|
45
|
-
def attribute_model
|
46
|
-
tmp_model = @instruction.associations_array
|
47
|
-
.reduce(@klass) do |obj, assoc|
|
48
|
-
obj.reflections[assoc.to_s]&.klass
|
49
|
-
end
|
50
|
-
# return tmp_model.klass if tmp_model.is_a?(ActiveRecord::Relation)
|
51
|
-
# tmp_model
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|