second_level_cache 2.2.6 → 2.3.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +16 -10
- data/lib/second_level_cache/active_record/fetch_by_uniq_key.rb +2 -2
- data/lib/second_level_cache/record_marshal.rb +3 -0
- data/lib/second_level_cache/version.rb +1 -1
- data/lib/second_level_cache.rb +10 -3
- data/second_level_cache.gemspec +1 -1
- data/test/model/account.rb +1 -1
- data/test/model/animal.rb +2 -2
- data/test/model/book.rb +1 -1
- data/test/model/image.rb +1 -1
- data/test/model/post.rb +1 -1
- data/test/model/topic.rb +1 -1
- data/test/model/user.rb +6 -2
- data/test/record_marshal_test.rb +6 -0
- data/test/second_level_cache_test.rb +4 -1
- metadata +8 -8
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 98025234cd167d1057980109b910f6988747877b
         | 
| 4 | 
            +
              data.tar.gz: 40f729aac59034003e7f6404321f47bfd8f67a55
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fb1d412af6f56f3e20938b4744f0a48b3d18abc4a556847001edf4a1fa13aaabb9ece974fa9d11720177f011970c3f085d0fd984e920bf21b4b9018dac47b01e
         | 
| 7 | 
            +
              data.tar.gz: dcec779ee5c1733a03b8058a3a7dc243ce33698af648e583d4ce118a879032f36f1da961da1a61c096edded58ccbdddb77bc44c812557f57fa3898460a919353
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -40,7 +40,7 @@ For example, cache User objects: | |
| 40 40 |  | 
| 41 41 | 
             
            ```ruby
         | 
| 42 42 | 
             
            class User < ActiveRecord::Base
         | 
| 43 | 
            -
               | 
| 43 | 
            +
              second_level_cache expires_in: 1.week
         | 
| 44 44 | 
             
            end
         | 
| 45 45 | 
             
            ```
         | 
| 46 46 |  | 
| @@ -67,7 +67,9 @@ Expires cache: | |
| 67 67 | 
             
            user = User.find(1)
         | 
| 68 68 | 
             
            user.expire_second_level_cache
         | 
| 69 69 | 
             
            ```
         | 
| 70 | 
            +
             | 
| 70 71 | 
             
            or expires cache using class method:
         | 
| 72 | 
            +
             | 
| 71 73 | 
             
            ```ruby
         | 
| 72 74 | 
             
            User.expire_second_level_cache(1)
         | 
| 73 75 | 
             
            ```
         | 
| @@ -97,15 +99,15 @@ User.select("id, name").find(1) | |
| 97 99 | 
             
            ```ruby
         | 
| 98 100 | 
             
            # user and account's write_second_level_cache operation will invoke after the logger.
         | 
| 99 101 | 
             
            ActiveRecord::Base.transaction do
         | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 102 | 
            +
              user.save
         | 
| 103 | 
            +
              account.save
         | 
| 104 | 
            +
              Rails.logger.info "info"
         | 
| 103 105 | 
             
            end # <- Cache write
         | 
| 104 106 |  | 
| 105 107 | 
             
            # if you want to do something after user and account's write_second_level_cache operation, do this way:
         | 
| 106 108 | 
             
            ActiveRecord::Base.transaction do
         | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            +
              user.save
         | 
| 110 | 
            +
              account.save
         | 
| 109 111 | 
             
            end # <- Cache write
         | 
| 110 112 | 
             
            Rails.logger.info "info"
         | 
| 111 113 | 
             
            ```
         | 
| @@ -119,8 +121,9 @@ DatabaseCleaner.strategy = :truncation | |
| 119 121 | 
             
            ## Configure
         | 
| 120 122 |  | 
| 121 123 | 
             
            In production env, we recommend to use [Dalli](https://github.com/mperham/dalli) as Rails cache store.
         | 
| 124 | 
            +
             | 
| 122 125 | 
             
            ```ruby
         | 
| 123 | 
            -
             | 
