active_hash 2.3.0 → 3.0.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 +4 -4
- data/CHANGELOG +3 -0
- data/README.md +8 -0
- data/active_hash.gemspec +1 -0
- data/lib/active_hash.rb +1 -0
- data/lib/active_hash/base.rb +7 -94
- data/lib/active_hash/relation.rb +128 -0
- data/lib/active_hash/version.rb +1 -1
- metadata +16 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 495ecea300cebeef38e96068866a539533b308e1799937aa9efdb8786e66eaf3
|
4
|
+
data.tar.gz: a149a1dc1d69ef1f416393384c7a2d8b7adbae874ca26d3f23b4c219d0df5514
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3206ab8403d58c5578fc5b4238a3834ea3fee6fe462618651d7e5377138855df959dec91df632c2882d00bd41b107ab9c46821f6724201cfc9547e0621d6d5bb
|
7
|
+
data.tar.gz: ce189a601b0800ead8e4e0586b72c008272fca5c55bd7da8bac536f28804fd9cb832550bd20a186095070b4fcb5401cdbe691408087ad5b32d1a23406e189fcf
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
2019-09-28 (v3.0.0)
|
2
|
+
- Make #where chainable [#178](https://github.com/zilkey/active_hash/pull/178)
|
3
|
+
|
1
4
|
2019-09-28 (v2.3.0)
|
2
5
|
- Add ::scope method (inspired by ActiveRecord) [#173](https://github.com/zilkey/active_hash/pull/173)
|
3
6
|
- Let `.find(nil)` raise ActiveHash::RecordNotFound (inspired by ActiveRecord) [#174](https://github.com/zilkey/active_hash/pull/174)
|
data/README.md
CHANGED
@@ -15,6 +15,14 @@ ActiveHash also ships with:
|
|
15
15
|
* ActiveFile: a base class that you can use to create file data sources
|
16
16
|
* ActiveYaml: a base class that will turn YAML into a hash and load the data into an ActiveHash object
|
17
17
|
|
18
|
+
## !!! Important notice !!!
|
19
|
+
We have changed returned value to chainable by v3.0.0. It's not just an `Array` instance anymore.
|
20
|
+
If it breaks your application, please report us on [issues](https://github.com/zilkey/active_hash/issues), and use v2.x.x as following..
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
gem 'active_hash', '~> 2.3.0'
|
24
|
+
```
|
25
|
+
|
18
26
|
## Installation
|
19
27
|
|
20
28
|
Bundler:
|
data/active_hash.gemspec
CHANGED
data/lib/active_hash.rb
CHANGED
data/lib/active_hash/base.rb
CHANGED
@@ -23,7 +23,7 @@ module ActiveHash
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def not(options)
|
26
|
-
return @
|
26
|
+
return @scope if options.blank?
|
27
27
|
|
28
28
|
# use index if searching by id
|
29
29
|
if options.key?(:id) || options.key?("id")
|
@@ -32,9 +32,11 @@ module ActiveHash
|
|
32
32
|
end
|
33
33
|
return candidates if options.blank?
|
34
34
|
|
35
|
-
(candidates || @records || []).reject do |record|
|
35
|
+
filtered_records = (candidates || @records || []).reject do |record|
|
36
36
|
match_options?(record, options)
|
37
37
|
end
|
38
|
+
|
39
|
+
ActiveHash::Relation.new(@scope.klass, filtered_records, {})
|
38
40
|
end
|
39
41
|
|
40
42
|
def match_options?(record, options)
|
@@ -182,76 +184,11 @@ module ActiveHash
|
|
182
184
|
record
|
183
185
|
end
|
184
186
|
|
185
|
-
def all(options={})
|
186
|
-
|
187
|
-
where(options[:conditions])
|
188
|
-
else
|
189
|
-
@records ||= []
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def where(options = :chain)
|
194
|
-
if options == :chain
|
195
|
-
return WhereChain.new(self)
|
196
|
-
elsif options.blank?
|
197
|
-
return @records
|
198
|
-
end
|
199
|
-
|
200
|
-
# use index if searching by id
|
201
|
-
if options.key?(:id) || options.key?("id")
|
202
|
-
ids = (options.delete(:id) || options.delete("id"))
|
203
|
-
ids = range_to_array(ids) if ids.is_a?(Range)
|
204
|
-
candidates = Array.wrap(ids).map { |id| find_by_id(id) }.compact
|
205
|
-
end
|
206
|
-
return candidates if options.blank?
|
207
|
-
|
208
|
-
(candidates || @records || []).select do |record|
|
209
|
-
match_options?(record, options)
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def find_by(options)
|
214
|
-
where(options).first
|
187
|
+
def all(options = {})
|
188
|
+
ActiveHash::Relation.new(self, @records || [], options[:conditions] || {})
|
215
189
|
end
|
216
190
|
|
217
|
-
|
218
|
-
find_by(options) || (raise RecordNotFound.new("Couldn't find #{name}"))
|
219
|
-
end
|
220
|
-
|
221
|
-
def match_options?(record, options)
|
222
|
-
options.all? do |col, match|
|
223
|
-
if match.kind_of?(Array)
|
224
|
-
match.any? { |v| normalize(v) == normalize(record[col]) }
|
225
|
-
else
|
226
|
-
normalize(record[col]) == normalize(match)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
private :match_options?
|
232
|
-
|
233
|
-
def normalize(v)
|
234
|
-
v.respond_to?(:to_sym) ? v.to_sym : v
|
235
|
-
end
|
236
|
-
|
237
|
-
private :normalize
|
238
|
-
|
239
|
-
def range_to_array(range)
|
240
|
-
return range.to_a unless range.end.nil?
|
241
|
-
|
242
|
-
e = data.last[:id]
|
243
|
-
(range.begin..e).to_a
|
244
|
-
end
|
245
|
-
|
246
|
-
private :range_to_array
|
247
|
-
|
248
|
-
def count
|
249
|
-
all.length
|
250
|
-
end
|
251
|
-
|
252
|
-
def pluck(*column_names)
|
253
|
-
column_names.map { |column_name| all.map(&column_name.to_sym) }.inject(&:zip)
|
254
|
-
end
|
191
|
+
delegate :where, :find, :find_by, :find_by!, :find_by_id, :count, :pluck, :first, :last, to: :all
|
255
192
|
|
256
193
|
def transaction
|
257
194
|
yield
|
@@ -269,30 +206,6 @@ module ActiveHash
|
|
269
206
|
@records = []
|
270
207
|
end
|
271
208
|
|
272
|
-
def find(id, * args)
|
273
|
-
case id
|
274
|
-
when :all
|
275
|
-
all
|
276
|
-
when :first
|
277
|
-
all(*args).first
|
278
|
-
when Array
|
279
|
-
id.map { |i| find(i) }
|
280
|
-
when nil
|
281
|
-
raise RecordNotFound.new("Couldn't find #{name} without an ID")
|
282
|
-
else
|
283
|
-
find_by_id(id) || begin
|
284
|
-
raise RecordNotFound.new("Couldn't find #{name} with ID=#{id}")
|
285
|
-
end
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
def find_by_id(id)
|
290
|
-
index = record_index[id.to_s]
|
291
|
-
index and @records[index]
|
292
|
-
end
|
293
|
-
|
294
|
-
delegate :first, :last, :to => :all
|
295
|
-
|
296
209
|
def fields(*args)
|
297
210
|
options = args.extract_options!
|
298
211
|
args.each do |field|
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module ActiveHash
|
2
|
+
class Relation
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
delegate :each, to: :records # Make Enumerable work
|
6
|
+
delegate :equal?, :==, :===, :eql?, to: :records
|
7
|
+
delegate :empty?, :length, :first, :second, :third, :last, to: :records
|
8
|
+
|
9
|
+
def initialize(klass, all_records, query_hash = nil)
|
10
|
+
self.klass = klass
|
11
|
+
self.all_records = all_records
|
12
|
+
self.query_hash = query_hash
|
13
|
+
self.records_dirty = false
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def where(query_hash = :chain)
|
18
|
+
return ActiveHash::Base::WhereChain.new(self) if query_hash == :chain
|
19
|
+
|
20
|
+
self.records_dirty = true unless query_hash.nil? || query_hash.keys.empty?
|
21
|
+
self.query_hash.merge!(query_hash || {})
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def all(options = {})
|
26
|
+
if options.has_key?(:conditions)
|
27
|
+
where(options[:conditions])
|
28
|
+
else
|
29
|
+
where({})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_by(options)
|
34
|
+
where(options).first
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_by!(options)
|
38
|
+
find_by(options) || (raise RecordNotFound.new("Couldn't find #{klass.name}"))
|
39
|
+
end
|
40
|
+
|
41
|
+
def find(id, *args)
|
42
|
+
case id
|
43
|
+
when :all
|
44
|
+
all
|
45
|
+
when :first
|
46
|
+
all(*args).first
|
47
|
+
when Array
|
48
|
+
id.map { |i| find(i) }
|
49
|
+
when nil
|
50
|
+
raise RecordNotFound.new("Couldn't find #{klass.name} without an ID")
|
51
|
+
else
|
52
|
+
find_by_id(id) || begin
|
53
|
+
raise RecordNotFound.new("Couldn't find #{klass.name} with ID=#{id}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_by_id(id)
|
59
|
+
index = klass.send(:record_index)[id.to_s] # TODO: Make index in Base publicly readable instead of using send?
|
60
|
+
index and records[index]
|
61
|
+
end
|
62
|
+
|
63
|
+
def count
|
64
|
+
length
|
65
|
+
end
|
66
|
+
|
67
|
+
def pluck(*column_names)
|
68
|
+
column_names.map { |column_name| all.map(&column_name.to_sym) }.inject(&:zip)
|
69
|
+
end
|
70
|
+
|
71
|
+
def reload
|
72
|
+
@records = filter_all_records_by_query_hash
|
73
|
+
end
|
74
|
+
|
75
|
+
attr_reader :query_hash, :klass, :all_records, :records_dirty
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
attr_writer :query_hash, :klass, :all_records, :records_dirty
|
80
|
+
|
81
|
+
def records
|
82
|
+
if @records.nil? || records_dirty
|
83
|
+
reload
|
84
|
+
else
|
85
|
+
@records
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def filter_all_records_by_query_hash
|
90
|
+
self.records_dirty = false
|
91
|
+
return all_records if query_hash.blank?
|
92
|
+
|
93
|
+
# use index if searching by id
|
94
|
+
if query_hash.key?(:id) || query_hash.key?("id")
|
95
|
+
ids = (query_hash.delete(:id) || query_hash.delete("id"))
|
96
|
+
ids = range_to_array(ids) if ids.is_a?(Range)
|
97
|
+
candidates = Array.wrap(ids).map { |id| klass.find_by_id(id) }.compact
|
98
|
+
end
|
99
|
+
|
100
|
+
return candidates if query_hash.blank?
|
101
|
+
|
102
|
+
(candidates || all_records || []).select do |record|
|
103
|
+
match_options?(record, query_hash)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def match_options?(record, options)
|
108
|
+
options.all? do |col, match|
|
109
|
+
if match.kind_of?(Array)
|
110
|
+
match.any? { |v| normalize(v) == normalize(record[col]) }
|
111
|
+
else
|
112
|
+
normalize(record[col]) == normalize(match)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def normalize(v)
|
118
|
+
v.respond_to?(:to_sym) ? v.to_sym : v
|
119
|
+
end
|
120
|
+
|
121
|
+
def range_to_array(range)
|
122
|
+
return range.to_a unless range.end.nil?
|
123
|
+
|
124
|
+
e = records.last[:id]
|
125
|
+
(range.begin..e).to_a
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/active_hash/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_hash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Dean
|
@@ -45,6 +45,20 @@ dependencies:
|
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 5.0.0
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: pry
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
48
62
|
description: Includes the ability to specify data using hashes, yml files or JSON
|
49
63
|
files
|
50
64
|
email: jeff@zilkey.com
|
@@ -61,6 +75,7 @@ files:
|
|
61
75
|
- lib/active_file/multiple_files.rb
|
62
76
|
- lib/active_hash.rb
|
63
77
|
- lib/active_hash/base.rb
|
78
|
+
- lib/active_hash/relation.rb
|
64
79
|
- lib/active_hash/version.rb
|
65
80
|
- lib/active_json/base.rb
|
66
81
|
- lib/active_yaml/aliases.rb
|