active_enumerable 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: db5edb0e4e9f6d7f8fd5a300614a183963166077
4
- data.tar.gz: e1b94fd1c797689656ba6191fdb9de1fe8ba6bfb
2
+ SHA256:
3
+ metadata.gz: cc502a24a0dd992d14b0cbd5cf430f6ea6b65923dee12b551f8647c5a3c02cd1
4
+ data.tar.gz: f70d7bd888c00b4b2629f984cea4ad772b42b9017f715277e170bd9c87b0933b
5
5
  SHA512:
6
- metadata.gz: 6c7f661c81d3ad8bc7a1c8cef010cd9dffb22bb668f7244b089352e9415216372b8fa522bb5afc1032e25779b7873bb7835217c02d972566fb9e05c2702f54a0
7
- data.tar.gz: 93a46896255357f33867972e7a6335285908ec7dd76383028db39caf80ef88741d7955388aa8d44cd68a60012ea7b5bb53bee0eda0401290ea723913851a2c72
6
+ metadata.gz: b020582e03b2e91502585cda638fda595e14dfde1eaf4b46fecf14e58159102ea4427f1692cdf6a9377f349765eba8bdcedd6c7b1b8128ffba3835247dc945e1
7
+ data.tar.gz: 6213bbf4af9acaa7ac1fc34e59ea17a8e605eb65e713deaf9f0e110fede4434020f8dc1fe9602f0c5650703f80ee2bde87a68d270e80c7a452a6255361d0d0f1
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Rubocop" enabled="false" level="WARNING" enabled_by_default="false" />
5
+ </profile>
6
+ </component>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
+
4
+ ## 1.1.0 - 2018-08-01
5
+ ### Feature
6
+ - `#where` can take a block that runs with instance exec for each record. Event allows for nested objects with method chaining.
7
+
3
8
  ## 1.0.0 - 2018-01-26
4
9
  - Remove mutation methods and ensure 100% test coverage
5
10
 
data/README.md CHANGED
@@ -24,6 +24,8 @@ Or install it yourself as:
24
24
 
25
25
  ## Usage
26
26
 
