diff options
Diffstat (limited to 'activesupport')
60 files changed, 1513 insertions, 342 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index cf41a20a5c..fed977775e 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,14 @@ *2.3.0 [Edge]* +* TimeWithZone#xmlschema accepts optional fraction_digits argument [#1725 state:resolved] [Nicholas Dainty] + +* Object#tap shim for Ruby < 1.8.7. Similar to Object#returning, tap yields self then returns self. [Jeremy Kemper] + array.select { ... }.tap(&:inspect).map { ... } + +* TimeWithZone#- gives correct result with wrapped DateTime, and with DateTime argument [Geoff Buesing] + +* Updated i18n gem to version 0.1.1 #1635 [Yaroslav Markin] + * Add :allow_nil option to delegate. #1127 [Sergio Gil] * Add Benchmark.ms convenience method to benchmark realtime in milliseconds. [Jeremy Kemper] diff --git a/activesupport/MIT-LICENSE b/activesupport/MIT-LICENSE index 2ba4e17035..d6fdf21596 100644 --- a/activesupport/MIT-LICENSE +++ b/activesupport/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2005-2008 David Heinemeier Hansson +Copyright (c) 2005-2009 David Heinemeier Hansson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index 445d8edf47..33bcf327f8 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -68,13 +68,13 @@ module ActiveSupport for severity in Severity.constants class_eval <<-EOT, __FILE__, __LINE__ - def #{severity.downcase}(message = nil, progname = nil, &block) - add(#{severity}, message, progname, &block) - end - - def #{severity.downcase}? - #{severity} >= @level - end + def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block) + add(#{severity}, message, progname, &block) # add(DEBUG, message, progname, &block) + end # end + # + def #{severity.downcase}? # def debug? + #{severity} >= @level # DEBUG >= @level + end # end EOT end 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/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 5cdcaf5ad1..86e66e0588 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -192,13 +192,8 @@ module ActiveSupport end def should_run_callback?(*args) - if options[:if] - evaluate_method(options[:if], *args) - elsif options[:unless] - !evaluate_method(options[:unless], *args) - else - true - end + [options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } && + ![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) } end end @@ -210,20 +205,24 @@ module ActiveSupport def define_callbacks(*callbacks) callbacks.each do |callback| class_eval <<-"end_eval" - def self.#{callback}(*methods, &block) - callbacks = CallbackChain.build(:#{callback}, *methods, &block) - (@#{callback}_callbacks ||= CallbackChain.new).concat callbacks - end - - def self.#{callback}_callback_chain - @#{callback}_callbacks ||= CallbackChain.new - - if superclass.respond_to?(:#{callback}_callback_chain) - CallbackChain.new(superclass.#{callback}_callback_chain + @#{callback}_callbacks) - else - @#{callback}_callbacks - end - end + def self.#{callback}(*methods, &block) # def self.before_save(*methods, &block) + callbacks = CallbackChain.build(:#{callback}, *methods, &block) # callbacks = CallbackChain.build(:before_save, *methods, &block) + @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new + @#{callback}_callbacks.concat callbacks # @before_save_callbacks.concat callbacks + end # end + # + def self.#{callback}_callback_chain # def self.before_save_callback_chain + @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new + # + if superclass.respond_to?(:#{callback}_callback_chain) # if superclass.respond_to?(:before_save_callback_chain) + CallbackChain.new( # CallbackChain.new( + superclass.#{callback}_callback_chain + # superclass.before_save_callback_chain + + @#{callback}_callbacks # @before_save_callbacks + ) # ) + else # else + @#{callback}_callbacks # @before_save_callbacks + end # end + end # end end_eval end end diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb index 186ca69c05..c795871474 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb @@ -11,17 +11,17 @@ class Class syms.flatten.each do |sym| next if sym.is_a?(Hash) class_eval(<<-EOS, __FILE__, __LINE__) - unless defined? @@#{sym} - @@#{sym} = nil - end - - def self.#{sym} - @@#{sym} - end - - def #{sym} - @@#{sym} - end + unless defined? @@#{sym} # unless defined? @@hair_colors + @@#{sym} = nil # @@hair_colors = nil + end # end + # + def self.#{sym} # def self.hair_colors + @@#{sym} # @@hair_colors + end # end + # + def #{sym} # def hair_colors + @@#{sym} # @@hair_colors + end # end EOS end end @@ -30,19 +30,19 @@ class Class options = syms.extract_options! syms.flatten.each do |sym| class_eval(<<-EOS, __FILE__, __LINE__) - unless defined? @@#{sym} - @@#{sym} = nil - end - - def self.#{sym}=(obj) - @@#{sym} = obj - end - - #{" - def #{sym}=(obj) - @@#{sym} = obj - end - " unless options[:instance_writer] == false } + unless defined? @@#{sym} # unless defined? @@hair_colors + @@#{sym} = nil # @@hair_colors = nil + end # end + # + def self.#{sym}=(obj) # def self.hair_colors=(obj) + @@#{sym} = obj # @@hair_colors = obj + end # end + # + #{" # + def #{sym}=(obj) # def hair_colors=(obj) + @@#{sym} = obj # @@hair_colors = obj + end # end + " unless options[:instance_writer] == false } # # instance writer above is generated unless options[:instance_writer] == false EOS end end diff --git a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb index 368317df9b..000ccf4d55 100644 --- a/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/delegating_attributes.rb @@ -9,22 +9,23 @@ class Class class_name_to_stop_searching_on = self.superclass.name.blank? ? "Object" : self.superclass.name names.each do |name| class_eval <<-EOS - def self.#{name} - if defined?(@#{name}) - @#{name} - elsif superclass < #{class_name_to_stop_searching_on} && superclass.respond_to?(:#{name}) - superclass.#{name} - end - end - def #{name} - self.class.#{name} - end - def self.#{name}? - !!#{name} - end - def #{name}? - !!#{name} - end + def self.#{name} # def self.only_reader + if defined?(@#{name}) # if defined?(@only_reader) + @#{name} # @only_reader + elsif superclass < #{class_name_to_stop_searching_on} && # elsif superclass < Object && + superclass.respond_to?(:#{name}) # superclass.respond_to?(:only_reader) + superclass.#{name} # superclass.only_reader + end # end + end # end + def #{name} # def only_reader + self.class.#{name} # self.class.only_reader + end # end + def self.#{name}? # def self.only_reader? + !!#{name} # !!only_reader + end # end + def #{name}? # def only_reader? + !!#{name} # !!only_reader + end # end EOS end end @@ -32,9 +33,9 @@ class Class def superclass_delegating_writer(*names) names.each do |name| class_eval <<-EOS - def self.#{name}=(value) - @#{name} = value - end + def self.#{name}=(value) # def self.only_writer=(value) + @#{name} = value # @only_writer = value + end # end EOS end end diff --git a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb index e6143a274b..1794afe77c 100644 --- a/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb +++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb @@ -11,13 +11,13 @@ class Class # :nodoc: syms.each do |sym| next if sym.is_a?(Hash) class_eval <<-EOS - def self.#{sym} - read_inheritable_attribute(:#{sym}) - end - - def #{sym} - self.class.#{sym} - end + def self.#{sym} # def self.before_add_for_comments + read_inheritable_attribute(:#{sym}) # read_inheritable_attribute(:before_add_for_comments) + end # end + # + def #{sym} # def before_add_for_comments + self.class.#{sym} # self.class.before_add_for_comments + end # end EOS end end @@ -26,15 +26,15 @@ class Class # :nodoc: options = syms.extract_options! syms.each do |sym| class_eval <<-EOS - def self.#{sym}=(obj) - write_inheritable_attribute(:#{sym}, obj) - end - - #{" - def #{sym}=(obj) - self.class.#{sym} = obj - end - " unless options[:instance_writer] == false } + def self.#{sym}=(obj) # def self.color=(obj) + write_inheritable_attribute(:#{sym}, obj) # write_inheritable_attribute(:color, obj) + end # end + # + #{" # + def #{sym}=(obj) # def color=(obj) + self.class.#{sym} = obj # self.class.color = obj + end # end + " unless options[:instance_writer] == false } # # the writer above is generated unless options[:instance_writer] == false EOS end end @@ -43,15 +43,15 @@ class Class # :nodoc: options = syms.extract_options! syms.each do |sym| class_eval <<-EOS - def self.#{sym}=(obj) - write_inheritable_array(:#{sym}, obj) - end - - #{" - def #{sym}=(obj) - self.class.#{sym} = obj - end - " unless options[:instance_writer] == false } + def self.#{sym}=(obj) # def self.levels=(obj) + write_inheritable_array(:#{sym}, obj) # write_inheritable_array(:levels, obj) + end # end + # + #{" # + def #{sym}=(obj) # def levels=(obj) + self.class.#{sym} = obj # self.class.levels = obj + end # end + " unless options[:instance_writer] == false } # # the writer above is generated unless options[:instance_writer] == false EOS end end @@ -60,15 +60,15 @@ class Class # :nodoc: options = syms.extract_options! syms.each do |sym| class_eval <<-EOS - def self.#{sym}=(obj) - write_inheritable_hash(:#{sym}, obj) - end - - #{" - def #{sym}=(obj) - self.class.#{sym} = obj - end - " unless options[:instance_writer] == false } + def self.#{sym}=(obj) # def self.nicknames=(obj) + write_inheritable_hash(:#{sym}, obj) # write_inheritable_hash(:nicknames, obj) + end # end + # + #{" # + def #{sym}=(obj) # def nicknames=(obj) + self.class.#{sym} = obj # self.class.nicknames = obj + end # end + " unless options[:instance_writer] == false } # # the writer above is generated unless options[:instance_writer] == false EOS 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/hash/slice.rb b/activesupport/lib/active_support/core_ext/hash/slice.rb index 88df49a69f..d845a6d8ca 100644 --- a/activesupport/lib/active_support/core_ext/hash/slice.rb +++ b/activesupport/lib/active_support/core_ext/hash/slice.rb @@ -24,10 +24,17 @@ module ActiveSupport #:nodoc: end # Replaces the hash with only the given keys. + # Returns a hash contained the removed key/value pairs + # {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d =>4} def slice!(*keys) - replace(slice(*keys)) + keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key) + omit = slice(*self.keys - keys) + hash = slice(*keys) + replace(hash) + omit end end end end end + diff --git a/activesupport/lib/active_support/core_ext/logger.rb b/activesupport/lib/active_support/core_ext/logger.rb index 24fe7294c9..858da7aa07 100644 --- a/activesupport/lib/active_support/core_ext/logger.rb +++ b/activesupport/lib/active_support/core_ext/logger.rb @@ -3,12 +3,12 @@ class Logger def self.define_around_helper(level) module_eval <<-end_eval - def around_#{level}(before_message, after_message, &block) - self.#{level}(before_message) - return_value = block.call(self) - self.#{level}(after_message) - return return_value - end + def around_#{level}(before_message, after_message, &block) # def around_debug(before_message, after_message, &block) + self.#{level}(before_message) # self.debug(before_message) + return_value = block.call(self) # return_value = block.call(self) + self.#{level}(after_message) # self.debug(after_message) + return return_value # return return_value + end # end end_eval end [:debug, :info, :error, :fatal].each {|level| define_around_helper(level) } diff --git a/activesupport/lib/active_support/core_ext/module/aliasing.rb b/activesupport/lib/active_support/core_ext/module/aliasing.rb index e640f64520..10fa520ba1 100644 --- a/activesupport/lib/active_support/core_ext/module/aliasing.rb +++ b/activesupport/lib/active_support/core_ext/module/aliasing.rb @@ -64,9 +64,9 @@ module ActiveSupport # e.title # => "Megastars" def alias_attribute(new_name, old_name) module_eval <<-STR, __FILE__, __LINE__+1 - def #{new_name}; self.#{old_name}; end - def #{new_name}?; self.#{old_name}?; end - def #{new_name}=(v); self.#{old_name} = v; end + def #{new_name}; self.#{old_name}; end # def subject; self.title; end + def #{new_name}?; self.#{old_name}?; end # def subject?; self.title?; end + def #{new_name}=(v); self.#{old_name} = v; end # def subject=(v); self.title = v; end STR end end diff --git a/activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb b/activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb index 683789d853..4d0198f028 100644 --- a/activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb +++ b/activesupport/lib/active_support/core_ext/module/attr_accessor_with_default.rb @@ -22,10 +22,10 @@ class Module raise 'Default value or block required' unless !default.nil? || block define_method(sym, block_given? ? block : Proc.new { default }) module_eval(<<-EVAL, __FILE__, __LINE__) - def #{sym}=(value) - class << self; attr_reader :#{sym} end - @#{sym} = value - end + def #{sym}=(value) # def age=(value) + class << self; attr_reader :#{sym} end # class << self; attr_reader :age end + @#{sym} = value # @age = value + end # end EVAL end end diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb index 51e1c9af90..9402cb8534 100644 --- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb @@ -15,17 +15,17 @@ class Module syms.each do |sym| next if sym.is_a?(Hash) class_eval(<<-EOS, __FILE__, __LINE__) - unless defined? @@#{sym} - @@#{sym} = nil - end - - def self.#{sym} - @@#{sym} - end - - def #{sym} - @@#{sym} - end + unless defined? @@#{sym} # unless defined? @@pagination_options + @@#{sym} = nil # @@pagination_options = nil + end # end + # + def self.#{sym} # def self.pagination_options + @@#{sym} # @@pagination_options + end # end + # + def #{sym} # def pagination_options + @@#{sym} # @@pagination_options + end # end EOS end end @@ -34,19 +34,19 @@ class Module options = syms.extract_options! syms.each do |sym| class_eval(<<-EOS, __FILE__, __LINE__) - unless defined? @@#{sym} - @@#{sym} = nil - end - - def self.#{sym}=(obj) - @@#{sym} = obj - end - - #{" - def #{sym}=(obj) - @@#{sym} = obj - end - " unless options[:instance_writer] == false } + unless defined? @@#{sym} # unless defined? @@pagination_options + @@#{sym} = nil # @@pagination_options = nil + end # end + # + def self.#{sym}=(obj) # def self.pagination_options=(obj) + @@#{sym} = obj # @@pagination_options = obj + end # end + # + #{" # + def #{sym}=(obj) # def pagination_options=(obj) + @@#{sym} = obj # @@pagination_options = obj + end # end + " unless options[:instance_writer] == false } # # instance writer above is generated unless options[:instance_writer] == false EOS end end diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 5c75bd4938..fb4b5f0f3c 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -112,9 +112,9 @@ class Module methods.each do |method| module_eval(<<-EOS, "(__DELEGATION__)", 1) - def #{prefix}#{method}(*args, &block) - #{allow_nil}#{to}.__send__(#{method.inspect}, *args, &block) - end + def #{prefix}#{method}(*args, &block) # def customer_name(*args, &block) + #{allow_nil}#{to}.__send__(#{method.inspect}, *args, &block) # client && client.__send__(:name, *args, &block) + end # end EOS end end diff --git a/activesupport/lib/active_support/core_ext/module/synchronization.rb b/activesupport/lib/active_support/core_ext/module/synchronization.rb index 251606024e..069db3fed0 100644 --- a/activesupport/lib/active_support/core_ext/module/synchronization.rb +++ b/activesupport/lib/active_support/core_ext/module/synchronization.rb @@ -26,11 +26,11 @@ class Module end module_eval(<<-EOS, __FILE__, __LINE__) - def #{aliased_method}_with_synchronization#{punctuation}(*args, &block) - #{with}.synchronize do - #{aliased_method}_without_synchronization#{punctuation}(*args, &block) - end - end + def #{aliased_method}_with_synchronization#{punctuation}(*args, &block) # def expire_with_synchronization(*args, &block) + #{with}.synchronize do # @@lock.synchronize do + #{aliased_method}_without_synchronization#{punctuation}(*args, &block) # expire_without_synchronization(*args, &block) + end # end + end # end EOS alias_method_chain method, :synchronization diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb index 46f9c7d676..4acdfa3d6c 100644 --- a/activesupport/lib/active_support/core_ext/object/misc.rb +++ b/activesupport/lib/active_support/core_ext/object/misc.rb @@ -40,6 +40,21 @@ class Object value end + # Yields <code>x</code> to the block, and then returns <code>x</code>. + # The primary purpose of this method is to "tap into" a method chain, + # in order to perform operations on intermediate results within the chain. + # + # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a. + # tap { |x| puts "array: #{x.inspect}" }. + # select { |x| x%2 == 0 }. + # tap { |x| puts "evens: #{x.inspect}" }. + # map { |x| x*x }. + # tap { |x| puts "squares: #{x.inspect}" } + def tap + yield self + self + end unless Object.respond_to?(:tap) + # An elegant way to factor duplication out of options passed to a series of # method calls. Each method called in the block, with the block variable as # the receiver, will have its options merged with the default +options+ hash @@ -72,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) if respond_to?(method, true) - 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/deprecation.rb b/activesupport/lib/active_support/deprecation.rb index 25b26e9c96..d20151661b 100644 --- a/activesupport/lib/active_support/deprecation.rb +++ b/activesupport/lib/active_support/deprecation.rb @@ -90,10 +90,15 @@ module ActiveSupport method_names.each do |method_name| alias_method_chain(method_name, :deprecation) do |target, punctuation| class_eval(<<-EOS, __FILE__, __LINE__) - def #{target}_with_deprecation#{punctuation}(*args, &block) - ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:#{method_name}, #{options[method_name].inspect}), caller) - #{target}_without_deprecation#{punctuation}(*args, &block) - end + def #{target}_with_deprecation#{punctuation}(*args, &block) # def generate_secret_with_deprecation(*args, &block) + ::ActiveSupport::Deprecation.warn( # ::ActiveSupport::Deprecation.warn( + self.class.deprecated_method_warning( # self.class.deprecated_method_warning( + :#{method_name}, # :generate_secret, + #{options[method_name].inspect}), # "You should use ActiveSupport::SecureRandom.hex(64)"), + caller # caller + ) # ) + #{target}_without_deprecation#{punctuation}(*args, &block) # generate_secret_without_deprecation(*args, &block) + end # end EOS end end diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb index fdb219dbf7..9da4048272 100644 --- a/activesupport/lib/active_support/json/decoding.rb +++ b/activesupport/lib/active_support/json/decoding.rb @@ -16,7 +16,7 @@ module ActiveSupport protected # matches YAML-formatted dates - DATE_REGEX = /^\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?$/ + DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[ \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)$/ # Ensure that ":" and "," are always followed by a space def convert_json_to_yaml(json) #:nodoc: 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/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index 9f2fd3a401..952b4d8063 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -59,34 +59,36 @@ module ActiveSupport memoized_ivar = ActiveSupport::Memoizable.memoized_ivar_for(symbol) class_eval <<-EOS, __FILE__, __LINE__ - include InstanceMethods - - raise "Already memoized #{symbol}" if method_defined?(:#{original_method}) - alias #{original_method} #{symbol} - - if instance_method(:#{symbol}).arity == 0 - def #{symbol}(reload = false) - if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? - #{memoized_ivar} = [#{original_method}.freeze] - end - #{memoized_ivar}[0] - end - else - def #{symbol}(*args) - #{memoized_ivar} ||= {} unless frozen? - reload = args.pop if args.last == true || args.last == :reload - - if defined?(#{memoized_ivar}) && #{memoized_ivar} - if !reload && #{memoized_ivar}.has_key?(args) - #{memoized_ivar}[args] - elsif #{memoized_ivar} - #{memoized_ivar}[args] = #{original_method}(*args).freeze - end - else - #{original_method}(*args) - end - end - end + include InstanceMethods # include InstanceMethods + # + if method_defined?(:#{original_method}) # if method_defined?(:_unmemoized_mime_type) + raise "Already memoized #{symbol}" # raise "Already memoized mime_type" + end # end + alias #{original_method} #{symbol} # alias _unmemoized_mime_type mime_type + # + if instance_method(:#{symbol}).arity == 0 # if instance_method(:mime_type).arity == 0 + def #{symbol}(reload = false) # def mime_type(reload = false) + if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? # if reload || !defined?(@_memoized_mime_type) || @_memoized_mime_type.empty? + #{memoized_ivar} = [#{original_method}.freeze] # @_memoized_mime_type = [_unmemoized_mime_type.freeze] + end # end + #{memoized_ivar}[0] # @_memoized_mime_type[0] + end # end + else # else + def #{symbol}(*args) # def mime_type(*args) + #{memoized_ivar} ||= {} unless frozen? # @_memoized_mime_type ||= {} unless frozen? + reload = args.pop if args.last == true || args.last == :reload # reload = args.pop if args.last == true || args.last == :reload + # + if defined?(#{memoized_ivar}) && #{memoized_ivar} # if defined?(@_memoized_mime_type) && @_memoized_mime_type + if !reload && #{memoized_ivar}.has_key?(args) # if !reload && @_memoized_mime_type.has_key?(args) + #{memoized_ivar}[args] # @_memoized_mime_type[args] + elsif #{memoized_ivar} # elsif @_memoized_mime_type + #{memoized_ivar}[args] = #{original_method}(*args).freeze # @_memoized_mime_type[args] = _unmemoized_mime_type(*args).freeze + end # end + else # else + #{original_method}(*args) # _unmemoized_mime_type(*args) + end # end + end # end + end # end EOS end end diff --git a/activesupport/lib/active_support/multibyte/unicode_database.rb b/activesupport/lib/active_support/multibyte/unicode_database.rb index 3b8cf8f9eb..a08f38cdbb 100644 --- a/activesupport/lib/active_support/multibyte/unicode_database.rb +++ b/activesupport/lib/active_support/multibyte/unicode_database.rb @@ -24,10 +24,10 @@ module ActiveSupport #:nodoc: # Lazy load the Unicode database so it's only loaded when it's actually used ATTRIBUTES.each do |attr_name| class_eval(<<-EOS, __FILE__, __LINE__) - def #{attr_name} - load - @#{attr_name} - end + def #{attr_name} # def codepoints + load # load + @#{attr_name} # @codepoints + end # end EOS end 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/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index bd136c2596..f8d12e82b3 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -12,7 +12,7 @@ module ActiveSupport if benchmark = ARGV.include?('--benchmark') # HAX for rake test { :benchmark => true, :runs => 4, - :metrics => [:process_time, :memory, :objects, :gc_runs, :gc_time], + :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time], :output => 'tmp/performance' } else { :benchmark => false, diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 9a2d283b30..1a59b2a08d 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -99,15 +99,19 @@ module ActiveSupport "#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}" end - def xmlschema - "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{formatted_offset(true, 'Z')}" + def xmlschema(fraction_digits = 0) + fraction = if fraction_digits > 0 + ".%i" % time.usec.to_s[0, fraction_digits] + end + + "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{fraction}#{formatted_offset(true, 'Z')}" end alias_method :iso8601, :xmlschema # 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 @@ -199,7 +203,7 @@ module ActiveSupport # If we're subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time, # otherwise move backwards #utc, for accuracy when moving across DST boundaries if other.acts_like?(:time) - utc - other + utc.to_f - other.to_f elsif duration_of_variable_length?(other) method_missing(:-, other) else @@ -234,9 +238,9 @@ module ActiveSupport %w(year mon month day mday wday yday hour min sec to_date).each do |method_name| class_eval <<-EOV - def #{method_name} - time.#{method_name} - end + def #{method_name} # def year + time.#{method_name} # time.year + end # end EOV end diff --git a/activesupport/lib/active_support/vendor.rb b/activesupport/lib/active_support/vendor.rb index 4525bba559..3d7d52ca71 100644 --- a/activesupport/lib/active_support/vendor.rb +++ b/activesupport/lib/active_support/vendor.rb @@ -22,8 +22,8 @@ end # TODO I18n gem has not been released yet # begin -# gem 'i18n', '~> 0.0.1' +# gem 'i18n', '~> 0.1.1' # rescue Gem::LoadError - $:.unshift "#{File.dirname(__FILE__)}/vendor/i18n-0.0.1" + $:.unshift "#{File.dirname(__FILE__)}/vendor/i18n-0.1.1/lib" require 'i18n' # end diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/.gitignore b/activesupport/lib/active_support/vendor/i18n-0.1.1/.gitignore new file mode 100644 index 0000000000..0f41a39f89 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +test/rails/fixtures +doc diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/MIT-LICENSE b/activesupport/lib/active_support/vendor/i18n-0.1.1/MIT-LICENSE new file mode 100755 index 0000000000..ed8e9ee66d --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008 The Ruby I18n team + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/README.textile b/activesupport/lib/active_support/vendor/i18n-0.1.1/README.textile new file mode 100644 index 0000000000..a07fc8426d --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/README.textile @@ -0,0 +1,20 @@ +h1. Ruby I18n gem + +I18n and localization solution for Ruby. + +For information please refer to http://rails-i18n.org + +h2. Authors + +* "Matt Aimonetti":http://railsontherun.com +* "Sven Fuchs":http://www.artweb-design.de +* "Joshua Harvey":http://www.workingwithrails.com/person/759-joshua-harvey +* "Saimon Moore":http://saimonmoore.net +* "Stephan Soller":http://www.arkanis-development.de + +h2. License + +MIT License. See the included MIT-LICENCE file. + + + diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/Rakefile b/activesupport/lib/active_support/vendor/i18n-0.1.1/Rakefile new file mode 100644 index 0000000000..2164e13e69 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/Rakefile @@ -0,0 +1,5 @@ +task :default => [:test] + +task :test do + ruby "test/all.rb" +end diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/i18n.gemspec b/activesupport/lib/active_support/vendor/i18n-0.1.1/i18n.gemspec new file mode 100644 index 0000000000..14294606bd --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/i18n.gemspec @@ -0,0 +1,27 @@ +Gem::Specification.new do |s| + s.name = "i18n" + s.version = "0.1.1" + s.date = "2008-10-26" + s.summary = "Internationalization support for Ruby" + s.email = "rails-i18n@googlegroups.com" + s.homepage = "http://rails-i18n.org" + s.description = "Add Internationalization support to your Ruby application." + s.has_rdoc = false + s.authors = ['Sven Fuchs', 'Joshua Harvey', 'Matt Aimonetti', 'Stephan Soller', 'Saimon Moore'] + s.files = [ + 'i18n.gemspec', + 'lib/i18n/backend/simple.rb', + 'lib/i18n/exceptions.rb', + 'lib/i18n.rb', + 'MIT-LICENSE', + 'README.textile' + ] + s.test_files = [ + 'test/all.rb', + 'test/i18n_exceptions_test.rb', + 'test/i18n_test.rb', + 'test/locale/en.rb', + 'test/locale/en.yml', + 'test/simple_backend_test.rb' + ] +end diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n.rb index 2ffe3618b5..b5ad094d0e 100755 --- a/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n.rb +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n.rb @@ -2,39 +2,39 @@ # Sven Fuchs (http://www.artweb-design.de), # Joshua Harvey (http://www.workingwithrails.com/person/759-joshua-harvey), # Saimon Moore (http://saimonmoore.net), -# Stephan Soller (http://www.arkanis-development.de/) +# Stephan Soller (http://www.arkanis-development.de/) # Copyright:: Copyright (c) 2008 The Ruby i18n Team # License:: MIT require 'i18n/backend/simple' require 'i18n/exceptions' -module I18n +module I18n @@backend = nil @@load_path = nil @@default_locale = :'en' @@exception_handler = :default_exception_handler - + class << self # Returns the current backend. Defaults to +Backend::Simple+. def backend @@backend ||= Backend::Simple.new end - + # Sets the current backend. Used to set a custom backend. - def backend=(backend) + def backend=(backend) @@backend = backend end - - # Returns the current default locale. Defaults to 'en' + + # Returns the current default locale. Defaults to :'en' def default_locale - @@default_locale + @@default_locale end - + # Sets the current default locale. Used to set a custom default locale. - def default_locale=(locale) - @@default_locale = locale + def default_locale=(locale) + @@default_locale = locale end - + # Returns the current locale. Defaults to I18n.default_locale. def locale Thread.current[:locale] ||= default_locale @@ -44,12 +44,12 @@ module I18n def locale=(locale) Thread.current[:locale] = locale end - + # Sets the exception handler. def exception_handler=(exception_handler) @@exception_handler = exception_handler end - + # Allow clients to register paths providing translation data sources. The # backend defines acceptable sources. # @@ -74,25 +74,25 @@ module I18n def reload! backend.reload! end - - # Translates, pluralizes and interpolates a given key using a given locale, + + # Translates, pluralizes and interpolates a given key using a given locale, # scope, and default, as well as interpolation values. # # *LOOKUP* # - # Translation data is organized as a nested hash using the upper-level keys - # as namespaces. <em>E.g.</em>, ActionView ships with the translation: + # Translation data is organized as a nested hash using the upper-level keys + # as namespaces. <em>E.g.</em>, ActionView ships with the translation: # <tt>:date => {:formats => {:short => "%b %d"}}</tt>. - # - # Translations can be looked up at any level of this hash using the key argument - # and the scope option. <em>E.g.</em>, in this example <tt>I18n.t :date</tt> + # + # Translations can be looked up at any level of this hash using the key argument + # and the scope option. <em>E.g.</em>, in this example <tt>I18n.t :date</tt> # returns the whole translations hash <tt>{:formats => {:short => "%b %d"}}</tt>. - # - # Key can be either a single key or a dot-separated key (both Strings and Symbols + # + # Key can be either a single key or a dot-separated key (both Strings and Symbols # work). <em>E.g.</em>, the short format can be looked up using both: # I18n.t 'date.formats.short' # I18n.t :'date.formats.short' - # + # # Scope can be either a single key, a dot-separated key or an array of keys # or dot-separated keys. Keys and scopes can be combined freely. So these # examples will all look up the same short date format: @@ -105,9 +105,9 @@ module I18n # # Translations can contain interpolation variables which will be replaced by # values passed to #translate as part of the options hash, with the keys matching - # the interpolation variable names. + # the interpolation variable names. # - # <em>E.g.</em>, with a translation <tt>:foo => "foo {{bar}}"</tt> the option + # <em>E.g.</em>, with a translation <tt>:foo => "foo {{bar}}"</tt> the option # value for the key +bar+ will be interpolated into the translation: # I18n.t :foo, :bar => 'baz' # => 'foo baz' # @@ -116,7 +116,7 @@ module I18n # Translation data can contain pluralized translations. Pluralized translations # are arrays of singluar/plural versions of translations like <tt>['Foo', 'Foos']</tt>. # - # Note that <tt>I18n::Backend::Simple</tt> only supports an algorithm for English + # Note that <tt>I18n::Backend::Simple</tt> only supports an algorithm for English # pluralization rules. Other algorithms can be supported by custom backends. # # This returns the singular version of a pluralized translation: @@ -125,9 +125,9 @@ module I18n # These both return the plural version of a pluralized translation: # I18n.t :foo, :count => 0 # => 'Foos' # I18n.t :foo, :count => 2 # => 'Foos' - # - # The <tt>:count</tt> option can be used both for pluralization and interpolation. - # <em>E.g.</em>, with the translation + # + # The <tt>:count</tt> option can be used both for pluralization and interpolation. + # <em>E.g.</em>, with the translation # <tt>:foo => ['{{count}} foo', '{{count}} foos']</tt>, count will # be interpolated to the pluralized translation: # I18n.t :foo, :count => 1 # => '1 foo' @@ -137,11 +137,11 @@ module I18n # This returns the translation for <tt>:foo</tt> or <tt>default</tt> if no translation was found: # I18n.t :foo, :default => 'default' # - # This returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt> if no + # This returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt> if no # translation for <tt>:foo</tt> was found: # I18n.t :foo, :default => :bar # - # Returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt> + # Returns the translation for <tt>:foo</tt> or the translation for <tt>:bar</tt> # or <tt>default</tt> if no translations for <tt>:foo</tt> and <tt>:bar</tt> were found. # I18n.t :foo, :default => [:bar, 'default'] # @@ -161,9 +161,9 @@ module I18n rescue I18n::ArgumentError => e raise e if options[:raise] send(@@exception_handler, e, locale, key, options) - end + end alias :t :translate - + # Localizes certain objects, such as dates and numbers to local formatting. def localize(object, options = {}) locale = options[:locale] || I18n.locale @@ -171,7 +171,7 @@ module I18n backend.localize(locale, object, format) end alias :l :localize - + protected # Handles exceptions raised in the backend. All exceptions except for # MissingTranslationData exceptions are re-raised. When a MissingTranslationData @@ -181,7 +181,7 @@ module I18n return exception.message if MissingTranslationData === exception raise exception end - + # Merges the given locale, key and scope into a single array of keys. # Splits keys that contain dots into multiple keys. Makes sure all # keys are Symbols. @@ -191,4 +191,4 @@ module I18n keys.flatten.map { |k| k.to_sym } end end -end
\ No newline at end of file +end diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/backend/simple.rb index bdda55d3fe..d298b3a85a 100644 --- a/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/backend/simple.rb @@ -6,21 +6,21 @@ module I18n INTERPOLATION_RESERVED_KEYS = %w(scope default) MATCH = /(\\\\)?\{\{([^\}]+)\}\}/ - # Accepts a list of paths to translation files. Loads translations from + # Accepts a list of paths to translation files. Loads translations from # plain Ruby (*.rb) or YAML files (*.yml). See #load_rb and #load_yml # for details. def load_translations(*filenames) filenames.each { |filename| load_file(filename) } end - - # Stores translations for the given locale in memory. + + # Stores translations for the given locale in memory. # This uses a deep merge for the translations hash, so existing # translations will be overwritten by new ones only at the deepest # level of the hash. def store_translations(locale, data) merge_translations(locale, data) end - + def translate(locale, key, options = {}) raise InvalidLocale.new(locale) if locale.nil? return key.map { |k| translate(locale, k, options) } if key.is_a? Array @@ -41,13 +41,13 @@ module I18n entry = interpolate(locale, entry, values) entry end - - # Acts the same as +strftime+, but returns a localized version of the - # formatted date string. Takes a key from the date/time formats - # translations as a format argument (<em>e.g.</em>, <tt>:short</tt> in <tt>:'date.formats'</tt>). + + # Acts the same as +strftime+, but returns a localized version of the + # formatted date string. Takes a key from the date/time formats + # translations as a format argument (<em>e.g.</em>, <tt>:short</tt> in <tt>:'date.formats'</tt>). def localize(locale, object, format = :default) raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime) - + type = object.respond_to?(:sec) ? 'time' : 'date' # TODO only translate these if format is a String? formats = translate(locale, :"#{type}.formats") @@ -57,14 +57,14 @@ module I18n # TODO only translate these if the format string is actually present # TODO check which format strings are present, then bulk translate then, then replace them - format.gsub!(/%a/, translate(locale, :"date.abbr_day_names")[object.wday]) + format.gsub!(/%a/, translate(locale, :"date.abbr_day_names")[object.wday]) format.gsub!(/%A/, translate(locale, :"date.day_names")[object.wday]) format.gsub!(/%b/, translate(locale, :"date.abbr_month_names")[object.mon]) format.gsub!(/%B/, translate(locale, :"date.month_names")[object.mon]) format.gsub!(/%p/, translate(locale, :"time.#{object.hour < 12 ? :am : :pm}")) if object.respond_to? :hour object.strftime(format) end - + def initialized? @initialized ||= false end @@ -79,12 +79,12 @@ module I18n load_translations(*I18n.load_path) @initialized = true end - + def translations @translations ||= {} end - - # Looks up a translation from the translations hash. Returns nil if + + # Looks up a translation from the translations hash. Returns nil if # eiher key is nil, or locale, scope or key do not exist as a key in the # nested translations hash. Splits keys or scopes containing dots # into multiple keys, i.e. <tt>currency.format</tt> is regarded the same as @@ -101,19 +101,19 @@ module I18n end end end - - # Evaluates a default translation. + + # Evaluates a default translation. # If the given default is a String it is used literally. If it is a Symbol # it will be translated with the given options. If it is an Array the first # translation yielded will be returned. - # - # <em>I.e.</em>, <tt>default(locale, [:foo, 'default'])</tt> will return +default+ if + # + # <em>I.e.</em>, <tt>default(locale, [:foo, 'default'])</tt> will return +default+ if # <tt>translate(locale, :foo)</tt> does not yield a result. def default(locale, default, options = {}) case default when String then default when Symbol then translate locale, default, options - when Array then default.each do |obj| + when Array then default.each do |obj| result = default(locale, obj, options.dup) and return result end and nil end @@ -135,10 +135,10 @@ module I18n end # Interpolates values into a given string. - # - # interpolate "file {{file}} opened by \\{{user}}", :file => 'test.txt', :user => 'Mr. X' + # + # interpolate "file {{file}} opened by \\{{user}}", :file => 'test.txt', :user => 'Mr. X' # # => "file test.txt opened by {{user}}" - # + # # Note that you have to double escape the <tt>\\</tt> when you want to escape # the <tt>{{...}}</tt> key in a string (once for the string and once for the # interpolation). @@ -167,8 +167,8 @@ module I18n result.force_encoding(original_encoding) if original_encoding result end - - # Loads a single translations file by delegating to #load_rb or + + # Loads a single translations file by delegating to #load_rb or # #load_yml depending on the file extension and directly merges the # data to the existing translations. Raises I18n::UnknownFileType # for all other file extensions. @@ -178,19 +178,19 @@ module I18n data = send :"load_#{type}", filename # TODO raise a meaningful exception if this does not yield a Hash data.each { |locale, d| merge_translations(locale, d) } end - + # Loads a plain Ruby translations file. eval'ing the file must yield # a Hash containing translation data with locales as toplevel keys. def load_rb(filename) eval(IO.read(filename), binding, filename) end - - # Loads a YAML translations file. The data must have locales as + + # Loads a YAML translations file. The data must have locales as # toplevel keys. def load_yml(filename) YAML::load(IO.read(filename)) end - + # Deep merges the given translations hash with the existing translations # for the given locale def merge_translations(locale, data) @@ -202,7 +202,7 @@ module I18n merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 } translations[locale].merge!(data, &merger) end - + # Return a new hash with all keys and nested keys converted to symbols. def deep_symbolize_keys(hash) hash.inject({}) { |result, (key, value)| diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/exceptions.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/exceptions.rb index 0f3eff1071..b5cea7acb4 100644 --- a/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/exceptions.rb +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/exceptions.rb @@ -1,6 +1,6 @@ module I18n class ArgumentError < ::ArgumentError; end - + class InvalidLocale < ArgumentError attr_reader :locale def initialize(locale) @@ -42,7 +42,7 @@ module I18n super "reserved key #{key.inspect} used in #{string.inspect}" end end - + class UnknownFileType < ArgumentError attr_reader :type, :filename def initialize(type, filename) @@ -50,4 +50,4 @@ module I18n super "can not load translations from #{filename}, the file type #{type} is not known" end end -end
\ No newline at end of file +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/all.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/all.rb new file mode 100644 index 0000000000..353712da49 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/all.rb @@ -0,0 +1,5 @@ +dir = File.dirname(__FILE__) +require dir + '/i18n_test.rb' +require dir + '/simple_backend_test.rb' +require dir + '/i18n_exceptions_test.rb' +# *require* dir + '/custom_backend_test.rb'
\ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_exceptions_test.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_exceptions_test.rb new file mode 100644 index 0000000000..dfcba6901f --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_exceptions_test.rb @@ -0,0 +1,100 @@ +$:.unshift "lib" + +require 'rubygems' +require 'test/unit' +require 'mocha' +require 'i18n' +require 'active_support' + +class I18nExceptionsTest < Test::Unit::TestCase + def test_invalid_locale_stores_locale + force_invalid_locale + rescue I18n::ArgumentError => e + assert_nil e.locale + end + + def test_invalid_locale_message + force_invalid_locale + rescue I18n::ArgumentError => e + assert_equal 'nil is not a valid locale', e.message + end + + def test_missing_translation_data_stores_locale_key_and_options + force_missing_translation_data + rescue I18n::ArgumentError => e + options = {:scope => :bar} + assert_equal 'de', e.locale + assert_equal :foo, e.key + assert_equal options, e.options + end + + def test_missing_translation_data_message + force_missing_translation_data + rescue I18n::ArgumentError => e + assert_equal 'translation missing: de, bar, foo', e.message + end + + def test_invalid_pluralization_data_stores_entry_and_count + force_invalid_pluralization_data + rescue I18n::ArgumentError => e + assert_equal [:bar], e.entry + assert_equal 1, e.count + end + + def test_invalid_pluralization_data_message + force_invalid_pluralization_data + rescue I18n::ArgumentError => e + assert_equal 'translation data [:bar] can not be used with :count => 1', e.message + end + + def test_missing_interpolation_argument_stores_key_and_string + force_missing_interpolation_argument + rescue I18n::ArgumentError => e + assert_equal 'bar', e.key + assert_equal "{{bar}}", e.string + end + + def test_missing_interpolation_argument_message + force_missing_interpolation_argument + rescue I18n::ArgumentError => e + assert_equal 'interpolation argument bar missing in "{{bar}}"', e.message + end + + def test_reserved_interpolation_key_stores_key_and_string + force_reserved_interpolation_key + rescue I18n::ArgumentError => e + assert_equal 'scope', e.key + assert_equal "{{scope}}", e.string + end + + def test_reserved_interpolation_key_message + force_reserved_interpolation_key + rescue I18n::ArgumentError => e + assert_equal 'reserved key "scope" used in "{{scope}}"', e.message + end + + private + def force_invalid_locale + I18n.backend.translate nil, :foo + end + + def force_missing_translation_data + I18n.backend.store_translations 'de', :bar => nil + I18n.backend.translate 'de', :foo, :scope => :bar + end + + def force_invalid_pluralization_data + I18n.backend.store_translations 'de', :foo => [:bar] + I18n.backend.translate 'de', :foo, :count => 1 + end + + def force_missing_interpolation_argument + I18n.backend.store_translations 'de', :foo => "{{bar}}" + I18n.backend.translate 'de', :foo, :baz => 'baz' + end + + def force_reserved_interpolation_key + I18n.backend.store_translations 'de', :foo => "{{scope}}" + I18n.backend.translate 'de', :foo, :baz => 'baz' + end +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_test.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_test.rb new file mode 100644 index 0000000000..bbb35ec809 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_test.rb @@ -0,0 +1,125 @@ +$:.unshift "lib" + +require 'rubygems' +require 'test/unit' +require 'mocha' +require 'i18n' +require 'active_support' + +class I18nTest < Test::Unit::TestCase + def setup + I18n.backend.store_translations :'en', { + :currency => { + :format => { + :separator => '.', + :delimiter => ',', + } + } + } + end + + def test_uses_simple_backend_set_by_default + assert I18n.backend.is_a?(I18n::Backend::Simple) + end + + def test_can_set_backend + assert_nothing_raised{ I18n.backend = self } + assert_equal self, I18n.backend + I18n.backend = I18n::Backend::Simple.new + end + + def test_uses_en_us_as_default_locale_by_default + assert_equal 'en', I18n.default_locale + end + + def test_can_set_default_locale + assert_nothing_raised{ I18n.default_locale = 'de' } + assert_equal 'de', I18n.default_locale + I18n.default_locale = 'en' + end + + def test_uses_default_locale_as_locale_by_default + assert_equal I18n.default_locale, I18n.locale + end + + def test_can_set_locale_to_thread_current + assert_nothing_raised{ I18n.locale = 'de' } + assert_equal 'de', I18n.locale + assert_equal 'de', Thread.current[:locale] + I18n.locale = 'en' + end + + def test_can_set_exception_handler + assert_nothing_raised{ I18n.exception_handler = :custom_exception_handler } + I18n.exception_handler = :default_exception_handler # revert it + end + + def test_uses_custom_exception_handler + I18n.exception_handler = :custom_exception_handler + I18n.expects(:custom_exception_handler) + I18n.translate :bogus + I18n.exception_handler = :default_exception_handler # revert it + end + + def test_delegates_translate_to_backend + I18n.backend.expects(:translate).with 'de', :foo, {} + I18n.translate :foo, :locale => 'de' + end + + def test_delegates_localize_to_backend + I18n.backend.expects(:localize).with 'de', :whatever, :default + I18n.localize :whatever, :locale => 'de' + end + + def test_translate_given_no_locale_uses_i18n_locale + I18n.backend.expects(:translate).with 'en', :foo, {} + I18n.translate :foo + end + + def test_translate_on_nested_symbol_keys_works + assert_equal ".", I18n.t(:'currency.format.separator') + end + + def test_translate_with_nested_string_keys_works + assert_equal ".", I18n.t('currency.format.separator') + end + + def test_translate_with_array_as_scope_works + assert_equal ".", I18n.t(:separator, :scope => ['currency.format']) + end + + def test_translate_with_array_containing_dot_separated_strings_as_scope_works + assert_equal ".", I18n.t(:separator, :scope => ['currency.format']) + end + + def test_translate_with_key_array_and_dot_separated_scope_works + assert_equal [".", ","], I18n.t(%w(separator delimiter), :scope => 'currency.format') + end + + def test_translate_with_dot_separated_key_array_and_scope_works + assert_equal [".", ","], I18n.t(%w(format.separator format.delimiter), :scope => 'currency') + end + + def test_translate_with_options_using_scope_works + I18n.backend.expects(:translate).with('de', :precision, :scope => :"currency.format") + I18n.with_options :locale => 'de', :scope => :'currency.format' do |locale| + locale.t :precision + end + end + + # def test_translate_given_no_args_raises_missing_translation_data + # assert_equal "translation missing: en, no key", I18n.t + # end + + def test_translate_given_a_bogus_key_raises_missing_translation_data + assert_equal "translation missing: en, bogus", I18n.t(:bogus) + end + + def test_localize_nil_raises_argument_error + assert_raises(I18n::ArgumentError) { I18n.l nil } + end + + def test_localize_object_raises_argument_error + assert_raises(I18n::ArgumentError) { I18n.l Object.new } + end +end diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.rb new file mode 100644 index 0000000000..6044ce10d9 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.rb @@ -0,0 +1 @@ +{:'en-Ruby' => {:foo => {:bar => "baz"}}}
\ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.yml b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.yml new file mode 100644 index 0000000000..0b298c9c0e --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.yml @@ -0,0 +1,3 @@ +en-Yaml: + foo: + bar: baz
\ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/simple_backend_test.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/simple_backend_test.rb new file mode 100644 index 0000000000..e181975f38 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.1/test/simple_backend_test.rb @@ -0,0 +1,502 @@ +# encoding: utf-8 +$:.unshift "lib" + +require 'rubygems' +require 'test/unit' +require 'mocha' +require 'i18n' +require 'time' +require 'yaml' + +module I18nSimpleBackendTestSetup + def setup_backend + # backend_reset_translations! + @backend = I18n::Backend::Simple.new + @backend.store_translations 'en', :foo => {:bar => 'bar', :baz => 'baz'} + @locale_dir = File.dirname(__FILE__) + '/locale' + end + alias :setup :setup_backend + + # def backend_reset_translations! + # I18n::Backend::Simple::ClassMethods.send :class_variable_set, :@@translations, {} + # end + + def backend_get_translations + # I18n::Backend::Simple::ClassMethods.send :class_variable_get, :@@translations + @backend.instance_variable_get :@translations + end + + def add_datetime_translations + @backend.store_translations :'de', { + :date => { + :formats => { + :default => "%d.%m.%Y", + :short => "%d. %b", + :long => "%d. %B %Y", + }, + :day_names => %w(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag), + :abbr_day_names => %w(So Mo Di Mi Do Fr Sa), + :month_names => %w(Januar Februar März April Mai Juni Juli August September Oktober November Dezember).unshift(nil), + :abbr_month_names => %w(Jan Feb Mar Apr Mai Jun Jul Aug Sep Okt Nov Dez).unshift(nil), + :order => [:day, :month, :year] + }, + :time => { + :formats => { + :default => "%a, %d. %b %Y %H:%M:%S %z", + :short => "%d. %b %H:%M", + :long => "%d. %B %Y %H:%M", + }, + :am => 'am', + :pm => 'pm' + }, + :datetime => { + :distance_in_words => { + :half_a_minute => 'half a minute', + :less_than_x_seconds => { + :one => 'less than 1 second', + :other => 'less than {{count}} seconds' + }, + :x_seconds => { + :one => '1 second', + :other => '{{count}} seconds' + }, + :less_than_x_minutes => { + :one => 'less than a minute', + :other => 'less than {{count}} minutes' + }, + :x_minutes => { + :one => '1 minute', + :other => '{{count}} minutes' + }, + :about_x_hours => { + :one => 'about 1 hour', + :other => 'about {{count}} hours' + }, + :x_days => { + :one => '1 day', + :other => '{{count}} days' + }, + :about_x_months => { + :one => 'about 1 month', + :other => 'about {{count}} months' + }, + :x_months => { + :one => '1 month', + :other => '{{count}} months' + }, + :about_x_years => { + :one => 'about 1 year', + :other => 'about {{count}} year' + }, + :over_x_years => { + :one => 'over 1 year', + :other => 'over {{count}} years' + } + } + } + } + end +end + +class I18nSimpleBackendTranslationsTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def test_store_translations_adds_translations # no, really :-) + @backend.store_translations :'en', :foo => 'bar' + assert_equal Hash[:'en', {:foo => 'bar'}], backend_get_translations + end + + def test_store_translations_deep_merges_translations + @backend.store_translations :'en', :foo => {:bar => 'bar'} + @backend.store_translations :'en', :foo => {:baz => 'baz'} + assert_equal Hash[:'en', {:foo => {:bar => 'bar', :baz => 'baz'}}], backend_get_translations + end + + def test_store_translations_forces_locale_to_sym + @backend.store_translations 'en', :foo => 'bar' + assert_equal Hash[:'en', {:foo => 'bar'}], backend_get_translations + end + + def test_store_translations_converts_keys_to_symbols + # backend_reset_translations! + @backend.store_translations 'en', 'foo' => {'bar' => 'bar', 'baz' => 'baz'} + assert_equal Hash[:'en', {:foo => {:bar => 'bar', :baz => 'baz'}}], backend_get_translations + end +end + +class I18nSimpleBackendTranslateTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def test_translate_calls_lookup_with_locale_given + @backend.expects(:lookup).with('de', :bar, [:foo]).returns 'bar' + @backend.translate 'de', :bar, :scope => [:foo] + end + + def test_given_no_keys_it_returns_the_default + assert_equal 'default', @backend.translate('en', nil, :default => 'default') + end + + def test_translate_given_a_symbol_as_a_default_translates_the_symbol + assert_equal 'bar', @backend.translate('en', nil, :scope => [:foo], :default => :bar) + end + + def test_translate_given_an_array_as_default_uses_the_first_match + assert_equal 'bar', @backend.translate('en', :does_not_exist, :scope => [:foo], :default => [:does_not_exist_2, :bar]) + end + + def test_translate_given_an_array_of_inexistent_keys_it_raises_missing_translation_data + assert_raises I18n::MissingTranslationData do + @backend.translate('en', :does_not_exist, :scope => [:foo], :default => [:does_not_exist_2, :does_not_exist_3]) + end + end + + def test_translate_an_array_of_keys_translates_all_of_them + assert_equal %w(bar baz), @backend.translate('en', [:bar, :baz], :scope => [:foo]) + end + + def test_translate_calls_pluralize + @backend.expects(:pluralize).with 'en', 'bar', 1 + @backend.translate 'en', :bar, :scope => [:foo], :count => 1 + end + + def test_translate_calls_interpolate + @backend.expects(:interpolate).with 'en', 'bar', {} + @backend.translate 'en', :bar, :scope => [:foo] + end + + def test_translate_calls_interpolate_including_count_as_a_value + @backend.expects(:interpolate).with 'en', 'bar', {:count => 1} + @backend.translate 'en', :bar, :scope => [:foo], :count => 1 + end + + def test_translate_given_nil_as_a_locale_raises_an_argument_error + assert_raises(I18n::InvalidLocale){ @backend.translate nil, :bar } + end + + def test_translate_with_a_bogus_key_and_no_default_raises_missing_translation_data + assert_raises(I18n::MissingTranslationData){ @backend.translate 'de', :bogus } + end +end + +class I18nSimpleBackendLookupTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + # useful because this way we can use the backend with no key for interpolation/pluralization + def test_lookup_given_nil_as_a_key_returns_nil + assert_nil @backend.send(:lookup, 'en', nil) + end + + def test_lookup_given_nested_keys_looks_up_a_nested_hash_value + assert_equal 'bar', @backend.send(:lookup, 'en', :bar, [:foo]) + end +end + +class I18nSimpleBackendPluralizeTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def test_pluralize_given_nil_returns_the_given_entry + entry = {:one => 'bar', :other => 'bars'} + assert_equal entry, @backend.send(:pluralize, nil, entry, nil) + end + + def test_pluralize_given_0_returns_zero_string_if_zero_key_given + assert_equal 'zero', @backend.send(:pluralize, nil, {:zero => 'zero', :one => 'bar', :other => 'bars'}, 0) + end + + def test_pluralize_given_0_returns_plural_string_if_no_zero_key_given + assert_equal 'bars', @backend.send(:pluralize, nil, {:one => 'bar', :other => 'bars'}, 0) + end + + def test_pluralize_given_1_returns_singular_string + assert_equal 'bar', @backend.send(:pluralize, nil, {:one => 'bar', :other => 'bars'}, 1) + end + + def test_pluralize_given_2_returns_plural_string + assert_equal 'bars', @backend.send(:pluralize, nil, {:one => 'bar', :other => 'bars'}, 2) + end + + def test_pluralize_given_3_returns_plural_string + assert_equal 'bars', @backend.send(:pluralize, nil, {:one => 'bar', :other => 'bars'}, 3) + end + + def test_interpolate_given_incomplete_pluralization_data_raises_invalid_pluralization_data + assert_raises(I18n::InvalidPluralizationData){ @backend.send(:pluralize, nil, {:one => 'bar'}, 2) } + end + + # def test_interpolate_given_a_string_raises_invalid_pluralization_data + # assert_raises(I18n::InvalidPluralizationData){ @backend.send(:pluralize, nil, 'bar', 2) } + # end + # + # def test_interpolate_given_an_array_raises_invalid_pluralization_data + # assert_raises(I18n::InvalidPluralizationData){ @backend.send(:pluralize, nil, ['bar'], 2) } + # end +end + +class I18nSimpleBackendInterpolateTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def test_interpolate_given_a_value_hash_interpolates_the_values_to_the_string + assert_equal 'Hi David!', @backend.send(:interpolate, nil, 'Hi {{name}}!', :name => 'David') + end + + def test_interpolate_given_a_value_hash_interpolates_into_unicode_string + assert_equal 'Häi David!', @backend.send(:interpolate, nil, 'Häi {{name}}!', :name => 'David') + end + + def test_interpolate_given_nil_as_a_string_returns_nil + assert_nil @backend.send(:interpolate, nil, nil, :name => 'David') + end + + def test_interpolate_given_an_non_string_as_a_string_returns_nil + assert_equal [], @backend.send(:interpolate, nil, [], :name => 'David') + end + + def test_interpolate_given_a_values_hash_with_nil_values_interpolates_the_string + assert_equal 'Hi !', @backend.send(:interpolate, nil, 'Hi {{name}}!', {:name => nil}) + end + + def test_interpolate_given_an_empty_values_hash_raises_missing_interpolation_argument + assert_raises(I18n::MissingInterpolationArgument) { @backend.send(:interpolate, nil, 'Hi {{name}}!', {}) } + end + + def test_interpolate_given_a_string_containing_a_reserved_key_raises_reserved_interpolation_key + assert_raises(I18n::ReservedInterpolationKey) { @backend.send(:interpolate, nil, '{{default}}', {:default => nil}) } + end +end + +class I18nSimpleBackendLocalizeDateTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def setup + @backend = I18n::Backend::Simple.new + add_datetime_translations + @date = Date.new 2008, 1, 1 + end + + def test_translate_given_the_short_format_it_uses_it + assert_equal '01. Jan', @backend.localize('de', @date, :short) + end + + def test_translate_given_the_long_format_it_uses_it + assert_equal '01. Januar 2008', @backend.localize('de', @date, :long) + end + + def test_translate_given_the_default_format_it_uses_it + assert_equal '01.01.2008', @backend.localize('de', @date, :default) + end + + def test_translate_given_a_day_name_format_it_returns_a_day_name + assert_equal 'Dienstag', @backend.localize('de', @date, '%A') + end + + def test_translate_given_an_abbr_day_name_format_it_returns_an_abbrevated_day_name + assert_equal 'Di', @backend.localize('de', @date, '%a') + end + + def test_translate_given_a_month_name_format_it_returns_a_month_name + assert_equal 'Januar', @backend.localize('de', @date, '%B') + end + + def test_translate_given_an_abbr_month_name_format_it_returns_an_abbrevated_month_name + assert_equal 'Jan', @backend.localize('de', @date, '%b') + end + + def test_translate_given_no_format_it_does_not_fail + assert_nothing_raised{ @backend.localize 'de', @date } + end + + def test_translate_given_an_unknown_format_it_does_not_fail + assert_nothing_raised{ @backend.localize 'de', @date, '%x' } + end + + def test_localize_nil_raises_argument_error + assert_raises(I18n::ArgumentError) { @backend.localize 'de', nil } + end + + def test_localize_object_raises_argument_error + assert_raises(I18n::ArgumentError) { @backend.localize 'de', Object.new } + end +end + +class I18nSimpleBackendLocalizeDateTimeTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def setup + @backend = I18n::Backend::Simple.new + add_datetime_translations + @morning = DateTime.new 2008, 1, 1, 6 + @evening = DateTime.new 2008, 1, 1, 18 + end + + def test_translate_given_the_short_format_it_uses_it + assert_equal '01. Jan 06:00', @backend.localize('de', @morning, :short) + end + + def test_translate_given_the_long_format_it_uses_it + assert_equal '01. Januar 2008 06:00', @backend.localize('de', @morning, :long) + end + + def test_translate_given_the_default_format_it_uses_it + assert_equal 'Di, 01. Jan 2008 06:00:00 +0000', @backend.localize('de', @morning, :default) + end + + def test_translate_given_a_day_name_format_it_returns_the_correct_day_name + assert_equal 'Dienstag', @backend.localize('de', @morning, '%A') + end + + def test_translate_given_an_abbr_day_name_format_it_returns_the_correct_abbrevated_day_name + assert_equal 'Di', @backend.localize('de', @morning, '%a') + end + + def test_translate_given_a_month_name_format_it_returns_the_correct_month_name + assert_equal 'Januar', @backend.localize('de', @morning, '%B') + end + + def test_translate_given_an_abbr_month_name_format_it_returns_the_correct_abbrevated_month_name + assert_equal 'Jan', @backend.localize('de', @morning, '%b') + end + + def test_translate_given_a_meridian_indicator_format_it_returns_the_correct_meridian_indicator + assert_equal 'am', @backend.localize('de', @morning, '%p') + assert_equal 'pm', @backend.localize('de', @evening, '%p') + end + + def test_translate_given_no_format_it_does_not_fail + assert_nothing_raised{ @backend.localize 'de', @morning } + end + + def test_translate_given_an_unknown_format_it_does_not_fail + assert_nothing_raised{ @backend.localize 'de', @morning, '%x' } + end +end + +class I18nSimpleBackendLocalizeTimeTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def setup + @old_timezone, ENV['TZ'] = ENV['TZ'], 'UTC' + @backend = I18n::Backend::Simple.new + add_datetime_translations + @morning = Time.parse '2008-01-01 6:00 UTC' + @evening = Time.parse '2008-01-01 18:00 UTC' + end + + def teardown + @old_timezone ? ENV['TZ'] = @old_timezone : ENV.delete('TZ') + end + + def test_translate_given_the_short_format_it_uses_it + assert_equal '01. Jan 06:00', @backend.localize('de', @morning, :short) + end + + def test_translate_given_the_long_format_it_uses_it + assert_equal '01. Januar 2008 06:00', @backend.localize('de', @morning, :long) + end + + # TODO Seems to break on Windows because ENV['TZ'] is ignored. What's a better way to do this? + # def test_translate_given_the_default_format_it_uses_it + # assert_equal 'Di, 01. Jan 2008 06:00:00 +0000', @backend.localize('de', @morning, :default) + # end + + def test_translate_given_a_day_name_format_it_returns_the_correct_day_name + assert_equal 'Dienstag', @backend.localize('de', @morning, '%A') + end + + def test_translate_given_an_abbr_day_name_format_it_returns_the_correct_abbrevated_day_name + assert_equal 'Di', @backend.localize('de', @morning, '%a') + end + + def test_translate_given_a_month_name_format_it_returns_the_correct_month_name + assert_equal 'Januar', @backend.localize('de', @morning, '%B') + end + + def test_translate_given_an_abbr_month_name_format_it_returns_the_correct_abbrevated_month_name + assert_equal 'Jan', @backend.localize('de', @morning, '%b') + end + + def test_translate_given_a_meridian_indicator_format_it_returns_the_correct_meridian_indicator + assert_equal 'am', @backend.localize('de', @morning, '%p') + assert_equal 'pm', @backend.localize('de', @evening, '%p') + end + + def test_translate_given_no_format_it_does_not_fail + assert_nothing_raised{ @backend.localize 'de', @morning } + end + + def test_translate_given_an_unknown_format_it_does_not_fail + assert_nothing_raised{ @backend.localize 'de', @morning, '%x' } + end +end + +class I18nSimpleBackendHelperMethodsTest < Test::Unit::TestCase + def setup + @backend = I18n::Backend::Simple.new + end + + def test_deep_symbolize_keys_works + result = @backend.send :deep_symbolize_keys, 'foo' => {'bar' => {'baz' => 'bar'}} + expected = {:foo => {:bar => {:baz => 'bar'}}} + assert_equal expected, result + end +end + +class I18nSimpleBackendLoadTranslationsTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def test_load_translations_with_unknown_file_type_raises_exception + assert_raises(I18n::UnknownFileType) { @backend.load_translations "#{@locale_dir}/en.xml" } + end + + def test_load_translations_with_ruby_file_type_does_not_raise_exception + assert_nothing_raised { @backend.load_translations "#{@locale_dir}/en.rb" } + end + + def test_load_rb_loads_data_from_ruby_file + data = @backend.send :load_rb, "#{@locale_dir}/en.rb" + assert_equal({:'en-Ruby' => {:foo => {:bar => "baz"}}}, data) + end + + def test_load_rb_loads_data_from_yaml_file + data = @backend.send :load_yml, "#{@locale_dir}/en.yml" + assert_equal({'en-Yaml' => {'foo' => {'bar' => 'baz'}}}, data) + end + + def test_load_translations_loads_from_different_file_formats + @backend = I18n::Backend::Simple.new + @backend.load_translations "#{@locale_dir}/en.rb", "#{@locale_dir}/en.yml" + expected = { + :'en-Ruby' => {:foo => {:bar => "baz"}}, + :'en-Yaml' => {:foo => {:bar => "baz"}} + } + assert_equal expected, backend_get_translations + end +end + +class I18nSimpleBackendReloadTranslationsTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def setup + @backend = I18n::Backend::Simple.new + I18n.load_path = [File.dirname(__FILE__) + '/locale/en.yml'] + assert_nil backend_get_translations + @backend.send :init_translations + end + + def teardown + I18n.load_path = [] + end + + def test_setup + assert_not_nil backend_get_translations + end + + def test_reload_translations_unloads_translations + @backend.reload! + assert_nil backend_get_translations + end + + def test_reload_translations_uninitializes_translations + @backend.reload! + assert_equal @backend.initialized?, false + end +end
\ No newline at end of file diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index d8506de986..e8e0b41d4d 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -1,18 +1,18 @@ require 'abstract_unit' -class CacheKeyTest < Test::Unit::TestCase +class CacheKeyTest < ActiveSupport::TestCase def test_expand_cache_key assert_equal 'name/1/2/true', ActiveSupport::Cache.expand_cache_key([1, '2', true], :name) end end -class CacheStoreSettingTest < Test::Unit::TestCase +class CacheStoreSettingTest < ActiveSupport::TestCase def test_file_fragment_cache_store store = ActiveSupport::Cache.lookup_store :file_store, "/path/to/cache/directory" assert_kind_of(ActiveSupport::Cache::FileStore, store) assert_equal "/path/to/cache/directory", store.cache_path end - + def test_drb_fragment_cache_store store = ActiveSupport::Cache.lookup_store :drb_store, "druby://localhost:9192" assert_kind_of(ActiveSupport::Cache::DRbStore, store) @@ -24,13 +24,13 @@ class CacheStoreSettingTest < Test::Unit::TestCase assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) assert_equal %w(localhost), store.addresses end - + def test_mem_cache_fragment_cache_store_with_multiple_servers store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1' assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) assert_equal %w(localhost 192.168.1.1), store.addresses end - + def test_mem_cache_fragment_cache_store_with_options store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost", '192.168.1.1', :namespace => 'foo' assert_kind_of(ActiveSupport::Cache::MemCacheStore, store) @@ -45,7 +45,7 @@ class CacheStoreSettingTest < Test::Unit::TestCase end end -class CacheStoreTest < Test::Unit::TestCase +class CacheStoreTest < ActiveSupport::TestCase def setup @cache = ActiveSupport::Cache.lookup_store(:memory_store) end @@ -116,9 +116,15 @@ module CacheStoreBehavior assert_equal 1, @cache.decrement('foo') assert_equal 1, @cache.read('foo', :raw => true).to_i end + + def test_exist + @cache.write('foo', 'bar') + assert @cache.exist?('foo') + assert !@cache.exist?('bar') + end end -class FileStoreTest < Test::Unit::TestCase +class FileStoreTest < ActiveSupport::TestCase def setup @cache = ActiveSupport::Cache.lookup_store(:file_store, Dir.pwd) end @@ -130,7 +136,7 @@ class FileStoreTest < Test::Unit::TestCase include CacheStoreBehavior end -class MemoryStoreTest < Test::Unit::TestCase +class MemoryStoreTest < ActiveSupport::TestCase def setup @cache = ActiveSupport::Cache.lookup_store(:memory_store) end @@ -145,28 +151,111 @@ class MemoryStoreTest < Test::Unit::TestCase end uses_memcached 'memcached backed store' do - class MemCacheStoreTest < Test::Unit::TestCase + class MemCacheStoreTest < ActiveSupport::TestCase def setup @cache = ActiveSupport::Cache.lookup_store(:mem_cache_store) + @data = @cache.instance_variable_get(:@data) @cache.clear end include CacheStoreBehavior def test_store_objects_should_be_immutable - @cache.write('foo', 'bar') - @cache.read('foo').gsub!(/.*/, 'baz') - assert_equal 'bar', @cache.read('foo') + @cache.with_local_cache do + @cache.write('foo', 'bar') + @cache.read('foo').gsub!(/.*/, 'baz') + assert_equal 'bar', @cache.read('foo') + end end def test_write_should_return_true_on_success - result = @cache.write('foo', 'bar') - assert_equal 'bar', @cache.read('foo') # make sure 'foo' was written - assert result + @cache.with_local_cache do + result = @cache.write('foo', 'bar') + assert_equal 'bar', @cache.read('foo') # make sure 'foo' was written + assert result + end + end + + def test_local_writes_are_persistent_on_the_remote_cache + @cache.with_local_cache do + @cache.write('foo', 'bar') + end + + assert_equal 'bar', @cache.read('foo') + end + + def test_clear_also_clears_local_cache + @cache.with_local_cache do + @cache.write('foo', 'bar') + @cache.clear + assert_nil @cache.read('foo') + end + end + + def test_local_cache_of_read_and_write + @cache.with_local_cache do + @cache.write('foo', 'bar') + @data.flush_all # Clear remote cache + assert_equal 'bar', @cache.read('foo') + end + end + + def test_local_cache_of_delete + @cache.with_local_cache do + @cache.write('foo', 'bar') + @cache.delete('foo') + @data.flush_all # Clear remote cache + assert_nil @cache.read('foo') + end + end + + def test_local_cache_of_exist + @cache.with_local_cache do + @cache.write('foo', 'bar') + @cache.instance_variable_set(:@data, nil) + @data.flush_all # Clear remote cache + assert @cache.exist?('foo') + end + end + + def test_local_cache_of_increment + @cache.with_local_cache do + @cache.write('foo', 1, :raw => true) + @cache.increment('foo') + @data.flush_all # Clear remote cache + assert_equal 2, @cache.read('foo', :raw => true).to_i + end + end + + def test_local_cache_of_decrement + @cache.with_local_cache do + @cache.write('foo', 1, :raw => true) + @cache.decrement('foo') + @data.flush_all # Clear remote cache + assert_equal 0, @cache.read('foo', :raw => true).to_i + end + end + + def test_exist_with_nulls_cached_locally + @cache.with_local_cache do + @cache.write('foo', 'bar') + @cache.delete('foo') + assert !@cache.exist?('foo') + end + end + + def test_middleware + app = lambda { |env| + result = @cache.write('foo', 'bar') + assert_equal 'bar', @cache.read('foo') # make sure 'foo' was written + assert result + } + app = @cache.middleware.new(app) + app.call({}) end end - class CompressedMemCacheStore < Test::Unit::TestCase + class CompressedMemCacheStore < ActiveSupport::TestCase def setup @cache = ActiveSupport::Cache.lookup_store(:compressed_mem_cache_store) @cache.clear diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index 25b8eecef5..2bc2e1eaf0 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -53,10 +53,41 @@ class Person < Record end class ConditionalPerson < Record + # proc before_save Proc.new { |r| r.history << [:before_save, :proc] }, :if => Proc.new { |r| true } before_save Proc.new { |r| r.history << "b00m" }, :if => Proc.new { |r| false } before_save Proc.new { |r| r.history << [:before_save, :proc] }, :unless => Proc.new { |r| false } before_save Proc.new { |r| r.history << "b00m" }, :unless => Proc.new { |r| true } + # symbol + before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :if => :yes + before_save Proc.new { |r| r.history << "b00m" }, :if => :no + before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :unless => :no + before_save Proc.new { |r| r.history << "b00m" }, :unless => :yes + # string + before_save Proc.new { |r| r.history << [:before_save, :string] }, :if => 'yes' + before_save Proc.new { |r| r.history << "b00m" }, :if => 'no' + before_save Proc.new { |r| r.history << [:before_save, :string] }, :unless => 'no' + before_save Proc.new { |r| r.history << "b00m" }, :unless => 'yes' + # Array with conditions + before_save Proc.new { |r| r.history << [:before_save, :symbol_array] }, :if => [:yes, :other_yes] + before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, :no] + before_save Proc.new { |r| r.history << [:before_save, :symbol_array] }, :unless => [:no, :other_no] + before_save Proc.new { |r| r.history << "b00m" }, :unless => [:yes, :no] + # Combined if and unless + before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, :if => :yes, :unless => :no + before_save Proc.new { |r| r.history << "b00m" }, :if => :yes, :unless => :yes + # Array with different types of conditions + before_save Proc.new { |r| r.history << [:before_save, :symbol_proc_string_array] }, :if => [:yes, Proc.new { |r| true }, 'yes'] + before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, Proc.new { |r| true }, 'no'] + # Array with different types of conditions comibned if and unless + before_save Proc.new { |r| r.history << [:before_save, :combined_symbol_proc_string_array] }, + :if => [:yes, Proc.new { |r| true }, 'yes'], :unless => [:no, 'no'] + before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, Proc.new { |r| true }, 'no'], :unless => [:no, 'no'] + + def yes; true; end + def other_yes; true; end + def no; false; end + def other_no; false; end def save run_callbacks(:before_save) @@ -90,7 +121,16 @@ class ConditionalCallbackTest < Test::Unit::TestCase person.save assert_equal [ [:before_save, :proc], - [:before_save, :proc] + [:before_save, :proc], + [:before_save, :symbol], + [:before_save, :symbol], + [:before_save, :string], + [:before_save, :string], + [:before_save, :symbol_array], + [:before_save, :symbol_array], + [:before_save, :combined_symbol], + [:before_save, :symbol_proc_string_array], + [:before_save, :combined_symbol_proc_string_array] ], person.history end end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 63ccb5a7da..b63ab30965 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -287,10 +287,14 @@ class HashExtTest < Test::Unit::TestCase # Should return a new hash with only the given keys. assert_equal expected, original.slice(:a, :b) assert_not_equal expected, original + end + + def test_slice_inplace + original = { :a => 'x', :b => 'y', :c => 10 } + expected = { :c => 10 } # Should replace the hash with only the given keys. assert_equal expected, original.slice!(:a, :b) - assert_equal expected, original end def test_slice_with_an_array_key @@ -300,10 +304,14 @@ class HashExtTest < Test::Unit::TestCase # Should return a new hash with only the given keys when given an array key. assert_equal expected, original.slice([:a, :b], :c) assert_not_equal expected, original + end + + def test_slice_inplace_with_an_array_key + original = { :a => 'x', :b => 'y', :c => 10, [:a, :b] => "an array key" } + expected = { :a => 'x', :b => 'y' } # Should replace the hash with only the given keys when given an array key. assert_equal expected, original.slice!([:a, :b], :c) - assert_equal expected, original end def test_slice_with_splatted_keys @@ -322,11 +330,17 @@ class HashExtTest < Test::Unit::TestCase # Should return a new hash with only the given keys. assert_equal expected, original.slice(*keys), keys.inspect assert_not_equal expected, original + end + end + def test_indifferent_slice_inplace + original = { :a => 'x', :b => 'y', :c => 10 }.with_indifferent_access + expected = { :c => 10 }.with_indifferent_access + + [['a', 'b'], [:a, :b]].each do |keys| # Should replace the hash with only the given keys. copy = original.dup assert_equal expected, copy.slice!(*keys) - assert_equal expected, copy end end diff --git a/activesupport/test/core_ext/integer_ext_test.rb b/activesupport/test/core_ext/integer_ext_test.rb index 5ab36226a1..b7006a5c86 100644 --- a/activesupport/test/core_ext/integer_ext_test.rb +++ b/activesupport/test/core_ext/integer_ext_test.rb @@ -28,8 +28,8 @@ class IntegerExtTest < Test::Unit::TestCase end def test_ordinalize - # These tests are mostly just to ensure that the ordinalize method exists - # It's results are tested comprehensively in the inflector test cases. + # These tests are mostly just to ensure that the ordinalize method exists. + # Its results are tested comprehensively in the inflector test cases. assert_equal '1st', 1.ordinalize assert_equal '8th', 8.ordinalize 1000000000000000000000000000000000000000000000000000000000000000000000.ordinalize diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb index 2f79b6f67f..0bdbd14f33 100644 --- a/activesupport/test/core_ext/object_and_class_ext_test.rb +++ b/activesupport/test/core_ext/object_and_class_ext_test.rb @@ -256,21 +256,13 @@ class ObjectTryTest < Test::Unit::TestCase def test_nonexisting_method method = :undefined_method assert !@string.respond_to?(method) - assert_nil @string.try(method) + assert_raises(NoMethodError) { @string.try(method) } end def test_valid_method assert_equal 5, @string.try(:size) end - def test_valid_private_method - class << @string - private :size - end - - assert_equal 5, @string.try(:size) - end - def test_argument_forwarding assert_equal 'Hey', @string.try(:sub, 'llo', 'y') end @@ -278,4 +270,13 @@ class ObjectTryTest < Test::Unit::TestCase def test_block_forwarding assert_equal 'Hey', @string.try(:sub, 'llo') { |match| 'y' } end + + def test_nil_to_type + assert_nil nil.try(:to_s) + assert_nil nil.try(:to_i) + end + + def test_false_try + assert_equal 'false', false.try(:to_s) + end end diff --git a/activesupport/test/core_ext/object_ext_test.rb b/activesupport/test/core_ext/object_ext_test.rb new file mode 100644 index 0000000000..a413d331c4 --- /dev/null +++ b/activesupport/test/core_ext/object_ext_test.rb @@ -0,0 +1,8 @@ +require 'abstract_unit' + +class ObjectExtTest < Test::Unit::TestCase + def test_tap_yields_and_returns_self + foo = Object.new + assert_equal foo, foo.tap { |x| assert_equal foo, x; :bar } + end +end diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index dc36336239..4dc1fec559 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -105,6 +105,15 @@ class TimeWithZoneTest < Test::Unit::TestCase end end + def test_xmlschema_with_fractional_seconds + silence_warnings do # silence warnings raised by tzinfo gem + @twz += 0.123456 # advance the time by a fraction of a second + assert_equal "1999-12-31T19:00:00.123-05:00", @twz.xmlschema(3) + assert_equal "1999-12-31T19:00:00.123456-05:00", @twz.xmlschema(6) + assert_equal "1999-12-31T19:00:00.123456-05:00", @twz.xmlschema(12) + end + end + def test_to_yaml silence_warnings do # silence warnings raised by tzinfo gem assert_equal "--- 1999-12-31 19:00:00 -05:00\n", @twz.to_yaml @@ -256,6 +265,15 @@ class TimeWithZoneTest < Test::Unit::TestCase twz2 = ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 2), ActiveSupport::TimeZone['UTC'] ) assert_equal 86_400.0, twz2 - twz1 end + + def test_minus_with_datetime + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 2), ActiveSupport::TimeZone['UTC'] ) - DateTime.civil(2000, 1, 1) + end + + def test_minus_with_wrapped_datetime + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new( DateTime.civil(2000, 1, 2), ActiveSupport::TimeZone['UTC'] ) - Time.utc(2000, 1, 1) + assert_equal 86_400.0, ActiveSupport::TimeWithZone.new( DateTime.civil(2000, 1, 2), ActiveSupport::TimeZone['UTC'] ) - DateTime.civil(2000, 1, 1) + end def test_plus_and_minus_enforce_spring_dst_rules silence_warnings do # silence warnings raised by tzinfo gem diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index 19ae3a01a8..558b03b90d 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -15,7 +15,8 @@ class TestJSONDecoding < Test::Unit::TestCase # no time zone %({a: "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"}, # needs to be *exact* - %({a: " 2007-01-01 01:12:34 Z "}) => {'a' => " 2007-01-01 01:12:34 Z "}, + %({a: " 2007-01-01 01:12:34 Z "}) => {'a' => " 2007-01-01 01:12:34 Z "}, + %({a: "2007-01-01 : it's your birthday"}) => {'a' => "2007-01-01 : it's your birthday"}, %([]) => [], %({}) => {}, %(1) => 1, diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index 8ed21cc9ad..2c5b4d0378 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -59,7 +59,7 @@ class TestJSONEncoding < Test::Unit::TestCase assert_equal %({\"a\": \"b\"}), { :a => :b }.to_json assert_equal %({\"a\": 1}), { 'a' => 1 }.to_json assert_equal %({\"a\": [1, 2]}), { 'a' => [1,2] }.to_json - assert_equal %({1: 2}), { 1 => 2 }.to_json + assert_equal %({"1": 2}), { 1 => 2 }.to_json sorted_json = '{' + {:a => :b, :c => :d}.to_json[1..-2].split(', ').sort.join(', ') + '}' assert_equal %({\"a\": \"b\", \"c\": \"d\"}), sorted_json @@ -80,7 +80,7 @@ class TestJSONEncoding < Test::Unit::TestCase def test_hash_key_identifiers_are_always_quoted values = {0 => 0, 1 => 1, :_ => :_, "$" => "$", "a" => "a", :A => :A, :A0 => :A0, "A0B" => "A0B"} - assert_equal %w( "$" "A" "A0" "A0B" "_" "a" 0 1 ), object_keys(values.to_json) + assert_equal %w( "$" "A" "A0" "A0B" "_" "a" "0" "1" ).sort, object_keys(values.to_json) end def test_hash_should_allow_key_filtering_with_only diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index 0e2aa4543d..fb76ca1ab6 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -98,7 +98,8 @@ class OrderedHashTest < Test::Unit::TestCase end def test_delete_if - (copy = @ordered_hash.dup).delete('pink') + copy = @ordered_hash.dup + copy.delete('pink') assert_equal copy, @ordered_hash.delete_if { |k, _| k == 'pink' } assert !@ordered_hash.keys.include?('pink') end @@ -115,6 +116,7 @@ class OrderedHashTest < Test::Unit::TestCase new_ordered_hash = @ordered_hash.reject { |k, _| k == 'pink' } assert_equal copy, @ordered_hash assert !new_ordered_hash.keys.include?('pink') + assert @ordered_hash.keys.include?('pink') end def test_clear @@ -140,4 +142,10 @@ class OrderedHashTest < Test::Unit::TestCase assert_equal [@keys.first, @values.first], pair assert !@ordered_hash.keys.include?(pair.first) end + + def test_keys + original = @ordered_hash.keys.dup + @ordered_hash.keys.pop + assert_equal original, @ordered_hash.keys + end end
\ No newline at end of file |