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 +5 -5
- data/.idea/inspectionProfiles/Project_Default.xml +6 -0
- data/.idea/vcs.xml +6 -0
- data/CHANGELOG.md +5 -0
- data/README.md +5 -0
- data/lib/active_enumerable/english_dsl.rb +3 -2
- data/lib/active_enumerable/finder.rb +16 -3
- data/lib/active_enumerable/method_caller.rb +21 -6
- data/lib/active_enumerable/version.rb +1 -1
- data/lib/active_enumerable/where.rb +10 -49
- data/lib/active_enumerable/where/where_not_chain.rb +26 -0
- data/lib/active_enumerable/where/where_or_chain.rb +23 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cc502a24a0dd992d14b0cbd5cf430f6ea6b65923dee12b551f8647c5a3c02cd1
|
4
|
+
data.tar.gz: f70d7bd888c00b4b2629f984cea4ad772b42b9017f715277e170bd9c87b0933b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b020582e03b2e91502585cda638fda595e14dfde1eaf4b46fecf14e58159102ea4427f1692cdf6a9377f349765eba8bdcedd6c7b1b8128ffba3835247dc945e1
|
7
|
+
data.tar.gz: 6213bbf4af9acaa7ac1fc34e59ea17a8e605eb65e713deaf9f0e110fede4434020f8dc1fe9602f0c5650703f80ee2bde87a68d270e80c7a452a6255361d0d0f1
|
data/.idea/vcs.xml
ADDED
data/CHANGELOG.md
CHANGED
@@ -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
|
-
|
43
|
+
case match
|
44
|
+
when Proc
|
45
|
+
proc_match(col, match)
|
46
|
+
when Hash
|
44
47
|
hash_match(col, match)
|
45
|
-
|
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 :
|
4
|
+
attr_reader :__object__, :raise_no_method
|
5
5
|
|
6
6
|
def initialize(object, raise_no_method: true)
|
7
|
-
@
|
7
|
+
@__object__ = object
|
8
8
|
@raise_no_method = raise_no_method
|
9
9
|
end
|
10
10
|
|
11
11
|
def call(method)
|
12
|
-
if
|
13
|
-
|
12
|
+
if __object__.is_a? Hash
|
13
|
+
wrap_return __object__.fetch(method)
|
14
14
|
else
|
15
|
-
|
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 #{
|
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,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__))
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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.
|
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
|
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.
|
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.
|