activeset 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46b1fb5697f15f8789f8d174bdee4e946862cbd1
4
- data.tar.gz: 2c05138de95c75628c2ddea4d24508ddbd511248
3
+ metadata.gz: fc73d4a0f511ddca2d0c895b7867816dc571102f
4
+ data.tar.gz: 02ac9b548790d30b2dac78a372b3ccc091769ed2
5
5
  SHA512:
6
- metadata.gz: 788668ec2fb6bf0bc24db2d2675e9dfea2cd9e852cd4197d411e6113486a2b2ac88c165b74a0dc74b944c2246ab101f2137cdcb62797d5871019301e877fb090
7
- data.tar.gz: 19a7388ad9014f195860aeb37732810a0dd5494d62a9721a0c4e18402d219ab81c004a4be97f4fe1ea9d835ab39ac0f6f915c472d29c37d13d39dbb92d296473
6
+ metadata.gz: 029232215b1cd1280f1b75757198bce5e97aa2e64603f2fa5c51aef8304407c7b56e1b0928a0e09fac080c9de272b00716842d94ad122a99f97d8f5337a1d58b
7
+ data.tar.gz: e73777713e06505233491977d66b4f48966e3ce5a50b4b99dcc242f00db13349e10ac3166a6ac5fff0da0cfcad02fffcf61359cba737b6e20c63d8694df8216a
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ v 0.3.1
2
+ - Implement an Instructions object layer for handling the hashes passed into Processors
3
+ v 0.3.0
4
+ - remove the typecasting functionality
5
+ - bug fixes
6
+ - improved specs
1
7
  v 0.2.0
2
8
  - allows for filtering and sorting enumerable collections via associated attributes
3
9
  v 0.1.0
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './entry'
4
+
5
+ class ActiveSet
6
+ class Instructions
7
+ attr_reader :hash
8
+
9
+ def initialize(hash)
10
+ @hash = hash
11
+ @flattened_hash = hash.flatten_keys
12
+ end
13
+
14
+ def process_adapter(set:, adapter:)
15
+ @flattened_hash.reject { |_, v| v.blank? }
16
+ .reduce(set) do |inner_set, (keypath, value)|
17
+ instruction = Entry.new(keypath, value)
18
+ adapter.new(instruction).process(inner_set)
19
+ end
20
+ end
21
+
22
+ def get(keypath)
23
+ @hash.dig(*keypath)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
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 :attribute, :operator, :associations_array, :associations_hash, :value_for, :resource_for,
14
+ to: :keypath
15
+
16
+ def initialize(keypath, value)
17
+ @keypath = KeyPath.new(keypath)
18
+ @value = Value.new(value)
19
+ end
20
+
21
+ def value
22
+ @value.raw
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/array/wrap'
4
+ require 'active_support/core_ext/object/try'
5
+
6
+ class ActiveSet
7
+ class Instructions
8
+ class Entry
9
+ class KeyPath
10
+ attr_reader :path
11
+
12
+ def initialize(path)
13
+ # `path` can be an Array (e.g. [:parent, :child, :grandchild])
14
+ # or a String (e.g. 'parent.child.grandchild')
15
+ @path = path.is_a?(String) ? path.split('.') : Array.wrap(path).map(&:to_s)
16
+ end
17
+
18
+ def attribute
19
+ attribute = @path.last
20
+ return attribute.sub(operator_regex, '') if attribute.match operator_regex
21
+ attribute
22
+ end
23
+
24
+ def operator
25
+ attribute = @path.last
26
+ return attribute[operator_regex, 1] if attribute.match operator_regex
27
+ '=='
28
+ end
29
+
30
+ def associations_array
31
+ @path.slice(0, @path.length - 1)
32
+ end
33
+
34
+ def associations_hash
35
+ associations_array.reverse.reduce({}) { |a, e| { e => a } }
36
+ end
37
+
38
+ def value_for(item:)
39
+ resource_for(item: item).send(attribute)
40
+ rescue
41
+ nil
42
+ end
43
+
44
+ def resource_for(item:)
45
+ associations_array.reduce(item, :try)
46
+ rescue
47
+ nil
48
+ end
49
+
50
+ private
51
+
52
+ def operator_regex
53
+ /\((.*?)\)/
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActiveSet
4
+ class Instructions
5
+ class Entry
6
+ class Value
7
+ attr_reader :raw
8
+
9
+ def initialize(value)
10
+ @raw = value
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../structure/path'
4
-
5
- class BaseAdapter
6
- def initialize(keypath, value)
7
- @structure_path = Structure::Path.new(keypath)
8
- @value = value
3
+ class ActiveSet
4
+ class BaseAdapter
5
+ def initialize(instruction)
6
+ @instruction = instruction
7
+ end
9
8
  end
