diff options
Diffstat (limited to 'activesupport/lib')
30 files changed, 262 insertions, 322 deletions
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 6b662ac660..6b87774978 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -42,7 +42,6 @@ module ActiveSupport autoload :DescendantsTracker autoload :FileUpdateChecker - autoload :FileWatcher autoload :LogSubscriber autoload :Notifications diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index e41731f3e7..88b50fc506 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -41,7 +41,7 @@ module ActiveSupport def initialize(log, level = DEBUG) @level = level - @buffer = {} + @buffer = Hash.new { |h,k| h[k] = [] } @auto_flushing = 1 @guard = Mutex.new @@ -100,13 +100,8 @@ module ActiveSupport def flush @guard.synchronize do - unless buffer.empty? - old_buffer = buffer - all_content = StringIO.new - old_buffer.each do |content| - all_content << content - end - @log.write(all_content.string) + buffer.each do |content| + @log.write(content) end # Important to do this even if buffer was empty or else @buffer will @@ -127,7 +122,7 @@ module ActiveSupport end def buffer - @buffer[Thread.current] ||= [] + @buffer[Thread.current] end def clear_buffer diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index 18182bbb40..a1376ae52a 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/file/atomic' require 'active_support/core_ext/string/conversions' +require 'active_support/core_ext/object/inclusion' require 'rack/utils' module ActiveSupport @@ -20,7 +21,7 @@ module ActiveSupport end def clear(options = nil) - root_dirs = Dir.entries(cache_path).reject{|f| ['.', '..'].include?(f)} + root_dirs = Dir.entries(cache_path).reject{|f| f.in?(['.', '..'])} FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)}) end @@ -120,7 +121,7 @@ module ActiveSupport # Lock a file for a block so only one process can modify it at a time. def lock_file(file_name, &block) # :nodoc: if File.exist?(file_name) - File.open(file_name, 'r') do |f| + File.open(file_name, 'r+') do |f| begin f.flock File::LOCK_EX yield @@ -161,7 +162,7 @@ module ActiveSupport # Delete empty directories in the cache. def delete_empty_directories(dir) return if dir == cache_path - if Dir.entries(dir).reject{|f| ['.', '..'].include?(f)}.empty? + if Dir.entries(dir).reject{|f| f.in?(['.', '..'])}.empty? File.delete(dir) rescue nil delete_empty_directories(File.dirname(dir)) end diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index b531a094cf..656cba625c 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -1,8 +1,10 @@ +require 'active_support/concern' require 'active_support/descendants_tracker' require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/kernel/singleton_class' +require 'active_support/core_ext/object/inclusion' module ActiveSupport # \Callbacks are code hooks that are run at key points in an object's lifecycle. @@ -411,11 +413,11 @@ module ActiveSupport # CallbackChain. # def __update_callbacks(name, filters = [], block = nil) #:nodoc: - type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before + type = filters.first.in?([:before, :after, :around]) ? filters.shift : :before options = filters.last.is_a?(Hash) ? filters.pop : {} filters.unshift(block) if block - ([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target| + ([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse.each do |target| chain = target.send("_#{name}_callbacks") yield target, chain.dup, type, filters, options target.__define_runner(name) diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb index c69a015f12..2df4fd1da1 100644 --- a/activesupport/lib/active_support/core_ext/array/access.rb +++ b/activesupport/lib/active_support/core_ext/array/access.rb @@ -3,10 +3,10 @@ class Array # # %w( a b c d ).from(0) # => %w( a b c d ) # %w( a b c d ).from(2) # => %w( c d ) - # %w( a b c d ).from(10) # => nil + # %w( a b c d ).from(10) # => %w() # %w().from(0) # => %w() def from(position) - self[position..-1] + self[position, length] || [] end # Returns the beginning of the array up to +position+. diff --git a/activesupport/lib/active_support/core_ext/array/random_access.rb b/activesupport/lib/active_support/core_ext/array/random_access.rb index ab1fa7cd5b..9eba4642b8 100644 --- a/activesupport/lib/active_support/core_ext/array/random_access.rb +++ b/activesupport/lib/active_support/core_ext/array/random_access.rb @@ -1,12 +1,15 @@ class Array # Backport of Array#sample based on Marc-Andre Lafortune's https://github.com/marcandre/backports/ # Returns a random element or +n+ random elements from the array. - # If the array is empty and +n+ is nil, returns <tt>nil</tt>. if +n+ is passed, returns <tt>[]</tt>. + # If the array is empty and +n+ is nil, returns <tt>nil</tt>. + # If +n+ is passed and its value is less than 0, it raises an +ArgumentError+ exception. + # If the value of +n+ is equal or greater than 0 it returns <tt>[]</tt>. # - # [1,2,3,4,5,6].sample # => 4 - # [1,2,3,4,5,6].sample(3) # => [2, 4, 5] - # [].sample # => nil - # [].sample(3) # => [] + # [1,2,3,4,5,6].sample # => 4 + # [1,2,3,4,5,6].sample(3) # => [2, 4, 5] + # [1,2,3,4,5,6].sample(-3) # => ArgumentError: negative sample number + # [].sample # => nil + # [].sample(3) # => [] def sample(n=nil) return self[Kernel.rand(size)] if n.nil? n = n.to_int diff --git a/activesupport/lib/active_support/core_ext/date_time/zones.rb b/activesupport/lib/active_support/core_ext/date_time/zones.rb index 82a4f7ac5a..6fa55a9255 100644 --- a/activesupport/lib/active_support/core_ext/date_time/zones.rb +++ b/activesupport/lib/active_support/core_ext/date_time/zones.rb @@ -16,6 +16,6 @@ class DateTime def in_time_zone(zone = ::Time.zone) return self unless zone - ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone)) + ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone)) end end diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index 3005fef44c..61a1d88b0e 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -108,7 +108,7 @@ class Hash raise "can't typecast #{entries.inspect}" end end - elsif value.has_key?("__content__") + elsif value['type'] == 'file' || value["__content__"].present? content = value["__content__"] if parser = ActiveSupport::XmlMini::PARSING[value["type"]] parser.arity == 1 ? parser.call(content) : parser.call(content, value) diff --git a/activesupport/lib/active_support/core_ext/module/deprecation.rb b/activesupport/lib/active_support/core_ext/module/deprecation.rb index 5a5b4e3f80..9c169a2598 100644 --- a/activesupport/lib/active_support/core_ext/module/deprecation.rb +++ b/activesupport/lib/active_support/core_ext/module/deprecation.rb @@ -1,3 +1,5 @@ +require 'active_support/deprecation' + class Module # Declare that a method has been deprecated. # deprecate :foo diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb index 790a26f5c1..9ad1e12699 100644 --- a/activesupport/lib/active_support/core_ext/object.rb +++ b/activesupport/lib/active_support/core_ext/object.rb @@ -2,6 +2,7 @@ require 'active_support/core_ext/object/acts_like' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/duplicable' require 'active_support/core_ext/object/try' +require 'active_support/core_ext/object/inclusion' require 'active_support/core_ext/object/conversions' require 'active_support/core_ext/object/instance_variables' diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb index d0c1ea8326..20085c4fb3 100644 --- a/activesupport/lib/active_support/core_ext/object/blank.rb +++ b/activesupport/lib/active_support/core_ext/object/blank.rb @@ -18,8 +18,8 @@ class Object !blank? end - # Returns object if it's #present? otherwise returns nil. - # object.presence is equivalent to object.present? ? object : nil. + # Returns object if it's <tt>present?</tt> otherwise returns +nil+. + # <tt>object.presence</tt> is equivalent to <tt>object.present? ? object : nil</tt>. # # This is handy for any representation of objects where blank is the same # as not present at all. For example, this simplifies a common check for @@ -37,39 +37,72 @@ class Object end end -class NilClass #:nodoc: +class NilClass + # +nil+ is blank: + # + # nil.blank? # => true + # def blank? true end end -class FalseClass #:nodoc: +class FalseClass + # +false+ is blank: + # + # false.blank? # => true + # def blank? true end end -class TrueClass #:nodoc: +class TrueClass + # +true+ is not blank: + # + # true.blank? # => false + # def blank? false end end -class Array #:nodoc: +class Array + # An array is blank if it's empty: + # + # [].blank? # => true + # [1,2,3].blank? # => false + # alias_method :blank?, :empty? end -class Hash #:nodoc: +class Hash + # A hash is blank if it's empty: + # + # {}.blank? # => true + # {:key => 'value'}.blank? # => false + # alias_method :blank?, :empty? end -class String #:nodoc: +class String + # A string is blank if it's empty or contains whitespaces only: + # + # "".blank? # => true + # " ".blank? # => true + # " something here ".blank? # => false + # def blank? self !~ /\S/ end end class Numeric #:nodoc: + # No number is blank: + # + # 1.blank? # => false + # 0.blank? # => false + # def blank? false end diff --git a/activesupport/lib/active_support/core_ext/object/duplicable.rb b/activesupport/lib/active_support/core_ext/object/duplicable.rb index b05325790c..02cb5dfee7 100644 --- a/activesupport/lib/active_support/core_ext/object/duplicable.rb +++ b/activesupport/lib/active_support/core_ext/object/duplicable.rb @@ -15,50 +15,89 @@ # That's why we hardcode the following cases and check duplicable? instead of # using that rescue idiom. class Object - # Can you safely .dup this object? - # False for nil, false, true, symbols, numbers, class and module objects; true otherwise. + # Can you safely dup this object? + # + # False for +nil+, +false+, +true+, symbols, numbers, class and module objects; + # true otherwise. def duplicable? true end end -class NilClass #:nodoc: +class NilClass + # +nil+ is not duplicable: + # + # nil.duplicable? # => false + # nil.dup # => TypeError: can't dup NilClass + # def duplicable? false end end -class FalseClass #:nodoc: +class FalseClass + # +false+ is not duplicable: + # + # false.duplicable? # => false + # false.dup # => TypeError: can't dup FalseClass + # def duplicable? false end end -class TrueClass #:nodoc: +class TrueClass + # +true+ is not duplicable: + # + # true.duplicable? # => false + # true.dup # => TypeError: can't dup TrueClass + # def duplicable? false end end -class Symbol #:nodoc: +class Symbol + # Symbols are not duplicable: + # + # :my_symbol.duplicable? # => false + # :my_symbol.dup # => TypeError: can't dup Symbol + # def duplicable? false end end -class Numeric #:nodoc: +class Numeric + # Numbers are not duplicable: + # + # 3.duplicable? # => false + # 3.dup # => TypeError: can't dup Fixnum + # def duplicable? false end end -class Class #:nodoc: +class Class + # Classes are not duplicable: + # + # c = Class.new # => #<Class:0x10328fd80> + # c.dup # => #<Class:0x10328fd80> + # + # Note +dup+ returned the same class object. def duplicable? false end end -class Module #:nodoc: +class Module + # Modules are not duplicable: + # + # m = Module.new # => #<Module:0x10328b6e0> + # m.dup # => #<Module:0x10328b6e0> + # + # Note +dup+ returned the same module object. def duplicable? false end diff --git a/activesupport/lib/active_support/core_ext/object/inclusion.rb b/activesupport/lib/active_support/core_ext/object/inclusion.rb new file mode 100644 index 0000000000..b5671f66d0 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/object/inclusion.rb @@ -0,0 +1,15 @@ +class Object + # Returns true if this object is included in the argument. Argument must be + # any object which responds to +#include?+. Usage: + # + # characters = ["Konata", "Kagami", "Tsukasa"] + # "Konata".in?(characters) # => true + # + # This will throw an ArgumentError if the argument doesn't respond + # to +#include?+. + def in?(another_object) + another_object.include?(self) + rescue NoMethodError + raise ArgumentError.new("The parameter passed to #in? must respond to #include?") + end +end diff --git a/activesupport/lib/active_support/core_ext/object/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb index 04619124a1..e77a9da0ec 100644 --- a/activesupport/lib/active_support/core_ext/object/try.rb +++ b/activesupport/lib/active_support/core_ext/object/try.rb @@ -9,12 +9,12 @@ class Object # # ==== Examples # - # Without try + # Without +try+ # @person && @person.name # or # @person ? @person.name : nil # - # With try + # With +try+ # @person.try(:name) # # +try+ also accepts arguments and/or a block, for the method it is trying @@ -34,7 +34,19 @@ class Object end end -class NilClass #:nodoc: +class NilClass + # Calling +try+ on +nil+ always returns +nil+. + # It becomes specially helpful when navigating through associations that may return +nil+. + # + # === Examples + # + # nil.try(:name) # => nil + # + # Without +try+ + # @person && !@person.children.blank? && @person.children.first.name + # + # With +try+ + # @person.try(:children).try(:first).try(:name) def try(*args) nil end diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb index 8fb8c31ade..72522d395c 100644 --- a/activesupport/lib/active_support/core_ext/string.rb +++ b/activesupport/lib/active_support/core_ext/string.rb @@ -11,3 +11,4 @@ require 'active_support/core_ext/string/output_safety' require 'active_support/core_ext/string/exclude' require 'active_support/core_ext/string/encoding' require 'active_support/core_ext/string/strip' +require 'active_support/core_ext/string/inquiry' diff --git a/activesupport/lib/active_support/core_ext/string/inquiry.rb b/activesupport/lib/active_support/core_ext/string/inquiry.rb new file mode 100644 index 0000000000..604f3bf4dc --- /dev/null +++ b/activesupport/lib/active_support/core_ext/string/inquiry.rb @@ -0,0 +1,13 @@ +require 'active_support/string_inquirer' + +class String + # Wraps the current string in the ActiveSupport::StringInquirer class, + # which gives you a prettier way to test for equality. Example: + # + # env = "production".inquiry + # env.production? # => true + # env.development? # => false + def inquiry + ActiveSupport::StringInquirer.new(self) + end +end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index addd4dab95..c27cbc37c5 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -9,7 +9,7 @@ class ERB # A utility method for escaping HTML tag characters. # This method is also aliased as <tt>h</tt>. # - # In your ERb templates, use this method to escape any unsafe content. For example: + # In your ERB templates, use this method to escape any unsafe content. For example: # <%=h @person.name %> # # ==== Example: diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb index ff90d7ca58..0c5962858e 100644 --- a/activesupport/lib/active_support/core_ext/time/zones.rb +++ b/activesupport/lib/active_support/core_ext/time/zones.rb @@ -34,29 +34,36 @@ class Time # end # end def zone=(time_zone) - Thread.current[:time_zone] = get_zone(time_zone) + Thread.current[:time_zone] = find_zone!(time_zone) end # Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done. def use_zone(time_zone) - old_zone, ::Time.zone = ::Time.zone, get_zone(time_zone) - yield - ensure - ::Time.zone = old_zone + new_zone = find_zone!(time_zone) + begin + old_zone, ::Time.zone = ::Time.zone, new_zone + yield + ensure + ::Time.zone = old_zone + end end - private - def get_zone(time_zone) - return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone) - # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone) - unless time_zone.respond_to?(:period_for_local) - time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone) rescue nil - end - # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone - if time_zone - time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone) - end + # Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones. + def find_zone!(time_zone) + return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone) + # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone) + unless time_zone.respond_to?(:period_for_local) + time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone) end + # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone + time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone) + rescue TZInfo::InvalidTimezoneIdentifier + raise ArgumentError, "Invalid Timezone: #{time_zone}" + end + + def find_zone(time_zone) + find_zone!(time_zone) rescue nil + end end # Returns the simultaneous time in <tt>Time.zone</tt>. @@ -74,6 +81,6 @@ class Time def in_time_zone(zone = ::Time.zone) return self unless zone - ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone)) + ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.find_zone!(zone)) end end diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb index ce0775a690..45b9dda5ca 100644 --- a/activesupport/lib/active_support/deprecation.rb +++ b/activesupport/lib/active_support/deprecation.rb @@ -9,7 +9,7 @@ module ActiveSupport # The version the deprecated behavior will be removed, by default. attr_accessor :deprecation_horizon end - self.deprecation_horizon = '3.1' + self.deprecation_horizon = '3.2' # By default, warnings are not silenced and debugging is off. self.silenced = false diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb index e136e4c5b3..d5d55b7207 100644 --- a/activesupport/lib/active_support/inflector/inflections.rb +++ b/activesupport/lib/active_support/inflector/inflections.rb @@ -96,7 +96,7 @@ module ActiveSupport def clear(scope = :all) case scope when :all - @plurals, @singulars, @uncountables = [], [], [] + @plurals, @singulars, @uncountables, @humans = [], [], [], [] else instance_variable_set "@#{scope}", [] end diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb deleted file mode 100644 index 533ba25da3..0000000000 --- a/activesupport/lib/active_support/json/backends/jsongem.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'json' unless defined?(JSON) - -module ActiveSupport - module JSON - module Backends - module JSONGem - ParseError = ::JSON::ParserError - extend self - - # Parses a JSON string or IO and convert it into an object - def decode(json) - if json.respond_to?(:read) - json = json.read - end - data = ::JSON.parse(json) - if ActiveSupport.parse_json_times - convert_dates_from(data) - else - data - end - end - - private - def convert_dates_from(data) - case data - when nil - nil - when DATE_REGEX - begin - DateTime.parse(data) - rescue ArgumentError - data - end - when Array - data.map! { |d| convert_dates_from(d) } - when Hash - data.each do |key, value| - data[key] = convert_dates_from(value) - end - else - data - end - end - end - end - end -end diff --git a/activesupport/lib/active_support/json/backends/yajl.rb b/activesupport/lib/active_support/json/backends/yajl.rb deleted file mode 100644 index 58818658c7..0000000000 --- a/activesupport/lib/active_support/json/backends/yajl.rb +++ /dev/null @@ -1,44 +0,0 @@ -require 'yajl' unless defined?(Yajl) - -module ActiveSupport - module JSON - module Backends - module Yajl - ParseError = ::Yajl::ParseError - extend self - - # Parses a JSON string or IO and convert it into an object - def decode(json) - data = ::Yajl::Parser.new.parse(json) - if ActiveSupport.parse_json_times - convert_dates_from(data) - else - data - end - end - - private - def convert_dates_from(data) - case data - when nil - nil - when DATE_REGEX - begin - DateTime.parse(data) - rescue ArgumentError - data - end - when Array - data.map! { |d| convert_dates_from(d) } - when Hash - data.each do |key, value| - data[key] = convert_dates_from(value) - end - else - data - end - end - end - end - end -end diff --git a/activesupport/lib/active_support/json/backends/yaml.rb b/activesupport/lib/active_support/json/backends/yaml.rb deleted file mode 100644 index 077eda548a..0000000000 --- a/activesupport/lib/active_support/json/backends/yaml.rb +++ /dev/null @@ -1,111 +0,0 @@ -require 'active_support/core_ext/string/starts_ends_with' - -module ActiveSupport - module JSON - module Backends - module Yaml - ParseError = ::StandardError - extend self - - EXCEPTIONS = [::ArgumentError] # :nodoc: - begin - require 'psych' - EXCEPTIONS << Psych::SyntaxError - rescue LoadError - end - - # Parses a JSON string or IO and converts it into an object - def decode(json) - if json.respond_to?(:read) - json = json.read - end - YAML.load(convert_json_to_yaml(json)) - rescue *EXCEPTIONS => e - raise ParseError, "Invalid JSON string: '%s'" % json - end - - protected - # Ensure that ":" and "," are always followed by a space - def convert_json_to_yaml(json) #:nodoc: - require 'strscan' unless defined? ::StringScanner - scanner, quoting, marks, pos, times = ::StringScanner.new(json), false, [], nil, [] - while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/) - case char = scanner[1] - when '"', "'" - if !quoting - quoting = char - pos = scanner.pos - elsif quoting == char - if valid_date?(json[pos..scanner.pos-2]) - # found a date, track the exact positions of the quotes so we can - # overwrite them with spaces later. - times << pos - end - quoting = false - end - when ":","," - marks << scanner.pos - 1 unless quoting - when "\\" - scanner.skip(/\\/) - end - end - - if marks.empty? - json.gsub(/\\([\\\/]|u[[:xdigit:]]{4})/) do - ustr = $1 - if ustr.start_with?('u') - char = [ustr[1..-1].to_i(16)].pack("U") - # "\n" needs extra escaping due to yaml formatting - char == "\n" ? "\\n" : char - elsif ustr == '\\' - '\\\\' - else - ustr - end - end - else - left_pos = [-1].push(*marks) - right_pos = marks << scanner.pos + scanner.rest_size - output = [] - left_pos.each_with_index do |left, i| - scanner.pos = left.succ - chunk = scanner.peek(right_pos[i] - scanner.pos + 1) - # overwrite the quotes found around the dates with spaces - while times.size > 0 && times[0] <= right_pos[i] - chunk.insert(times.shift - scanner.pos - 1, '! ') - end - chunk.gsub!(/\\([\\\/]|u[[:xdigit:]]{4})/) do - ustr = $1 - if ustr.start_with?('u') - char = [ustr[1..-1].to_i(16)].pack("U") - # "\n" needs extra escaping due to yaml formatting - char == "\n" ? "\\n" : char - elsif ustr == '\\' - '\\\\' - else - ustr - end - end - output << chunk - end - output = output * " " - - output.gsub!(/\\\//, '/') - output - end - end - - private - def valid_date?(date_string) - begin - date_string =~ DATE_REGEX && DateTime.parse(date_string) - rescue ArgumentError - false - end - end - - end - end - end -end - diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb index c1f6330c6c..cbeb6c0a28 100644 --- a/activesupport/lib/active_support/json/decoding.rb +++ b/activesupport/lib/active_support/json/decoding.rb @@ -1,32 +1,31 @@ require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/module/delegation' +require 'multi_json' module ActiveSupport # Look for and parse json strings that look like ISO 8601 times. mattr_accessor :parse_json_times module JSON - # Listed in order of preference. - DECODERS = %w(Yajl Yaml) - class << self - attr_reader :parse_error - delegate :decode, :to => :backend + def decode(json, options ={}) + data = MultiJson.decode(json, options) + if ActiveSupport.parse_json_times + convert_dates_from(data) + else + data + end + end - def backend - set_default_backend unless defined?(@backend) - @backend + def engine + MultiJson.engine end + alias :backend :engine - def backend=(name) - if name.is_a?(Module) - @backend = name - else - require "active_support/json/backends/#{name.to_s.downcase}" - @backend = ActiveSupport::JSON::Backends::const_get(name) - end - @parse_error = @backend::ParseError + def engine=(name) + MultiJson.engine = name end + alias :backend= :engine= def with_backend(name) old_backend, self.backend = backend, name @@ -35,15 +34,30 @@ module ActiveSupport self.backend = old_backend end - def set_default_backend - DECODERS.find do |name| + def parse_error + MultiJson::DecodeError + end + + private + + def convert_dates_from(data) + case data + when nil + nil + when DATE_REGEX begin - self.backend = name - true - rescue LoadError - # Try next decoder. - false + DateTime.parse(data) + rescue ArgumentError + data end + when Array + data.map! { |d| convert_dates_from(d) } + when Hash + data.each do |key, value| + data[key] = convert_dates_from(value) + end + else + data end end end diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb index 10675edac5..1c4dd24227 100644 --- a/activesupport/lib/active_support/log_subscriber.rb +++ b/activesupport/lib/active_support/log_subscriber.rb @@ -81,7 +81,7 @@ module ActiveSupport # Flush all log_subscribers' logger. def flush_all! - flushable_loggers.each(&:flush) + flushable_loggers.each { |log| log.flush } end end diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb index c2deba3b1b..04df2ea562 100644 --- a/activesupport/lib/active_support/railtie.rb +++ b/activesupport/lib/active_support/railtie.rb @@ -46,7 +46,7 @@ module ActiveSupport # If assigned value cannot be matched to a TimeZone, an exception will be raised. initializer "active_support.initialize_time_zone" do |app| require 'active_support/core_ext/time/zones' - zone_default = Time.__send__(:get_zone, app.config.time_zone) + zone_default = Time.find_zone!(app.config.time_zone) unless zone_default raise \ diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index fb52fc7083..8d6c27e381 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -5,16 +5,9 @@ require 'active_support/testing/deprecation' require 'active_support/testing/declarative' require 'active_support/testing/pending' require 'active_support/testing/isolation' +require 'active_support/testing/mochaing' require 'active_support/core_ext/kernel/reporting' -begin - silence_warnings { require 'mocha' } -rescue LoadError - # Fake Mocha::ExpectationError so we can rescue it in #run. Bleh. - Object.const_set :Mocha, Module.new - Mocha.const_set :ExpectationError, Class.new(StandardError) -end - module ActiveSupport class TestCase < ::Test::Unit::TestCase if defined? MiniTest diff --git a/activesupport/lib/active_support/testing/mochaing.rb b/activesupport/lib/active_support/testing/mochaing.rb new file mode 100644 index 0000000000..4ad75a6681 --- /dev/null +++ b/activesupport/lib/active_support/testing/mochaing.rb @@ -0,0 +1,7 @@ +begin + silence_warnings { require 'mocha' } +rescue LoadError + # Fake Mocha::ExpectationError so we can rescue it in #run. Bleh. + Object.const_set :Mocha, Module.new + Mocha.const_set :ExpectationError, Class.new(StandardError) +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/testing/pending.rb b/activesupport/lib/active_support/testing/pending.rb index 3d119e2fba..feac7bc347 100644 --- a/activesupport/lib/active_support/testing/pending.rb +++ b/activesupport/lib/active_support/testing/pending.rb @@ -11,32 +11,36 @@ module ActiveSupport @@at_exit = false def pending(description = "", &block) - if description.is_a?(Symbol) - is_pending = $tags[description] - return block.call unless is_pending - end + if defined?(::MiniTest) + skip(description.blank? ? nil : description) + else + if description.is_a?(Symbol) + is_pending = $tags[description] + return block.call unless is_pending + end - if block_given? - failed = false + if block_given? + failed = false - begin - block.call - rescue Exception - failed = true - end + begin + block.call + rescue Exception + failed = true + end - flunk("<#{description}> did not fail.") unless failed - end + flunk("<#{description}> did not fail.") unless failed + end - caller[0] =~ (/(.*):(.*):in `(.*)'/) - @@pending_cases << "#{$3} at #{$1}, line #{$2}" - print "P" + caller[0] =~ (/(.*):(.*):in `(.*)'/) + @@pending_cases << "#{$3} at #{$1}, line #{$2}" + print "P" - @@at_exit ||= begin - at_exit do - puts "\nPending Cases:" - @@pending_cases.each do |test_case| - puts test_case + @@at_exit ||= begin + at_exit do + puts "\nPending Cases:" + @@pending_cases.each do |test_case| + puts test_case + end end end end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index c66aa78ce8..3d092529d6 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -1,5 +1,6 @@ require "active_support/values/time_zone" require 'active_support/core_ext/object/acts_like' +require 'active_support/core_ext/object/inclusion' module ActiveSupport # A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are @@ -309,7 +310,7 @@ module ActiveSupport end def marshal_load(variables) - initialize(variables[0].utc, ::Time.__send__(:get_zone, variables[1]), variables[2].utc) + initialize(variables[0].utc, ::Time.find_zone(variables[1]), variables[2].utc) end # Ensure proxy class responds to all methods that underlying time instance responds to. @@ -344,7 +345,7 @@ module ActiveSupport end def duration_of_variable_length?(obj) - ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :days].include? p[0] } + ActiveSupport::Duration === obj && obj.parts.any? {|p| p[0].in?([:years, :months, :days]) } end end end |