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
         
     |