activeset 0.7.1 → 0.8.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/.hound.yml +32 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +6 -2
- data/CHANGELOG +6 -0
- data/README.md +3 -0
- data/activeset.gemspec +2 -1
- data/bin/console +6 -5
- data/lib/active_set.rb +1 -1
- data/lib/active_set/column_instruction.rb +6 -4
- data/lib/active_set/exporting/csv_strategy.rb +43 -0
- data/lib/active_set/exporting/operation.rb +1 -37
- data/lib/active_set/filtering/active_record_strategy.rb +86 -0
- data/lib/active_set/filtering/enumerable_strategy.rb +78 -0
- data/lib/active_set/filtering/operation.rb +6 -153
- data/lib/active_set/paginating/active_record_strategy.rb +28 -0
- data/lib/active_set/paginating/enumerable_strategy.rb +33 -0
- data/lib/active_set/paginating/operation.rb +3 -51
- data/lib/active_set/sorting/active_record_strategy.rb +76 -0
- data/lib/active_set/sorting/enumerable_strategy.rb +46 -0
- data/lib/active_set/sorting/operation.rb +4 -113
- data/lib/helpers/throws.rb +2 -2
- data/lib/helpers/transform_to_sortable_numeric.rb +27 -19
- data/lib/patches/core_ext/hash/flatten_keys.rb +13 -16
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7d4ed6e6770fc71dc3a001a2dc9c19a871445e3
|
4
|
+
data.tar.gz: c1db7e7e4a0b3942563018e2404af6e645bcd68e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd2718bbacff6f512f9ad90cb33e87a1b14eaadbe85774949e2df5b02439836e1e58a5b21286f6c9481b5efdb6239715d35465ab8341b5be2e907e2007f941c0
|
7
|
+
data.tar.gz: 833e98c0cf55ef9dc7229922070ba6e02f35ce2801728489f968ee08efaf689b62242592a22ca8cc23012263af4003c6f8de1213e6317b1c224e788919c9ff31
|
data/.hound.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
rubocop:
|
2
|
+
config_file: .rubocop.yml
|
3
|
+
|
4
|
+
reek:
|
5
|
+
enabled: true
|
6
|
+
|
7
|
+
coffeescript:
|
8
|
+
enabled: false
|
9
|
+
credo:
|
10
|
+
enabled: false
|
11
|
+
css:
|
12
|
+
enabled: false
|
13
|
+
eslint:
|
14
|
+
enabled: false
|
15
|
+
flake8:
|
16
|
+
enabled: false
|
17
|
+
golint:
|
18
|
+
enabled: false
|
19
|
+
haml:
|
20
|
+
enabled: false
|
21
|
+
jshint:
|
22
|
+
enabled: false
|
23
|
+
sass-lint:
|
24
|
+
enabled: false
|
25
|
+
scss:
|
26
|
+
enabled: false
|
27
|
+
shellcheck:
|
28
|
+
enabled: false
|
29
|
+
swiftlint:
|
30
|
+
enabled: false
|
31
|
+
tslint:
|
32
|
+
enabled: false
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
v 0.8.0
|
2
|
+
- simplify the `inspect` method for ActiveSet instances, only showing the instructions
|
3
|
+
- split the strategy files from the operation files
|
4
|
+
- update how ActiveRecord filtering works
|
5
|
+
+ instruction operators must now be ARel methods, not SQL operators
|
6
|
+
- memoize the `transform_to_sortable_numeric` method
|
1
7
|
v 0.7.1
|
2
8
|
- Fix a small bug with Enumberable filtering of metaprogrammatically defined getter methods
|
3
9
|
v 0.7.0
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# ActiveSet
|
2
2
|
|
3
|
+
[](https://travis-ci.com/fractaledmind/activeset)
|
4
|
+
[](https://codecov.io/gh/fractaledmind/activeset)
|
5
|
+
|
3
6
|
## Installation
|
4
7
|
|
5
8
|
Add this line to your application's Gemfile:
|
data/activeset.gemspec
CHANGED
@@ -6,7 +6,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.name = 'activeset'
|
9
|
-
spec.version = '0.
|
9
|
+
spec.version = '0.8.0'
|
10
10
|
spec.authors = ['Stephen Margheim']
|
11
11
|
spec.email = ['stephen.margheim@gmail.com']
|
12
12
|
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency 'activesupport', '>= 4.0.2'
|
26
26
|
|
27
27
|
spec.add_development_dependency 'bundler', '~> 1.15'
|
28
|
+
spec.add_development_dependency 'codecov'
|
28
29
|
spec.add_development_dependency 'combustion', '~> 0.7.0'
|
29
30
|
spec.add_development_dependency 'database_cleaner', '~> 1.6.1'
|
30
31
|
spec.add_development_dependency 'factory_bot', '~> 4.8.0'
|
data/bin/console
CHANGED
@@ -4,20 +4,21 @@
|
|
4
4
|
ENV['RAILS_ENV'] ||= 'test'
|
5
5
|
|
6
6
|
require 'bundler'
|
7
|
+
require 'simplecov'
|
8
|
+
require 'codecov'
|
9
|
+
require 'combustion'
|
10
|
+
|
11
|
+
Combustion.initialize! :active_record, :action_controller, :action_view
|
7
12
|
Bundler.require :default, :development
|
8
13
|
|
9
14
|
require 'bundler/setup'
|
10
15
|
require 'active_set'
|
11
16
|
require 'ostruct'
|
12
17
|
|
13
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
14
|
-
# with your gem easier. You can also use a different console, if you like.
|
15
|
-
|
16
|
-
Combustion.initialize! :active_record
|
17
|
-
|
18
18
|
begin
|
19
19
|
FactoryBot.find_definitions
|
20
20
|
rescue FactoryBot::DuplicateDefinitionError
|
21
|
+
nil
|
21
22
|
end
|
22
23
|
|
23
24
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
data/lib/active_set.rb
CHANGED
@@ -12,12 +12,10 @@ class ActiveSet
|
|
12
12
|
def key
|
13
13
|
return @instructions_hash[:key] if @instructions_hash.key? :key
|
14
14
|
|
15
|
-
|
16
|
-
return titleized unless attribute_instruction.attribute
|
15
|
+
return titleized_attribute_key unless attribute_instruction.attribute
|
17
16
|
|
18
17
|
attribute_resource = attribute_instruction.resource_for(item: @item)
|
19
|
-
return
|
20
|
-
return titleized unless attribute_resource.class.respond_to?(:human_attribute_name)
|
18
|
+
return titleized_attribute_key unless attribute_resource&.class&.respond_to?(:human_attribute_name)
|
21
19
|
|
22
20
|
attribute_resource.class.human_attribute_name(attribute_instruction.attribute)
|
23
21
|
end
|
@@ -40,5 +38,9 @@ class ActiveSet
|
|
40
38
|
|
41
39
|
'—'
|
42
40
|
end
|
41
|
+
|
42
|
+
def titleized_attribute_key
|
43
|
+
attribute_instruction.keypath.map(&:titleize).join(' ')
|
44
|
+
end
|
43
45
|
end
|
44
46
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../column_instruction'
|
4
|
+
|
5
|
+
class ActiveSet
|
6
|
+
module Exporting
|
7
|
+
class CSVStrategy
|
8
|
+
require 'csv'
|
9
|
+
|
10
|
+
def initialize(set, column_instructions)
|
11
|
+
@set = set
|
12
|
+
@column_instructions = column_instructions
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
::CSV.generate do |output|
|
17
|
+
output << column_keys_for(item: @set.first)
|
18
|
+
@set.each do |item|
|
19
|
+
output << column_values_for(item: item)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def column_keys_for(item:)
|
27
|
+
columns.map do |column|
|
28
|
+
ColumnInstruction.new(column, item).key
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def column_values_for(item:)
|
33
|
+
columns.map do |column|
|
34
|
+
ColumnInstruction.new(column, item).value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def columns
|
39
|
+
@column_instructions.compact
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative './csv_strategy'
|
4
4
|
|
5
5
|
class ActiveSet
|
6
6
|
module Exporting
|
@@ -26,41 +26,5 @@ class ActiveSet
|
|
26
26
|
return CSVStrategy if format == 'csv'
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
30
|
-
class CSVStrategy
|
31
|
-
require 'csv'
|
32
|
-
|
33
|
-
def initialize(set, column_instructions)
|
34
|
-
@set = set
|
35
|
-
@column_instructions = column_instructions
|
36
|
-
end
|
37
|
-
|
38
|
-
def execute
|
39
|
-
::CSV.generate do |output|
|
40
|
-
output << column_keys_for(item: @set.first)
|
41
|
-
@set.each do |item|
|
42
|
-
output << column_values_for(item: item)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def column_keys_for(item:)
|
50
|
-
columns.map do |column|
|
51
|
-
ColumnInstruction.new(column, item).key
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def column_values_for(item:)
|
56
|
-
columns.map do |column|
|
57
|
-
ColumnInstruction.new(column, item).value
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def columns
|
62
|
-
@column_instructions.compact
|
63
|
-
end
|
64
|
-
end
|
65
29
|
end
|
66
30
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ActiveSet
|
4
|
+
module Filtering
|
5
|
+
class ActiveRecordStrategy
|
6
|
+
def initialize(set, attribute_instruction)
|
7
|
+
@set = set
|
8
|
+
@attribute_instruction = attribute_instruction
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
return false unless @set.respond_to? :to_sql
|
13
|
+
|
14
|
+
if execute_where_operation?
|
15
|
+
statement = where_operation
|
16
|
+
elsif execute_merge_operation?
|
17
|
+
statement = merge_operation
|
18
|
+
else
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
return false if throws?(ActiveRecord::StatementInvalid) { statement.load }
|
23
|
+
|
24
|
+
statement
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def execute_where_operation?
|
30
|
+
return false unless attribute_model
|
31
|
+
return false unless attribute_model.respond_to?(:attribute_names)
|
32
|
+
return false unless attribute_model.attribute_names.include?(@attribute_instruction.attribute)
|
33
|
+
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute_merge_operation?
|
38
|
+
return false unless attribute_model
|
39
|
+
return false unless attribute_model.respond_to?(@attribute_instruction.attribute)
|
40
|
+
return false if attribute_model.method(@attribute_instruction.attribute).arity.zero?
|
41
|
+
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def where_operation
|
46
|
+
arel_table = Arel::Table.new(attribute_model.table_name)
|
47
|
+
arel_column = arel_table[@attribute_instruction.attribute]
|
48
|
+
|
49
|
+
initial_relation
|
50
|
+
.where(
|
51
|
+
arel_column.send(
|
52
|
+
@attribute_instruction.operator(default: 'eq'),
|
53
|
+
@attribute_instruction.value
|
54
|
+
)
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def merge_operation
|
59
|
+
initial_relation
|
60
|
+
.merge(
|
61
|
+
attribute_model.public_send(
|
62
|
+
@attribute_instruction.attribute,
|
63
|
+
@attribute_instruction.value
|
64
|
+
)
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
def initial_relation
|
69
|
+
return @set if @attribute_instruction.associations_array.empty?
|
70
|
+
|
71
|
+
@set.eager_load(@attribute_instruction.associations_hash)
|
72
|
+
end
|
73
|
+
|
74
|
+
def attribute_model
|
75
|
+
return @set.klass if @attribute_instruction.associations_array.empty?
|
76
|
+
return @attribute_model if defined? @attribute_model
|
77
|
+
|
78
|
+
@attribute_model = @attribute_instruction
|
79
|
+
.associations_array
|
80
|
+
.reduce(@set) do |obj, assoc|
|
81
|
+
obj.reflections[assoc.to_s]&.klass
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ActiveSet
|
4
|
+
module Filtering
|
5
|
+
class EnumerableStrategy
|
6
|
+
def initialize(set, attribute_instruction)
|
7
|
+
@set = set
|
8
|
+
@attribute_instruction = attribute_instruction
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
return false unless @set.respond_to? :select
|
13
|
+
|
14
|
+
@set.select do |item|
|
15
|
+
next attribute_matches_for?(item) if can_match_attribute_for?(item)
|
16
|
+
next class_method_matches_for?(item) if can_match_class_method_for?(item)
|
17
|
+
|
18
|
+
next false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def can_match_attribute_for?(item)
|
25
|
+
attribute_item = attribute_item_for(item)
|
26
|
+
|
27
|
+
return false unless attribute_item
|
28
|
+
return false unless attribute_item.respond_to?(@attribute_instruction.attribute)
|
29
|
+
return false if attribute_item.method(@attribute_instruction.attribute).arity.positive?
|
30
|
+
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
def can_match_class_method_for?(item)
|
35
|
+
attribute_item = attribute_item_for(item)
|
36
|
+
|
37
|
+
return false unless attribute_item
|
38
|
+
return false unless attribute_item.class
|
39
|
+
return false unless attribute_item.class.respond_to?(@attribute_instruction.attribute)
|
40
|
+
return false if attribute_item.class.method(@attribute_instruction.attribute).arity.zero?
|
41
|
+
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def attribute_matches_for?(item)
|
46
|
+
@attribute_instruction
|
47
|
+
.value_for(item: item)
|
48
|
+
.public_send(
|
49
|
+
@attribute_instruction.operator,
|
50
|
+
@attribute_instruction.value
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
# rubocop:disable Metrics/MethodLength
|
55
|
+
def class_method_matches_for?(item)
|
56
|
+
maybe_item_or_collection_or_nil = attribute_item_for(item)
|
57
|
+
.class
|
58
|
+
.public_send(
|
59
|
+
@attribute_instruction.attribute,
|
60
|
+
@attribute_instruction.value
|
61
|
+
)
|
62
|
+
if maybe_item_or_collection_or_nil.nil?
|
63
|
+
false
|
64
|
+
elsif maybe_item_or_collection_or_nil.respond_to?(:each)
|
65
|
+
maybe_item_or_collection_or_nil.include? attribute_item_for(item)
|
66
|
+
else
|
67
|
+
maybe_item_or_collection_or_nil.present?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
# rubocop:enable Metrics/MethodLength
|
71
|
+
|
72
|
+
def attribute_item_for(item)
|
73
|
+
@attribute_instruction
|
74
|
+
.resource_for(item: item)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../attribute_instruction'
|
4
|
+
require_relative './enumerable_strategy'
|
5
|
+
require_relative './active_record_strategy'
|
4
6
|
|
5
7
|
class ActiveSet
|
6
8
|
module Filtering
|
@@ -10,10 +12,11 @@ class ActiveSet
|
|
10
12
|
@instructions_hash = instructions_hash
|
11
13
|
end
|
12
14
|
|
15
|
+
# rubocop:disable Metrics/MethodLength
|
13
16
|
def execute
|
14
17
|
attribute_instructions = @instructions_hash
|
15
|
-
|
16
|
-
|
18
|
+
.flatten_keys
|
19
|
+
.map { |k, v| AttributeInstruction.new(k, v) }
|
17
20
|
|
18
21
|
activerecord_filtered_set = attribute_instructions.reduce(@set) do |set, attribute_instruction|
|
19
22
|
maybe_set_or_false = ActiveRecordStrategy.new(set, attribute_instruction).execute
|
@@ -30,161 +33,11 @@ class ActiveSet
|
|
30
33
|
maybe_set_or_false.presence || set
|
31
34
|
end
|
32
35
|
end
|
36
|
+
# rubocop:enable Metrics/MethodLength
|
33
37
|
|
34
38
|
def operation_instructions
|
35
39
|
@instructions_hash.symbolize_keys
|
36
40
|
end
|
37
41
|
end
|
38
|
-
|
39
|
-
class EnumerableStrategy
|
40
|
-
def initialize(set, attribute_instruction)
|
41
|
-
@set = set
|
42
|
-
@attribute_instruction = attribute_instruction
|
43
|
-
end
|
44
|
-
|
45
|
-
def execute
|
46
|
-
return false unless @set.respond_to? :select
|
47
|
-
|
48
|
-
@set.select do |item|
|
49
|
-
if can_match_attribute_for?(item)
|
50
|
-
next attribute_matches_for?(item)
|
51
|
-
elsif can_match_class_method_for?(item)
|
52
|
-
next class_method_matches_for?(item)
|
53
|
-
else
|
54
|
-
next false
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def can_match_attribute_for?(item)
|
62
|
-
attribute_item = attribute_item_for(item)
|
63
|
-
|
64
|
-
return false unless attribute_item
|
65
|
-
return false unless attribute_item.respond_to?(@attribute_instruction.attribute)
|
66
|
-
return false if attribute_item.method(@attribute_instruction.attribute).arity > 0
|
67
|
-
|
68
|
-
true
|
69
|
-
end
|
70
|
-
|
71
|
-
def can_match_class_method_for?(item)
|
72
|
-
attribute_item = attribute_item_for(item)
|
73
|
-
|
74
|
-
return false unless attribute_item
|
75
|
-
return false unless attribute_item.class
|
76
|
-
return false unless attribute_item.class.respond_to?(@attribute_instruction.attribute)
|
77
|
-
return false if attribute_item.class.method(@attribute_instruction.attribute).arity.zero?
|
78
|
-
|
79
|
-
true
|
80
|
-
end
|
81
|
-
|
82
|
-
def attribute_matches_for?(item)
|
83
|
-
@attribute_instruction
|
84
|
-
.value_for(item: item)
|
85
|
-
.public_send(
|
86
|
-
@attribute_instruction.operator,
|
87
|
-
@attribute_instruction.value
|
88
|
-
)
|
89
|
-
end
|
90
|
-
|
91
|
-
def class_method_matches_for?(item)
|
92
|
-
maybe_item_or_collection_or_nil = attribute_item_for(item)
|
93
|
-
.class
|
94
|
-
.public_send(
|
95
|
-
@attribute_instruction.attribute,
|
96
|
-
@attribute_instruction.value
|
97
|
-
)
|
98
|
-
if maybe_item_or_collection_or_nil.nil?
|
99
|
-
false
|
100
|
-
elsif maybe_item_or_collection_or_nil.respond_to?(:each)
|
101
|
-
maybe_item_or_collection_or_nil.include? attribute_item_for(item)
|
102
|
-
else
|
103
|
-
maybe_item_or_collection_or_nil.present?
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def attribute_item_for(item)
|
108
|
-
@attribute_instruction
|
109
|
-
.resource_for(item: item)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
class ActiveRecordStrategy
|
114
|
-
def initialize(set, attribute_instruction)
|
115
|
-
@set = set
|
116
|
-
@attribute_instruction = attribute_instruction
|
117
|
-
end
|
118
|
-
|
119
|
-
def execute
|
120
|
-
return false unless @set.respond_to? :to_sql
|
121
|
-
|
122
|
-
if execute_where_operation?
|
123
|
-
statement = where_operation
|
124
|
-
elsif execute_merge_operation?
|
125
|
-
statement = merge_operation
|
126
|
-
else
|
127
|
-
return false
|
128
|
-
end
|
129
|
-
|
130
|
-
return false if throws?(ActiveRecord::StatementInvalid) { statement.load }
|
131
|
-
|
132
|
-
statement
|
133
|
-
end
|
134
|
-
|
135
|
-
private
|
136
|
-
|
137
|
-
def execute_where_operation?
|
138
|
-
return false unless attribute_model
|
139
|
-
return false unless attribute_model.respond_to?(:attribute_names)
|
140
|
-
return false unless attribute_model.attribute_names.include?(@attribute_instruction.attribute)
|
141
|
-
|
142
|
-
true
|
143
|
-
end
|
144
|
-
|
145
|
-
def execute_merge_operation?
|
146
|
-
return false unless attribute_model
|
147
|
-
return false unless attribute_model.respond_to?(@attribute_instruction.attribute)
|
148
|
-
return false if attribute_model.method(@attribute_instruction.attribute).arity.zero?
|
149
|
-
|
150
|
-
true
|
151
|
-
end
|
152
|
-
|
153
|
-
def where_operation
|
154
|
-
arel_operator = @attribute_instruction.operator(default: '=')
|
155
|
-
arel_column = Arel::Table.new(attribute_model.table_name)[@attribute_instruction.attribute]
|
156
|
-
arel_value = Arel.sql(ActiveRecord::Base.connection.quote(@attribute_instruction.value))
|
157
|
-
|
158
|
-
@set.eager_load(@attribute_instruction.associations_hash)
|
159
|
-
.where(
|
160
|
-
Arel::Nodes::InfixOperation.new(
|
161
|
-
arel_operator,
|
162
|
-
arel_column,
|
163
|
-
arel_value
|
164
|
-
)
|
165
|
-
)
|
166
|
-
end
|
167
|
-
|
168
|
-
def merge_operation
|
169
|
-
@set.eager_load(@attribute_instruction.associations_hash)
|
170
|
-
.merge(
|
171
|
-
attribute_model.public_send(
|
172
|
-
@attribute_instruction.attribute,
|
173
|
-
@attribute_instruction.value
|
174
|
-
)
|
175
|
-
)
|
176
|
-
end
|
177
|
-
|
178
|
-
def attribute_model
|
179
|
-
return @set.klass if @attribute_instruction.associations_array.empty?
|
180
|
-
return @attribute_model if defined? @attribute_model
|
181
|
-
|
182
|
-
@attribute_model = @attribute_instruction
|
183
|
-
.associations_array
|
184
|
-
.reduce(@set) do |obj, assoc|
|
185
|
-
obj.reflections[assoc.to_s]&.klass
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
42
|
end
|
190
43
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ActiveSet
|
4
|
+
module Paginating
|
5
|
+
class ActiveRecordStrategy
|
6
|
+
def initialize(set, operation_instructions)
|
7
|
+
@set = set
|
8
|
+
@operation_instructions = operation_instructions
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
return false unless @set.respond_to? :to_sql
|
13
|
+
return @set.none if @set.length <= @operation_instructions[:size] &&
|
14
|
+
@operation_instructions[:page] > 1
|
15
|
+
|
16
|
+
@set.limit(@operation_instructions[:size]).offset(page_offset)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def page_offset
|
22
|
+
return 0 if @operation_instructions[:page] == 1
|
23
|
+
|
24
|
+
@operation_instructions[:size] * (@operation_instructions[:page] - 1)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ActiveSet
|
4
|
+
module Paginating
|
5
|
+
class EnumerableStrategy
|
6
|
+
def initialize(set, operation_instructions)
|
7
|
+
@set = set
|
8
|
+
@operation_instructions = operation_instructions
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
return [] if @set.count <= @operation_instructions[:size] &&
|
13
|
+
@operation_instructions[:page] > 1
|
14
|
+
|
15
|
+
@set[page_start..page_end] || []
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def page_start
|
21
|
+
return 0 if @operation_instructions[:page] == 1
|
22
|
+
|
23
|
+
@operation_instructions[:size] * (@operation_instructions[:page] - 1)
|
24
|
+
end
|
25
|
+
|
26
|
+
def page_end
|
27
|
+
return page_start if @operation_instructions[:size] == 1
|
28
|
+
|
29
|
+
page_start + @operation_instructions[:size] - 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative './enumerable_strategy'
|
4
|
+
require_relative './active_record_strategy'
|
5
|
+
|
3
6
|
class ActiveSet
|
4
7
|
module Paginating
|
5
8
|
class Operation
|
@@ -47,56 +50,5 @@ class ActiveSet
|
|
47
50
|
maybe_integer_or_hash
|
48
51
|
end
|
49
52
|
end
|
50
|
-
|
51
|
-
class EnumerableStrategy
|
52
|
-
def initialize(set, operation_instructions)
|
53
|
-
@set = set
|
54
|
-
@operation_instructions = operation_instructions
|
55
|
-
end
|
56
|
-
|
57
|
-
def execute
|
58
|
-
return [] if @set.count <= @operation_instructions[:size] &&
|
59
|
-
@operation_instructions[:page] > 1
|
60
|
-
|
61
|
-
@set[page_start..page_end] || []
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def page_start
|
67
|
-
return 0 if @operation_instructions[:page] == 1
|
68
|
-
|
69
|
-
@operation_instructions[:size] * (@operation_instructions[:page] - 1)
|
70
|
-
end
|
71
|
-
|
72
|
-
def page_end
|
73
|
-
return page_start if @operation_instructions[:size] == 1
|
74
|
-
|
75
|
-
page_start + @operation_instructions[:size] - 1
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
class ActiveRecordStrategy
|
80
|
-
def initialize(set, operation_instructions)
|
81
|
-
@set = set
|
82
|
-
@operation_instructions = operation_instructions
|
83
|
-
end
|
84
|
-
|
85
|
-
def execute
|
86
|
-
return false unless @set.respond_to? :to_sql
|
87
|
-
return @set.none if @set.length <= @operation_instructions[:size] &&
|
88
|
-
@operation_instructions[:page] > 1
|
89
|
-
|
90
|
-
@set.limit(@operation_instructions[:size]).offset(page_offset)
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
|
95
|
-
def page_offset
|
96
|
-
return 0 if @operation_instructions[:page] == 1
|
97
|
-
|
98
|
-
@operation_instructions[:size] * (@operation_instructions[:page] - 1)
|
99
|
-
end
|
100
|
-
end
|
101
53
|
end
|
102
54
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ActiveSet
|
4
|
+
module Sorting
|
5
|
+
class ActiveRecordStrategy
|
6
|
+
def initialize(set, attribute_instructions)
|
7
|
+
@set = set
|
8
|
+
@attribute_instructions = attribute_instructions
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
return false unless @set.respond_to? :to_sql
|
13
|
+
|
14
|
+
executable_instructions.reduce(set_with_eager_loaded_associations) do |set, attribute_instruction|
|
15
|
+
statement = set.merge(order_operation_for(attribute_instruction))
|
16
|
+
|
17
|
+
return false if throws?(ActiveRecord::StatementInvalid) { statement.load }
|
18
|
+
|
19
|
+
attribute_instruction.processed = true
|
20
|
+
statement
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def executable_instructions
|
25
|
+
return {} unless @set.respond_to? :to_sql
|
26
|
+
|
27
|
+
@attribute_instructions.select do |attribute_instruction|
|
28
|
+
attribute_model = attribute_model_for(attribute_instruction)
|
29
|
+
next false unless attribute_model
|
30
|
+
next false unless attribute_model.respond_to?(:attribute_names)
|
31
|
+
next false unless attribute_model.attribute_names.include?(attribute_instruction.attribute)
|
32
|
+
|
33
|
+
true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def set_with_eager_loaded_associations
|
40
|
+
associations_hash = @attribute_instructions.reduce({}) { |h, i| h.merge(i.associations_hash) }
|
41
|
+
@set.eager_load(associations_hash)
|
42
|
+
end
|
43
|
+
|
44
|
+
def order_operation_for(attribute_instruction)
|
45
|
+
attribute_model = attribute_model_for(attribute_instruction)
|
46
|
+
|
47
|
+
arel_column = Arel::Table.new(attribute_model.table_name)[attribute_instruction.attribute]
|
48
|
+
arel_column = case_insensitive?(attribute_instruction) ? arel_column.lower : arel_column
|
49
|
+
|
50
|
+
arel_direction = direction_operator(attribute_instruction.value)
|
51
|
+
|
52
|
+
attribute_model.order(arel_column.send(arel_direction))
|
53
|
+
end
|
54
|
+
|
55
|
+
def attribute_model_for(attribute_instruction)
|
56
|
+
return @set.klass if attribute_instruction.associations_array.empty?
|
57
|
+
|
58
|
+
attribute_instruction
|
59
|
+
.associations_array
|
60
|
+
.reduce(@set) do |obj, assoc|
|
61
|
+
obj.reflections[assoc.to_s]&.klass
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def case_insensitive?(attribute_instruction)
|
66
|
+
attribute_instruction.operator.to_s.casecmp('i').zero?
|
67
|
+
end
|
68
|
+
|
69
|
+
def direction_operator(direction)
|
70
|
+
return :desc if direction.to_s.downcase.start_with? 'desc'
|
71
|
+
|
72
|
+
:asc
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../helpers/transform_to_sortable_numeric'
|
4
|
+
|
5
|
+
class ActiveSet
|
6
|
+
module Sorting
|
7
|
+
class EnumerableStrategy
|
8
|
+
def initialize(set, attribute_instructions)
|
9
|
+
@set = set
|
10
|
+
@attribute_instructions = attribute_instructions
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute
|
14
|
+
# http://brandon.dimcheff.com/2009/11/18/rubys-sort-vs-sort-by/
|
15
|
+
@set.sort_by do |item|
|
16
|
+
@attribute_instructions.map do |instruction|
|
17
|
+
sortable_numeric_for(instruction, item) * direction_multiplier(instruction.value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def sortable_numeric_for(instruction, item)
|
23
|
+
value = instruction.value_for(item: item)
|
24
|
+
if value.is_a?(String) || value.is_a?(Symbol)
|
25
|
+
value = if case_insensitive?(instruction, value)
|
26
|
+
value.to_s.downcase
|
27
|
+
else
|
28
|
+
value.to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
transform_to_sortable_numeric(value)
|
33
|
+
end
|
34
|
+
|
35
|
+
def case_insensitive?(instruction, _value)
|
36
|
+
instruction.operator.to_s.casecmp('i').zero?
|
37
|
+
end
|
38
|
+
|
39
|
+
def direction_multiplier(direction)
|
40
|
+
return -1 if direction.to_s.downcase.start_with? 'desc'
|
41
|
+
|
42
|
+
1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../attribute_instruction'
|
4
|
-
require_relative '
|
4
|
+
require_relative './enumerable_strategy'
|
5
|
+
require_relative './active_record_strategy'
|
5
6
|
|
6
7
|
class ActiveSet
|
7
8
|
module Sorting
|
@@ -13,8 +14,8 @@ class ActiveSet
|
|
13
14
|
|
14
15
|
def execute
|
15
16
|
attribute_instructions = @instructions_hash
|
16
|
-
|
17
|
-
|
17
|
+
.flatten_keys
|
18
|
+
.map { |k, v| AttributeInstruction.new(k, v) }
|
18
19
|
|
19
20
|
activerecord_strategy = ActiveRecordStrategy.new(@set, attribute_instructions)
|
20
21
|
if activerecord_strategy.executable_instructions == attribute_instructions
|
@@ -30,115 +31,5 @@ class ActiveSet
|
|
30
31
|
@instructions_hash.symbolize_keys
|
31
32
|
end
|
32
33
|
end
|
33
|
-
|
34
|
-
class EnumerableStrategy
|
35
|
-
def initialize(set, attribute_instructions)
|
36
|
-
@set = set
|
37
|
-
@attribute_instructions = attribute_instructions
|
38
|
-
end
|
39
|
-
|
40
|
-
def execute
|
41
|
-
# http://brandon.dimcheff.com/2009/11/18/rubys-sort-vs-sort-by/
|
42
|
-
@set.sort_by do |item|
|
43
|
-
@attribute_instructions.map do |instruction|
|
44
|
-
sortable_numeric_for(instruction, item) * direction_multiplier(instruction.value)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def sortable_numeric_for(instruction, item)
|
50
|
-
value = instruction.value_for(item: item)
|
51
|
-
if value.is_a?(String) || value.is_a?(Symbol)
|
52
|
-
value = if case_insensitive?(instruction, value)
|
53
|
-
value.to_s.downcase
|
54
|
-
else
|
55
|
-
value.to_s
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
transform_to_sortable_numeric(value)
|
60
|
-
end
|
61
|
-
|
62
|
-
def case_insensitive?(instruction, _value)
|
63
|
-
instruction.operator.to_s.casecmp('i').zero?
|
64
|
-
end
|
65
|
-
|
66
|
-
def direction_multiplier(direction)
|
67
|
-
return -1 if direction.to_s.downcase.start_with? 'desc'
|
68
|
-
|
69
|
-
1
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
class ActiveRecordStrategy
|
74
|
-
def initialize(set, attribute_instructions)
|
75
|
-
@set = set
|
76
|
-
@attribute_instructions = attribute_instructions
|
77
|
-
end
|
78
|
-
|
79
|
-
def execute
|
80
|
-
return false unless @set.respond_to? :to_sql
|
81
|
-
|
82
|
-
executable_instructions.reduce(set_with_eager_loaded_associations) do |set, attribute_instruction|
|
83
|
-
statement = set.merge(order_operation_for(attribute_instruction))
|
84
|
-
|
85
|
-
return false if throws?(ActiveRecord::StatementInvalid) { statement.load }
|
86
|
-
|
87
|
-
attribute_instruction.processed = true
|
88
|
-
statement
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def executable_instructions
|
93
|
-
return {} unless @set.respond_to? :to_sql
|
94
|
-
|
95
|
-
@attribute_instructions.select do |attribute_instruction|
|
96
|
-
attribute_model = attribute_model_for(attribute_instruction)
|
97
|
-
next false unless attribute_model
|
98
|
-
next false unless attribute_model.respond_to?(:attribute_names)
|
99
|
-
next false unless attribute_model.attribute_names.include?(attribute_instruction.attribute)
|
100
|
-
|
101
|
-
true
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def set_with_eager_loaded_associations
|
108
|
-
associations_hash = @attribute_instructions.reduce({}) { |h, i| h.merge(i.associations_hash) }
|
109
|
-
@set.eager_load(associations_hash)
|
110
|
-
end
|
111
|
-
|
112
|
-
def order_operation_for(attribute_instruction)
|
113
|
-
attribute_model = attribute_model_for(attribute_instruction)
|
114
|
-
|
115
|
-
arel_column = Arel::Table.new(attribute_model.table_name)[attribute_instruction.attribute]
|
116
|
-
arel_column = case_insensitive?(attribute_instruction) ? arel_column.lower : arel_column
|
117
|
-
|
118
|
-
arel_direction = direction_operator(attribute_instruction.value)
|
119
|
-
|
120
|
-
attribute_model.order(arel_column.send(arel_direction))
|
121
|
-
end
|
122
|
-
|
123
|
-
def attribute_model_for(attribute_instruction)
|
124
|
-
return @set.klass if attribute_instruction.associations_array.empty?
|
125
|
-
|
126
|
-
attribute_instruction
|
127
|
-
.associations_array
|
128
|
-
.reduce(@set) do |obj, assoc|
|
129
|
-
obj.reflections[assoc.to_s]&.klass
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def case_insensitive?(attribute_instruction)
|
134
|
-
attribute_instruction.operator.to_s.casecmp('i').zero?
|
135
|
-
end
|
136
|
-
|
137
|
-
def direction_operator(direction)
|
138
|
-
return :desc if direction.to_s.downcase.start_with? 'desc'
|
139
|
-
|
140
|
-
:asc
|
141
|
-
end
|
142
|
-
end
|
143
34
|
end
|
144
35
|
end
|
data/lib/helpers/throws.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Style/AsciiComments
|
3
4
|
# Returns a Numeric for `value` that respects sort-order
|
4
5
|
# can be used in Enumerable#sort_by
|
5
6
|
#
|
@@ -12,25 +13,32 @@
|
|
12
13
|
# transform_to_sortable_numeric(Date.new(2000, 12, 25))
|
13
14
|
# => 977720400000
|
14
15
|
|
16
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
15
17
|
def transform_to_sortable_numeric(value)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
# https://www.justinweiss.com/articles/4-simple-memoization-patterns-in-ruby-and-one-gem/#and-what-about-parameters
|
19
|
+
@sortable_numeric ||= Hash.new do |h, key|
|
20
|
+
h[key] = if key.is_a?(Numeric)
|
21
|
+
key
|
22
|
+
elsif key == true
|
23
|
+
1
|
24
|
+
elsif key == false
|
25
|
+
0
|
26
|
+
elsif key.is_a?(String) || key.is_a?(Symbol)
|
27
|
+
key
|
28
|
+
.to_s # 'aB09ü'
|
29
|
+
.split('') # ["a", "B", "0", "9", "ü"]
|
30
|
+
.map { |char| char.ord.to_s.rjust(3, '0') } # ["097", "066", "048", "057", "252"]
|
31
|
+
.insert(1, '.') # ["097", ".", "066", "048", "057", "252"]
|
32
|
+
.reduce(&:concat) # "097.066048057252"
|
33
|
+
.to_r # (24266512014313/250000000000)
|
34
|
+
elsif key.respond_to?(:to_time)
|
35
|
+
# https://stackoverflow.com/a/30604935/2884386
|
36
|
+
(key.to_time.to_f * 1000).round
|
37
|
+
else
|
38
|
+
key
|
39
|
+
end
|
28
40
|
end
|
29
|
-
|
30
|
-
# https://stackoverflow.com/a/30604935/2884386
|
31
|
-
return (value.to_time.to_f * 1000).round if value.respond_to?(:to_time)
|
32
|
-
|
33
|
-
# :nocov:
|
34
|
-
value
|
35
|
-
# :nocov:
|
41
|
+
@sortable_numeric[value]
|
36
42
|
end
|
43
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
44
|
+
# rubocop:enable Style/AsciiComments
|
@@ -8,8 +8,6 @@ class Hash
|
|
8
8
|
# hash = { person: { name: { first: 'Rob' }, age: '28' } }
|
9
9
|
# hash.flatten_keys_to_array
|
10
10
|
# => {[:person, :name, :first] => "Rob", [:person, :age]=>"28" }
|
11
|
-
# hash
|
12
|
-
# => { person: { name: { first: 'Rob' }, age: '28' } }
|
13
11
|
def flatten_keys_to_array
|
14
12
|
_flatten_keys(self)
|
15
13
|
end
|
@@ -19,9 +17,7 @@ class Hash
|
|
19
17
|
#
|
20
18
|
# hash = { person: { name: { first: 'Rob' }, age: '28' } }
|
21
19
|
# hash.flatten_keys_to_dotpath
|
22
|
-
# => { 'person.name.first' => "Rob",
|
23
|
-
# hash
|
24
|
-
# => { person: { name: { first: 'Rob' }, age: '28' } }
|
20
|
+
# => { 'person.name.first' => "Rob", 'person.age'=>"28" }
|
25
21
|
def flatten_keys_to_dotpath
|
26
22
|
_flatten_keys(self, ->(*keys) { keys.join('.') })
|
27
23
|
end
|
@@ -30,31 +26,32 @@ class Hash
|
|
30
26
|
#
|
31
27
|
# hash = { person: { name: { first: 'Rob' }, age: '28' } }
|
32
28
|
# hash.flatten_keys_to_html_attribute
|
33
|
-
# => { 'person-name-first' => "Rob",
|
34
|
-
# hash
|
35
|
-
# => { person: { name: { first: 'Rob' }, age: '28' } }
|
29
|
+
# => { 'person-name-first' => "Rob", 'person-age'=>"28" }
|
36
30
|
def flatten_keys_to_html_attribute
|
37
31
|
_flatten_keys(self, ->(*keys) { keys.join('-') })
|
38
32
|
end
|
39
33
|
|
40
|
-
# Returns a flat hash where all nested keys are collapsed into a string of keys
|
34
|
+
# Returns a flat hash where all nested keys are collapsed into a string of keys
|
35
|
+
# fitting the Rails request param pattern.
|
41
36
|
#
|
42
37
|
# hash = { person: { name: { first: 'Rob' }, age: '28' } }
|
43
38
|
# hash.flatten_keys_to_rails_param
|
44
|
-
# => { 'person[name][first]' => "Rob", [
|
45
|
-
# hash
|
46
|
-
# => { person: { name: { first: 'Rob' }, age: '28' } }
|
39
|
+
# => { 'person[name][first]' => "Rob", 'person[age]'=>"28" }
|
47
40
|
def flatten_keys_to_rails_param
|
48
41
|
_flatten_keys(self, ->(*keys) { keys.map(&:to_s).reduce { |memo, key| memo + "[#{key}]" } })
|
49
42
|
end
|
50
43
|
|
51
44
|
private
|
52
45
|
|
53
|
-
# refactored
|
46
|
+
# refactored from https://stackoverflow.com/a/23861946/2884386
|
54
47
|
def _flatten_keys(input, keypath_gen = ->(*keys) { keys }, keys = [], output = {})
|
55
|
-
|
56
|
-
|
57
|
-
input.
|
48
|
+
if input.is_a? Hash
|
49
|
+
input.each { |k, v| _flatten_keys(v, keypath_gen, keys + Array(k), output) }
|
50
|
+
# elsif input.is_a? Array
|
51
|
+
# input.each_with_index { |v, i| _flatten_keys(v, keypath_gen, keys + Array(i), output) }
|
52
|
+
else
|
53
|
+
return output.merge!(keypath_gen.call(*keys) => input)
|
54
|
+
end
|
58
55
|
|
59
56
|
output
|
60
57
|
end
|
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.8.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: 2018-
|
11
|
+
date: 2018-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.15'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: codecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: combustion
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -186,6 +200,7 @@ extensions: []
|
|
186
200
|
extra_rdoc_files: []
|
187
201
|
files:
|
188
202
|
- ".gitignore"
|
203
|
+
- ".hound.yml"
|
189
204
|
- ".rspec"
|
190
205
|
- ".rubocop.yml"
|
191
206
|
- ".ruby-version"
|
@@ -203,9 +218,16 @@ files:
|
|
203
218
|
- lib/active_set.rb
|
204
219
|
- lib/active_set/attribute_instruction.rb
|
205
220
|
- lib/active_set/column_instruction.rb
|
221
|
+
- lib/active_set/exporting/csv_strategy.rb
|
206
222
|
- lib/active_set/exporting/operation.rb
|
223
|
+
- lib/active_set/filtering/active_record_strategy.rb
|
224
|
+
- lib/active_set/filtering/enumerable_strategy.rb
|
207
225
|
- lib/active_set/filtering/operation.rb
|
226
|
+
- lib/active_set/paginating/active_record_strategy.rb
|
227
|
+
- lib/active_set/paginating/enumerable_strategy.rb
|
208
228
|
- lib/active_set/paginating/operation.rb
|
229
|
+
- lib/active_set/sorting/active_record_strategy.rb
|
230
|
+
- lib/active_set/sorting/enumerable_strategy.rb
|
209
231
|
- lib/active_set/sorting/operation.rb
|
210
232
|
- lib/helpers/throws.rb
|
211
233
|
- lib/helpers/transform_to_sortable_numeric.rb
|