diff options
Diffstat (limited to 'activesupport/lib')
16 files changed, 179 insertions, 40 deletions
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 6a6c861458..83174d3a85 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -10,6 +10,10 @@ module ActiveSupport autoload :MemCacheStore, 'active_support/cache/mem_cache_store' autoload :CompressedMemCacheStore, 'active_support/cache/compressed_mem_cache_store' + module Strategy + autoload :LocalCache, 'active_support/cache/strategy/local_cache' + end + # Creates a new CacheStore object according to the given options. # # If no arguments are passed to this method, then a new diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index f9a7fb1440..4d8e1fdd67 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -13,6 +13,7 @@ module ActiveSupport # server goes down, then MemCacheStore will ignore it until it goes back # online. # - Time-based expiry support. See #write and the +:expires_in+ option. + # - Per-request in memory cache for all communication with the MemCache server(s). class MemCacheStore < Store module Response # :nodoc: STORED = "STORED\r\n" @@ -38,6 +39,8 @@ module ActiveSupport addresses = ["localhost"] if addresses.empty? @addresses = addresses @data = MemCache.new(addresses, options) + + extend Strategy::LocalCache end def read(key, options = nil) # :nodoc: @@ -80,6 +83,7 @@ module ActiveSupport def exist?(key, options = nil) # :nodoc: # Doesn't call super, cause exist? in memcache is in fact a read # But who cares? Reading is very fast anyway + # Local cache is checked first, if it doesn't know then memcache itself is read from !read(key, options).nil? end @@ -94,7 +98,6 @@ module ActiveSupport def decrement(key, amount = 1) # :nodoc: log("decrement", key, amount) - response = @data.decr(key, amount) response == Response::NOT_FOUND ? nil : response rescue MemCache::MemCacheError @@ -102,6 +105,8 @@ module ActiveSupport end def delete_matched(matcher, options = nil) # :nodoc: + # don't do any local caching at present, just pass + # through and let the error happen super raise "Not supported by Memcache" end diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb new file mode 100644 index 0000000000..621358d701 --- /dev/null +++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb @@ -0,0 +1,104 @@ +module ActiveSupport + module Cache + module Strategy + module LocalCache + # this allows caching of the fact that there is nothing in the remote cache + NULL = 'remote_cache_store:null' + + def with_local_cache + Thread.current[thread_local_key] = MemoryStore.new + yield + ensure + Thread.current[thread_local_key] = nil + end + + def middleware + @middleware ||= begin + klass = Class.new + klass.class_eval(<<-EOS, __FILE__, __LINE__) + def initialize(app) + @app = app + end + + def call(env) + Thread.current[:#{thread_local_key}] = MemoryStore.new + @app.call(env) + ensure + Thread.current[:#{thread_local_key}] = nil + end + EOS + klass + end + end + + def read(key, options = nil) + value = local_cache && local_cache.read(key) + if value == NULL + nil + elsif value.nil? + value = super + local_cache.write(key, value || NULL) if local_cache + value + else + # forcing the value to be immutable + value.dup + end + end + + def write(key, value, options = nil) + value = value.to_s if respond_to?(:raw?) && raw?(options) + local_cache.write(key, value || NULL) if local_cache + super + end + + def delete(key, options = nil) + local_cache.write(key, NULL) if local_cache + super + end + + def exist(key, options = nil) + value = local_cache.read(key) if local_cache + if value == NULL + false + elsif value + true + else + super + end + end + + def increment(key, amount = 1) + if value = super + local_cache.write(key, value.to_s) if local_cache + value + else + nil + end + end + + def decrement(key, amount = 1) + if value = super + local_cache.write(key, value.to_s) if local_cache + value + else + nil + end + end + + def clear + local_cache.clear if local_cache + super + end + + private + def thread_local_key + @thread_local_key ||= "#{self.class.name.underscore}_local_cache".gsub("/", "_").to_sym + end + + def local_cache + Thread.current[thread_local_key] + end + end + end + end +end diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb index d2d9699d01..8d9f023361 100644 --- a/activesupport/lib/active_support/core_ext/date/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date/conversions.rb @@ -31,7 +31,7 @@ module ActiveSupport #:nodoc: # # This method is aliased to <tt>to_s</tt>. # - # ==== Examples: + # ==== Examples # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007 # # date.to_formatted_s(:db) # => "2007-11-10" @@ -76,7 +76,7 @@ module ActiveSupport #:nodoc: # Converts a Date instance to a Time, where the time is set to the beginning of the day. # The timezone can be either :local or :utc (default :local). # - # ==== Examples: + # ==== Examples # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007 # # date.to_time # => Sat Nov 10 00:00:00 0800 2007 @@ -90,7 +90,7 @@ module ActiveSupport #:nodoc: # Converts a Date instance to a DateTime, where the time is set to the beginning of the day # and UTC offset is set to 0. # - # ==== Example: + # ==== Examples # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007 # # date.to_datetime # => Sat, 10 Nov 2007 00:00:00 0000 diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb index c0175a5f28..7c948267b3 100644 --- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb @@ -25,7 +25,7 @@ module ActiveSupport #:nodoc: # # This method is aliased to <tt>to_s</tt>. # - # === Examples: + # === Examples # datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000 # # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00" diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index a254e45624..991a5a6a89 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -75,7 +75,7 @@ module ActiveSupport #:nodoc: # Converts a hash into a string suitable for use as a URL query string. An optional <tt>namespace</tt> can be # passed to enclose the param names (see example below). # - # ==== Example: + # ==== Examples # { :name => 'David', :nationality => 'Danish' }.to_query # => "name=David&nationality=Danish" # # { :name => 'David', :nationality => 'Danish' }.to_query('user') # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish" diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb index 7312bcb416..af9d372d76 100644 --- a/activesupport/lib/active_support/core_ext/hash/keys.rb +++ b/activesupport/lib/active_support/core_ext/hash/keys.rb @@ -38,7 +38,7 @@ module ActiveSupport #:nodoc: # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols # as keys, this will fail. # - # ==== Examples: + # ==== Examples # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years" # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age" # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb index c0a109ecf3..4acdfa3d6c 100644 --- a/activesupport/lib/active_support/core_ext/object/misc.rb +++ b/activesupport/lib/active_support/core_ext/object/misc.rb @@ -87,21 +87,4 @@ class Object respond_to? "acts_like_#{duck}?" end - # Tries to send the method only if object responds to it. Return +nil+ otherwise. - # It will also forward any arguments and/or block like Object#send does. - # - # ==== Example : - # - # # Without try - # @person ? @person.name : nil - # - # With try - # @person.try(:name) - # - # # try also accepts arguments/blocks for the method it is trying - # Person.try(:find, 1) - # @people.try(:map) {|p| p.name} - def try(method, *args, &block) - send(method, *args, &block) unless self.nil? - end end diff --git a/activesupport/lib/active_support/core_ext/range/conversions.rb b/activesupport/lib/active_support/core_ext/range/conversions.rb index 932bdedad3..45b0826b62 100644 --- a/activesupport/lib/active_support/core_ext/range/conversions.rb +++ b/activesupport/lib/active_support/core_ext/range/conversions.rb @@ -15,7 +15,7 @@ module ActiveSupport #:nodoc: end # Gives a human readable format of the range. # - # ==== Example: + # ==== Example # # [1..100].to_formatted_s # => "1..100" def to_formatted_s(format = :default) diff --git a/activesupport/lib/active_support/core_ext/try.rb b/activesupport/lib/active_support/core_ext/try.rb new file mode 100644 index 0000000000..0dccd40c55 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/try.rb @@ -0,0 +1,30 @@ +class Object + # Tries to send the method only if object responds to it. Return +nil+ otherwise. + # It will also forward any arguments and/or block like Object#send does. + # + # ==== Examples + # + # Without try + # @person && @person.name + # or + # @person ? @person.name : nil + # + # With try + # @person.try(:name) + # + # Try also accepts arguments/blocks for the method it is trying + # Person.try(:find, 1) + # @people.try(:collect) {|p| p.name} + #-- + # This method def is for rdoc only. The alias_method below overrides it as an optimization. + def try(method, *args, &block) + send(method, *args, &block) + end + alias_method :try, :__send__ +end + +class NilClass + def try(*args) + nil + end +end diff --git a/activesupport/lib/active_support/json/encoders/date.rb b/activesupport/lib/active_support/json/encoders/date.rb index 1fc99c466f..cc84de1388 100644 --- a/activesupport/lib/active_support/json/encoders/date.rb +++ b/activesupport/lib/active_support/json/encoders/date.rb @@ -2,7 +2,7 @@ class Date # Returns a JSON string representing the date. If ActiveSupport.use_standard_json_time_format is set to true, the # ISO 8601 format is used. # - # ==== Examples: + # ==== Examples # # # With ActiveSupport.use_standard_json_time_format = true # Date.new(2005,2,1).to_json diff --git a/activesupport/lib/active_support/json/encoders/date_time.rb b/activesupport/lib/active_support/json/encoders/date_time.rb index e259930033..6c85824105 100644 --- a/activesupport/lib/active_support/json/encoders/date_time.rb +++ b/activesupport/lib/active_support/json/encoders/date_time.rb @@ -2,7 +2,7 @@ class DateTime # Returns a JSON string representing the datetime. If ActiveSupport.use_standard_json_time_format is set to true, the # ISO 8601 format is used. # - # ==== Examples: + # ==== Examples # # # With ActiveSupport.use_standard_json_time_format = true # DateTime.civil(2005,2,1,15,15,10).to_json diff --git a/activesupport/lib/active_support/json/encoders/hash.rb b/activesupport/lib/active_support/json/encoders/hash.rb index b9bdd55fa5..16dc8337f5 100644 --- a/activesupport/lib/active_support/json/encoders/hash.rb +++ b/activesupport/lib/active_support/json/encoders/hash.rb @@ -5,7 +5,7 @@ class Hash # the hash keys. For example: # # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json - # # => {"name": "Konata Izumi", 1: 2, "age": 16} + # # => {"name": "Konata Izumi", "1": 2, "age": 16} # # The keys in the JSON string are unordered due to the nature of hashes. # @@ -39,7 +39,7 @@ class Hash returning result = '{' do result << hash_keys.map do |key| - "#{ActiveSupport::JSON.encode(key)}: #{ActiveSupport::JSON.encode(self[key], options)}" + "#{ActiveSupport::JSON.encode(key.to_s)}: #{ActiveSupport::JSON.encode(self[key], options)}" end * ', ' result << '}' end diff --git a/activesupport/lib/active_support/json/encoders/time.rb b/activesupport/lib/active_support/json/encoders/time.rb index 09fc614889..f45a0059e8 100644 --- a/activesupport/lib/active_support/json/encoders/time.rb +++ b/activesupport/lib/active_support/json/encoders/time.rb @@ -2,7 +2,7 @@ class Time # Returns a JSON string representing the time. If ActiveSupport.use_standard_json_time_format is set to true, the # ISO 8601 format is used. # - # ==== Examples: + # ==== Examples # # # With ActiveSupport.use_standard_json_time_format = true # Time.utc(2005,2,1,15,15,10).to_json diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index 3def0be639..25ea505813 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -10,10 +10,14 @@ module ActiveSupport @keys = [] end + def initialize_copy(other) + super + # make a deep copy of keys + @keys = other.keys + end + def []=(key, value) - if !has_key?(key) - @keys << key - end + @keys << key if !has_key?(key) super end @@ -24,6 +28,12 @@ module ActiveSupport end super end + + def delete_if + super + sync_keys! + self + end def reject! super @@ -36,7 +46,7 @@ module ActiveSupport end def keys - @keys + @keys.dup end def values @@ -56,7 +66,7 @@ module ActiveSupport end def each - keys.each {|key| yield [key, self[key]]} + @keys.each {|key| yield [key, self[key]]} end alias_method :each_pair, :each @@ -73,13 +83,16 @@ module ActiveSupport [k, v] end + def merge!(other_hash) + other_hash.each {|k,v| self[k] = v } + self + end + def merge(other_hash) - result = dup - other_hash.each {|k,v| result[k]=v} - result + dup.merge!(other_hash) end - private + private def sync_keys! @keys.delete_if {|k| !has_key?(k)} diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 82b47b6c47..3a5a083629 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -111,7 +111,7 @@ module ActiveSupport # Returns a JSON string representing the TimeWithZone. If ActiveSupport.use_standard_json_time_format is set to # true, the ISO 8601 format is used. # - # ==== Examples: + # ==== Examples # # # With ActiveSupport.use_standard_json_time_format = true # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json |