activeset 0.3.1 → 0.4.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/CHANGELOG +6 -0
- data/lib/active_set.rb +6 -6
- data/lib/active_set/instructions/base.rb +14 -6
- data/lib/active_set/instructions/entry.rb +2 -1
- data/lib/active_set/processors/base_adapter.rb +9 -1
- data/lib/active_set/processors/filter/active_record_adapter.rb +28 -9
- data/lib/active_set/processors/filter/enumerable_adapter.rb +10 -16
- data/lib/active_set/processors/paginate/enumerable_adapter.rb +7 -2
- data/lib/active_set/processors/paginate_processor.rb +1 -2
- data/lib/active_set/processors/sort/active_record_adapter.rb +10 -7
- data/lib/active_set/processors/sort/enumerable_adapter.rb +16 -5
- data/lib/active_set/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eaba5e4aae16ae6f0dc4c2fad28b8c7177231448
|
4
|
+
data.tar.gz: 5d9b7ec416a8462f9a98db7f7aa04472357ccd9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79079f1f927cb72e863a15a1f0ccee14a3cb3b2b3f7e32cc5b40e2dc71ee52c0b76ba4af21c46e8b98b896183c739f78662f58e16596fef10f5dccd829486df1
|
7
|
+
data.tar.gz: be55e192739fe5b3bdcb6a1a6775ec932310467440826c7362c102e2aaba0595facd02acba55f30d30f243ba26101a971f7758b37130dcfe47001196d0ef909b
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
v 0.4.0
|
2
|
+
- fix bug with filtering against falsey values
|
3
|
+
- remove hack of casting DateTime and Time objects to Integer for filtering
|
4
|
+
- add support for ActiveRecord :time columns
|
5
|
+
- ensure that an adapter is only run if necessary for a particular instruction; that is, try to process the instruction with the first adapter, if it succeeds, don't run any other adapters, if it doesn't, try the next adapter, etc.
|
6
|
+
- allow ActiveRecord sets to be filtered by a scope method
|
1
7
|
v 0.3.1
|
2
8
|
- Implement an Instructions object layer for handling the hashes passed into Processors
|
3
9
|
v 0.3.0
|
data/lib/active_set.rb
CHANGED
@@ -32,18 +32,18 @@ class ActiveSet
|
|
32
32
|
@set.respond_to?(method_name) || super
|
33
33
|
end
|
34
34
|
|
35
|
-
def filter(
|
36
|
-
filterer = FilterProcessor.new(@set,
|
35
|
+
def filter(instructions)
|
36
|
+
filterer = FilterProcessor.new(@set, instructions)
|
37
37
|
self.class.new(filterer.process)
|
38
38
|
end
|
39
39
|
|
40
|
-
def sort(
|
41
|
-
sorter = SortProcessor.new(@set,
|
40
|
+
def sort(instructions)
|
41
|
+
sorter = SortProcessor.new(@set, instructions)
|
42
42
|
self.class.new(sorter.process)
|
43
43
|
end
|
44
44
|
|
45
|
-
def paginate(
|
46
|
-
paginater = PaginateProcessor.new(@set,
|
45
|
+
def paginate(instructions)
|
46
|
+
paginater = PaginateProcessor.new(@set, instructions)
|
47
47
|
self.class.new(paginater.process)
|
48
48
|
end
|
49
49
|
end
|
@@ -8,19 +8,27 @@ class ActiveSet
|
|
8
8
|
|
9
9
|
def initialize(hash)
|
10
10
|
@hash = hash
|
11
|
-
@flattened_hash = hash.flatten_keys
|
11
|
+
@flattened_hash = hash.flatten_keys.transform_keys { |k| k.map(&:to_s) }
|
12
12
|
end
|
13
13
|
|
14
14
|
def process_adapter(set:, adapter:)
|
15
|
-
@flattened_hash.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
@flattened_hash.reduce(set) do |inner_set, (keypath, value)|
|
16
|
+
instruction = Entry.new(keypath, value)
|
17
|
+
output = adapter.new(inner_set, instruction).process
|
18
|
+
remove_from_instruction_set(key: instruction.path) if output[:processed]
|
19
|
+
|
20
|
+
output[:set]
|
21
|
+
end
|
20
22
|
end
|
21
23
|
|
22
24
|
def get(keypath)
|
23
25
|
@hash.dig(*keypath)
|
24
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def remove_from_instruction_set(key:)
|
31
|
+
@flattened_hash.delete(key)
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
@@ -10,7 +10,8 @@ class ActiveSet
|
|
10
10
|
class Entry
|
11
11
|
attr_reader :keypath
|
12
12
|
|
13
|
-
delegate :attribute, :operator, :associations_array,
|
13
|
+
delegate :path, :attribute, :operator, :associations_array,
|
14
|
+
:associations_hash, :value_for, :resource_for,
|
14
15
|
to: :keypath
|
15
16
|
|
16
17
|
def initialize(keypath, value)
|
@@ -2,8 +2,16 @@
|
|
2
2
|
|
3
3
|
class ActiveSet
|
4
4
|
class BaseAdapter
|
5
|
-
def initialize(instruction)
|
5
|
+
def initialize(set, instruction)
|
6
|
+
@set = set
|
6
7
|
@instruction = instruction
|
7
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
|
8
16
|
end
|
9
17
|
end
|
@@ -6,26 +6,40 @@ require_relative '../base_processor'
|
|
6
6
|
class ActiveSet
|
7
7
|
class FilterProcessor < BaseProcessor
|
8
8
|
class ActiveRecordAdapter < BaseAdapter
|
9
|
-
def process
|
10
|
-
@set
|
11
|
-
return
|
12
|
-
return
|
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
13
|
|
14
|
-
|
14
|
+
return_set
|
15
15
|
end
|
16
16
|
|
17
17
|
private
|
18
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
|
+
|
19
29
|
def attribute_is_field?
|
20
30
|
return false unless attribute_model
|
21
31
|
attribute_model.attribute_names
|
22
32
|
.include?(@instruction.attribute)
|
23
33
|
end
|
24
34
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
29
43
|
end
|
30
44
|
|
31
45
|
def arel_operation
|
@@ -41,6 +55,11 @@ class ActiveSet
|
|
41
55
|
end
|
42
56
|
end
|
43
57
|
|
58
|
+
def arel_eager_load_associations
|
59
|
+
@set.includes(@instruction.associations_hash)
|
60
|
+
.references(@instruction.associations_hash)
|
61
|
+
end
|
62
|
+
|
44
63
|
def arel_column
|
45
64
|
arel_table[@instruction.attribute]
|
46
65
|
end
|
@@ -5,28 +5,22 @@ require_relative '../base_adapter'
|
|
5
5
|
class ActiveSet
|
6
6
|
class FilterProcessor < BaseProcessor
|
7
7
|
class EnumerableAdapter < BaseAdapter
|
8
|
-
def process
|
9
|
-
|
10
|
-
value_for(item).send(@instruction.operator,
|
11
|
-
passed_value)
|
12
|
-
end
|
8
|
+
def process
|
9
|
+
return_set(filtered_set)
|
13
10
|
end
|
14
11
|
|
15
12
|
private
|
16
13
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def passed_value
|
22
|
-
convert_datetime_values_to_integer(@instruction.value)
|
14
|
+
def filtered_set
|
15
|
+
@set.select do |item|
|
16
|
+
select_comparison_for(item: item)
|
17
|
+
end
|
23
18
|
end
|
24
19
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
value.to_i
|
20
|
+
def select_comparison_for(item:)
|
21
|
+
@instruction.value_for(item: item)
|
22
|
+
.send(@instruction.operator,
|
23
|
+
@instruction.value)
|
30
24
|
end
|
31
25
|
end
|
32
26
|
end
|
@@ -6,12 +6,17 @@ require_relative '../base_processor'
|
|
6
6
|
class ActiveSet
|
7
7
|
class PaginateProcessor < BaseProcessor
|
8
8
|
class EnumerableAdapter < BaseAdapter
|
9
|
-
def process
|
10
|
-
set.
|
9
|
+
def process
|
10
|
+
return return_set if @set.count < pagesize
|
11
|
+
return_set(paginated_set)
|
11
12
|
end
|
12
13
|
|
13
14
|
private
|
14
15
|
|
16
|
+
def paginated_set
|
17
|
+
@set.each_slice(pagesize).take(page_number).last
|
18
|
+
end
|
19
|
+
|
15
20
|
def pagesize
|
16
21
|
@instruction.value
|
17
22
|
end
|
@@ -6,8 +6,7 @@ require_relative './paginate/enumerable_adapter'
|
|
6
6
|
class ActiveSet
|
7
7
|
class PaginateProcessor < BaseProcessor
|
8
8
|
def process
|
9
|
-
|
10
|
-
adapter.new(instruction).process(@set)
|
9
|
+
adapter.new(@set, instruction).process
|
11
10
|
end
|
12
11
|
|
13
12
|
private
|
@@ -6,14 +6,11 @@ require_relative '../base_processor'
|
|
6
6
|
class ActiveSet
|
7
7
|
class SortProcessor < BaseProcessor
|
8
8
|
class ActiveRecordAdapter < BaseAdapter
|
9
|
-
def process
|
10
|
-
@set
|
11
|
-
return
|
12
|
-
return @set unless attribute_is_field?
|
9
|
+
def process
|
10
|
+
return return_set unless @set.respond_to? :to_sql
|
11
|
+
return return_set unless attribute_is_field?
|
13
12
|
|
14
|
-
|
15
|
-
.references(@instruction.associations_hash)
|
16
|
-
.merge(arel_operation)
|
13
|
+
return_set(processed_set)
|
17
14
|
end
|
18
15
|
|
19
16
|
private
|
@@ -24,6 +21,12 @@ class ActiveSet
|
|
24
21
|
.include?(@instruction.attribute)
|
25
22
|
end
|
26
23
|
|
24
|
+
def processed_set
|
25
|
+
@set.includes(@instruction.associations_hash)
|
26
|
+
.references(@instruction.associations_hash)
|
27
|
+
.merge(arel_operation)
|
28
|
+
end
|
29
|
+
|
27
30
|
def arel_operation
|
28
31
|
column = case_insensitive? ? arel_column.lower : arel_column
|
29
32
|
attribute_model.order(column.send(@instruction.value))
|
@@ -6,15 +6,22 @@ require_relative '../base_processor'
|
|
6
6
|
class ActiveSet
|
7
7
|
class SortProcessor < BaseProcessor
|
8
8
|
class EnumerableAdapter < BaseAdapter
|
9
|
-
def process
|
10
|
-
|
11
|
-
attribute_value = @instruction.value_for(item: item)
|
12
|
-
case_insensitive?(attribute_value) ? insensify(attribute_value) : attribute_value
|
13
|
-
end.tap { |c| c.reverse! if @instruction.value.to_s == 'desc' }
|
9
|
+
def process
|
10
|
+
return_set(sorted_set)
|
14
11
|
end
|
15
12
|
|
16
13
|
private
|
17
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
|
+
|
18
25
|
def case_insensitive?(value)
|
19
26
|
# Cannot sort pure Booleans or Nils, so we _must_ cast to Strings
|
20
27
|
return true if value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
@@ -25,6 +32,10 @@ class ActiveSet
|
|
25
32
|
def insensify(value)
|
26
33
|
value.to_s.downcase
|
27
34
|
end
|
35
|
+
|
36
|
+
def descending?
|
37
|
+
@instruction.value.to_s == 'desc'
|
38
|
+
end
|
28
39
|
end
|
29
40
|
end
|
30
41
|
end
|
data/lib/active_set/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeset
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Margheim
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|