active_enumerable 1.0.0 → 1.1.0

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