frozen_record 0.25.5 → 0.26.2

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
2
  SHA256:
3
- metadata.gz: b8fc155c1a350f49fbc79e245cc768722c9880cd0010b7829a33aea0ac55ab69
4
- data.tar.gz: a16dde142d53022fb3b76b8262326d774342f4158b7d1ec018bf0a4879d41d77
3
+ metadata.gz: e162699e1ec4c32223be26afd36c1222bedeea90b8d0f26e05407641c9f01ccd
4
+ data.tar.gz: f4f6dcb51344bf99558e278a746e4ae5527355ed8771c7be26186af2cab630a1
5
5
  SHA512:
6
- metadata.gz: 4a315f98d4d6c79dc0ac6146715fdee499d383fc9d5e550bbdc7278655a19da2b744923ed41f7f445fc4175f575f6ea1330e77381edfe77fa5dbd4152e6446bb
7
- data.tar.gz: d9e7d61a94c6504ecb0c3fc4e298487bfa30a5d9fd7b527657fc51259246aa23030567f676d2ff06595dca1b1de7a78281bb2380b19ae23145ccd04397dd0799
6
+ metadata.gz: 594beed9888fc9379882815828f1d85a0941b143b03d177662fd02a8460867135003eeeb1391ad473f393c78f299c9e0c3ed45c9dcee88dee7bc7940ce3662c4
7
+ data.tar.gz: bcc049e4643b24bca1c98f8947a924c97f829a2a66798fbe798cbeba744d9934c0b81cbb2bb5c29f686d8d6af723f99299312d56e7e484524021c57613d02f4d
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -12,7 +12,7 @@ jobs:
12
12
  minimal: [ false, true ]
13
13
  name: Ruby ${{ matrix.ruby }} tests, minimal=${{ matrix.minimal }}
14
14
  steps:
15
- - uses: actions/checkout@v2
15
+ - uses: actions/checkout@v3
16
16
  - name: Set up Ruby
17
17
  uses: ruby/setup-ruby@v1
18
18
  with:
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
  [![Build Status](https://secure.travis-ci.org/byroot/frozen_record.svg)](http://travis-ci.org/byroot/frozen_record)
4
4
  [![Gem Version](https://badge.fury.io/rb/frozen_record.svg)](http://badge.fury.io/rb/frozen_record)
5
5
 
6
- Activec Record-like interface for **read only** access to static data files of reasonable size.
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 or large unindexed datasets.
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 }
@@ -20,7 +20,6 @@ Gem::Specification.new do |spec|
20
20
  spec.required_ruby_version = '>= 2.5'
21
21
 
22
22
  spec.add_runtime_dependency 'activemodel'
23
- spec.add_runtime_dependency 'dedup'
24
23
 
25
24
  spec.add_development_dependency 'rake'
26
25
  spec.add_development_dependency 'rspec'
@@ -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) || Dedup::EMPTY_ARRAY
22
+ JSON.load_file(file_path, freeze: true) || [].freeze
23
23
  end
24
24
  else
25
25
  def load(file_path)
26
- Dedup.deep_intern!(JSON.load_file(file_path) || Dedup::EMPTY_ARRAY)
26
+ JSON.load_file(file_path) || [].freeze
27
27
  end
28
28
  end
29
29
  else
30
30
  def load(file_path)
31
- Dedup.deep_intern!(JSON.parse(File.read(file_path)) || Dedup::EMPTY_ARRAY)
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) || Dedup::EMPTY_ARRAY
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) || Dedup::EMPTY_ARRAY
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) || Dedup::EMPTY_ARRAY
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) || Dedup::EMPTY_ARRAY
71
+ YAML.load(yaml, freeze: true) || [].freeze
72
72
  end
73
73
  else
74
74
  def load_file(path)
75
- Dedup.deep_intern!(YAML.load_file(path) || Dedup::EMPTY_ARRAY)
75
+ YAML.load_file(path) || [].freeze
76
76
  end
77
77
 
78
78
  def load_string(yaml)
79
- Dedup.deep_intern!(YAML.load(yaml) || Dedup::EMPTY_ARRAY)
79
+ YAML.load(yaml) || [].freeze
80
80
  end
81
81
  end
82
82
  end
@@ -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(Dedup.deep_intern!(default_attributes.transform_keys(&:to_s)))
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, :find, :find_each, :find_by_id, :find_by, :find_by!, :where, :first, :first!, :last, :last!,
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
- @records = nil
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], Dedup.deep_intern!(attributes[attr]))
65
+ instance_variable_set(self.class._attributes_cache[attr], attributes[attr])
66
66
  end
67
67
  end
68
68
 
@@ -4,8 +4,6 @@ require 'yaml'
4
4
  require 'set'
5
5
  require 'active_model'
6
6
 
7
- require 'dedup'
8
-
9
7
  require 'frozen_record/version'
10
8
  require 'frozen_record/scope'
11
9
  require 'frozen_record/index'
@@ -34,12 +34,17 @@ module FrozenRecord
34
34
  end
35
35
 
36
36
  def find_by_id(id)
37
- matching_records.find { |r| r.id == id }
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
- find_by_id(id) or raise RecordNotFound, "Couldn't find a record with ID = #{id.inspect}"
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)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FrozenRecord
4
- VERSION = '0.25.5'
4
+ VERSION = '0.26.2'
5
5
  end
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.25.5
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-06-17 00:00:00.000000000 Z
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.1.2
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