activeset 0.5.8 → 0.6.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 +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,37 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../
|
4
|
-
require_relative '../
|
3
|
+
require_relative '../adapter_base'
|
4
|
+
require_relative '../processor_base'
|
5
5
|
|
6
6
|
class ActiveSet
|
7
|
-
class
|
8
|
-
class ActiveRecordAdapter <
|
7
|
+
class Processor::Paginate < Processor::Base
|
8
|
+
class ActiveRecordAdapter < Adapter::Base
|
9
9
|
def process
|
10
|
-
return
|
10
|
+
return false unless @set.respond_to? :to_sql
|
11
|
+
return @set.none if @set.length <= page_size && page_number > 1
|
11
12
|
|
12
|
-
|
13
|
+
@set.limit(page_size).offset(page_offset)
|
13
14
|
end
|
14
15
|
|
15
16
|
private
|
16
17
|
|
17
|
-
def paginated_set
|
18
|
-
return @set.none if @set.length <= page_size && page_number > 1
|
19
|
-
@set.limit(page_size).offset(page_offset)
|
20
|
-
end
|
21
|
-
|
22
18
|
def page_offset
|
23
19
|
return 0 if page_number == 1
|
20
|
+
|
24
21
|
page_size * (page_number - 1)
|
25
22
|
end
|
26
23
|
|
27
24
|
def page_size
|
28
|
-
@
|
25
|
+
@instructions.get('size').to_i
|
29
26
|
end
|
30
27
|
|
31
28
|
def page_number
|
32
|
-
num = @
|
29
|
+
num = @instructions.get('page').to_i
|
33
30
|
return 1 if (num - 1).negative?
|
34
31
|
return 1 if (num - 1).zero?
|
32
|
+
|
35
33
|
num
|
36
34
|
end
|
37
35
|
end
|
@@ -1,39 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../
|
4
|
-
require_relative '../
|
3
|
+
require_relative '../adapter_base'
|
4
|
+
require_relative '../processor_base'
|
5
5
|
|
6
6
|
class ActiveSet
|
7
|
-
class
|
8
|
-
class EnumerableAdapter <
|
7
|
+
class Processor::Paginate < Processor::Base
|
8
|
+
class EnumerableAdapter < Adapter::Base
|
9
9
|
def process
|
10
|
-
return_set(paginated_set)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def paginated_set
|
16
10
|
return [] if @set.count <= page_size && page_number > 1
|
17
11
|
|
18
12
|
@set[page_start..page_end] || []
|
19
13
|
end
|
20
14
|
|
15
|
+
private
|
16
|
+
|
21
17
|
def page_start
|
22
18
|
return 0 if page_number == 1
|
19
|
+
|
23
20
|
page_size * (page_number - 1)
|
24
21
|
end
|
25
22
|
|
26
23
|
def page_end
|
27
24
|
return page_start if page_size == 1
|
25
|
+
|
28
26
|
page_start + page_size - 1
|
29
27
|
end
|
30
28
|
|
31
29
|
def page_size
|
32
|
-
@
|
30
|
+
@instructions.get('size').to_i
|
33
31
|
end
|
34
32
|
|
35
33
|
def page_number
|
36
|
-
num = @
|
34
|
+
num = @instructions.get('page').to_i
|
37
35
|
(num.to_i - 1).negative? ? 0 : num
|
38
36
|
end
|
39
37
|
end
|
@@ -0,0 +1,19 @@
|
|
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
|
@@ -0,0 +1,50 @@
|
|
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 ActiveRecordAdapter < Adapter::ActiveRecord
|
10
|
+
def process
|
11
|
+
@instructions.reduce(@set) do |set, _instruction|
|
12
|
+
# set Adapter::Base#instruction, which many methods depend on
|
13
|
+
self.instruction = _instruction
|
14
|
+
|
15
|
+
return false unless @set.respond_to?(:to_sql)
|
16
|
+
return false unless can_query_with_active_record?
|
17
|
+
|
18
|
+
statement = arel_eager_load_associations
|
19
|
+
.merge(arel_operation)
|
20
|
+
|
21
|
+
return false if throws?(ActiveRecord::StatementInvalid) { statement.load }
|
22
|
+
|
23
|
+
statement
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def arel_operation
|
30
|
+
arel_direction = arel_direction(instruction.value)
|
31
|
+
|
32
|
+
attribute_model.order(arel_column.send(arel_direction))
|
33
|
+
end
|
34
|
+
|
35
|
+
def arel_column
|
36
|
+
case_insensitive? ? super.lower : super
|
37
|
+
end
|
38
|
+
|
39
|
+
def case_insensitive?
|
40
|
+
instruction.operator.to_s.downcase == 'i'
|
41
|
+
end
|
42
|
+
|
43
|
+
def arel_direction(direction)
|
44
|
+
return 'desc' if direction.to_s.downcase.start_with? 'desc'
|
45
|
+
|
46
|
+
'asc'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../adapter_base'
|
4
|
+
require_relative '../processor_base'
|
5
|
+
|
6
|
+
class ActiveSet
|
7
|
+
class Processor::Sort < Processor::Base
|
8
|
+
class EnumerableAdapter < Adapter::Base
|
9
|
+
def process
|
10
|
+
@set.sort do |left, right|
|
11
|
+
@instructions.reduce(0) do |diff, instruction|
|
12
|
+
# set Adapter::Base#instruction, which many methods depend on
|
13
|
+
self.instruction = instruction
|
14
|
+
|
15
|
+
# `left` and `right` differed at an earlier order entry
|
16
|
+
next diff if diff != 0
|
17
|
+
|
18
|
+
left_value = sortable_attribute_for(left)
|
19
|
+
right_value = sortable_attribute_for(right)
|
20
|
+
|
21
|
+
# handle `nil` values
|
22
|
+
next 0 if left_value.nil? && right_value.nil?
|
23
|
+
next 1 if left_value.nil?
|
24
|
+
next -1 if right_value.nil?
|
25
|
+
|
26
|
+
# do the actual comparison
|
27
|
+
comparison = left_value <=> right_value
|
28
|
+
next comparison * direction_multiplier(instruction.value)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def sortable_attribute_for(item)
|
36
|
+
value = instruction.value_for(item: item)
|
37
|
+
|
38
|
+
return value.to_s.downcase if case_insensitive?(value)
|
39
|
+
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
def case_insensitive?(value)
|
44
|
+
# Cannot sort pure Booleans or Nils, so we _must_ cast to Strings
|
45
|
+
return true if value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
46
|
+
return true if value.is_a?(NilClass)
|
47
|
+
|
48
|
+
instruction.operator.to_s.downcase == 'i'
|
49
|
+
end
|
50
|
+
|
51
|
+
def direction_multiplier(direction)
|
52
|
+
return -1 if direction.to_s.downcase.start_with? 'desc'
|
53
|
+
|
54
|
+
1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './
|
4
|
-
require_relative './
|
3
|
+
require_relative './processor_base'
|
4
|
+
require_relative './processor_transform/csv_adapter'
|
5
5
|
|
6
6
|
class ActiveSet
|
7
|
-
class
|
7
|
+
class Processor::Transform < Processor::Base
|
8
8
|
def process
|
9
9
|
fail "Format #{format} is not currently supported as option for tranform" unless %w[csv].include?(format)
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
adapter_for(format: format)
|
12
|
+
.new(@set, columns)
|
13
|
+
.process
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
@@ -2,20 +2,15 @@
|
|
2
2
|
|
3
3
|
require 'csv'
|
4
4
|
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
+
require 'active_support/core_ext/string/inflections'
|
5
6
|
|
6
|
-
require_relative '../
|
7
|
-
require_relative '../
|
7
|
+
require_relative '../adapter_base'
|
8
|
+
require_relative '../processor_base'
|
8
9
|
|
9
10
|
class ActiveSet
|
10
|
-
class
|
11
|
-
class CSVAdapter <
|
11
|
+
class Processor::Transform < Processor::Base
|
12
|
+
class CSVAdapter < Adapter::Base
|
12
13
|
def process
|
13
|
-
return_set(transformed_set)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def transformed_set
|
19
14
|
::CSV.generate do |output|
|
20
15
|
output << column_keys_for(item: @set.first)
|
21
16
|
@set.each do |item|
|
@@ -24,6 +19,8 @@ class ActiveSet
|
|
24
19
|
end
|
25
20
|
end
|
26
21
|
|
22
|
+
private
|
23
|
+
|
27
24
|
def column_keys_for(item:)
|
28
25
|
columns.map do |column|
|
29
26
|
ColumnInstruction.new(column, item).key
|
@@ -37,7 +34,7 @@ class ActiveSet
|
|
37
34
|
end
|
38
35
|
|
39
36
|
def columns
|
40
|
-
@
|
37
|
+
@instructions.compact
|
41
38
|
end
|
42
39
|
|
43
40
|
class ColumnInstruction
|
@@ -48,8 +45,8 @@ class ActiveSet
|
|
48
45
|
|
49
46
|
def key
|
50
47
|
return @hash[:key] if @hash.key? :key
|
51
|
-
return attribute_model.human_attribute_name(
|
52
|
-
instruction_entry.
|
48
|
+
return attribute_model.human_attribute_name(instructions_entry.attribute) if attribute_model.respond_to? :human_attribute_name
|
49
|
+
instruction_entry.keypath.map(&:titleize).join(' ')
|
53
50
|
end
|
54
51
|
|
55
52
|
def value
|
@@ -61,7 +58,7 @@ class ActiveSet
|
|
61
58
|
private
|
62
59
|
|
63
60
|
def instruction_entry
|
64
|
-
|
61
|
+
Instruction.new(@hash[:value], nil)
|
65
62
|
end
|
66
63
|
|
67
64
|
def attribute_model
|
data/lib/active_set/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Returns a Boolean for whether the block raises the Exception expected
|
4
|
+
#
|
5
|
+
# throws?(StandardError) { raise }
|
6
|
+
# => true
|
7
|
+
# throws?(NameError) { raise NameError }
|
8
|
+
# => true
|
9
|
+
# throws?(NoMethodError) { raise NameError }
|
10
|
+
# => false
|
11
|
+
# throws?(StandardError) { 'foo' }
|
12
|
+
# => false
|
13
|
+
|
14
|
+
def throws?(exception) # &block
|
15
|
+
yield
|
16
|
+
return false
|
17
|
+
rescue Exception => e
|
18
|
+
return e.is_a? exception
|
19
|
+
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.6.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-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -171,25 +171,27 @@ files:
|
|
171
171
|
- bin/console
|
172
172
|
- bin/setup
|
173
173
|
- config.ru
|
174
|
+
- lib/.DS_Store
|
174
175
|
- lib/active_set.rb
|
175
|
-
- lib/active_set
|
176
|
-
- lib/active_set/
|
177
|
-
- lib/active_set/
|
178
|
-
- lib/active_set/
|
179
|
-
- lib/active_set/
|
180
|
-
- lib/active_set/
|
181
|
-
- lib/active_set/
|
182
|
-
- lib/active_set/
|
183
|
-
- lib/active_set/
|
184
|
-
- lib/active_set/
|
185
|
-
- lib/active_set/
|
186
|
-
- lib/active_set/
|
187
|
-
- lib/active_set/
|
188
|
-
- lib/active_set/
|
189
|
-
- lib/active_set/
|
190
|
-
- lib/active_set/
|
191
|
-
- lib/active_set/
|
176
|
+
- lib/active_set/.DS_Store
|
177
|
+
- lib/active_set/adapter_activerecord.rb
|
178
|
+
- lib/active_set/adapter_base.rb
|
179
|
+
- lib/active_set/instruction.rb
|
180
|
+
- lib/active_set/instructions.rb
|
181
|
+
- lib/active_set/processor_base.rb
|
182
|
+
- lib/active_set/processor_filter.rb
|
183
|
+
- lib/active_set/processor_filter/active_record_adapter.rb
|
184
|
+
- lib/active_set/processor_filter/enumerable_adapter.rb
|
185
|
+
- lib/active_set/processor_paginate.rb
|
186
|
+
- lib/active_set/processor_paginate/active_record_adapter.rb
|
187
|
+
- lib/active_set/processor_paginate/enumerable_adapter.rb
|
188
|
+
- lib/active_set/processor_sort.rb
|
189
|
+
- lib/active_set/processor_sort/active_record_adapter.rb
|
190
|
+
- lib/active_set/processor_sort/enumerable_adapter.rb
|
191
|
+
- lib/active_set/processor_transform.rb
|
192
|
+
- lib/active_set/processor_transform/csv_adapter.rb
|
192
193
|
- lib/active_set/version.rb
|
194
|
+
- lib/helpers/throws.rb
|
193
195
|
- lib/patches/core_ext/hash/flatten_keys.rb
|
194
196
|
homepage: https://github.com/fractaledmind/activeset
|
195
197
|
licenses:
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/hash/keys'
|
4
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
-
|
6
|
-
require_relative './entry'
|
7
|
-
|
8
|
-
class ActiveSet
|
9
|
-
class Instructions
|
10
|
-
attr_reader :hash
|
11
|
-
|
12
|
-
def initialize(hash)
|
13
|
-
@hash = hash.with_indifferent_access
|
14
|
-
@flattened_hash = hash.flatten_keys.transform_keys { |k| k.map(&:to_s) }
|
15
|
-
end
|
16
|
-
|
17
|
-
def process_adapter(set:, adapter:)
|
18
|
-
@flattened_hash.reduce(set) do |inner_set, (keypath, value)|
|
19
|
-
instruction = Entry.new(keypath, value)
|
20
|
-
output = adapter.new(inner_set, instruction).process
|
21
|
-
remove_from_instruction_set(key: instruction.path) if output[:processed]
|
22
|
-
|
23
|
-
output[:set]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def get(keypath)
|
28
|
-
@hash.dig(*keypath)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def remove_from_instruction_set(key:)
|
34
|
-
@flattened_hash.delete(key)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/module/delegation'
|
4
|
-
|
5
|
-
require_relative 'entry/keypath'
|
6
|
-
require_relative 'entry/value'
|
7
|
-
|
8
|
-
class ActiveSet
|
9
|
-
class Instructions
|
10
|
-
class Entry
|
11
|
-
attr_reader :keypath
|
12
|
-
|
13
|
-
delegate :path, :attribute, :operator, :associations_array,
|
14
|
-
:associations_hash, :value_for, :resource_for, :titleized,
|
15
|
-
to: :keypath
|
16
|
-
|
17
|
-
def initialize(keypath, value)
|
18
|
-
@keypath = KeyPath.new(keypath)
|
19
|
-
@value = Value.new(value)
|
20
|
-
end
|
21
|
-
|
22
|
-
def value
|
23
|
-
@value.raw
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|