10
9
  end
@@ -1,19 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'patches/core_ext/hash/flatten_keys'
4
+ require_relative '../instructions/base'
4
5
 
5
- class BaseProcessor
6
- def self.queue_adapter(adapter)
7
- @adapters ||= []
8
- @adapters |= [adapter]
9
- end
6
+ class ActiveSet
7
+ class BaseProcessor
8
+ def self.queue_adapter(adapter)
9
+ @adapters ||= []
10
+ @adapters |= [adapter]
11
+ end
10
12
 
11
- def initialize(set, structure)
12
- @set = set
13
- @structure = structure.flatten_keys
14
- end
13
+ def initialize(set, instructions)
14
+ @set = set
15
+ @instructions = Instructions.new(instructions)
16
+ end
15
17
 
16
- def adapters
17
- self.class.instance_variable_get(:@adapters)
18
+ def adapters
19
+ self.class.instance_variable_get(:@adapters)
20
+ end
18
21
  end
19
22
  end
@@ -19,34 +19,34 @@ class ActiveSet
19
19
  def attribute_is_field?
20
20
  return false unless attribute_model
21
21
  attribute_model.attribute_names
22
- .include?(@structure_path.attribute)
22
+ .include?(@instruction.attribute)
23
23
  end
24
24
 
25
25
  def query
26
- @set.includes(@structure_path.to_h)
27
- .references(@structure_path.to_h)
26
+ @set.includes(@instruction.associations_hash)
27
+ .references(@instruction.associations_hash)
28
28
  .where(arel_operation)
29
29
  end
30
30
 
31
31
  def arel_operation
