cache_back 0.5.0 → 0.5.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.
- data/VERSION +1 -1
- data/lib/cache_back.rb +0 -1
- data/lib/cache_back/cache.rb +6 -0
- data/lib/cache_back/conditions_parser.rb +45 -38
- data/lib/cache_back/configuration_mixin.rb +4 -33
- data/lib/cache_back/dirty_mixin.rb +2 -0
- data/lib/cache_back/read_mixin.rb +2 -3
- data/lib/cache_back/reload_association_mixin.rb +2 -3
- data/lib/cache_back/write_mixin.rb +19 -5
- data/test/cache_expiry_test.rb +14 -14
- metadata +2 -3
- data/lib/cache_back/rack_middleware.rb +0 -13
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.5. | 
| 1 | 
            +
            0.5.1
         | 
    
        data/lib/cache_back.rb
    CHANGED
    
    
    
        data/lib/cache_back/cache.rb
    CHANGED
    
    
| @@ -4,57 +4,64 @@ module CacheBack | |
| 4 4 | 
             
                  @model_class = model_class
         | 
| 5 5 | 
             
                end
         | 
| 6 6 |  | 
| 7 | 
            -
                def attribute_value_pairs(options | 
| 8 | 
            -
                   | 
| 9 | 
            -
                   | 
| 7 | 
            +
                def attribute_value_pairs(options)
         | 
| 8 | 
            +
                  #pulls out the conditions from each hash
         | 
| 9 | 
            +
                  condition_fragments = [options[:conditions]]
         | 
| 10 10 |  | 
| 11 | 
            -
                   | 
| 12 | 
            -
                   | 
| 13 | 
            -
             | 
| 14 | 
            -
                  pairs = from_scope.inject(from_options) do |memo, pair|
         | 
| 15 | 
            -
                    attribute = pair[0]
         | 
| 16 | 
            -
                    if memo_pair = memo.find{ |p| p[0] == attribute}
         | 
| 17 | 
            -
                      memo_pair[0] = Array(memo_pair[0])
         | 
| 18 | 
            -
                      memo_pair[0] << pair[1]
         | 
| 19 | 
            -
                    else
         | 
| 20 | 
            -
                      memo << pair
         | 
| 21 | 
            -
                    end
         | 
| 11 | 
            +
                  #add the scope to the mix
         | 
| 12 | 
            +
                  if scope = @model_class.send(:scope, :find)
         | 
| 13 | 
            +
                    condition_fragments << scope[:conditions]
         | 
| 22 14 | 
             
                  end
         | 
| 23 15 |  | 
| 24 | 
            -
                   | 
| 16 | 
            +
                  #add the type if we are on STI
         | 
| 17 | 
            +
                  condition_fragments << {:type => @model_class.name} if @model_class.finder_needs_type_condition?
         | 
| 25 18 |  | 
| 26 | 
            -
                   | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 19 | 
            +
                  condition_fragments.compact!
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  #parses each conditions fragment but bails if one of the did not parse
         | 
| 22 | 
            +
                  attributes_fragments = condition_fragments.map do |condition_fragment|
         | 
| 23 | 
            +
                    attributes_fragment = attributes_for_conditions(condition_fragment)
         | 
| 24 | 
            +
                    return nil unless attributes_fragment
         | 
| 25 | 
            +
                    attributes_fragment
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  #merges the hashes but bails if there is an overlap
         | 
| 29 | 
            +
                  attributes = attributes_fragments.inject({}) do |memo, attributes_fragment|
         | 
| 30 | 
            +
                    attributes_fragment.each do |attribute, value|
         | 
| 31 | 
            +
                      return nil if memo.has_key?(attribute)
         | 
| 32 | 
            +
                      memo[attribute] = value
         | 
| 36 33 | 
             
                    end
         | 
| 34 | 
            +
                    memo
         | 
| 37 35 | 
             
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  attributes.keys.sort.map { |attribute| [attribute.to_sym, attributes[attribute]] }
         | 
| 38 38 | 
             
                end
         | 
| 39 39 |  | 
| 40 | 
            -
                def  | 
| 41 | 
            -
                  case conditions
         | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 40 | 
            +
                def attributes_for_conditions(conditions)
         | 
| 41 | 
            +
                  pairs = case conditions
         | 
| 42 | 
            +
                    when Hash
         | 
| 43 | 
            +
                      return conditions.stringify_keys
         | 
| 44 | 
            +
                    when String
         | 
| 45 | 
            +
                      parse_indices_from_condition(conditions)
         | 
| 46 | 
            +
                    when Array
         | 
| 47 | 
            +
                      parse_indices_from_condition(*conditions)
         | 
| 48 | 
            +
                    when NilClass
         | 
| 49 | 
            +
                      []
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  return nil unless pairs
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  pairs.inject({}) do |memo, pair|
         | 
| 55 | 
            +
                    return nil if memo.has_key?(pair[0])
         | 
| 56 | 
            +
                    memo[pair[0]] = pair[1]
         | 
| 57 | 
            +
                    memo
         | 
| 50 58 | 
             
                  end
         | 
| 51 59 | 
             
                end
         | 
| 52 60 |  | 
| 53 61 | 
             
                AND = /\s+AND\s+/i
         | 
| 54 62 | 
             
                TABLE_AND_COLUMN = /(?:(?:`|")?(\w+)(?:`|")?\.)?(?:`|")?(\w+)(?:`|")?/ # Matches: `users`.id, `users`.`id`, users.id, id
         | 
| 55 63 | 
             
                VALUE = /'?(\d+|\?|(?:(?:[^']|'')*))'?/                     # Matches: 123, ?, '123', '12''3'
         | 
| 56 | 
            -
                KEY_EQ_VALUE =  | 
| 57 | 
            -
                ORDER = /^#{TABLE_AND_COLUMN}\s*(ASC|DESC)?$/i              # Matches: COLUMN ASC, COLUMN DESC, COLUMN
         | 
| 64 | 
            +
                KEY_EQ_VALUE = /^[\(\s]*#{TABLE_AND_COLUMN}\s+=\s+#{VALUE}[\)\s]*$/ # Matches: KEY = VALUE, (KEY = VALUE), ()(KEY = VALUE))
         | 
| 58 65 |  | 
| 59 66 | 
             
                def parse_indices_from_condition(conditions = '', *values)
         | 
| 60 67 | 
             
                  values = values.dup
         | 
| @@ -69,4 +76,4 @@ module CacheBack | |
| 69 76 | 
             
                  end
         | 
| 70 77 | 
             
                end
         | 
| 71 78 | 
             
              end
         | 
| 72 | 
            -
            end
         | 
| 79 | 
            +
            end
         | 
| @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            require 'active_support'
         | 
| 2 | 
            +
            require 'zlib'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module CacheBack
         | 
| 4 5 | 
             
              autoload :ReadMixin, 'cache_back/read_mixin'
         | 
| @@ -6,37 +7,12 @@ module CacheBack | |
| 6 7 | 
             
              autoload :DirtyMixin, 'cache_back/dirty_mixin'
         | 
| 7 8 |  | 
| 8 9 | 
             
              module ConfigurationMixin
         | 
| 9 | 
            -
                def  | 
| 10 | 
            -
                  @ | 
| 11 | 
            -
                end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                def inherited_cache_back_version
         | 
| 14 | 
            -
                  if self == ActiveRecord::Base
         | 
| 15 | 
            -
                    @cache_back_version
         | 
| 16 | 
            -
                  else
         | 
| 17 | 
            -
                    @cache_back_version ||= superclass.inherited_cache_back_version
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
                end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                def inherited_cache_back_options
         | 
| 22 | 
            -
                  if self == ActiveRecord::Base
         | 
| 23 | 
            -
                    @cache_back_option
         | 
| 24 | 
            -
                  else
         | 
| 25 | 
            -
                    @cache_back_option ||= superclass.inherited_cache_back_options
         | 
| 26 | 
            -
                  end
         | 
| 10 | 
            +
                def cache_back_key_prefix
         | 
| 11 | 
            +
                  @cache_back_key_prefix ||= "cache_back/#{table_name}/version=#{Zlib.crc32(column_names.sort.join)}/"
         | 
| 27 12 | 
             
                end
         | 
| 28 13 |  | 
| 29 14 | 
             
                def cache_back_key_for(attribute_value_pairs)
         | 
| 30 | 
            -
                   | 
| 31 | 
            -
                  attribute_value_pairs.each do |attribute, value|
         | 
| 32 | 
            -
                    key << "/#{attribute}="
         | 
| 33 | 
            -
                    if value.is_a?(Array)
         | 
| 34 | 
            -
                      key << value.join(',')
         | 
| 35 | 
            -
                    else
         | 
| 36 | 
            -
                      key << value.to_s
         | 
| 37 | 
            -
                    end
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
                  key
         | 
| 15 | 
            +
                  cache_back_key_prefix + attribute_value_pairs.map {|attribute, value| attribute.to_s + '=' + value.to_s}.join('/')
         | 
| 40 16 | 
             
                end
         | 
| 41 17 |  | 
| 42 18 | 
             
                def cache_back_key_for_id(id)
         | 
| @@ -58,12 +34,7 @@ module CacheBack | |
| 58 34 | 
             
                end
         | 
| 59 35 |  | 
| 60 36 | 
             
                def has_cache_back_on(*args)
         | 
| 61 | 
            -
                  options = args.extract_options!
         | 
| 62 37 | 
             
                  attributes = args.sort! { |x, y| x.to_s <=> y.to_s }
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                  @cache_back_version ||= options.delete(:version) || '1'
         | 
| 65 | 
            -
                  @cache_back_option ||= options
         | 
| 66 | 
            -
             | 
| 67 38 | 
             
                  if attributes != [:id] && !cache_back_indices.include?([:id])
         | 
| 68 39 | 
             
                    has_cache_back_on(:id)
         | 
| 69 40 | 
             
                  end
         | 
| @@ -19,7 +19,7 @@ module CacheBack | |
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 21 | 
             
                def find_every_with_cache_back(options)
         | 
| 22 | 
            -
                  attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options | 
| 22 | 
            +
                  attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options) if cache_safe?(options)
         | 
| 23 23 |  | 
| 24 24 | 
             
                  limit = (options[:limit] || (scope(:find) || {})[:limit])
         | 
| 25 25 |  | 
| @@ -48,7 +48,7 @@ module CacheBack | |
| 48 48 | 
             
                end
         | 
| 49 49 |  | 
| 50 50 | 
             
                def find_some_with_cache_back(ids, options)
         | 
| 51 | 
            -
                  attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options | 
| 51 | 
            +
                  attribute_value_pairs = cache_back_conditions_parser.attribute_value_pairs(options) if cache_safe?(options)
         | 
| 52 52 | 
             
                  attribute_value_pairs << [:id, ids] if attribute_value_pairs
         | 
| 53 53 |  | 
| 54 54 | 
             
                  limit = (options[:limit] || (scope(:find) || {})[:limit])
         | 
| @@ -88,6 +88,5 @@ module CacheBack | |
| 88 88 | 
             
                  def cache_back_conditions_parser
         | 
| 89 89 | 
             
                    @cache_back_conditions_parser ||= CacheBack::ConditionsParser.new(self)
         | 
| 90 90 | 
             
                  end
         | 
| 91 | 
            -
             | 
| 92 91 | 
             
              end
         | 
| 93 92 | 
             
            end
         | 
| @@ -2,9 +2,8 @@ module CacheBack | |
| 2 2 | 
             
              module ReloadAssociationMixin
         | 
| 3 3 | 
             
                def reload_with_cache_back_clearing(*args)
         | 
| 4 4 | 
             
                  # TODO we could calculate the right key to clear by parsing the association conditions.
         | 
| 5 | 
            -
                  # this would clear less keys | 
| 6 | 
            -
                   | 
| 7 | 
            -
                  target.clear_cache_back_indices if target.respond_to?(:clear_cache_back_indices)
         | 
| 5 | 
            +
                  # this would clear less keys
         | 
| 6 | 
            +
                  CacheBack.cache.reset!
         | 
| 8 7 | 
             
                  reload_without_cache_back_clearing(*args)
         | 
| 9 8 | 
             
                end
         | 
| 10 9 |  | 
| @@ -20,29 +20,43 @@ module CacheBack | |
| 20 20 |  | 
| 21 21 | 
             
                  def store_in_cache_back
         | 
| 22 22 | 
             
                    if !readonly? && cache_back_key
         | 
| 23 | 
            -
                      CacheBack.cache.write(cache_back_key, self | 
| 23 | 
            +
                      CacheBack.cache.write(cache_back_key, self)
         | 
| 24 24 | 
             
                    end
         | 
| 25 25 | 
             
                  end
         | 
| 26 26 |  | 
| 27 | 
            -
                  def  | 
| 27 | 
            +
                  def cache_back_keys
         | 
| 28 28 | 
             
                    new_attributes = attributes.symbolize_keys
         | 
| 29 29 |  | 
| 30 30 | 
             
                    old_attributes = Hash[changes.map {|attribute, values| [attribute, values[0]]}].symbolize_keys
         | 
| 31 31 | 
             
                    old_attributes.reverse_merge!(new_attributes)
         | 
| 32 32 |  | 
| 33 | 
            +
                    keys = []
         | 
| 33 34 | 
             
                    self.class.cache_back_indices.each do |index|
         | 
| 34 35 | 
             
                      old_key = self.class.cache_back_key_for(index.map { |attribute| [attribute, old_attributes[attribute]]})
         | 
| 35 36 | 
             
                      new_key = self.class.cache_back_key_for(index.map { |attribute| [attribute, new_attributes[attribute]]})
         | 
| 36 37 |  | 
| 37 38 | 
             
                      [old_key, new_key].uniq.each do |key|
         | 
| 38 | 
            -
                         | 
| 39 | 
            -
                         | 
| 39 | 
            +
                        keys << key
         | 
| 40 | 
            +
                        keys << "#{key}/first"
         | 
| 40 41 | 
             
                      end
         | 
| 41 42 | 
             
                    end
         | 
| 43 | 
            +
                    keys
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  def clear_cache_back_indices
         | 
| 47 | 
            +
                    cache_back_keys.each do |key|
         | 
| 48 | 
            +
                      CacheBack.cache.delete(key)
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def clear_local_cache_back_indices
         | 
| 53 | 
            +
                    cache_back_keys.each do |key|
         | 
| 54 | 
            +
                      CacheBack.cache.delete_local(key)
         | 
| 55 | 
            +
                    end
         | 
| 42 56 | 
             
                  end
         | 
| 43 57 |  | 
| 44 58 | 
             
                  def reload_with_cache_back_clearing(*args)
         | 
| 45 | 
            -
                     | 
| 59 | 
            +
                    clear_local_cache_back_indices
         | 
| 46 60 | 
             
                    reload_without_cache_back_clearing(*args)
         | 
| 47 61 | 
             
                  end
         | 
| 48 62 | 
             
                end
         | 
    
        data/test/cache_expiry_test.rb
    CHANGED
    
    | @@ -20,12 +20,12 @@ class CacheExpiryTest < ActiveSupport::TestCase | |
| 20 20 | 
             
                end
         | 
| 21 21 |  | 
| 22 22 | 
             
                should "clear all indices for instance when deleted" do
         | 
| 23 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 24 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 25 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 26 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 27 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 28 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 23 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "id=#{@post.id}")
         | 
| 24 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "id=#{@post.id}/first")
         | 
| 25 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=#{@post.title}")
         | 
| 26 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=#{@post.title}/first")
         | 
| 27 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "blog_id=#{@post.blog_id}")
         | 
| 28 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "blog_id=#{@post.blog_id}/first")
         | 
| 29 29 | 
             
                  CacheBack.cache.expects(:delete).never
         | 
| 30 30 |  | 
| 31 31 | 
             
                  @post.destroy
         | 
| @@ -38,14 +38,14 @@ class CacheExpiryTest < ActiveSupport::TestCase | |
| 38 38 | 
             
                end
         | 
| 39 39 |  | 
| 40 40 | 
             
                should "clear all indices for instance when updated" do
         | 
| 41 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 42 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 43 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 44 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 45 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 46 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 47 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 48 | 
            -
                  CacheBack.cache.expects(:delete).with(" | 
| 41 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "id=#{@post.id}")
         | 
| 42 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "id=#{@post.id}/first")
         | 
| 43 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=#{@post.title}")
         | 
| 44 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=#{@post.title}/first")
         | 
| 45 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=new title")
         | 
| 46 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "title=new title/first")
         | 
| 47 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "blog_id=#{@post.blog_id}")
         | 
| 48 | 
            +
                  CacheBack.cache.expects(:delete).with(Post.cache_back_key_prefix + "blog_id=#{@post.blog_id}/first")
         | 
| 49 49 | 
             
                  CacheBack.cache.expects(:delete).never
         | 
| 50 50 |  | 
| 51 51 | 
             
                  @post.title = "new title"
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: cache_back
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 0.5. | 
| 4 | 
            +
              version: 0.5.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - Mick Staugaard
         | 
| @@ -9,7 +9,7 @@ autorequire: | |
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 |  | 
| 12 | 
            -
            date: 2009-11- | 
| 12 | 
            +
            date: 2009-11-30 00:00:00 -08:00
         | 
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: 
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -53,7 +53,6 @@ files: | |
| 53 53 | 
             
            - lib/cache_back/conditions_parser.rb
         | 
| 54 54 | 
             
            - lib/cache_back/configuration_mixin.rb
         | 
| 55 55 | 
             
            - lib/cache_back/dirty_mixin.rb
         | 
| 56 | 
            -
            - lib/cache_back/rack_middleware.rb
         | 
| 57 56 | 
             
            - lib/cache_back/read_mixin.rb
         | 
| 58 57 | 
             
            - lib/cache_back/reload_association_mixin.rb
         | 
| 59 58 | 
             
            - lib/cache_back/write_mixin.rb
         |