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,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
|