32
- Arel::Nodes::InfixOperation.new(@structure_path.operator,
32
+ Arel::Nodes::InfixOperation.new(@instruction.operator,
33
33
  arel_column,
34
34
  arel_value)
35
35
  end
36
36
 
37
37
  def attribute_model
38
- @structure_path.to_a
39
- .reduce(@set) do |obj, assoc|
40
- obj.reflections[assoc.to_s]&.klass
41
- end
38
+ @instruction.associations_array
39
+ .reduce(@set) do |obj, assoc|
40
+ obj.reflections[assoc.to_s]&.klass
41
+ end
42
42
  end
43
43
 
44
44
  def arel_column
45
- arel_table[@structure_path.attribute]
45
+ arel_table[@instruction.attribute]
46
46
  end
47
47
 
48
48
  def arel_value
49
- Arel.sql(ActiveRecord::Base.connection.quote(@value))
49
+ Arel.sql(ActiveRecord::Base.connection.quote(@instruction.value))
50
50
  end
51
51
 
52
52
  def arel_table
@@ -7,7 +7,7 @@ class ActiveSet
7
7
  class EnumerableAdapter < BaseAdapter
8
8
  def process(set)
9
9
  set.select do |item|
10
- value_for(item).send(@structure_path.operator,
10
+ value_for(item).send(@instruction.operator,
11
11
  passed_value)
12
12
  end
13
13
  end
@@ -15,11 +15,11 @@ class ActiveSet
15
15
  private
16
16
 
17
17
  def value_for(item)
18
- convert_datetime_values_to_integer(@structure_path.value_for(item: item))
18
+ convert_datetime_values_to_integer(@instruction.value_for(item: item))
19
19
  end
20
20
 
21
21
  def passed_value
22
- convert_datetime_values_to_integer(@value)
22
+ convert_datetime_values_to_integer(@instruction.value)
23
23
  end
24
24
 
25
25
  def convert_datetime_values_to_integer(value)
@@ -13,10 +13,7 @@ class ActiveSet
13
13
 
14
14
  def process
15
15
  adapters.reduce(@set) do |outer_set, adapter|
16
- @structure.reject { |_, v| v.blank? }
17
- .reduce(outer_set) do |inner_set, (keypath, value)|
18
- adapter.new(keypath, value).process(inner_set)
19
- end
16
+ @instructions.process_adapter(set: outer_set, adapter: adapter)
20
17
  end
21
18
  end
22
19
  end
@@ -13,11 +13,11 @@ class ActiveSet
13
13
  private
14
14
 
15
15
  def pagesize
16
- @value
16
+ @instruction.value
17
17
  end
18
18
 
19
19
  def page_number
20
- @structure_path.attribute.to_i
20
+ @instruction.attribute.to_i
21
21
  end
22
22
  end
23
23
  end
@@ -7,7 +7,7 @@ class ActiveSet
7
7
  class PaginateProcessor < BaseProcessor
8
8
  def process
9
9
  return @set if @set.count < pagesize
10
- adapter.new(page_number, pagesize).process(@set)
10
+ adapter.new(instruction).process(@set)
11
11
  end
12
12
 
13
13
  private
@@ -16,12 +16,16 @@ class ActiveSet
16
16
  EnumerableAdapter
17
17
  end
18
18
 
19
+ def instruction
20
+ Instructions::Entry.new(page_number, pagesize)
21
+ end
22
+
19
23
  def page_number
20
- @structure[[:page]] || 1
24
+ @instructions.get(:page) || 1
21
25
  end
22
26
 
23
27
  def pagesize
24
- @structure[[:size]] || 25
28
+ @instructions.get(:size) || 25
25
29
  end
26
30
  end
27
31
  end
@@ -11,8 +11,8 @@ class ActiveSet
11
11
  return @set unless @set.respond_to? :to_sql
12
12
  return @set unless attribute_is_field?
13
13
 
14
- @set.includes(@structure_path.to_h)
15
- .references(@structure_path.to_h)
14
+ @set.includes(@instruction.associations_hash)
15
+ .references(@instruction.associations_hash)
16
16
  .merge(arel_operation)
17
17
  end
18
18
 
@@ -21,32 +21,32 @@ class ActiveSet
21
21
  def attribute_is_field?
22
22
  return false unless attribute_model
23
23
  attribute_model.attribute_names
24
- .include?(@structure_path.attribute)
25
- end
26
-
27
- def case_insensitive?
28
- @structure_path.operator.to_s == 'i'
24
+ .include?(@instruction.attribute)
29
25
  end
30
26
 
31
27
  def arel_operation
32
28
  column = case_insensitive? ? arel_column.lower : arel_column
33
- attribute_model.order(column.send(@value))
29
+ attribute_model.order(column.send(@instruction.value))
34
30
  end
35
31
 
36
32
  def attribute_model
37
- @structure_path.to_a
38
- .reduce(@set) do |obj, assoc|
39
- obj.reflections[assoc.to_s]&.klass
40
- end
33
+ @instruction.associations_array
34
+ .reduce(@set) do |obj, assoc|
35
+ obj.reflections[assoc.to_s]&.klass
36
+ end
41
37
  end
42
38
 
43
39
  def arel_column
44
- arel_table[@structure_path.attribute]
40
+ arel_table[@instruction.attribute]
45
41
  end
46
42
 
47
43
  def arel_table
48
44
  Arel::Table.new(attribute_model.table_name)
49
45
  end
46
+
47
+ def case_insensitive?
48
+ @instruction.operator.to_s == 'i'
49
+ end
50
50
  end
51
51
  end
52
52
  end
@@ -8,9 +8,9 @@ class ActiveSet
8
8
  class EnumerableAdapter < BaseAdapter
9
9
  def process(set)
10
10
  set.sort_by do |item|
11
- attribute_value = @structure_path.value_for(item: item)
11
+ attribute_value = @instruction.value_for(item: item)
12
12
  case_insensitive?(attribute_value) ? insensify(attribute_value) : attribute_value
13
- end.tap { |c| c.reverse! if @value.to_s == 'desc' }
13
+ end.tap { |c| c.reverse! if @instruction.value.to_s == 'desc' }
14
14
  end
15
15
 
16
16
  private
@@ -19,7 +19,7 @@ class ActiveSet
19
19
  # Cannot sort pure Booleans or Nils, so we _must_ cast to Strings
20
20
  return true if value.is_a?(TrueClass) || value.is_a?(FalseClass)
21
21
  return true if value.is_a?(NilClass)
22
- @structure_path.operator.to_s == 'i'
22
+ @instruction.operator.to_s == 'i'
23
23
  end
24
24
 
25
25
  def insensify(value)
@@ -13,10 +13,7 @@ class ActiveSet
13
13
 
14
14
  def process
15
15
  adapters.reduce(@set) do |outer_set, adapter|
16
- @structure.reject { |_, v| v.blank? }
17
- .reduce(outer_set) do |inner_set, (keypath, value)|
18
- adapter.new(keypath, value).process(inner_set)
19
- end
16
+ @instructions.process_adapter(set: outer_set, adapter: adapter)
20
17
  end
21
18
  end
22
19
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ActiveSet
4
- VERSION = '0.3.0'
4
+ VERSION = '0.3.1'
5
5
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/array/wrap'
4
+
3
5
  class Hash
4
6
  # Returns a flat hash where all nested keys are collapsed into a an array of keys.
5
7
  #
@@ -24,7 +26,7 @@ class Hash
24
26
 
25
27
  def _flatten_keys(h, keys = [], res = {})
26
28
  return res.merge!(keys => h) unless h.is_a? Hash
27
- h.each { |k, r| _flatten_keys(r, keys + [k], res) }
29
+ h.each { |k, r| _flatten_keys(r, keys + Array.wrap(k), res) }
28
30
  res
29
31
  end
30
32
  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.3.0
4
+ version: 0.3.1
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-09-15 00:00:00.000000000 Z
11
+ date: 2017-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -171,6 +171,10 @@ files:
171
171
  - bin/setup
172
172
  - config.ru
173
173
  - lib/active_set.rb
174
+ - lib/active_set/instructions/base.rb
175
+ - lib/active_set/instructions/entry.rb
176
+ - lib/active_set/instructions/entry/keypath.rb
177
+ - lib/active_set/instructions/entry/value.rb
174
178
  - lib/active_set/processors/base_adapter.rb
175
179
  - lib/active_set/processors/base_processor.rb
176
180
  - lib/active_set/processors/filter/active_record_adapter.rb
@@ -181,7 +185,6 @@ files:
181
185
  - lib/active_set/processors/sort/active_record_adapter.rb
182
186
  - lib/active_set/processors/sort/enumerable_adapter.rb
183
187
  - lib/active_set/processors/sort_processor.rb
184
- - lib/active_set/structure/path.rb
185
188
  - lib/active_set/version.rb
186
189
  - lib/patches/core_ext/hash/flatten_keys.rb
187
190
  homepage: https://github.com/fractaledmind/activeset
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support/core_ext/array/wrap'
4
- require 'active_support/core_ext/object/try'
5
-
6
- module Structure
7
- class Path
8
- attr_reader :path
9
-
10
- def initialize(path)
11
- # `path` can be an Array (e.g. [:parent, :child, :grandchild])
12
- # or a String (e.g. 'parent.child.grandchild')
13
- @path = path.is_a?(String) ? path.split('.') : Array.wrap(path).map(&:to_s)
14
- end
15
-
16
- def attribute
17
- attribute = @path.last
18
- return attribute.sub(operator_regex, '') if attribute.match operator_regex
19
- attribute
20
- end
21
-
22
- def operator
23
- attribute = @path.last
24
- return attribute[operator_regex, 1] if attribute.match operator_regex
25
- '=='
26
- end
27
-
28
- def to_a
29
- @path.slice(0, @path.length - 1)
30
- end
31
-
32
- def to_h
33
- to_a.reverse.reduce({}) { |a, e| { e => a } }
34
- end
35
-
36
- def value_for(item:)
37
- resource_for(item: item).send(attribute)
38
- rescue
39
- nil
40
- end
41
-
42
- def resource_for(item:)
43
- to_a.reduce(item, :try)
44
- rescue
45
- nil
46
- end
47
-
48
- private
49
-
50
- def operator_regex
51
- /\((.*?)\)/
52
- end
53
- end
54
- end