frozen_record 0.19.4 → 0.21.1
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/workflows/main.yml +32 -0
- data/frozen_record.gemspec +2 -1
- data/lib/frozen_record.rb +2 -26
- data/lib/frozen_record/backends/empty.json +1 -0
- data/lib/frozen_record/backends/json.rb +20 -3
- data/lib/frozen_record/backends/yaml.rb +29 -3
- data/lib/frozen_record/base.rb +6 -12
- data/lib/frozen_record/compact.rb +5 -4
- data/lib/frozen_record/minimal.rb +27 -0
- data/lib/frozen_record/scope.rb +3 -2
- data/lib/frozen_record/serialization.rb +13 -0
- data/lib/frozen_record/version.rb +1 -1
- data/spec/scope_spec.rb +6 -1
- data/spec/spec_helper.rb +11 -1
- data/spec/support/country.rb +4 -0
- metadata +9 -9
- data/.travis.yml +0 -5
- data/lib/frozen_record/deduplication.rb +0 -57
- data/spec/deduplication_spec.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a25a269067396d2e6054a57c514b1251e39dca90928e7bdd837bfbb9ef8d2cf
|
4
|
+
data.tar.gz: 77b55ee24e39590dd213c157b22e3707c8f551a051df34f516a1e9d061d4eb6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1d23916d54278598ec3ba29e5c1000f4adb0f13566db9be7900e5344199e36fe02254539a531a26d8b2d211e62f3916438c98032e7166795fbbf1681a170b91
|
7
|
+
data.tar.gz: af66cb72d621f8d6008de238d7f0846bf576200437fbdead4cfcdd1d598af62ac4d29bd801efd14420bfddb4470301312eb992628e2c7185e21b8dbee0381f6e
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
matrix:
|
10
|
+
ruby: [ '2.5', '2.6', '2.7', '3.0' ]
|
11
|
+
minimal: [ false, true ]
|
12
|
+
name: Ruby ${{ matrix.ruby }} tests, minimal=${{ matrix.minimal }}
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
- name: Setup Ruby
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: ${{ matrix.ruby }}
|
19
|
+
- uses: actions/cache@v2
|
20
|
+
with:
|
21
|
+
path: vendor/bundle
|
22
|
+
key: ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ hashFiles('Gemfile', 'frozen_record.gemspec') }}
|
23
|
+
restore-keys: |
|
24
|
+
${{ runner.os }}-${{ matrix.ruby }}-gems-
|
25
|
+
- name: Bundle install
|
26
|
+
run: |
|
27
|
+
gem install bundler
|
28
|
+
bundle install --jobs 4 --retry 3 --path=vendor/bundle
|
29
|
+
- name: Run tests
|
30
|
+
env:
|
31
|
+
MINIMAL: ${{ matrix.minimal }}
|
32
|
+
run: bundle exec rake
|
data/frozen_record.gemspec
CHANGED
@@ -20,7 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.required_ruby_version = '>= 2.5'
|
21
21
|
|
22
22
|
spec.add_runtime_dependency 'activemodel'
|
23
|
-
spec.
|
23
|
+
spec.add_runtime_dependency 'dedup'
|
24
|
+
|
24
25
|
spec.add_development_dependency 'rake'
|
25
26
|
spec.add_development_dependency 'rspec'
|
26
27
|
spec.add_development_dependency 'pry'
|
data/lib/frozen_record.rb
CHANGED
@@ -1,29 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require 'active_support/all'
|
6
|
-
require 'active_model'
|
7
|
-
|
8
|
-
require 'frozen_record/version'
|
9
|
-
require 'frozen_record/scope'
|
10
|
-
require 'frozen_record/index'
|
11
|
-
require 'frozen_record/base'
|
12
|
-
require 'frozen_record/compact'
|
13
|
-
require 'frozen_record/deduplication'
|
14
|
-
|
15
|
-
module FrozenRecord
|
16
|
-
RecordNotFound = Class.new(StandardError)
|
17
|
-
|
18
|
-
class << self
|
19
|
-
attr_accessor :deprecated_yaml_erb_backend
|
20
|
-
|
21
|
-
def eager_load!
|
22
|
-
Base.descendants.each(&:eager_load!)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
self.deprecated_yaml_erb_backend = true
|
27
|
-
end
|
28
|
-
|
3
|
+
require 'frozen_record/minimal'
|
4
|
+
require 'frozen_record/serialization'
|
29
5
|
require 'frozen_record/railtie' if defined?(Rails)
|
@@ -0,0 +1 @@
|
|
1
|
+
true
|
@@ -9,9 +9,26 @@ module FrozenRecord
|
|
9
9
|
"#{model_name.underscore.pluralize}.json"
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
if JSON.respond_to?(:load_file)
|
13
|
+
supports_freeze = begin
|
14
|
+
JSON.load_file(File.expand_path('../empty.json', __FILE__), freeze: true)
|
15
|
+
rescue ArgumentError
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
if supports_freeze
|
20
|
+
def load(file_path)
|
21
|
+
JSON.load_file(file_path, freeze: true) || Dedup::EMPTY_ARRAY
|
22
|
+
end
|
23
|
+
else
|
24
|
+
def load(file_path)
|
25
|
+
Dedup.deep_intern!(JSON.load_file(file_path) || Dedup::EMPTY_ARRAY)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
else
|
29
|
+
def load(file_path)
|
30
|
+
Dedup.deep_intern!(JSON.parse(File.read(file_path)) || Dedup::EMPTY_ARRAY)
|
31
|
+
end
|
15
32
|
end
|
16
33
|
end
|
17
34
|
end
|
@@ -34,15 +34,41 @@ module FrozenRecord
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
load_string(yml_data)
|
38
38
|
else
|
39
39
|
if file_path.end_with?('.erb')
|
40
|
-
|
40
|
+
load_string(ERB.new(File.read(file_path)).result)
|
41
41
|
else
|
42
|
-
|
42
|
+
load_file(file_path)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
supports_freeze = begin
|
50
|
+
YAML.load_file(File.expand_path('../empty.json', __FILE__), freeze: true)
|
51
|
+
rescue ArgumentError
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
if supports_freeze
|
56
|
+
def load_file(path)
|
57
|
+
YAML.load_file(path, freeze: true) || Dedup::EMPTY_ARRAY
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_string(yaml)
|
61
|
+
YAML.load(yaml, freeze: true) || Dedup::EMPTY_ARRAY
|
62
|
+
end
|
63
|
+
else
|
64
|
+
def load_file(path)
|
65
|
+
Dedup.deep_intern!(YAML.load_file(path) || Dedup::EMPTY_ARRAY)
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_string(yaml)
|
69
|
+
Dedup.deep_intern!(YAML.load(yaml) || Dedup::EMPTY_ARRAY)
|
70
|
+
end
|
71
|
+
end
|
46
72
|
end
|
47
73
|
end
|
48
74
|
end
|
data/lib/frozen_record/base.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'set'
|
4
3
|
require 'active_support/descendants_tracker'
|
5
4
|
require 'frozen_record/backends'
|
6
|
-
require 'objspace'
|
7
5
|
|
8
6
|
module FrozenRecord
|
9
7
|
class Base
|
@@ -11,11 +9,6 @@ module FrozenRecord
|
|
11
9
|
extend ActiveModel::Naming
|
12
10
|
include ActiveModel::Conversion
|
13
11
|
include ActiveModel::AttributeMethods
|
14
|
-
include ActiveModel::Serializers::JSON
|
15
|
-
|
16
|
-
if defined? ActiveModel::Serializers::Xml
|
17
|
-
include ActiveModel::Serializers::Xml
|
18
|
-
end
|
19
12
|
|
20
13
|
FIND_BY_PATTERN = /\Afind_by_(\w+)(!?)/
|
21
14
|
FALSY_VALUES = [false, nil, 0, -''].to_set
|
@@ -52,7 +45,7 @@ module FrozenRecord
|
|
52
45
|
alias_method :set_default_attributes, :default_attributes=
|
53
46
|
private :set_default_attributes
|
54
47
|
def default_attributes=(default_attributes)
|
55
|
-
set_default_attributes(
|
48
|
+
set_default_attributes(Dedup.deep_intern!(default_attributes.transform_keys(&:to_s)))
|
56
49
|
end
|
57
50
|
|
58
51
|
alias_method :set_primary_key, :primary_key=
|
@@ -146,8 +139,9 @@ module FrozenRecord
|
|
146
139
|
|
147
140
|
@records ||= begin
|
148
141
|
records = backend.load(file_path)
|
149
|
-
|
150
|
-
|
142
|
+
if default_attributes
|
143
|
+
records = records.map { |r| assign_defaults!(r.dup).freeze }.freeze
|
144
|
+
end
|
151
145
|
@attributes = list_attributes(records).freeze
|
152
146
|
define_attribute_methods(@attributes.to_a)
|
153
147
|
records = records.map { |r| load(r) }.freeze
|
@@ -164,7 +158,7 @@ module FrozenRecord
|
|
164
158
|
private :load
|
165
159
|
|
166
160
|
def new(attrs = {})
|
167
|
-
load(assign_defaults!(attrs.
|
161
|
+
load(assign_defaults!(attrs.transform_keys(&:to_s)))
|
168
162
|
end
|
169
163
|
|
170
164
|
private
|
@@ -245,7 +239,7 @@ module FrozenRecord
|
|
245
239
|
private
|
246
240
|
|
247
241
|
def attribute?(attribute_name)
|
248
|
-
FALSY_VALUES.
|
242
|
+
!FALSY_VALUES.include?(self[attribute_name]) && self[attribute_name].present?
|
249
243
|
end
|
250
244
|
|
251
245
|
def attribute_method?(attribute_name)
|
@@ -13,8 +13,9 @@ module FrozenRecord
|
|
13
13
|
|
14
14
|
@records ||= begin
|
15
15
|
records = backend.load(file_path)
|
16
|
-
|
17
|
-
|
16
|
+
if default_attributes
|
17
|
+
records = records.map { |r| assign_defaults!(r.dup).freeze }.freeze
|
18
|
+
end
|
18
19
|
@attributes = list_attributes(records).freeze
|
19
20
|
build_attributes_cache
|
20
21
|
define_attribute_methods(@attributes.to_a)
|
@@ -67,13 +68,13 @@ module FrozenRecord
|
|
67
68
|
|
68
69
|
def attributes=(attributes)
|
69
70
|
self.class.attributes.each do |attr|
|
70
|
-
instance_variable_set(self.class._attributes_cache[attr],
|
71
|
+
instance_variable_set(self.class._attributes_cache[attr], Dedup.deep_intern!(attributes[attr]))
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
74
75
|
def attribute?(attribute_name)
|
75
76
|
val = self[attribute_name]
|
76
|
-
Base::FALSY_VALUES.
|
77
|
+
!Base::FALSY_VALUES.include?(val) && val.present?
|
77
78
|
end
|
78
79
|
end
|
79
80
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'set'
|
5
|
+
require 'active_model'
|
6
|
+
|
7
|
+
require 'dedup'
|
8
|
+
|
9
|
+
require 'frozen_record/version'
|
10
|
+
require 'frozen_record/scope'
|
11
|
+
require 'frozen_record/index'
|
12
|
+
require 'frozen_record/base'
|
13
|
+
require 'frozen_record/compact'
|
14
|
+
|
15
|
+
module FrozenRecord
|
16
|
+
RecordNotFound = Class.new(StandardError)
|
17
|
+
|
18
|
+
class << self
|
19
|
+
attr_accessor :deprecated_yaml_erb_backend
|
20
|
+
|
21
|
+
def eager_load!
|
22
|
+
Base.descendants.each(&:eager_load!)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
self.deprecated_yaml_erb_backend = true
|
27
|
+
end
|
data/lib/frozen_record/scope.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module FrozenRecord
|
4
4
|
class Scope
|
5
|
-
|
5
|
+
DISALLOWED_ARRAY_METHODS = [
|
6
6
|
:compact!, :flatten!, :reject!, :reverse!, :rotate!, :map!,
|
7
7
|
:shuffle!, :slice!, :sort!, :sort_by!, :delete_if,
|
8
8
|
:keep_if, :pop, :shift, :delete_at, :compact
|
@@ -227,13 +227,14 @@ module FrozenRecord
|
|
227
227
|
super
|
228
228
|
end
|
229
229
|
end
|
230
|
+
ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
|
230
231
|
|
231
232
|
def delegate_to_class(*args, &block)
|
232
233
|
scoping { @klass.public_send(*args, &block) }
|
233
234
|
end
|
234
235
|
|
235
236
|
def array_delegable?(method)
|
236
|
-
Array.method_defined?(method) &&
|
237
|
+
Array.method_defined?(method) && !DISALLOWED_ARRAY_METHODS.include?(method)
|
237
238
|
end
|
238
239
|
|
239
240
|
def where!(criterias)
|
data/spec/scope_spec.rb
CHANGED
@@ -193,6 +193,11 @@ describe 'querying' do
|
|
193
193
|
expect(countries.length).to be == 0
|
194
194
|
end
|
195
195
|
|
196
|
+
it 'is chainable with methods of the form `def method(*args, **kargs)' do
|
197
|
+
countries = Country.republics.continent_and_capital('Europe', capital: 'Paris')
|
198
|
+
expect(countries.length).to be == 1
|
199
|
+
end
|
200
|
+
|
196
201
|
it 'can be used with arrays' do
|
197
202
|
countries = Country.where(id: [1,2])
|
198
203
|
expect(countries.length).to be == 2
|
@@ -410,7 +415,7 @@ describe 'querying' do
|
|
410
415
|
|
411
416
|
end
|
412
417
|
|
413
|
-
describe '.as_json' do
|
418
|
+
describe '.as_json', exclude_minimal: true do
|
414
419
|
|
415
420
|
it 'serialize the results' do
|
416
421
|
json = Country.all.as_json
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
lib = File.expand_path('../lib', __FILE__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
3
|
|
4
|
+
minimal = ENV['MINIMAL'] == 'true'
|
5
|
+
|
4
6
|
require 'pry'
|
5
7
|
require 'simplecov'
|
6
8
|
require 'coveralls'
|
@@ -10,7 +12,14 @@ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
|
10
12
|
]
|
11
13
|
SimpleCov.start
|
12
14
|
|
13
|
-
require '
|
15
|
+
require 'objspace'
|
16
|
+
|
17
|
+
if minimal
|
18
|
+
require 'frozen_record/minimal'
|
19
|
+
else
|
20
|
+
require 'frozen_record'
|
21
|
+
end
|
22
|
+
|
14
23
|
require 'frozen_record/test_helper'
|
15
24
|
|
16
25
|
FrozenRecord::Base.base_path = File.join(File.dirname(__FILE__), 'fixtures')
|
@@ -22,6 +31,7 @@ FrozenRecord.eager_load!
|
|
22
31
|
RSpec.configure do |config|
|
23
32
|
config.run_all_when_everything_filtered = true
|
24
33
|
config.filter_run :focus
|
34
|
+
config.filter_run_excluding :exclude_minimal if minimal
|
25
35
|
|
26
36
|
config.order = 'random'
|
27
37
|
|
data/spec/support/country.rb
CHANGED
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.21.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -25,13 +25,13 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: dedup
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
|
-
type: :
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
@@ -101,9 +101,9 @@ executables: []
|
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
|
+
- ".github/workflows/main.yml"
|
104
105
|
- ".gitignore"
|
105
106
|
- ".rspec"
|
106
|
-
- ".travis.yml"
|
107
107
|
- Gemfile
|
108
108
|
- LICENSE.txt
|
109
109
|
- README.md
|
@@ -114,17 +114,18 @@ files:
|
|
114
114
|
- frozen_record.gemspec
|
115
115
|
- lib/frozen_record.rb
|
116
116
|
- lib/frozen_record/backends.rb
|
117
|
+
- lib/frozen_record/backends/empty.json
|
117
118
|
- lib/frozen_record/backends/json.rb
|
118
119
|
- lib/frozen_record/backends/yaml.rb
|
119
120
|
- lib/frozen_record/base.rb
|
120
121
|
- lib/frozen_record/compact.rb
|
121
|
-
- lib/frozen_record/deduplication.rb
|
122
122
|
- lib/frozen_record/index.rb
|
123
|
+
- lib/frozen_record/minimal.rb
|
123
124
|
- lib/frozen_record/railtie.rb
|
124
125
|
- lib/frozen_record/scope.rb
|
126
|
+
- lib/frozen_record/serialization.rb
|
125
127
|
- lib/frozen_record/test_helper.rb
|
126
128
|
- lib/frozen_record/version.rb
|
127
|
-
- spec/deduplication_spec.rb
|
128
129
|
- spec/fixtures/animals.json
|
129
130
|
- spec/fixtures/cars.yml
|
130
131
|
- spec/fixtures/countries.yml.erb
|
@@ -156,12 +157,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
157
|
- !ruby/object:Gem::Version
|
157
158
|
version: '0'
|
158
159
|
requirements: []
|
159
|
-
rubygems_version: 3.1.
|
160
|
+
rubygems_version: 3.1.4
|
160
161
|
signing_key:
|
161
162
|
specification_version: 4
|
162
163
|
summary: ActiveRecord like interface to read only access and query static YAML files
|
163
164
|
test_files:
|
164
|
-
- spec/deduplication_spec.rb
|
165
165
|
- spec/fixtures/animals.json
|
166
166
|
- spec/fixtures/cars.yml
|
167
167
|
- spec/fixtures/countries.yml.erb
|
data/.travis.yml
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support/core_ext/object/duplicable'
|
4
|
-
|
5
|
-
module FrozenRecord
|
6
|
-
module Deduplication
|
7
|
-
extend self
|
8
|
-
|
9
|
-
# We deduplicate data in place because it is assumed it directly
|
10
|
-
# comes from the parser, and won't be held by anyone.
|
11
|
-
#
|
12
|
-
# Frozen Hashes and Arrays are ignored because they are likely
|
13
|
-
# the result of the use of YAML anchor. Meaning we already deduplicated
|
14
|
-
# them.
|
15
|
-
if RUBY_VERSION >= '2.7'
|
16
|
-
def deep_deduplicate!(data)
|
17
|
-
case data
|
18
|
-
when Hash
|
19
|
-
return data if data.frozen?
|
20
|
-
data.transform_keys! { |k| deep_deduplicate!(k) }
|
21
|
-
data.transform_values! { |v| deep_deduplicate!(v) }
|
22
|
-
data.freeze
|
23
|
-
when Array
|
24
|
-
return data if data.frozen?
|
25
|
-
data.map! { |d| deep_deduplicate!(d) }.freeze
|
26
|
-
when String
|
27
|
-
-data
|
28
|
-
else
|
29
|
-
data.duplicable? ? data.freeze : data
|
30
|
-
end
|
31
|
-
end
|
32
|
-
else
|
33
|
-
def deep_deduplicate!(data)
|
34
|
-
case data
|
35
|
-
when Hash
|
36
|
-
return data if data.frozen?
|
37
|
-
data.transform_keys! { |k| deep_deduplicate!(k) }
|
38
|
-
data.transform_values! { |v| deep_deduplicate!(v) }
|
39
|
-
data.freeze
|
40
|
-
when Array
|
41
|
-
return data if data.frozen?
|
42
|
-
data.map! { |d| deep_deduplicate!(d) }.freeze
|
43
|
-
when String
|
44
|
-
# String#-@ doesn't deduplicate the string if it's tainted.
|
45
|
-
# So in such case we need to untaint it first.
|
46
|
-
if data.tainted?
|
47
|
-
-(+data).untaint
|
48
|
-
else
|
49
|
-
-data
|
50
|
-
end
|
51
|
-
else
|
52
|
-
data.duplicable? ? data.freeze : data
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/spec/deduplication_spec.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'deduplication' do
|
4
|
-
|
5
|
-
it 'deduplicate string values' do
|
6
|
-
pending("Strings can't be deduplicated before Ruby 2.5") if RUBY_VERSION < '2.5'
|
7
|
-
|
8
|
-
records = [
|
9
|
-
{ 'name' => 'George'.dup },
|
10
|
-
]
|
11
|
-
|
12
|
-
expect(records[0]['name']).to_not equal 'George'.freeze
|
13
|
-
FrozenRecord::Deduplication.deep_deduplicate!(records)
|
14
|
-
expect(records[0]['name']).to equal 'George'.freeze
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'handles duplicated references' do
|
18
|
-
# This simulates the YAML anchor behavior
|
19
|
-
tags = { 'foo' => 'bar' }
|
20
|
-
records = [
|
21
|
-
{ 'name' => 'George', 'tags' => tags },
|
22
|
-
{ 'name' => 'Peter', 'tags' => tags },
|
23
|
-
]
|
24
|
-
|
25
|
-
expect(records[0]['tags']).to_not be_frozen
|
26
|
-
FrozenRecord::Deduplication.deep_deduplicate!(records)
|
27
|
-
expect(records[0]['tags']).to be_frozen
|
28
|
-
expect(records[0]['tags']).to equal records[1]['tags']
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|