| 126 | 
            +
            config.cache_store = [:dalli_store, APP_CONFIG["memcached_host"], { namespace: "ns", compress: true }]
         | 
| 124 127 | 
             
            ```
         | 
| 125 128 |  | 
| 126 129 | 
             
            ## Tips:
         | 
| @@ -131,15 +134,17 @@ you can only change the `cache_key_prefix`: | |
| 131 134 | 
             
            ```ruby
         | 
| 132 135 | 
             
            SecondLevelCache.configure.cache_key_prefix = "slc1"
         | 
| 133 136 | 
             
            ```
         | 
| 134 | 
            -
             | 
| 137 | 
            +
             | 
| 138 | 
            +
            * SecondLevelCache was added model schema digest as cache version, this means when you add/remove/change columns, the caches of this Model will expires.
         | 
| 139 | 
            +
            * When your want change the model cache version by manualy, just add the `version` option like this:
         | 
| 135 140 |  | 
| 136 141 | 
             
            ```ruby
         | 
| 137 142 | 
             
            class User < ActiveRecord::Base
         | 
| 138 | 
            -
               | 
| 143 | 
            +
              second_level_cache version: 2, expires_in: 1.week
         | 
| 139 144 | 
             
            end
         | 
| 140 145 | 
             
            ```
         | 
| 141 146 |  | 
| 142 | 
            -
            * It provides a great feature, not hits db when fetching record via unique key(not primary key).
         | 
| 147 | 
            +
            * It provides a great feature, not hits db when fetching record via unique key (not primary key).
         | 
| 143 148 |  | 
| 144 149 | 
             
            ```ruby
         | 
| 145 150 | 
             
            # this will fetch from cache
         | 
| @@ -156,6 +161,7 @@ user = User.fetch_by_uniq_keys!(nick_name: "hooopo") # this will raise `ActiveRe | |
| 156 161 | 
             
            Answer.includes(:question).limit(10).order("id DESC").each{|answer| answer.question.title}
         | 
| 157 162 | 
             
            Answer Load (0.2ms)  SELECT `answers`.* FROM `answers` ORDER BY id DESC LIMIT 10 # Only one SQL query and one Rails.cache.read_multi fetching operation.
         | 