27
+ [Documentation](http://www.rubydoc.info/gems/active_enumerable/1.0.0)
28
+
27
29
  ### ActiveRecord Like Querying
28
30
 
29
31
  ```ruby
@@ -48,6 +50,9 @@ customers.sum(:credit)
48
50
 
49
51
  customers << { paid: true, credit: 1500 } # accepts Hashes
50
52
 
53
+ customers.where{ paid && credit == 1000 }
54
+ # => <#Customers [{paid: true, credit: 1000}]
55
+
51
56
  class Customer
52
57
  attr_reader :paid, :credit
53
58
  def initialize(paid:, credit:)
@@ -26,11 +26,12 @@ module ActiveEnumerable
26
26
 
27
27
  # @param [Hash, Object] matches is list of sub conditions or associations to query.
28
28
  # Or this can by any value to compare the result from attr.
29
- def of(matches)
29
+ def of(matches=nil, &block)
30
+ raise ArgumentError if matches.nil? && block.nil?
30
31
  if all_conditions.empty? || !(all_conditions.last.count == 1)
31
32
  raise UnmetCondition, ".has(attr) must be call before calling #of."
32
33
  else
33
- all_conditions.last << matches
34
+ all_conditions.last << (matches || block)
34
35
  self
35
36
  end
36
37
  end
@@ -38,11 +38,14 @@ module ActiveEnumerable
38
38
  #
39
39
  # @param [Hash] conditions
40
40
  # @return [true, false]
41
- def is_of(conditions={})
41
+ def is_of(conditions = {})
42
42
  conditions.all? do |col, match|
43
- if match.is_a? Hash
43
+ case match
44
+ when Proc
45
+ proc_match(col, match)
46
+ when Hash
44
47
  hash_match(col, match)
45
- elsif match.is_a? Array
48
+ when Array
46
49
  array_match(col, match)
47
50
  else
48
51
  compare(col, match)
@@ -52,6 +55,16 @@ module ActiveEnumerable
52
55
 
53
56
  private
54
57
 
58
+ def proc_match(col, match)
59
+ return @method_caller.instance_exec(&match) unless col
60
+ next_record = @method_caller.call(col)
61
+ if next_record.is_a? Array
62
+ next_record.all? { |record| Finder.new(record).is_of({nil => match}) }
63
+ else
64
+ MethodCaller.new(next_record).instance_exec(&match)
65
+ end
66
+ end
67
+
55
68
  def hash_match(col, match)
56
69
  next_record = @method_caller.call(col)
57
70
  if next_record.is_a? Array
@@ -1,23 +1,38 @@
1
1
  module ActiveEnumerable
2
2
  # @private
3
3
  class MethodCaller
4
- attr_reader :object, :raise_no_method
4
+ attr_reader :__object__, :raise_no_method
5
5
 
6
6
  def initialize(object, raise_no_method: true)
7
- @object = object
7
+ @__object__ = object
8
8
  @raise_no_method = raise_no_method
9
9
  end
10
10
 
11
11
  def call(method)
12
- if object.is_a? Hash
13
- object.fetch(method)
12
+ if __object__.is_a? Hash
13
+ wrap_return __object__.fetch(method)
14
14
  else
15
- object.public_send(method)
15
+ wrap_return __object__.public_send(method)
16
16
  end
17
17
  rescue NoMethodError => e
18
18
  raise e if raise_no_method
19
19
  rescue KeyError => e
20
- raise e, "#{e.message} for #{object}" if raise_no_method
20
+ raise e, "#{e.message} for #{__object__}" if raise_no_method
21
+ end
22
+
23
+ def method_missing(method)
24
+ call(method)
25
+ end
26
+
27
+ private
28
+
29
+ def wrap_return(return_value)
30
+ case return_value
31
+ when Hash
32
+ self.class.new(return_value, raise_no_method: raise_no_method)
33
+ else
34
+ return_value
35
+ end
21
36
  end
22
37
  end
23
38
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveEnumerable
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,30 +1,9 @@
1
1
  require "active_enumerable/finder"
2
+ require "active_enumerable/where/where_not_chain"
3
+ require "active_enumerable/where/where_or_chain"
2
4
 
3
5
  module ActiveEnumerable
4
6
  module Where
5
- class WhereNotChain
6
- def initialize(collection, parent_class)
7
- @collection = collection
8
- @parent_class = parent_class
9
- end
10
-
11
- # Returns a new relation expressing WHERE + NOT condition according to
12
- # the conditions in the arguments.
13
- #
14
- # #not accepts conditions as a string, array, or hash. See Where#where for
15
- # more details on each format.
16
- #
17
- # <#ActiveEnumerable>.where.not(name: "Jon")
18
- # <#ActiveEnumerable>.where.not(name: nil)
19
- # <#ActiveEnumerable>.where.not(name: %w(Ko1 Nobu))
20
- # <#ActiveEnumerable>.where.not(name: "Jon", role: "admin")
21
- def not(conditions={})
22
- @parent_class.call(@collection.reject do |record|
23
- Finder.new(record).is_of(conditions)
24
- end)
25
- end
26
- end
27
-
28
7
  # Returns a new relation, which is the result of filtering the current relation
29
8
  # according to the conditions in the arguments.
30
9
  #
@@ -58,35 +37,17 @@ module ActiveEnumerable
58
37
  # <#ActiveEnumerable>.where(id: 1).or(author_id: 3)
59
38
  #
60
39
  # @see ActiveEnumerable::Finder#is_of for all usages of conditions.
61
- def where(conditions=nil)
62
- return WhereNotChain.new(all, method(:__new_relation__)) if conditions.nil?
63
- enable_or create_where_relation(conditions, to_a.select do |record|
64
- Finder.new(record).is_of(conditions)
65
- end)
66
- end
67
-
68
- def enable_or(relation)
69
- pre_where_to_a = to_a
70
- relation.define_singleton_method(:or) do |conditions_or_relation|
71
- conditions = get_conditions(conditions_or_relation)
72
- or_result = create_where_relation(where_conditions, pre_where_to_a).where(conditions)
73
- create_where_relation(or_result.where_conditions, relation.to_a.concat(or_result.to_a).uniq)
74
- end
75
- relation
76
- end
77
-
78
- private :enable_or
79
-
80
- def get_conditions(conditions_or_relation)
81
- if conditions_or_relation.respond_to?(:where_conditions)
82
- conditions_or_relation.where_conditions
83
- else
84
- conditions_or_relation
40
+ def where(conditions = nil, &block)
41
+ return WhereNotChain.new(all, method(:__new_relation__)) unless conditions || block
42
+ conditions = conditions || { nil => block }
43
+ create_where_relation(conditions, to_a.select do |record|
44
+ Finder.new(record).is_of(conditions || { nil => block })
45
+ end).tap do |where|
46
+ where.extend(WhereOrChain)
47
+ where.original_collection = to_a
85
48
  end
86
49
  end
87
50
 
88
- private :get_conditions
89
-
90
51
  def where_conditions
91
52
  @where_conditions ||= {}
92
53
  end
@@ -0,0 +1,26 @@
1
+ module ActiveEnumerable
2
+ module Where
3
+ class WhereNotChain
4
+ def initialize(collection, parent_class)
5
+ @collection = collection
6
+ @parent_class = parent_class
7
+ end
8
+
9
+ # Returns a new relation expressing WHERE + NOT condition according to
10
+ # the conditions in the arguments.
11
+ #
12
+ # #not accepts conditions as a string, array, or hash. See Where#where for
13
+ # more details on each format.
14
+ #
15
+ # <#ActiveEnumerable>.where.not(name: "Jon")
16
+ # <#ActiveEnumerable>.where.not(name: nil)
17
+ # <#ActiveEnumerable>.where.not(name: %w(Ko1 Nobu))
18
+ # <#ActiveEnumerable>.where.not(name: "Jon", role: "admin")
19
+ def not(conditions = {})
20
+ @parent_class.call(@collection.reject do |record|
21
+ Finder.new(record).is_of(conditions)
22
+ end)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveEnumerable
2
+ module Where
3
+ module WhereOrChain
4
+ def or(conditions_or_relation)
5
+ conditions = get_conditions(conditions_or_relation)
6
+ or_result = create_where_relation(where_conditions, original_collection).where(conditions)
7
+ create_where_relation(or_result.where_conditions, to_a.concat(or_result.to_a).uniq)
8
+ end
9
+
10
+ attr_accessor :original_collection
11
+
12
+ private
13
+
14
+ def get_conditions(conditions_or_relation)
15
+ if conditions_or_relation.respond_to?(:where_conditions)
16
+ conditions_or_relation.where_conditions
17
+ else
18
+ conditions_or_relation
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_enumerable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dustin Zeisler
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-01-27 00:00:00.000000000 Z
11
+ date: 2018-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -75,6 +75,8 @@ extensions: []
75
75
  extra_rdoc_files: []
76
76
  files:
77
77
  - ".gitignore"
78
+ - ".idea/inspectionProfiles/Project_Default.xml"
79
+ - ".idea/vcs.xml"
78
80
  - ".rspec"
79
81
  - ".travis.yml"
80
82
  - CHANGELOG.md
@@ -100,6 +102,8 @@ files:
100
102
  - lib/active_enumerable/scopes.rb
101
103
  - lib/active_enumerable/version.rb
102
104
  - lib/active_enumerable/where.rb
105
+ - lib/active_enumerable/where/where_not_chain.rb
106
+ - lib/active_enumerable/where/where_or_chain.rb
103
107
  homepage: https://github.com/zeisler/active_enumerable
104
108
  licenses:
105
109
  - MIT
@@ -120,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
124
  version: '0'
121
125
  requirements: []
122
126
  rubyforge_project:
123
- rubygems_version: 2.6.14
127
+ rubygems_version: 2.7.7
124
128
  signing_key:
125
129
  specification_version: 4
126
130
  summary: Provides ActiveRecord like query methods for use in Ruby Enumerable collections.