diff options
Diffstat (limited to 'activesupport/lib/active_support')
18 files changed, 279 insertions, 176 deletions
diff --git a/activesupport/lib/active_support/buffered_logger.rb b/activesupport/lib/active_support/buffered_logger.rb index 136e245859..775f9928e6 100644 --- a/activesupport/lib/active_support/buffered_logger.rb +++ b/activesupport/lib/active_support/buffered_logger.rb @@ -1,5 +1,9 @@ require 'thread' +require 'logger' +require 'active_support/core_ext/logger' require 'active_support/core_ext/class/attribute_accessors' +require 'active_support/deprecation' +require 'fileutils' module ActiveSupport # Inspired by the buffered logger idea by Ezra @@ -25,40 +29,35 @@ module ActiveSupport # Silences the logger for the duration of the block. def silence(temporary_level = ERROR) if silencer - old_logger_level = @tmp_levels[Thread.current] begin - @tmp_levels[Thread.current] = temporary_level - yield self + logger = self.class.new @log_dest, temporary_level + yield logger ensure - if old_logger_level - @tmp_levels[Thread.current] = old_logger_level - else - @tmp_levels.delete(Thread.current) - end + logger.close end else yield self end end + deprecate :silence - attr_writer :level attr_reader :auto_flushing + deprecate :auto_flushing def initialize(log, level = DEBUG) @level = level - @tmp_levels = {} - @buffer = Hash.new { |h,k| h[k] = [] } - @auto_flushing = 1 - @guard = Mutex.new - - if log.respond_to?(:write) - @log = log - elsif File.exist?(log) - @log = open_log(log, (File::WRONLY | File::APPEND)) - else - FileUtils.mkdir_p(File.dirname(log)) - @log = open_log(log, (File::WRONLY | File::APPEND | File::CREAT)) + @log_dest = log + + unless log.respond_to?(:write) + unless File.exist?(File.dirname(log)) + ActiveSupport::Deprecation.warn(<<-eowarn) +Automatic directory creation for '#{log}' is deprecated. Please make sure the directory for your log file exists before creating the logger. + eowarn + FileUtils.mkdir_p(File.dirname(log)) + end end + + @log = open_logfile log end def open_log(log, mode) @@ -67,20 +66,18 @@ module ActiveSupport open_log.sync = true end end + deprecate :open_log def level - @tmp_levels[Thread.current] || @level + @log.level + end + + def level=(l) + @log.level = l end def add(severity, message = nil, progname = nil, &block) - return if level > severity - message = (message || (block && block.call) || progname).to_s - # If a newline is necessary then create a new message ending with a newline. - # Ensures that the original message is not mutated. - message = "#{message}\n" unless message[-1] == ?\n - buffer << message - auto_flush - message + @log.add(severity, message, progname, &block) end # Dynamically add methods such as: @@ -104,62 +101,25 @@ module ActiveSupport # never auto-flush. If you turn auto-flushing off, be sure to regularly # flush the log yourself -- it will eat up memory until you do. def auto_flushing=(period) - @auto_flushing = - case period - when true; 1 - when false, nil, 0; MAX_BUFFER_SIZE - when Integer; period - else raise ArgumentError, "Unrecognized auto_flushing period: #{period.inspect}" - end end + deprecate :auto_flushing= def flush - @guard.synchronize do - write_buffer(buffer) - - # Important to do this even if buffer was empty or else @buffer will - # accumulate empty arrays for each request where nothing was logged. - clear_buffer + end + deprecate :flush - # Clear buffers associated with dead threads or else spawned threads - # that don't call flush will result in a memory leak. - flush_dead_buffers - end + def respond_to?(method, include_private = false) + return false if method.to_s == "flush" + super end def close - flush - @log.close if @log.respond_to?(:close) - @log = nil + @log.close end - protected - def auto_flush - flush if buffer.size >= @auto_flushing - end - - def buffer - @buffer[Thread.current] - end - - def clear_buffer - @buffer.delete(Thread.current) - end - - # Find buffers created by threads that are no longer alive and flush them to the log - # in order to prevent memory leaks from spawned threads. - def flush_dead_buffers #:nodoc: - @buffer.keys.reject{|thread| thread.alive?}.each do |thread| - buffer = @buffer[thread] - write_buffer(buffer) - @buffer.delete(thread) - end - end - - def write_buffer(buffer) - buffer.each do |content| - @log.write(content) - end - end + private + def open_logfile(log) + Logger.new log + end end end diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 07f5fcdeb3..9711ed6f73 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -16,6 +16,7 @@ module ActiveSupport autoload :FileStore, 'active_support/cache/file_store' autoload :MemoryStore, 'active_support/cache/memory_store' autoload :MemCacheStore, 'active_support/cache/mem_cache_store' + autoload :NullStore, 'active_support/cache/null_store' # These options mean something to all cache implementations. Individual cache # implementations may support additional options. diff --git a/activesupport/lib/active_support/cache/null_store.rb b/activesupport/lib/active_support/cache/null_store.rb new file mode 100644 index 0000000000..4427eaafcd --- /dev/null +++ b/activesupport/lib/active_support/cache/null_store.rb @@ -0,0 +1,44 @@ +module ActiveSupport + module Cache + # A cache store implementation which doesn't actually store anything. Useful in + # development and test environments where you don't want caching turned on but + # need to go through the caching interface. + # + # This cache does implement the local cache strategy, so values will actually + # be cached inside blocks that utilize this strategy. See + # ActiveSupport::Cache::Strategy::LocalCache for more details. + class NullStore < Store + def initialize(options = nil) + super(options) + extend Strategy::LocalCache + end + + def clear(options = nil) + end + + def cleanup(options = nil) + end + + def increment(name, amount = 1, options = nil) + end + + def decrement(name, amount = 1, options = nil) + end + + def delete_matched(matcher, options = nil) + end + + protected + def read_entry(key, options) # :nodoc: + end + + def write_entry(key, entry, options) # :nodoc: + true + end + + def delete_entry(key, options) # :nodoc: + false + end + end + end +end diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index ea37355fc1..11069301f1 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -81,6 +81,14 @@ module ActiveSupport send("_run_#{kind}_callbacks", *args, &block) end + private + + # A hook invoked everytime a before callback is halted. + # This can be overriden in AS::Callback implementors in order + # to provide better debugging/logging. + def halted_callback_hook(filter) + end + class Callback #:nodoc:# @@_callback_sequence = 0 @@ -173,12 +181,14 @@ module ActiveSupport # end <<-RUBY_EVAL if !halted && #{@compiled_options} - # This double assignment is to prevent warnings in 1.9.3. I would - # remove the `result` variable, but apparently some other - # generated code is depending on this variable being set sometimes - # and sometimes not. + # This double assignment is to prevent warnings in 1.9.3 as + # the `result` variable is not always used except if the + # terminator code refers to it. result = result = #{@filter} halted = (#{chain.config[:terminator]}) + if halted + halted_callback_hook(#{@raw_filter.inspect.inspect}) + end end RUBY_EVAL when :around diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index 9343bb7106..d9856f2e84 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -63,6 +63,13 @@ module Enumerable end end + # Plucks the value of the passed method for each element and returns the result as an array. Example: + # + # people.pluck(:name) # => [ "David Heinemeier Hansson", "Jamie Heinemeier Hansson" ] + def pluck(method) + collect { |element| element.send(method) } + end + # Iterates over a collection, passing the current element *and* the # +memo+ to the block. Handy for building up hashes or # reducing collections down to one object. Examples: diff --git a/activesupport/lib/active_support/core_ext/module/synchronization.rb b/activesupport/lib/active_support/core_ext/module/synchronization.rb index ed16c2f71b..061621c0ef 100644 --- a/activesupport/lib/active_support/core_ext/module/synchronization.rb +++ b/activesupport/lib/active_support/core_ext/module/synchronization.rb @@ -1,6 +1,7 @@ require 'thread' require 'active_support/core_ext/module/aliasing' require 'active_support/core_ext/array/extract_options' +require 'active_support/core_ext/module/deprecation' class Module # Synchronize access around a method, delegating synchronization to a @@ -40,4 +41,5 @@ class Module alias_method_chain method, :synchronization end end + deprecate :synchronize end diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb index aae1cfccf2..400db2ce39 100644 --- a/activesupport/lib/active_support/core_ext/string/multibyte.rb +++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb @@ -44,7 +44,7 @@ class String end end - def is_utf8? #:nodoc + def is_utf8? case encoding when Encoding::UTF_8 valid_encoding? 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 5d7f74bb65..c6d861d124 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -6,21 +6,33 @@ class ERB HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' } JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' } - # 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: - # <%=h @person.name %> - # - # ==== Example: - # puts html_escape("is a > 0 & a < 10?") - # # => is a > 0 & a < 10? - def html_escape(s) - s = s.to_s - if s.html_safe? - s - else - s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<").html_safe + # Detect whether 1.9 can transcode with XML escaping. + if '"><&""' == ('><&"'.encode('utf-8', :xml => :attr) rescue false) + # 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: + # <%=h @person.name %> + # + # ==== Example: + # puts html_escape("is a > 0 & a < 10?") + # # => is a > 0 & a < 10? + def html_escape(s) + s = s.to_s + if s.html_safe? + s + else + s.encode(s.encoding, :xml => :attr)[1...-1].html_safe + end + end + else + def html_escape(s) #:nodoc: + s = s.to_s + if s.html_safe? + s + else + s.gsub(/[&"><]/n) { |special| HTML_ESCAPE[special] }.html_safe + end end end diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 1372e71a61..43dd22654a 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -71,14 +71,24 @@ module ActiveSupport #:nodoc: # # This is handled by walking back up the watch stack and adding the constants # found by child.rb to the list of original constants in parent.rb - class WatchStack < Hash + class WatchStack + include Enumerable + # @watching is a stack of lists of constants being watched. For instance, # if parent.rb is autoloaded, the stack will look like [[Object]]. If parent.rb # then requires namespace/child.rb, the stack will look like [[Object], [Namespace]]. def initialize @watching = [] - super { |h,k| h[k] = [] } + @stack = Hash.new { |h,k| h[k] = [] } + end + + def each(&block) + @stack.each(&block) + end + + def watching? + !@watching.empty? end # return a list of new constants found since the last call to watch_namespaces @@ -89,7 +99,7 @@ module ActiveSupport #:nodoc: @watching.last.each do |namespace| # Retrieve the constants that were present under the namespace when watch_namespaces # was originally called - original_constants = self[namespace].last + original_constants = @stack[namespace].last mod = Inflector.constantize(namespace) if Dependencies.qualified_const_defined?(namespace) next unless mod.is_a?(Module) @@ -102,7 +112,7 @@ module ActiveSupport #:nodoc: # element of self[Object] will be an Array of the constants that were present # before parent.rb was required. The second element will be an Array of the # constants that were present before child.rb was required. - self[namespace].each do |namespace_constants| + @stack[namespace].each do |namespace_constants| namespace_constants.concat(new_constants) end @@ -126,13 +136,14 @@ module ActiveSupport #:nodoc: Inflector.constantize(module_name).local_constant_names : [] watching << module_name - self[module_name] << original_constants + @stack[module_name] << original_constants end @watching << watching end + private def pop_modules(modules) - modules.each { |mod| self[mod].pop } + modules.each { |mod| @stack[mod].pop } end end @@ -219,8 +230,8 @@ module ActiveSupport #:nodoc: end def load_dependency(file) - if Dependencies.load? - Dependencies.new_constants_in(Object) { yield }.presence + if Dependencies.load? && ActiveSupport::Dependencies.constant_watch_stack.watching? + Dependencies.new_constants_in(Object) { yield } else yield end @@ -229,13 +240,13 @@ module ActiveSupport #:nodoc: raise end - def load(file, *) + def load(file, wrap = false) result = false load_dependency(file) { result = super } result end - def require(file, *) + def require(file) result = false load_dependency(file) { result = super } result diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb index f76ddff038..a4ad2da137 100644 --- a/activesupport/lib/active_support/file_update_checker.rb +++ b/activesupport/lib/active_support/file_update_checker.rb @@ -1,8 +1,28 @@ +require "active_support/core_ext/array/wrap" +require "active_support/core_ext/array/extract_options" + module ActiveSupport - # This class is responsible to track files and invoke the given block - # whenever one of these files are changed. For example, this class - # is used by Rails to reload the I18n framework whenever they are - # changed upon a new request. + # \FileUpdateChecker specifies the API used by Rails to watch files + # and control reloading. The API depends on four methods: + # + # * +initialize+ which expects two parameters and one block as + # described below; + # + # * +updated?+ which returns a boolean if there were updates in + # the filesystem or not; + # + # * +execute+ which executes the given block on initialization + # and updates the counter to the latest timestamp; + # + # * +execute_if_updated+ which just executes the block if it was updated; + # + # After initialization, a call to +execute_if_updated+ must execute + # the block only if there was really a change in the filesystem. + # + # == Examples + # + # This class is used by Rails to reload the I18n framework whenever + # they are changed upon a new request. # # i18n_reloader = ActiveSupport::FileUpdateChecker.new(paths) do # I18n.reload! @@ -13,24 +33,89 @@ module ActiveSupport # end # class FileUpdateChecker - attr_reader :paths, :last_update_at - - def initialize(paths, calculate=false, &block) - @paths = paths + # It accepts two parameters on initialization. The first is an array + # of files and the second is an optional hash of directories. The hash must + # have directories as keys and the value is an array of extensions to be + # watched under that directory. + # + # This method must also receive a block that will be called once a path changes. + # + # == Implementation details + # + # This particular implementation checks for added and updated files, + # but not removed files. Directories lookup are compiled to a glob for + # performance. Therefore, while someone can add new files to the +files+ + # array after initialization (and parts of Rails do depend on this feature), + # adding new directories after initialization is not allowed. + # + # Notice that other objects that implements FileUpdateChecker API may + # not even allow new files to be added after initialization. If this + # is the case, we recommend freezing the +files+ after initialization to + # avoid changes that won't make effect. + def initialize(files, dirs={}, &block) + @files = files + @glob = compile_glob(dirs) @block = block - @last_update_at = calculate ? updated_at : nil + @updated_at = nil + @last_update_at = updated_at + end + + # Check if any of the entries were updated. If so, the updated_at + # value is cached until the block is executed via +execute+ or +execute_if_updated+ + def updated? + current_updated_at = updated_at + if @last_update_at < current_updated_at + @updated_at = updated_at + true + else + false + end end - def updated_at - paths.map { |path| File.mtime(path) }.max + # Executes the given block and updates the counter to latest timestamp. + def execute + @last_update_at = updated_at + @block.call + ensure + @updated_at = nil end + # Execute the block given if updated. def execute_if_updated - current_update_at = self.updated_at - if @last_update_at != current_update_at - @last_update_at = current_update_at - @block.call + if updated? + execute + true + else + false + end + end + + private + + def updated_at #:nodoc: + @updated_at || begin + all = [] + all.concat @files.select { |f| File.exists?(f) } + all.concat Dir[@glob] if @glob + all.map { |path| File.mtime(path) }.max || Time.at(0) end end + + def compile_glob(hash) #:nodoc: + hash.freeze # Freeze so changes aren't accidently pushed + return if hash.empty? + + globs = [] + hash.each do |key, value| + globs << "#{key}/**/*#{compile_ext(value)}" + end + "{#{globs.join(",")}}" + end + + def compile_ext(array) #:nodoc: + array = Array.wrap(array) + return if array.empty? + ".{#{array.join(",")}}" + end end end diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 636f019cd5..674e4acfd6 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -16,6 +16,10 @@ module ActiveSupport dup end + def nested_under_indifferent_access + self + end + def initialize(constructor = {}) if constructor.is_a?(Hash) super() diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb index 4c59fe9ac9..bbeb8d82c6 100644 --- a/activesupport/lib/active_support/i18n_railtie.rb +++ b/activesupport/lib/active_support/i18n_railtie.rb @@ -10,14 +10,19 @@ module I18n config.i18n.fallbacks = ActiveSupport::OrderedOptions.new def self.reloader - @reloader ||= ActiveSupport::FileUpdateChecker.new([]){ I18n.reload! } + @reloader ||= ActiveSupport::FileUpdateChecker.new(reloader_paths){ I18n.reload! } + end + + def self.reloader_paths + @reloader_paths ||= [] end # Add <tt>I18n::Railtie.reloader</tt> to ActionDispatch callbacks. Since, at this # point, no path was added to the reloader, I18n.reload! is not triggered # on to_prepare callbacks. This will only happen on the config.after_initialize # callback below. - initializer "i18n.callbacks" do + initializer "i18n.callbacks" do |app| + app.reloaders << I18n::Railtie.reloader ActionDispatch::Reloader.to_prepare do I18n::Railtie.reloader.execute_if_updated end @@ -58,8 +63,8 @@ module I18n init_fallbacks(fallbacks) if fallbacks && validate_fallbacks(fallbacks) - reloader.paths.concat I18n.load_path - reloader.execute_if_updated + reloader_paths.concat I18n.load_path + reloader.execute @i18n_inited = true end diff --git a/activesupport/lib/active_support/inflections.rb b/activesupport/lib/active_support/inflections.rb index daf2a1e1d9..527cce2594 100644 --- a/activesupport/lib/active_support/inflections.rb +++ b/activesupport/lib/active_support/inflections.rb @@ -16,8 +16,8 @@ module ActiveSupport inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies') inflect.plural(/(x|ch|ss|sh)$/i, '\1es') inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices') - inflect.plural(/([m|l])ouse$/i, '\1ice') - inflect.plural(/([m|l])ice$/i, '\1ice') + inflect.plural(/(m|l)ouse$/i, '\1ice') + inflect.plural(/(m|l)ice$/i, '\1ice') inflect.plural(/^(ox)$/i, '\1en') inflect.plural(/^(oxen)$/i, '\1') inflect.plural(/(quiz)$/i, '\1zes') @@ -35,7 +35,7 @@ module ActiveSupport inflect.singular(/(s)eries$/i, '\1eries') inflect.singular(/(m)ovies$/i, '\1ovie') inflect.singular(/(x|ch|ss|sh)es$/i, '\1') - inflect.singular(/([m|l])ice$/i, '\1ouse') + inflect.singular(/(m|l)ice$/i, '\1ouse') inflect.singular(/(bus)es$/i, '\1') inflect.singular(/(o)es$/i, '\1') inflect.singular(/(shoe)s$/i, '\1') diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index b0fd3a3c0e..925fa2a2c7 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -281,4 +281,4 @@ class DateTime strftime('%Y/%m/%d %H:%M:%S %z') end end -end +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/tagged_logging.rb b/activesupport/lib/active_support/tagged_logging.rb index a59fc26d5d..0f3ac0c132 100644 --- a/activesupport/lib/active_support/tagged_logging.rb +++ b/activesupport/lib/active_support/tagged_logging.rb @@ -30,7 +30,7 @@ module ActiveSupport @logger.add(severity, "#{tags_text}#{message}", progname, &block) end - %w( fatal error warn info debug unkown ).each do |severity| + %w( fatal error warn info debug unknown ).each do |severity| eval <<-EOM, nil, __FILE__, __LINE__ + 1 def #{severity}(progname = nil, &block) add(Logger::#{severity.upcase}, progname, &block) @@ -38,9 +38,9 @@ module ActiveSupport EOM end - def flush(*args) + def flush @tags.delete(Thread.current) - @logger.flush(*args) if @logger.respond_to?(:flush) + @logger.flush if @logger.respond_to?(:flush) end def method_missing(method, *args) diff --git a/activesupport/lib/active_support/whiny_nil.rb b/activesupport/lib/active_support/whiny_nil.rb index 577db5018e..a065233679 100644 --- a/activesupport/lib/active_support/whiny_nil.rb +++ b/activesupport/lib/active_support/whiny_nil.rb @@ -1,21 +1,6 @@ # Extensions to +nil+ which allow for more helpful error messages for people who # are new to Rails. # -# Ruby raises NoMethodError if you invoke a method on an object that does not -# respond to it: -# -# $ ruby -e nil.destroy -# -e:1: undefined method `destroy' for nil:NilClass (NoMethodError) -# -# With these extensions, if the method belongs to the public interface of the -# classes in NilClass::WHINERS the error message suggests which could be the -# actual intended class: -# -# $ rails runner nil.destroy -# ... -# You might have expected an instance of ActiveRecord::Base. -# ... -# # NilClass#id exists in Ruby 1.8 (though it is deprecated). Since +id+ is a fundamental # method of Active Record models NilClass#id is redefined as well to raise a RuntimeError # and warn the user. She probably wanted a model database identifier and the 4 @@ -25,36 +10,13 @@ # By default it is on in development and test modes, and it is off in production # mode. class NilClass - METHOD_CLASS_MAP = Hash.new - def self.add_whiner(klass) - methods = klass.public_instance_methods - public_instance_methods - class_name = klass.name - methods.each { |method| METHOD_CLASS_MAP[method.to_sym] = class_name } + ActiveSupport::Deprecation.warn "NilClass.add_whiner is deprecated and this functionality is " \ + "removed from Rails versions as it affects Ruby 1.9 performance.", caller end - add_whiner ::Array - # Raises a RuntimeError when you attempt to call +id+ on +nil+. def id raise RuntimeError, "Called id for nil, which would mistakenly be #{object_id} -- if you really wanted the id of nil, use object_id", caller end - - private - def method_missing(method, *args) - if klass = METHOD_CLASS_MAP[method] - raise_nil_warning_for klass, method, caller - else - super - end - end - - # Raises a NoMethodError when you attempt to call a method on +nil+. - def raise_nil_warning_for(class_name = nil, selector = nil, with_caller = nil) - message = "You have a nil object when you didn't expect it!" - message << "\nYou might have expected an instance of #{class_name}." if class_name - message << "\nThe error occurred while evaluating nil.#{selector}" if selector - - raise NoMethodError, message, with_caller || caller - end end diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb index 93a8474c05..6c222b83ba 100644 --- a/activesupport/lib/active_support/xml_mini/jdom.rb +++ b/activesupport/lib/active_support/xml_mini/jdom.rb @@ -70,7 +70,7 @@ module ActiveSupport hash = get_attributes(element) child_nodes = element.child_nodes - if child_nodes.any? + if child_nodes.length > 0 for i in 0...child_nodes.length child = child_nodes.item(i) merge_element!(hash, child) unless child.node_type == Node.TEXT_NODE diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb index fb539e9c88..04ec9e8ab8 100644 --- a/activesupport/lib/active_support/xml_mini/nokogiri.rb +++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb @@ -26,7 +26,7 @@ module ActiveSupport else data.ungetc(char) doc = Nokogiri::XML(data) - raise doc.errors.first if doc.errors.any? + raise doc.errors.first if doc.errors.length > 0 doc.to_hash end end |