frozen_record 0.25.5 → 0.26.2
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/.github/dependabot.yml +6 -0
- data/.github/workflows/main.yml +1 -1
- data/CHANGELOG.md +10 -0
- data/README.md +2 -2
- data/benchmark/querying +7 -0
- data/frozen_record.gemspec +0 -1
- data/lib/frozen_record/backends/json.rb +3 -3
- data/lib/frozen_record/backends/yaml.rb +6 -6
- data/lib/frozen_record/base.rb +35 -4
- data/lib/frozen_record/compact.rb +1 -1
- data/lib/frozen_record/minimal.rb +0 -2
- data/lib/frozen_record/scope.rb +7 -2
- data/lib/frozen_record/version.rb +1 -1
- data/spec/scope_spec.rb +5 -1
- metadata +4 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e162699e1ec4c32223be26afd36c1222bedeea90b8d0f26e05407641c9f01ccd
|
4
|
+
data.tar.gz: f4f6dcb51344bf99558e278a746e4ae5527355ed8771c7be26186af2cab630a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 594beed9888fc9379882815828f1d85a0941b143b03d177662fd02a8460867135003eeeb1391ad473f393c78f299c9e0c3ed45c9dcee88dee7bc7940ce3662c4
|
7
|
+
data.tar.gz: bcc049e4643b24bca1c98f8947a924c97f829a2a66798fbe798cbeba744d9934c0b81cbb2bb5c29f686d8d6af723f99299312d56e7e484524021c57613d02f4d
|
data/.github/workflows/main.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
- Fix `Model.find_by` fastpath raising an error when called before records are loaded.
|
4
|
+
|
5
|
+
# v0.26.1
|
6
|
+
|
7
|
+
- Optimized single attribute lookup.
|
8
|
+
|
9
|
+
# v0.26.0
|
10
|
+
|
11
|
+
- Drop dependency on `dedup` gem.
|
12
|
+
|
3
13
|
# v0.25.5
|
4
14
|
|
5
15
|
- `FrozenRecord::Base#==` now returns `false` if the primary key is `nil` (to match the `ActiveRecord::Base` implementation)
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[](http://travis-ci.org/byroot/frozen_record)
|
4
4
|
[](http://badge.fury.io/rb/frozen_record)
|
5
5
|
|
6
|
-
|
6
|
+
Active Record-like interface for **read only** access to static data files of reasonable size.
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
@@ -156,7 +156,7 @@ The primary key isn't indexed by default.
|
|
156
156
|
|
157
157
|
## Limitations
|
158
158
|
|
159
|
-
Frozen Record is not meant to operate
|
159
|
+
Frozen Record is not meant to operate on large unindexed datasets.
|
160
160
|
|
161
161
|
To ensure that it doesn't happen by accident, you can set `FrozenRecord::Base.max_records_scan = 500` (or whatever limit makes sense to you), in your development and test environments.
|
162
162
|
This setting will cause Frozen Record to raise an error if it has to scan more than `max_records_scan` records. This property can also be set on a per model basis.
|
data/benchmark/querying
CHANGED
@@ -23,6 +23,13 @@ class LargeCountry < Country
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
LargeCountry.eager_load!
|
27
|
+
|
28
|
+
puts "=== unique index lookup ==="
|
29
|
+
Benchmark.ips do |x|
|
30
|
+
x.report('pk lookup') { LargeCountry.find_by(name: "Canada1") }
|
31
|
+
end
|
32
|
+
|
26
33
|
puts "=== simple scalar match ==="
|
27
34
|
Benchmark.ips do |x|
|
28
35
|
x.report('simple') { LargeCountry.nato.size }
|
data/frozen_record.gemspec
CHANGED
@@ -19,16 +19,16 @@ module FrozenRecord
|
|
19
19
|
|
20
20
|
if supports_freeze
|
21
21
|
def load(file_path)
|
22
|
-
JSON.load_file(file_path, freeze: true) ||
|
22
|
+
JSON.load_file(file_path, freeze: true) || [].freeze
|
23
23
|
end
|
24
24
|
else
|
25
25
|
def load(file_path)
|
26
|
-
|
26
|
+
JSON.load_file(file_path) || [].freeze
|
27
27
|
end
|
28
28
|
end
|
29
29
|
else
|
30
30
|
def load(file_path)
|
31
|
-
|
31
|
+
JSON.parse(File.read(file_path)) || [].freeze
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -56,27 +56,27 @@ module FrozenRecord
|
|
56
56
|
|
57
57
|
if YAML.respond_to?(:unsafe_load_file)
|
58
58
|
def load_file(path)
|
59
|
-
YAML.unsafe_load_file(path, freeze: true) ||
|
59
|
+
YAML.unsafe_load_file(path, freeze: true) || [].freeze
|
60
60
|
end
|
61
61
|
|
62
62
|
def load_string(yaml)
|
63
|
-
YAML.unsafe_load(yaml, freeze: true) ||
|
63
|
+
YAML.unsafe_load(yaml, freeze: true) || [].freeze
|
64
64
|
end
|
65
65
|
elsif supports_freeze
|
66
66
|
def load_file(path)
|
67
|
-
YAML.load_file(path, freeze: true) ||
|
67
|
+
YAML.load_file(path, freeze: true) || [].freeze
|
68
68
|
end
|
69
69
|
|
70
70
|
def load_string(yaml)
|
71
|
-
YAML.load(yaml, freeze: true) ||
|
71
|
+
YAML.load(yaml, freeze: true) || [].freeze
|
72
72
|
end
|
73
73
|
else
|
74
74
|
def load_file(path)
|
75
|
-
|
75
|
+
YAML.load_file(path) || [].freeze
|
76
76
|
end
|
77
77
|
|
78
78
|
def load_string(yaml)
|
79
|
-
|
79
|
+
YAML.load(yaml) || [].freeze
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
data/lib/frozen_record/base.rb
CHANGED
@@ -69,7 +69,7 @@ module FrozenRecord
|
|
69
69
|
alias_method :set_default_attributes, :default_attributes=
|
70
70
|
private :set_default_attributes
|
71
71
|
def default_attributes=(default_attributes)
|
72
|
-
set_default_attributes(
|
72
|
+
set_default_attributes(default_attributes.transform_keys(&:to_s))
|
73
73
|
end
|
74
74
|
|
75
75
|
alias_method :set_primary_key, :primary_key=
|
@@ -107,7 +107,7 @@ module FrozenRecord
|
|
107
107
|
store[:scope] = scope
|
108
108
|
end
|
109
109
|
|
110
|
-
delegate :each, :
|
110
|
+
delegate :each, :find_each, :where, :first, :first!, :last, :last!,
|
111
111
|
:pluck, :ids, :order, :limit, :offset, :minimum, :maximum, :average, :sum, :count,
|
112
112
|
to: :current_scope
|
113
113
|
|
@@ -123,6 +123,32 @@ module FrozenRecord
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
+
def find_by_id(id)
|
127
|
+
find_by(primary_key => id)
|
128
|
+
end
|
129
|
+
|
130
|
+
def find(id)
|
131
|
+
raise RecordNotFound, "Can't lookup record without ID" unless id
|
132
|
+
find_by(primary_key => id) or raise RecordNotFound, "Couldn't find a record with ID = #{id.inspect}"
|
133
|
+
end
|
134
|
+
|
135
|
+
def find_by(criterias)
|
136
|
+
if criterias.size == 1
|
137
|
+
criterias.each do |attribute, value|
|
138
|
+
attribute = attribute.to_s
|
139
|
+
if index = index_definitions[attribute]
|
140
|
+
load_records
|
141
|
+
return index.lookup(value).first
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
current_scope.find_by(criterias)
|
146
|
+
end
|
147
|
+
|
148
|
+
def find_by!(criterias)
|
149
|
+
find_by(criterias) or raise RecordNotFound, "No record matched"
|
150
|
+
end
|
151
|
+
|
126
152
|
def add_index(attribute, unique: false)
|
127
153
|
index = unique ? UniqueIndex.new(self, attribute) : Index.new(self, attribute)
|
128
154
|
self.index_definitions = index_definitions.merge(index.attribute => index).freeze
|
@@ -156,10 +182,15 @@ module FrozenRecord
|
|
156
182
|
load_records
|
157
183
|
end
|
158
184
|
|
185
|
+
def unload!
|
186
|
+
@records = nil
|
187
|
+
index_definitions.values.each(&:reset)
|
188
|
+
undefine_attribute_methods
|
189
|
+
end
|
190
|
+
|
159
191
|
def load_records(force: false)
|
160
192
|
if force || (auto_reloading && file_changed?)
|
161
|
-
|
162
|
-
undefine_attribute_methods
|
193
|
+
unload!
|
163
194
|
end
|
164
195
|
|
165
196
|
@records ||= begin
|
@@ -62,7 +62,7 @@ module FrozenRecord
|
|
62
62
|
|
63
63
|
def attributes=(attributes)
|
64
64
|
self.class.attributes.each do |attr|
|
65
|
-
instance_variable_set(self.class._attributes_cache[attr],
|
65
|
+
instance_variable_set(self.class._attributes_cache[attr], attributes[attr])
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
data/lib/frozen_record/scope.rb
CHANGED
@@ -34,12 +34,17 @@ module FrozenRecord
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def find_by_id(id)
|
37
|
-
|
37
|
+
find_by(@klass.primary_key => id)
|
38
38
|
end
|
39
39
|
|
40
40
|
def find(id)
|
41
41
|
raise RecordNotFound, "Can't lookup record without ID" unless id
|
42
|
-
|
42
|
+
|
43
|
+
scope = self
|
44
|
+
if @limit || @offset
|
45
|
+
scope = limit(nil).offset(nil)
|
46
|
+
end
|
47
|
+
scope.find_by_id(id) or raise RecordNotFound, "Couldn't find a record with ID = #{id.inspect}"
|
43
48
|
end
|
44
49
|
|
45
50
|
def find_by(criterias)
|
data/spec/scope_spec.rb
CHANGED
@@ -101,7 +101,6 @@ describe 'querying' do
|
|
101
101
|
country = Country.find_by_id(42)
|
102
102
|
expect(country).to be_nil
|
103
103
|
end
|
104
|
-
|
105
104
|
end
|
106
105
|
|
107
106
|
describe '.find_by' do
|
@@ -116,6 +115,11 @@ describe 'querying' do
|
|
116
115
|
expect(country).to be_nil
|
117
116
|
end
|
118
117
|
|
118
|
+
it 'load records' do
|
119
|
+
Country.unload!
|
120
|
+
country = Country.find_by(name: 'France')
|
121
|
+
expect(country.name).to be == 'France'
|
122
|
+
end
|
119
123
|
end
|
120
124
|
|
121
125
|
describe '.find_by!' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: frozen_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.26.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: dedup
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: rake
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,6 +59,7 @@ executables: []
|
|
73
59
|
extensions: []
|
74
60
|
extra_rdoc_files: []
|
75
61
|
files:
|
62
|
+
- ".github/dependabot.yml"
|
76
63
|
- ".github/workflows/main.yml"
|
77
64
|
- ".gitignore"
|
78
65
|
- ".rspec"
|
@@ -137,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
124
|
- !ruby/object:Gem::Version
|
138
125
|
version: '0'
|
139
126
|
requirements: []
|
140
|
-
rubygems_version: 3.
|
127
|
+
rubygems_version: 3.3.7
|
141
128
|
signing_key:
|
142
129
|
specification_version: 4
|
143
130
|
summary: ActiveRecord like interface to read only access and query static YAML files
|