| 158 163 | 
             
            ```
         | 
| 164 | 
            +
             | 
| 159 165 | 
             
            [Details for read_multi feature](http://hooopo.writings.io/articles/a9cae5e0).
         | 
| 160 166 |  | 
| 161 167 | 
             
            ## Contributors
         | 
| @@ -21,7 +21,7 @@ module SecondLevelCache | |
| 21 21 | 
             
                  end
         | 
| 22 22 |  | 
| 23 23 | 
             
                  def fetch_by_uniq_keys!(where_values)
         | 
| 24 | 
            -
                    fetch_by_uniq_keys(where_values) ||  | 
| 24 | 
            +
                    fetch_by_uniq_keys(where_values) || raise(::ActiveRecord::RecordNotFound)
         | 
| 25 25 | 
             
                  end
         | 
| 26 26 |  | 
| 27 27 | 
             
                  def fetch_by_uniq_key(value, uniq_key_name)
         | 
| @@ -33,7 +33,7 @@ module SecondLevelCache | |
| 33 33 | 
             
                  def fetch_by_uniq_key!(value, uniq_key_name)
         | 
| 34 34 | 
             
                    # puts "[Deprecated] will remove in the future,
         | 
| 35 35 | 
             
                    # use fetch_by_uniq_keys! method instead."
         | 
| 36 | 
            -
                    fetch_by_uniq_key(value, uniq_key_name) ||  | 
| 36 | 
            +
                    fetch_by_uniq_key(value, uniq_key_name) || raise(::ActiveRecord::RecordNotFound)
         | 
| 37 37 | 
             
                  end
         | 
| 38 38 |  | 
| 39 39 | 
             
                  private
         | 
| @@ -31,6 +31,9 @@ module RecordMarshal | |
| 31 31 | 
             
                    next if attributes[name].nil? || attributes[name].is_a?(String)
         | 
| 32 32 | 
             
                    if coder.is_a?(::ActiveRecord::Coders::YAMLColumn)
         | 
| 33 33 | 
             
                      attributes[name] = coder.dump(attributes[name]) if attributes[name].is_a?(coder.object_class)
         | 
| 34 | 
            +
                    elsif coder.is_a?(::ActiveRecord::Store::IndifferentCoder)
         | 
| 35 | 
            +
                      # https://github.com/rails/rails/blob/5b14129/activerecord/lib/active_record/store.rb#L179
         | 
| 36 | 
            +
                      attributes[name] = coder.dump(attributes[name])
         | 
| 34 37 | 
             
                    elsif coder == ::ActiveRecord::Coders::JSON
         | 
| 35 38 | 
             
                      attributes[name] = attributes[name].to_json
         | 
| 36 39 | 
             
                    end
         | 
    
        data/lib/second_level_cache.rb
    CHANGED
    
    | @@ -20,11 +20,11 @@ module SecondLevelCache | |
| 20 20 |  | 
| 21 21 | 
             
                  delegate :logger, :cache_store, :cache_key_prefix, to: SecondLevelCache
         | 
| 22 22 |  | 
| 23 | 
            -
                  def  | 
| 23 | 
            +
                  def second_level_cache(options = {})
         | 
| 24 24 | 
             
                    @second_level_cache_enabled = true
         | 
| 25 25 | 
             
                    @second_level_cache_options = options
         | 
| 26 | 
            -
                    @second_level_cache_options[:expires_in] ||= 1.week
         | 
| 27 26 | 
             
                    @second_level_cache_options[:version] ||= 0
         | 
| 27 | 
            +
                    @second_level_cache_options[:expires_in] ||= 1.week
         | 
| 28 28 | 
             
                    relation.class.send :prepend, SecondLevelCache::ActiveRecord::FinderMethods
         | 
| 29 29 | 
             
                    prepend SecondLevelCache::ActiveRecord::Core
         | 
| 30 30 | 
             
                  end
         | 
| @@ -46,8 +46,15 @@ module SecondLevelCache | |
| 46 46 | 
             
                    @second_level_cache_enabled = old
         | 
| 47 47 | 
             
                  end
         | 
| 48 48 |  | 
| 49 | 
            +
                  # Get MD5 digest of this Model schema
         | 
| 50 | 
            +
                  # http://api.rubyonrails.org/classes/ActiveRecord/Core/ClassMethods.html#method-i-inspect
         | 
| 49 51 | 
             
                  def cache_version
         | 
| 50 | 
            -
                     | 
| 52 | 
            +
                    return @cache_version if defined? @cache_version
         | 
| 53 | 
            +
                    # This line is copy from:
         | 
| 54 | 
            +
                    # https://github.com/rails/rails/blob/f9a5f48/activerecord/lib/active_record/core.rb#L236
         | 
| 55 | 
            +
                    attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ', '
         | 
| 56 | 
            +
                    model_schema_digest = Digest::MD5.hexdigest(attr_list)
         | 
| 57 | 
            +
                    @cache_version = "#{second_level_cache_options[:version]}/#{model_schema_digest}"
         | 
| 51 58 | 
             
                  end
         | 
| 52 59 |  | 
| 53 60 | 
             
                  def second_level_cache_key(id)
         | 
    
        data/second_level_cache.gemspec
    CHANGED
    
    | @@ -37,5 +37,5 @@ Gem::Specification.new do |gem| | |
| 37 37 | 
             
              gem.add_development_dependency 'rake'
         | 
| 38 38 | 
             
              gem.add_development_dependency 'pry'
         | 
| 39 39 | 
             
              gem.add_development_dependency 'database_cleaner', '~> 1.3.0'
         | 
| 40 | 
            -
              gem.add_development_dependency 'rubocop' | 
| 40 | 
            +
              gem.add_development_dependency 'rubocop'
         | 
| 41 41 | 
             
            end
         | 
    
        data/test/model/account.rb
    CHANGED
    
    
    
        data/test/model/animal.rb
    CHANGED
    
    
    
        data/test/model/book.rb
    CHANGED
    
    
    
        data/test/model/image.rb
    CHANGED
    
    
    
        data/test/model/post.rb
    CHANGED
    
    
    
        data/test/model/topic.rb
    CHANGED
    
    
    
        data/test/model/user.rb
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            ActiveRecord::Base.connection.create_table(:users, force: true) do |t|
         | 
| 2 2 | 
             
              t.text    :options
         | 
| 3 3 | 
             
              t.text    :json_options
         | 
| 4 | 
            +
              t.text    :extras
         | 
| 4 5 | 
             
              t.string  :name, unique: true
         | 
| 5 6 | 
             
              t.string  :email
         | 
| 6 7 | 
             
              t.integer :status, default: 0
         | 
| @@ -24,9 +25,12 @@ end | |
| 24 25 |  | 
| 25 26 | 
             
            class User < ActiveRecord::Base
         | 
| 26 27 | 
             
              CACHE_VERSION = 3
         | 
| 28 | 
            +
              second_level_cache(version: CACHE_VERSION, expires_in: 3.days)
         | 
| 29 | 
            +
             | 
| 27 30 | 
             
              serialize :options, Array
         | 
| 28 31 | 
             
              serialize :json_options, JSON if ::ActiveRecord::VERSION::STRING >= '4.1.0'
         | 
| 29 | 
            -
               | 
| 32 | 
            +
              store :extras, accessors: [:tagline, :gender]
         | 
| 33 | 
            +
             | 
| 30 34 | 
             
              has_one  :account
         | 
| 31 35 | 
             
              has_one  :forked_user_link, foreign_key: 'forked_to_user_id'
         | 
| 32 36 | 
             
              has_one  :forked_from_user, through: :forked_user_link
         | 
| @@ -39,7 +43,7 @@ class User < ActiveRecord::Base | |
| 39 43 | 
             
            end
         | 
| 40 44 |  | 
| 41 45 | 
             
            class Namespace < ActiveRecord::Base
         | 
| 42 | 
            -
               | 
| 46 | 
            +
              second_level_cache version: 1, expires_in: 3.days
         | 
| 43 47 |  | 
| 44 48 | 
             
              belongs_to :user
         | 
| 45 49 | 
             
            end
         | 
    
        data/test/record_marshal_test.rb
    CHANGED
    
    | @@ -4,14 +4,17 @@ class RecordMarshalTest < ActiveSupport::TestCase | |
| 4 4 | 
             
              def setup
         | 
| 5 5 | 
             
                if ::ActiveRecord::VERSION::STRING >= '4.1.0'
         | 
| 6 6 | 
             
                  @json_options = { 'name' => 'Test', 'age' => 18, 'hash' => { 'name' => 'dup' } }
         | 
| 7 | 
            +
                  @extras = { 'tagline' => 'Hello world', 'gender' => 1 }
         | 
| 7 8 | 
             
                  @user = User.create name: 'csdn',
         | 
| 8 9 | 
             
                                      email: 'test@csdn.com',
         | 
| 9 10 | 
             
                                      options: [1, 2],
         | 
| 11 | 
            +
                                      extras: @extras,
         | 
| 10 12 | 
             
                                      json_options: @json_options,
         | 
| 11 13 | 
             
                                      status: :active
         | 
| 12 14 | 
             
                else
         | 
| 13 15 | 
             
                  @user = User.create name: 'csdn',
         | 
| 14 16 | 
             
                                      email: 'test@csdn.com',
         | 
| 17 | 
            +
                                      extras: @extras,
         | 
| 15 18 | 
             
                                      options: [1, 2]
         | 
| 16 19 | 
             
                end
         | 
| 17 20 | 
             
              end
         | 
| @@ -30,6 +33,9 @@ class RecordMarshalTest < ActiveSupport::TestCase | |
| 30 33 | 
             
                assert_equal Array, User.read_second_level_cache(@user.id).reload.options.class
         | 
| 31 34 | 
             
                assert_equal User.read_second_level_cache(@user.id).changed?, false
         | 
| 32 35 | 
             
                assert_equal [1, 2], User.read_second_level_cache(@user.id).options
         | 
| 36 | 
            +
                assert_equal @extras, User.read_second_level_cache(@user.id).extras
         | 
| 37 | 
            +
                assert_equal 'Hello world', User.read_second_level_cache(@user.id).tagline
         | 
| 38 | 
            +
                assert_equal 1, User.read_second_level_cache(@user.id).gender
         | 
| 33 39 | 
             
                if ::ActiveRecord::VERSION::STRING >= '4.1.0'
         | 
| 34 40 | 
             
                  result = User.read_second_level_cache(@user.id)
         | 
| 35 41 | 
             
                  assert_equal @json_options['name'], result.json_options['name']
         | 
| @@ -6,7 +6,10 @@ class SecondLevelCacheTest < ActiveSupport::TestCase | |
| 6 6 | 
             
              end
         | 
| 7 7 |  | 
| 8 8 | 
             
              def test_should_get_cache_key
         | 
| 9 | 
            -
                 | 
| 9 | 
            +
                attr_list = User.attribute_types.map { |name, type| "#{name}: #{type.type}" } * ', '
         | 
| 10 | 
            +
                table_digest = Digest::MD5.hexdigest(attr_list)
         | 
| 11 | 
            +
                refute_nil table_digest
         | 
| 12 | 
            +
                assert_equal "slc/users/#{@user.id}/#{User::CACHE_VERSION}/#{table_digest}", @user.second_level_cache_key
         | 
| 10 13 | 
             
              end
         | 
| 11 14 |  | 
| 12 15 | 
             
              def test_should_write_and_read_cache
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: second_level_cache
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2. | 
| 4 | 
            +
              version: 2.3.0.beta
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Hooopo
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2017-01-11 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         | 
| @@ -110,16 +110,16 @@ dependencies: | |
| 110 110 | 
             
              name: rubocop
         | 
| 111 111 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 112 112 | 
             
                requirements:
         | 
| 113 | 
            -
                - - " | 
| 113 | 
            +
                - - ">="
         | 
| 114 114 | 
             
                  - !ruby/object:Gem::Version
         | 
| 115 | 
            -
                    version: 0 | 
| 115 | 
            +
                    version: '0'
         | 
| 116 116 | 
             
              type: :development
         | 
| 117 117 | 
             
              prerelease: false
         | 
| 118 118 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 119 119 | 
             
                requirements:
         | 
| 120 | 
            -
                - - " | 
| 120 | 
            +
                - - ">="
         | 
| 121 121 | 
             
                  - !ruby/object:Gem::Version
         | 
| 122 | 
            -
                    version: 0 | 
| 122 | 
            +
                    version: '0'
         | 
| 123 123 | 
             
            description: Write Through and Read Through caching library inspired by CacheMoney
         | 
| 124 124 | 
             
              and cache_fu, support  ActiveRecord 4.
         | 
| 125 125 | 
             
            email:
         | 
| @@ -184,9 +184,9 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 184 184 | 
             
                  version: '0'
         | 
| 185 185 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 186 186 | 
             
              requirements:
         | 
| 187 | 
            -
              - - " | 
| 187 | 
            +
              - - ">"
         | 
| 188 188 | 
             
                - !ruby/object:Gem::Version
         | 
| 189 | 
            -
                  version:  | 
| 189 | 
            +
                  version: 1.3.1
         | 
| 190 190 | 
             
            requirements: []
         | 
| 191 191 | 
             
            rubyforge_project: 
         | 
| 192 192 | 
             
            rubygems_version: 2.5.1
         |