From 6de83562f91028629bd24447aa521bc72ef8277a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 27 Feb 2009 14:22:39 +0100 Subject: Force all internal calls to Array#to_sentence to use English [#2010 state:resolved] --- activesupport/lib/active_support/core_ext/array/conversions.rb | 5 ++--- activesupport/lib/active_support/duration.rb | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index a9b50ca92d..ba8e022fb2 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -7,10 +7,9 @@ module ActiveSupport #:nodoc: # * :two_words_connector - The sign or word used to join the elements in arrays with two elements (default: " and ") # * :last_word_connector - The sign or word used to join the last element in arrays with three or more elements (default: ", and ") def to_sentence(options = {}) - - default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale]) + default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale]) default_two_words_connector = I18n.translate(:'support.array.two_words_connector', :locale => options[:locale]) - default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale]) + default_last_word_connector = I18n.translate(:'support.array.last_word_connector', :locale => options[:locale]) # Try to emulate to_senteces previous to 2.3 if options.has_key?(:connector) || options.has_key?(:skip_last_comma) diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb index c41e86dfd1..f64661c5b1 100644 --- a/activesupport/lib/active_support/duration.rb +++ b/activesupport/lib/active_support/duration.rb @@ -70,7 +70,7 @@ module ActiveSupport [:years, :months, :days, :minutes, :seconds].map do |length| n = consolidated[length] "#{n} #{n == 1 ? length.to_s.singularize : length.to_s}" if n.nonzero? - end.compact.to_sentence + end.compact.to_sentence(:locale => :en) end protected -- cgit v1.2.3 From 77b0994c7835610982d708ce7ce5cd95e6e99e5a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 27 Feb 2009 14:46:23 +0100 Subject: Prep for RC2 later today --- activesupport/CHANGELOG | 2 +- activesupport/lib/active_support/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 70bea27cd1..5d9b77bbf5 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,4 +1,4 @@ -*Edge* +*2.3.1 [RC2] (February 27th, 2009)* * Update bundled memcache-client from 1.5.0.5 to 1.6.4.99. See http://www.mikeperham.com/2009/02/15/memcache-client-performance/ [Mike Perham] diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb index 3e2b29b327..8b65fffa08 100644 --- a/activesupport/lib/active_support/version.rb +++ b/activesupport/lib/active_support/version.rb @@ -2,7 +2,7 @@ module ActiveSupport module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 0 + TINY = 1 STRING = [MAJOR, MINOR, TINY].join('.') end -- cgit v1.2.3 From 943d64b1c857944666bff2572857abe866615274 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Fri, 27 Feb 2009 17:07:06 +0100 Subject: Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) (Akira Matsuda) [#2038 state:committed] Signed-off-by: David Heinemeier Hansson --- activesupport/CHANGELOG | 2 + activesupport/lib/active_support/vendor.rb | 4 +- .../active_support/vendor/i18n-0.1.1/.gitignore | 3 - .../active_support/vendor/i18n-0.1.1/MIT-LICENSE | 20 - .../vendor/i18n-0.1.1/README.textile | 20 - .../lib/active_support/vendor/i18n-0.1.1/Rakefile | 5 - .../active_support/vendor/i18n-0.1.1/i18n.gemspec | 27 - .../active_support/vendor/i18n-0.1.1/lib/i18n.rb | 199 -------- .../vendor/i18n-0.1.1/lib/i18n/backend/simple.rb | 222 -------- .../vendor/i18n-0.1.1/lib/i18n/exceptions.rb | 53 -- .../active_support/vendor/i18n-0.1.1/test/all.rb | 5 - .../vendor/i18n-0.1.1/test/i18n_exceptions_test.rb | 100 ---- .../vendor/i18n-0.1.1/test/i18n_test.rb | 125 ----- .../vendor/i18n-0.1.1/test/locale/en.rb | 1 - .../vendor/i18n-0.1.1/test/locale/en.yml | 3 - .../vendor/i18n-0.1.1/test/simple_backend_test.rb | 524 ------------------- .../active_support/vendor/i18n-0.1.3/MIT-LICENSE | 20 + .../vendor/i18n-0.1.3/README.textile | 20 + .../lib/active_support/vendor/i18n-0.1.3/Rakefile | 5 + .../active_support/vendor/i18n-0.1.3/i18n.gemspec | 27 + .../active_support/vendor/i18n-0.1.3/lib/i18n.rb | 199 ++++++++ .../vendor/i18n-0.1.3/lib/i18n/backend/simple.rb | 214 ++++++++ .../vendor/i18n-0.1.3/lib/i18n/exceptions.rb | 53 ++ .../active_support/vendor/i18n-0.1.3/test/all.rb | 5 + .../vendor/i18n-0.1.3/test/i18n_exceptions_test.rb | 100 ++++ .../vendor/i18n-0.1.3/test/i18n_test.rb | 125 +++++ .../vendor/i18n-0.1.3/test/locale/en.rb | 1 + .../vendor/i18n-0.1.3/test/locale/en.yml | 3 + .../vendor/i18n-0.1.3/test/simple_backend_test.rb | 568 +++++++++++++++++++++ 29 files changed, 1344 insertions(+), 1309 deletions(-) delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/.gitignore delete mode 100755 activesupport/lib/active_support/vendor/i18n-0.1.1/MIT-LICENSE delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/README.textile delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/Rakefile delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/i18n.gemspec delete mode 100755 activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n.rb delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/backend/simple.rb delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/exceptions.rb delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/test/all.rb delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_exceptions_test.rb delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_test.rb delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.rb delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.yml delete mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.1/test/simple_backend_test.rb create mode 100755 activesupport/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/README.textile create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/Rakefile create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec create mode 100755 activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/test/all.rb create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml create mode 100644 activesupport/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 5d9b77bbf5..c0f24a103d 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *2.3.1 [RC2] (February 27th, 2009)* +* Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda] + * Update bundled memcache-client from 1.5.0.5 to 1.6.4.99. See http://www.mikeperham.com/2009/02/15/memcache-client-performance/ [Mike Perham] * Ruby 1.9.1p0 fix: URI.unescape can decode multibyte chars. #2033 [MOROHASHI Kyosuke] diff --git a/activesupport/lib/active_support/vendor.rb b/activesupport/lib/active_support/vendor.rb index 39da70a9f3..28852e65c8 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.1.1' +# gem 'i18n', '~> 0.1.3' # rescue Gem::LoadError - $:.unshift "#{File.dirname(__FILE__)}/vendor/i18n-0.1.1/lib" + $:.unshift "#{File.dirname(__FILE__)}/vendor/i18n-0.1.3/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 deleted file mode 100644 index 0f41a39f89..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.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 deleted file mode 100755 index ed8e9ee66d..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/MIT-LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index a07fc8426d..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/README.textile +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 2164e13e69..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/Rakefile +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index 14294606bd..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/i18n.gemspec +++ /dev/null @@ -1,27 +0,0 @@ -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.1.1/lib/i18n.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n.rb deleted file mode 100755 index 76361bed90..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n.rb +++ /dev/null @@ -1,199 +0,0 @@ -# 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/) -# Copyright:: Copyright (c) 2008 The Ruby i18n Team -# License:: MIT -require 'i18n/backend/simple' -require 'i18n/exceptions' - -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) - @@backend = backend - end - - # Returns the current default locale. Defaults to :'en' - def default_locale - @@default_locale - end - - # Sets the current default locale. Used to set a custom default 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 - end - - # Sets the current locale pseudo-globally, i.e. in the Thread.current hash. - def locale=(locale) - Thread.current[:locale] = locale - end - - # Returns an array of locales for which translations are available - def available_locales - backend.available_locales - 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. - # - # E.g. the provided SimpleBackend accepts a list of paths to translation - # files which are either named *.rb and contain plain Ruby Hashes or are - # named *.yml and contain YAML data. So for the SimpleBackend clients may - # register translation files like this: - # I18n.load_path << 'path/to/locale/en.yml' - def load_path - @@load_path ||= [] - end - - # Sets the load path instance. Custom implementations are expected to - # behave like a Ruby Array. - def load_path=(load_path) - @@load_path = load_path - end - - # Tells the backend to reload translations. Used in situations like the - # Rails development environment. Backends can implement whatever strategy - # is useful. - def reload! - backend.reload! - end - - # 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. E.g., ActionView ships with the translation: - # :date => {:formats => {:short => "%b %d"}}. - # - # Translations can be looked up at any level of this hash using the key argument - # and the scope option. E.g., in this example I18n.t :date - # returns the whole translations hash {:formats => {:short => "%b %d"}}. - # - # Key can be either a single key or a dot-separated key (both Strings and Symbols - # work). E.g., 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: - # I18n.t 'date.formats.short' - # I18n.t 'formats.short', :scope => 'date' - # I18n.t 'short', :scope => 'date.formats' - # I18n.t 'short', :scope => %w(date formats) - # - # *INTERPOLATION* - # - # 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. - # - # E.g., with a translation :foo => "foo {{bar}}" the option - # value for the key +bar+ will be interpolated into the translation: - # I18n.t :foo, :bar => 'baz' # => 'foo baz' - # - # *PLURALIZATION* - # - # Translation data can contain pluralized translations. Pluralized translations - # are arrays of singluar/plural versions of translations like ['Foo', 'Foos']. - # - # Note that I18n::Backend::Simple 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: - # I18n.t :foo, :count => 1 # => 'Foo' - # - # These both return the plural version of a pluralized translation: - # I18n.t :foo, :count => 0 # => 'Foos' - # I18n.t :foo, :count => 2 # => 'Foos' - # - # The :count option can be used both for pluralization and interpolation. - # E.g., with the translation - # :foo => ['{{count}} foo', '{{count}} foos'], count will - # be interpolated to the pluralized translation: - # I18n.t :foo, :count => 1 # => '1 foo' - # - # *DEFAULTS* - # - # This returns the translation for :foo or default if no translation was found: - # I18n.t :foo, :default => 'default' - # - # This returns the translation for :foo or the translation for :bar if no - # translation for :foo was found: - # I18n.t :foo, :default => :bar - # - # Returns the translation for :foo or the translation for :bar - # or default if no translations for :foo and :bar were found. - # I18n.t :foo, :default => [:bar, 'default'] - # - # BULK LOOKUP - # - # This returns an array with the translations for :foo and :bar. - # I18n.t [:foo, :bar] - # - # Can be used with dot-separated nested keys: - # I18n.t [:'baz.foo', :'baz.bar'] - # - # Which is the same as using a scope option: - # I18n.t [:foo, :bar], :scope => :baz - def translate(key, options = {}) - locale = options.delete(:locale) || I18n.locale - backend.translate(locale, key, options) - rescue I18n::ArgumentError => e - raise e if options[:raise] - send(@@exception_handler, e, locale, key, options) - end - alias :t :translate - - # Localizes certain objects, such as dates and numbers to local formatting. - def localize(object, options = {}) - locale = options[:locale] || I18n.locale - format = options[:format] || :default - 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 - # was caught and the option :raise is not set the handler returns an error - # message string containing the key/scope. - def default_exception_handler(exception, locale, key, options) - 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. - def normalize_translation_keys(locale, key, scope) - keys = [locale] + Array(scope) + [key] - keys = keys.map { |k| k.to_s.split(/\./) } - keys.flatten.map { |k| k.to_sym } - end - end -end diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/backend/simple.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/backend/simple.rb deleted file mode 100644 index b54164d496..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/backend/simple.rb +++ /dev/null @@ -1,222 +0,0 @@ -require 'yaml' - -module I18n - module Backend - class Simple - INTERPOLATION_RESERVED_KEYS = %w(scope default) - MATCH = /(\\\\)?\{\{([^\}]+)\}\}/ - - # 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. - # 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 - - reserved = :scope, :default - count, scope, default = options.values_at(:count, *reserved) - options.delete(:default) - values = options.reject { |name, value| reserved.include?(name) } - - entry = lookup(locale, key, scope) - if entry.nil? - entry = default(locale, default, options) - if entry.nil? - raise(I18n::MissingTranslationData.new(locale, key, options)) - end - end - entry = pluralize(locale, entry, count) - 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 (e.g., :short in :'date.formats'). - 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") - format = formats[format.to_sym] if formats && formats[format.to_sym] - # TODO raise exception unless format found? - format = format.to_s.dup - - # 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.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 - - # Returns an array of locales for which translations are available - def available_locales - init_translations unless initialized? - translations.keys - end - - def reload! - @initialized = false - @translations = nil - end - - protected - def init_translations - load_translations(*I18n.load_path.flatten) - @initialized = true - end - - def translations - @translations ||= {} - end - - # 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. currency.format is regarded the same as - # %w(currency format). - def lookup(locale, key, scope = []) - return unless key - init_translations unless initialized? - keys = I18n.send(:normalize_translation_keys, locale, key, scope) - keys.inject(translations) do |result, k| - if (x = result[k.to_sym]).nil? - return nil - else - x - end - end - end - - # 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. - # - # I.e., default(locale, [:foo, 'default']) will return +default+ if - # translate(locale, :foo) 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| - result = default(locale, obj, options.dup) and return result - end and nil - end - rescue MissingTranslationData - nil - end - - # Picks a translation from an array according to English pluralization - # rules. It will pick the first translation if count is not equal to 1 - # and the second translation if it is equal to 1. Other backends can - # implement more flexible or complex pluralization rules. - def pluralize(locale, entry, count) - return entry unless entry.is_a?(Hash) and count - # raise InvalidPluralizationData.new(entry, count) unless entry.is_a?(Hash) - key = :zero if count == 0 && entry.has_key?(:zero) - key ||= count == 1 ? :one : :other - raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key) - entry[key] - end - - # Interpolates values into a given string. - # - # 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 \\ when you want to escape - # the {{...}} key in a string (once for the string and once for the - # interpolation). - def interpolate(locale, string, values = {}) - return string unless string.is_a?(String) - - if string.respond_to?(:force_encoding) - original_encoding = string.encoding - string.force_encoding(Encoding::BINARY) - end - - result = string.gsub(MATCH) do - escaped, pattern, key = $1, $2, $2.to_sym - - if escaped - pattern - elsif INTERPOLATION_RESERVED_KEYS.include?(pattern) - raise ReservedInterpolationKey.new(pattern, string) - elsif !values.include?(key) - raise MissingInterpolationArgument.new(pattern, string) - else - values[key].to_s - end - end - - result.force_encoding(original_encoding) if original_encoding - result - end - - # 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. - def load_file(filename) - type = File.extname(filename).tr('.', '').downcase - raise UnknownFileType.new(type, filename) unless respond_to?(:"load_#{type}") - 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 - # 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) - locale = locale.to_sym - translations[locale] ||= {} - data = deep_symbolize_keys(data) - - # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809 - 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)| - value = deep_symbolize_keys(value) if value.is_a? Hash - result[(key.to_sym rescue key) || key] = value - result - } - end - end - end -end \ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/exceptions.rb b/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/exceptions.rb deleted file mode 100644 index b5cea7acb4..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/lib/i18n/exceptions.rb +++ /dev/null @@ -1,53 +0,0 @@ -module I18n - class ArgumentError < ::ArgumentError; end - - class InvalidLocale < ArgumentError - attr_reader :locale - def initialize(locale) - @locale = locale - super "#{locale.inspect} is not a valid locale" - end - end - - class MissingTranslationData < ArgumentError - attr_reader :locale, :key, :options - def initialize(locale, key, options) - @key, @locale, @options = key, locale, options - keys = I18n.send(:normalize_translation_keys, locale, key, options[:scope]) - keys << 'no key' if keys.size < 2 - super "translation missing: #{keys.join(', ')}" - end - end - - class InvalidPluralizationData < ArgumentError - attr_reader :entry, :count - def initialize(entry, count) - @entry, @count = entry, count - super "translation data #{entry.inspect} can not be used with :count => #{count}" - end - end - - class MissingInterpolationArgument < ArgumentError - attr_reader :key, :string - def initialize(key, string) - @key, @string = key, string - super "interpolation argument #{key} missing in #{string.inspect}" - end - end - - class ReservedInterpolationKey < ArgumentError - attr_reader :key, :string - def initialize(key, string) - @key, @string = key, string - super "reserved key #{key.inspect} used in #{string.inspect}" - end - end - - class UnknownFileType < ArgumentError - attr_reader :type, :filename - def initialize(type, filename) - @type, @filename = type, filename - super "can not load translations from #{filename}, the file type #{type} is not known" - end - end -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 deleted file mode 100644 index 353712da49..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/all.rb +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index dfcba6901f..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_exceptions_test.rb +++ /dev/null @@ -1,100 +0,0 @@ -$:.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 deleted file mode 100644 index bbb35ec809..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/i18n_test.rb +++ /dev/null @@ -1,125 +0,0 @@ -$:.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 deleted file mode 100644 index 6044ce10d9..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.rb +++ /dev/null @@ -1 +0,0 @@ -{:'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 deleted file mode 100644 index 0b298c9c0e..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/locale/en.yml +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 8ba7036abf..0000000000 --- a/activesupport/lib/active_support/vendor/i18n-0.1.1/test/simple_backend_test.rb +++ /dev/null @@ -1,524 +0,0 @@ -# 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 I18nSimpleBackendAvailableLocalesTest < Test::Unit::TestCase - def test_available_locales - @backend = I18n::Backend::Simple.new - @backend.store_translations 'de', :foo => 'bar' - @backend.store_translations 'en', :foo => 'foo' - - assert_equal ['de', 'en'], @backend.available_locales.map{|locale| locale.to_s }.sort - 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 I18nSimpleBackendLoadPathTest < Test::Unit::TestCase - include I18nSimpleBackendTestSetup - - def test_nested_load_paths_do_not_break_locale_loading - @backend = I18n::Backend::Simple.new - I18n.load_path = [[File.dirname(__FILE__) + '/locale/en.yml']] - assert_nil backend_get_translations - assert_nothing_raised { @backend.send :init_translations } - assert_not_nil 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/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE b/activesupport/lib/active_support/vendor/i18n-0.1.3/MIT-LICENSE new file mode 100755 index 0000000000..ed8e9ee66d --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/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.3/README.textile b/activesupport/lib/active_support/vendor/i18n-0.1.3/README.textile new file mode 100644 index 0000000000..a07fc8426d --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/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.3/Rakefile b/activesupport/lib/active_support/vendor/i18n-0.1.3/Rakefile new file mode 100644 index 0000000000..2164e13e69 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/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.3/i18n.gemspec b/activesupport/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec new file mode 100644 index 0000000000..f102689a6f --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/i18n.gemspec @@ -0,0 +1,27 @@ +Gem::Specification.new do |s| + s.name = "i18n" + s.version = "0.1.3" + s.date = "2009-01-09" + 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.1.3/lib/i18n.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb new file mode 100755 index 0000000000..76361bed90 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n.rb @@ -0,0 +1,199 @@ +# 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/) +# Copyright:: Copyright (c) 2008 The Ruby i18n Team +# License:: MIT +require 'i18n/backend/simple' +require 'i18n/exceptions' + +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) + @@backend = backend + end + + # Returns the current default locale. Defaults to :'en' + def default_locale + @@default_locale + end + + # Sets the current default locale. Used to set a custom default 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 + end + + # Sets the current locale pseudo-globally, i.e. in the Thread.current hash. + def locale=(locale) + Thread.current[:locale] = locale + end + + # Returns an array of locales for which translations are available + def available_locales + backend.available_locales + 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. + # + # E.g. the provided SimpleBackend accepts a list of paths to translation + # files which are either named *.rb and contain plain Ruby Hashes or are + # named *.yml and contain YAML data. So for the SimpleBackend clients may + # register translation files like this: + # I18n.load_path << 'path/to/locale/en.yml' + def load_path + @@load_path ||= [] + end + + # Sets the load path instance. Custom implementations are expected to + # behave like a Ruby Array. + def load_path=(load_path) + @@load_path = load_path + end + + # Tells the backend to reload translations. Used in situations like the + # Rails development environment. Backends can implement whatever strategy + # is useful. + def reload! + backend.reload! + end + + # 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. E.g., ActionView ships with the translation: + # :date => {:formats => {:short => "%b %d"}}. + # + # Translations can be looked up at any level of this hash using the key argument + # and the scope option. E.g., in this example I18n.t :date + # returns the whole translations hash {:formats => {:short => "%b %d"}}. + # + # Key can be either a single key or a dot-separated key (both Strings and Symbols + # work). E.g., 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: + # I18n.t 'date.formats.short' + # I18n.t 'formats.short', :scope => 'date' + # I18n.t 'short', :scope => 'date.formats' + # I18n.t 'short', :scope => %w(date formats) + # + # *INTERPOLATION* + # + # 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. + # + # E.g., with a translation :foo => "foo {{bar}}" the option + # value for the key +bar+ will be interpolated into the translation: + # I18n.t :foo, :bar => 'baz' # => 'foo baz' + # + # *PLURALIZATION* + # + # Translation data can contain pluralized translations. Pluralized translations + # are arrays of singluar/plural versions of translations like ['Foo', 'Foos']. + # + # Note that I18n::Backend::Simple 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: + # I18n.t :foo, :count => 1 # => 'Foo' + # + # These both return the plural version of a pluralized translation: + # I18n.t :foo, :count => 0 # => 'Foos' + # I18n.t :foo, :count => 2 # => 'Foos' + # + # The :count option can be used both for pluralization and interpolation. + # E.g., with the translation + # :foo => ['{{count}} foo', '{{count}} foos'], count will + # be interpolated to the pluralized translation: + # I18n.t :foo, :count => 1 # => '1 foo' + # + # *DEFAULTS* + # + # This returns the translation for :foo or default if no translation was found: + # I18n.t :foo, :default => 'default' + # + # This returns the translation for :foo or the translation for :bar if no + # translation for :foo was found: + # I18n.t :foo, :default => :bar + # + # Returns the translation for :foo or the translation for :bar + # or default if no translations for :foo and :bar were found. + # I18n.t :foo, :default => [:bar, 'default'] + # + # BULK LOOKUP + # + # This returns an array with the translations for :foo and :bar. + # I18n.t [:foo, :bar] + # + # Can be used with dot-separated nested keys: + # I18n.t [:'baz.foo', :'baz.bar'] + # + # Which is the same as using a scope option: + # I18n.t [:foo, :bar], :scope => :baz + def translate(key, options = {}) + locale = options.delete(:locale) || I18n.locale + backend.translate(locale, key, options) + rescue I18n::ArgumentError => e + raise e if options[:raise] + send(@@exception_handler, e, locale, key, options) + end + alias :t :translate + + # Localizes certain objects, such as dates and numbers to local formatting. + def localize(object, options = {}) + locale = options[:locale] || I18n.locale + format = options[:format] || :default + 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 + # was caught and the option :raise is not set the handler returns an error + # message string containing the key/scope. + def default_exception_handler(exception, locale, key, options) + 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. + def normalize_translation_keys(locale, key, scope) + keys = [locale] + Array(scope) + [key] + keys = keys.map { |k| k.to_s.split(/\./) } + keys.flatten.map { |k| k.to_sym } + end + end +end diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb new file mode 100644 index 0000000000..c09acd7d2d --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/backend/simple.rb @@ -0,0 +1,214 @@ +require 'yaml' + +module I18n + module Backend + class Simple + INTERPOLATION_RESERVED_KEYS = %w(scope default) + MATCH = /(\\\\)?\{\{([^\}]+)\}\}/ + + # 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. + # 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 + + reserved = :scope, :default + count, scope, default = options.values_at(:count, *reserved) + options.delete(:default) + values = options.reject { |name, value| reserved.include?(name) } + + entry = lookup(locale, key, scope) + if entry.nil? + entry = default(locale, default, options) + if entry.nil? + raise(I18n::MissingTranslationData.new(locale, key, options)) + end + end + entry = pluralize(locale, entry, count) + 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 (e.g., :short in :'date.formats'). + 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") + format = formats[format.to_sym] if formats && formats[format.to_sym] + # TODO raise exception unless format found? + format = format.to_s.dup + + # 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.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 + + # Returns an array of locales for which translations are available + def available_locales + init_translations unless initialized? + translations.keys + end + + def reload! + @initialized = false + @translations = nil + end + + protected + def init_translations + load_translations(*I18n.load_path.flatten) + @initialized = true + end + + def translations + @translations ||= {} + end + + # 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. currency.format is regarded the same as + # %w(currency format). + def lookup(locale, key, scope = []) + return unless key + init_translations unless initialized? + keys = I18n.send(:normalize_translation_keys, locale, key, scope) + keys.inject(translations) do |result, k| + if (x = result[k.to_sym]).nil? + return nil + else + x + end + end + end + + # 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. + # + # I.e., default(locale, [:foo, 'default']) will return +default+ if + # translate(locale, :foo) 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| + result = default(locale, obj, options.dup) and return result + end and nil + end + rescue MissingTranslationData + nil + end + + # Picks a translation from an array according to English pluralization + # rules. It will pick the first translation if count is not equal to 1 + # and the second translation if it is equal to 1. Other backends can + # implement more flexible or complex pluralization rules. + def pluralize(locale, entry, count) + return entry unless entry.is_a?(Hash) and count + # raise InvalidPluralizationData.new(entry, count) unless entry.is_a?(Hash) + key = :zero if count == 0 && entry.has_key?(:zero) + key ||= count == 1 ? :one : :other + raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key) + entry[key] + end + + # Interpolates values into a given string. + # + # 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 \\ when you want to escape + # the {{...}} key in a string (once for the string and once for the + # interpolation). + def interpolate(locale, string, values = {}) + return string unless string.is_a?(String) + + string.gsub(MATCH) do + escaped, pattern, key = $1, $2, $2.to_sym + + if escaped + pattern + elsif INTERPOLATION_RESERVED_KEYS.include?(pattern) + raise ReservedInterpolationKey.new(pattern, string) + elsif !values.include?(key) + raise MissingInterpolationArgument.new(pattern, string) + else + values[key].to_s + end + end + end + + # 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. + def load_file(filename) + type = File.extname(filename).tr('.', '').downcase + raise UnknownFileType.new(type, filename) unless respond_to?(:"load_#{type}") + 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 + # 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) + locale = locale.to_sym + translations[locale] ||= {} + data = deep_symbolize_keys(data) + + # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809 + 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)| + value = deep_symbolize_keys(value) if value.is_a? Hash + result[(key.to_sym rescue key) || key] = value + result + } + end + end + end +end \ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb new file mode 100644 index 0000000000..b5cea7acb4 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/lib/i18n/exceptions.rb @@ -0,0 +1,53 @@ +module I18n + class ArgumentError < ::ArgumentError; end + + class InvalidLocale < ArgumentError + attr_reader :locale + def initialize(locale) + @locale = locale + super "#{locale.inspect} is not a valid locale" + end + end + + class MissingTranslationData < ArgumentError + attr_reader :locale, :key, :options + def initialize(locale, key, options) + @key, @locale, @options = key, locale, options + keys = I18n.send(:normalize_translation_keys, locale, key, options[:scope]) + keys << 'no key' if keys.size < 2 + super "translation missing: #{keys.join(', ')}" + end + end + + class InvalidPluralizationData < ArgumentError + attr_reader :entry, :count + def initialize(entry, count) + @entry, @count = entry, count + super "translation data #{entry.inspect} can not be used with :count => #{count}" + end + end + + class MissingInterpolationArgument < ArgumentError + attr_reader :key, :string + def initialize(key, string) + @key, @string = key, string + super "interpolation argument #{key} missing in #{string.inspect}" + end + end + + class ReservedInterpolationKey < ArgumentError + attr_reader :key, :string + def initialize(key, string) + @key, @string = key, string + super "reserved key #{key.inspect} used in #{string.inspect}" + end + end + + class UnknownFileType < ArgumentError + attr_reader :type, :filename + def initialize(type, filename) + @type, @filename = type, filename + super "can not load translations from #{filename}, the file type #{type} is not known" + end + end +end \ No newline at end of file diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.3/test/all.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/all.rb new file mode 100644 index 0000000000..353712da49 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/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.3/test/i18n_exceptions_test.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/i18n_exceptions_test.rb new file mode 100644 index 0000000000..dfcba6901f --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/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.3/test/i18n_test.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb new file mode 100644 index 0000000000..bbb35ec809 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/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.3/test/locale/en.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/locale/en.rb new file mode 100644 index 0000000000..6044ce10d9 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/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.3/test/locale/en.yml b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/locale/en.yml new file mode 100644 index 0000000000..0b298c9c0e --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/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.3/test/simple_backend_test.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb new file mode 100644 index 0000000000..7b7b137579 --- /dev/null +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb @@ -0,0 +1,568 @@ +# 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 I18nSimpleBackendAvailableLocalesTest < Test::Unit::TestCase + def test_available_locales + @backend = I18n::Backend::Simple.new + @backend.store_translations 'de', :foo => 'bar' + @backend.store_translations 'en', :foo => 'foo' + + assert_equal ['de', 'en'], @backend.available_locales.map{|locale| locale.to_s }.sort + 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_an_unicode_value_hash_interpolates_to_the_string + assert_equal 'Hi ゆきひろ!', @backend.send(:interpolate, nil, 'Hi {{name}}!', :name => 'ゆきひろ') + end + + def test_interpolate_given_an_unicode_value_hash_interpolates_into_unicode_string + assert_equal 'こんにちは、ゆきひろさん!', @backend.send(:interpolate, nil, 'こんにちは、{{name}}さん!', :name => 'ゆきひろ') + end + + if Kernel.const_defined?(:Encoding) + def test_interpolate_given_a_non_unicode_multibyte_value_hash_interpolates_into_a_string_with_the_same_encoding + assert_equal euc_jp('Hi ゆきひろ!'), @backend.send(:interpolate, nil, 'Hi {{name}}!', :name => euc_jp('ゆきひろ')) + end + + def test_interpolate_given_an_unicode_value_hash_into_a_non_unicode_multibyte_string_raises_encoding_compatibility_error + assert_raises(Encoding::CompatibilityError) do + @backend.send(:interpolate, nil, euc_jp('こんにちは、{{name}}さん!'), :name => 'ゆきひろ') + end + end + + def test_interpolate_given_a_non_unicode_multibyte_value_hash_into_an_unicode_string_raises_encoding_compatibility_error + assert_raises(Encoding::CompatibilityError) do + @backend.send(:interpolate, nil, 'こんにちは、{{name}}さん!', :name => euc_jp('ゆきひろ')) + end + end + 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 + + private + + def euc_jp(string) + string.encode!(Encoding::EUC_JP) + 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 I18nSimpleBackendLoadPathTest < Test::Unit::TestCase + include I18nSimpleBackendTestSetup + + def teardown + I18n.load_path = [] + end + + def test_nested_load_paths_do_not_break_locale_loading + @backend = I18n::Backend::Simple.new + I18n.load_path = [[File.dirname(__FILE__) + '/locale/en.yml']] + assert_nil backend_get_translations + assert_nothing_raised { @backend.send :init_translations } + assert_not_nil backend_get_translations + end + + def test_adding_arrays_of_filenames_to_load_path_do_not_break_locale_loading + @backend = I18n::Backend::Simple.new + I18n.load_path << Dir[File.dirname(__FILE__) + '/locale/*.{rb,yml}'] + assert_nil backend_get_translations + assert_nothing_raised { @backend.send :init_translations } + assert_not_nil 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 -- cgit v1.2.3 From 7058c1366ee33f3095b8737c2b71876702cddea6 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 28 Feb 2009 10:30:49 +0100 Subject: So it didnt happen yesterday, but very soon! Just need the final details ironed out --- activesupport/CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index c0f24a103d..2ac432e39e 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,4 +1,4 @@ -*2.3.1 [RC2] (February 27th, 2009)* +*2.3.1 [RC2] (February ?, 2009)* * Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda] -- cgit v1.2.3 From a242abbad8e2204a6ae7a4f8415abe71c9773a9c Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 3 Mar 2009 19:10:12 -0800 Subject: Skip backtrace filters if BACKTRACE environment variable is set --- activesupport/lib/active_support/test_case.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index 97b2b6ef9c..f05d4098fc 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -20,7 +20,7 @@ module ActiveSupport alias_method :method_name, :name else # TODO: Figure out how to get the Rails::BacktraceFilter into minitest/unit - if defined?(Rails) + if defined?(Rails) && ENV['BACKTRACE'].nil? require 'rails/backtrace_cleaner' Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit } end -- cgit v1.2.3 From cb534524389bb4f407fc268a0bb7a7cffb6785a9 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 3 Mar 2009 19:10:33 -0800 Subject: Fix OrderedHash#to_hash to return self instead of a new hash with self as default value --- activesupport/lib/active_support/ordered_hash.rb | 2 +- activesupport/test/ordered_hash_test.rb | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index 66aab9e562..d3cd2bcddd 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -54,7 +54,7 @@ module ActiveSupport end def to_hash - Hash.new(self) + self end def each_key diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index fb76ca1ab6..9c17145b9f 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -45,6 +45,10 @@ class OrderedHashTest < Test::Unit::TestCase assert_nil @ordered_hash.delete(bad_key) end + def test_to_hash + assert_same @ordered_hash, @ordered_hash.to_hash + end + def test_has_key assert_equal true, @ordered_hash.has_key?('blue') assert_equal true, @ordered_hash.key?('blue') @@ -148,4 +152,4 @@ class OrderedHashTest < Test::Unit::TestCase @ordered_hash.keys.pop assert_equal original, @ordered_hash.keys end -end \ No newline at end of file +end -- cgit v1.2.3 From 9d13b9eed8652b85df11294d8135bbfc36a86563 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 4 Mar 2009 16:20:49 -0800 Subject: Fix OrderedHash#inspect recursion --- activesupport/lib/active_support/ordered_hash.rb | 2 +- activesupport/test/ordered_hash_test.rb | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index d3cd2bcddd..fed8094a24 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -93,7 +93,7 @@ module ActiveSupport end def inspect - "#" + "#" end private diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index 9c17145b9f..7cd8c8a8f4 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -4,9 +4,11 @@ class OrderedHashTest < Test::Unit::TestCase def setup @keys = %w( blue green red pink orange ) @values = %w( 000099 009900 aa0000 cc0066 cc6633 ) + @hash = Hash.new @ordered_hash = ActiveSupport::OrderedHash.new @keys.each_with_index do |key, index| + @hash[key] = @values[index] @ordered_hash[key] = @values[index] end end @@ -17,7 +19,7 @@ class OrderedHashTest < Test::Unit::TestCase end def test_access - assert @keys.zip(@values).all? { |k, v| @ordered_hash[k] == v } + assert @hash.all? { |k, v| @ordered_hash[k] == v } end def test_assignment @@ -152,4 +154,8 @@ class OrderedHashTest < Test::Unit::TestCase @ordered_hash.keys.pop assert_equal original, @ordered_hash.keys end + + def test_inspect + assert @ordered_hash.inspect.include?(@hash.inspect) + end end -- cgit v1.2.3 From dfef3d8b14b5d3dcb61d83c30d5d5b27d33ff530 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 5 Mar 2009 11:00:04 +0100 Subject: Release RC2 today --- activesupport/CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 2ac432e39e..bbece6349a 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,4 +1,4 @@ -*2.3.1 [RC2] (February ?, 2009)* +*2.3.1 [RC2] (March 5, 2009)* * Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda] -- cgit v1.2.3 From c67d25e3c4e636d7c94909a7398231a634accf46 Mon Sep 17 00:00:00 2001 From: Niels Ganser Date: Fri, 6 Mar 2009 14:40:54 +0000 Subject: Ensure ActiveSupport::Memoizable respects private methods. [#2138 state:resolved] Signed-off-by: Pratik Naik --- activesupport/lib/active_support/memoizable.rb | 4 ++++ activesupport/test/memoizable_test.rb | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index 952b4d8063..71cfe61739 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -88,6 +88,10 @@ module ActiveSupport #{original_method}(*args) # _unmemoized_mime_type(*args) end # end end # end + end # end + # + if private_method_defined?(#{original_method.inspect}) # if private_method_defined?(:_unmemoized_mime_type) + private #{symbol.inspect} # private :mime_type end # end EOS end diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb index 069ae27eb2..39420c5a3a 100644 --- a/activesupport/test/memoizable_test.rb +++ b/activesupport/test/memoizable_test.rb @@ -4,10 +4,12 @@ class MemoizableTest < Test::Unit::TestCase class Person extend ActiveSupport::Memoizable - attr_reader :name_calls, :age_calls + attr_reader :name_calls, :age_calls, :is_developer_calls + def initialize @name_calls = 0 @age_calls = 0 + @is_developer_calls = 0 end def name @@ -31,6 +33,14 @@ class MemoizableTest < Test::Unit::TestCase end memoize :name, :age + + private + + def is_developer? + @is_developer_calls += 1 + "Yes" + end + memoize :is_developer? end class Company @@ -223,4 +233,15 @@ class MemoizableTest < Test::Unit::TestCase company.memoize :name assert_raise(RuntimeError) { company.memoize :name } end + + def test_private_method_memoization + person = Person.new + + assert_raise(NoMethodError) { person.is_developer? } + assert_equal "Yes", person.send(:is_developer?) + assert_equal 1, person.is_developer_calls + assert_equal "Yes", person.send(:is_developer?) + assert_equal 1, person.is_developer_calls + end + end -- cgit v1.2.3 From 20d3892f46c553e8ca3d4e8d223a3bd92789556d Mon Sep 17 00:00:00 2001 From: Sam Granieri Date: Sat, 7 Mar 2009 10:54:27 +0000 Subject: Allow String#parameterize to accept a separator [#2157 state:resolved] Signed-off-by: Pratik Naik --- .../lib/active_support/core_ext/string/inflections.rb | 4 ++-- activesupport/test/core_ext/string_ext_test.rb | 18 ++++++++++++++++++ activesupport/test/inflector_test_cases.rb | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb index 15ad3d99cc..48e812aaf8 100644 --- a/activesupport/lib/active_support/core_ext/string/inflections.rb +++ b/activesupport/lib/active_support/core_ext/string/inflections.rb @@ -102,8 +102,8 @@ module ActiveSupport #:nodoc: # # <%= link_to(@person.name, person_path %> # # => Donald E. Knuth - def parameterize - Inflector.parameterize(self) + def parameterize(sep = '-') + Inflector.parameterize(self, sep) end # Creates the name of a table like Rails does for models to table names. This method diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index e232bf8384..6c9b7e7236 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -77,6 +77,24 @@ class StringInflectionsTest < Test::Unit::TestCase end end + def test_string_parameterized_normal + StringToParameterized.each do |normal, slugged| + assert_equal(normal.parameterize, slugged) + end + end + + def test_string_parameterized_no_separator + StringToParameterizeWithNoSeparator.each do |normal, slugged| + assert_equal(normal.parameterize(''), slugged) + end + end + + def test_string_parameterized_underscore + StringToParameterizeWithUnderscore.each do |normal, slugged| + assert_equal(normal.parameterize('_'), slugged) + end + end + def test_humanize UnderscoreToHuman.each do |underscore, human| assert_equal(human, underscore.humanize) diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb index b7ac467c37..584cbff3e7 100644 --- a/activesupport/test/inflector_test_cases.rb +++ b/activesupport/test/inflector_test_cases.rb @@ -154,6 +154,22 @@ module InflectorTestCases "Squeeze separators" => "squeeze-separators" } + StringToParameterizeWithNoSeparator = { + "Donald E. Knuth" => "donaldeknuth", + "Random text with *(bad)* characters" => "randomtextwithbadcharacters", + "Trailing bad characters!@#" => "trailingbadcharacters", + "!@#Leading bad characters" => "leadingbadcharacters", + "Squeeze separators" => "squeezeseparators" + } + + StringToParameterizeWithUnderscore = { + "Donald E. Knuth" => "donald_e_knuth", + "Random text with *(bad)* characters" => "random_text_with_bad_characters", + "Trailing bad characters!@#" => "trailing_bad_characters", + "!@#Leading bad characters" => "leading_bad_characters", + "Squeeze separators" => "squeeze_separators" + } + # Ruby 1.9 doesn't do Unicode normalization yet. if RUBY_VERSION >= '1.9' StringToParameterizedAndNormalized = { -- cgit v1.2.3 From 74387884819e8b6e16c3f67388610b8d1192cb4d Mon Sep 17 00:00:00 2001 From: George Ogata Date: Tue, 30 Dec 2008 14:16:15 +0100 Subject: Make Chars#slice! behave more like String#slice! [#1243 state:resolved] - Chars#slice! now returns the slice instead of itself - Chars#slice! now removes the slice from itself Signed-off-by: Pratik Naik --- activesupport/lib/active_support/multibyte/chars.rb | 16 ++++++++++++++-- activesupport/test/multibyte_chars_test.rb | 14 +++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index 62b6d798ef..60f082bcc1 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -344,7 +344,19 @@ module ActiveSupport #:nodoc: end alias_method :[], :slice - # Converts first character in the string to Unicode value + # Like String#slice!, except instead of byte offsets you specify character offsets. + # + # Example: + # s = 'こんにちは' + # s.mb_chars.slice!(2..3).to_s #=> "にち" + # s #=> "こんは" + def slice!(*args) + slice = self[*args] + self[*args] = '' + slice + end + + # Returns the codepoint of the first character in the string. # # Example: # 'こんにちは'.mb_chars.ord #=> 12371 @@ -432,7 +444,7 @@ module ActiveSupport #:nodoc: chars(self.class.tidy_bytes(@wrapped_string)) end - %w(lstrip rstrip strip reverse upcase downcase slice tidy_bytes capitalize).each do |method| + %w(lstrip rstrip strip reverse upcase downcase tidy_bytes capitalize).each do |method| define_method("#{method}!") do |*args| unless args.nil? @wrapped_string = send(method, *args).to_s diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 067c461837..0644dbe603 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -123,7 +123,6 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase [:rstrip!, :lstrip!, :strip!, :reverse!, :upcase!, :downcase!, :capitalize!].each do |method| assert_equal @chars.object_id, @chars.send(method).object_id end - assert_equal @chars.object_id, @chars.slice!(1).object_id end def test_overridden_bang_methods_change_wrapped_string @@ -133,10 +132,6 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase proxy.send(method) assert_not_equal original, proxy.to_s end - proxy = chars('Café') - proxy.slice!(3) - assert_equal 'é', proxy.to_s - proxy = chars('òu') proxy.capitalize! assert_equal 'Òu', proxy.to_s @@ -391,6 +386,15 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert_equal nil, @chars.slice(7..6) end + def test_slice_bang_returns_sliced_out_substring + assert_equal 'にち', @chars.slice!(1..2) + end + + def test_slice_bang_removes_the_slice_from_the_receiver + @chars.slice!(1..2) + assert_equal 'こわ', @chars + end + def test_slice_should_throw_exceptions_on_invalid_arguments assert_raise(TypeError) { @chars.slice(2..3, 1) } assert_raise(TypeError) { @chars.slice(1, 2..3) } -- cgit v1.2.3 From 1c36172c13fc51b22167f5e8fc41b1da9f8fcb2a Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 8 Mar 2009 13:11:58 -0700 Subject: Ruby 1.9 compat: rename deprecated assert_raises to assert_raise. [#1617 state:resolved] --- .../vendor/i18n-0.1.3/test/i18n_test.rb | 4 +-- .../vendor/i18n-0.1.3/test/simple_backend_test.rb | 26 ++++++++--------- activesupport/test/core_ext/class_test.rb | 6 ++-- activesupport/test/core_ext/hash_ext_test.rb | 4 +-- activesupport/test/core_ext/load_error_test.rb | 4 +-- .../test/core_ext/module/synchronization_test.rb | 4 +-- activesupport/test/core_ext/module_test.rb | 10 +++---- .../test/core_ext/object_and_class_ext_test.rb | 4 +-- activesupport/test/core_ext/time_with_zone_test.rb | 2 +- activesupport/test/dependencies_test.rb | 22 +++++++------- activesupport/test/inflector_test.rb | 8 ++--- activesupport/test/json/decoding_test.rb | 2 +- activesupport/test/json/encoding_test.rb | 2 +- activesupport/test/message_encryptor_test.rb | 2 +- activesupport/test/message_verifier_test.rb | 2 +- activesupport/test/multibyte_chars_test.rb | 34 +++++++++++----------- activesupport/test/string_inquirer_test.rb | 2 +- activesupport/test/time_zone_test.rb | 2 +- 18 files changed, 70 insertions(+), 70 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb index bbb35ec809..50d6832c9e 100644 --- a/activesupport/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/i18n_test.rb @@ -116,10 +116,10 @@ class I18nTest < Test::Unit::TestCase end def test_localize_nil_raises_argument_error - assert_raises(I18n::ArgumentError) { I18n.l nil } + assert_raise(I18n::ArgumentError) { I18n.l nil } end def test_localize_object_raises_argument_error - assert_raises(I18n::ArgumentError) { I18n.l Object.new } + assert_raise(I18n::ArgumentError) { I18n.l Object.new } end end diff --git a/activesupport/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb index 7b7b137579..65f3ac11a6 100644 --- a/activesupport/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb +++ b/activesupport/lib/active_support/vendor/i18n-0.1.3/test/simple_backend_test.rb @@ -155,7 +155,7 @@ class I18nSimpleBackendTranslateTest < Test::Unit::TestCase end def test_translate_given_an_array_of_inexistent_keys_it_raises_missing_translation_data - assert_raises I18n::MissingTranslationData do + assert_raise I18n::MissingTranslationData do @backend.translate('en', :does_not_exist, :scope => [:foo], :default => [:does_not_exist_2, :does_not_exist_3]) end end @@ -180,11 +180,11 @@ class I18nSimpleBackendTranslateTest < Test::Unit::TestCase end def test_translate_given_nil_as_a_locale_raises_an_argument_error - assert_raises(I18n::InvalidLocale){ @backend.translate nil, :bar } + assert_raise(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 } + assert_raise(I18n::MissingTranslationData){ @backend.translate 'de', :bogus } end end @@ -230,15 +230,15 @@ class I18nSimpleBackendPluralizeTest < Test::Unit::TestCase end def test_interpolate_given_incomplete_pluralization_data_raises_invalid_pluralization_data - assert_raises(I18n::InvalidPluralizationData){ @backend.send(:pluralize, nil, {:one => 'bar'}, 2) } + assert_raise(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) } + # assert_raise(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) } + # assert_raise(I18n::InvalidPluralizationData){ @backend.send(:pluralize, nil, ['bar'], 2) } # end end @@ -267,13 +267,13 @@ class I18nSimpleBackendInterpolateTest < Test::Unit::TestCase end def test_interpolate_given_an_unicode_value_hash_into_a_non_unicode_multibyte_string_raises_encoding_compatibility_error - assert_raises(Encoding::CompatibilityError) do + assert_raise(Encoding::CompatibilityError) do @backend.send(:interpolate, nil, euc_jp('こんにちは、{{name}}さん!'), :name => 'ゆきひろ') end end def test_interpolate_given_a_non_unicode_multibyte_value_hash_into_an_unicode_string_raises_encoding_compatibility_error - assert_raises(Encoding::CompatibilityError) do + assert_raise(Encoding::CompatibilityError) do @backend.send(:interpolate, nil, 'こんにちは、{{name}}さん!', :name => euc_jp('ゆきひろ')) end end @@ -292,11 +292,11 @@ class I18nSimpleBackendInterpolateTest < Test::Unit::TestCase end def test_interpolate_given_an_empty_values_hash_raises_missing_interpolation_argument - assert_raises(I18n::MissingInterpolationArgument) { @backend.send(:interpolate, nil, 'Hi {{name}}!', {}) } + assert_raise(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}) } + assert_raise(I18n::ReservedInterpolationKey) { @backend.send(:interpolate, nil, '{{default}}', {:default => nil}) } end private @@ -352,11 +352,11 @@ class I18nSimpleBackendLocalizeDateTest < Test::Unit::TestCase end def test_localize_nil_raises_argument_error - assert_raises(I18n::ArgumentError) { @backend.localize 'de', nil } + assert_raise(I18n::ArgumentError) { @backend.localize 'de', nil } end def test_localize_object_raises_argument_error - assert_raises(I18n::ArgumentError) { @backend.localize 'de', Object.new } + assert_raise(I18n::ArgumentError) { @backend.localize 'de', Object.new } end end @@ -486,7 +486,7 @@ 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" } + assert_raise(I18n::UnknownFileType) { @backend.load_translations "#{@locale_dir}/en.xml" } end def test_load_translations_with_ruby_file_type_does_not_raise_exception diff --git a/activesupport/test/core_ext/class_test.rb b/activesupport/test/core_ext/class_test.rb index 9c6071d478..48d8a78acf 100644 --- a/activesupport/test/core_ext/class_test.rb +++ b/activesupport/test/core_ext/class_test.rb @@ -19,19 +19,19 @@ class ClassTest < Test::Unit::TestCase def test_removing_class_in_root_namespace assert A.is_a?(Class) Class.remove_class(A) - assert_raises(NameError) { A.is_a?(Class) } + assert_raise(NameError) { A.is_a?(Class) } end def test_removing_class_in_one_level_namespace assert X::B.is_a?(Class) Class.remove_class(X::B) - assert_raises(NameError) { X::B.is_a?(Class) } + assert_raise(NameError) { X::B.is_a?(Class) } end def test_removing_class_in_two_level_namespace assert Y::Z::C.is_a?(Class) Class.remove_class(Y::Z::C) - assert_raises(NameError) { Y::Z::C.is_a?(Class) } + assert_raise(NameError) { Y::Z::C.is_a?(Class) } end def test_retrieving_subclasses diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index b63ab30965..f1f1f15426 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -234,7 +234,7 @@ class HashExtTest < Test::Unit::TestCase { :failure => "stuff", :funny => "business" }.assert_valid_keys(:failure, :funny) end - assert_raises(ArgumentError, "Unknown key(s): failore") do + assert_raise(ArgumentError, "Unknown key(s): failore") do { :failore => "stuff", :funny => "business" }.assert_valid_keys([ :failure, :funny ]) { :failore => "stuff", :funny => "business" }.assert_valid_keys(:failure, :funny) end @@ -884,7 +884,7 @@ class QueryTest < Test::Unit::TestCase end def test_expansion_count_is_limited - assert_raises RuntimeError do + assert_raise RuntimeError do attack_xml = <<-EOT :mutex - assert_raises(ArgumentError) do + assert_raise(ArgumentError) do @target.synchronize :to_s, :with => :mutex end end diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index a5d98507ba..0d3d10f333 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -92,8 +92,8 @@ class ModuleTest < Test::Unit::TestCase end def test_missing_delegation_target - assert_raises(ArgumentError) { eval($nowhere) } - assert_raises(ArgumentError) { eval($noplace) } + assert_raise(ArgumentError) { eval($nowhere) } + assert_raise(ArgumentError) { eval($noplace) } end def test_delegation_prefix @@ -141,7 +141,7 @@ class ModuleTest < Test::Unit::TestCase def test_delegation_without_allow_nil_and_nil_value david = Someone.new("David") - assert_raises(NoMethodError) { david.street } + assert_raise(NoMethodError) { david.street } end def test_parent @@ -314,7 +314,7 @@ class MethodAliasingTest < Test::Unit::TestCase alias_method_chain :duck, :orange end - assert_raises NoMethodError do + assert_raise NoMethodError do @instance.duck end @@ -330,7 +330,7 @@ class MethodAliasingTest < Test::Unit::TestCase alias_method_chain :duck, :orange end - assert_raises NoMethodError do + assert_raise NoMethodError do @instance.duck end 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 0bdbd14f33..b6515e05a0 100644 --- a/activesupport/test/core_ext/object_and_class_ext_test.rb +++ b/activesupport/test/core_ext/object_and_class_ext_test.rb @@ -109,7 +109,7 @@ end class ObjectTests < Test::Unit::TestCase def test_suppress_re_raises - assert_raises(LoadError) { suppress(ArgumentError) {raise LoadError} } + assert_raise(LoadError) { suppress(ArgumentError) {raise LoadError} } end def test_suppress_supresses suppress(ArgumentError) { raise ArgumentError } @@ -256,7 +256,7 @@ class ObjectTryTest < Test::Unit::TestCase def test_nonexisting_method method = :undefined_method assert !@string.respond_to?(method) - assert_raises(NoMethodError) { @string.try(method) } + assert_raise(NoMethodError) { @string.try(method) } end def test_valid_method diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index 1de6a2ac2e..accfe51ed6 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -751,7 +751,7 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < Test::Unit::TestCase def test_use_zone_with_exception_raised Time.zone = 'Alaska' - assert_raises RuntimeError do + assert_raise RuntimeError do Time.use_zone('Hawaii') { raise RuntimeError } end assert_equal ActiveSupport::TimeZone['Alaska'], Time.zone diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index fe04b91f2b..a21f09403f 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -43,7 +43,7 @@ class DependenciesTest < Test::Unit::TestCase end def test_missing_dependency_raises_missing_source_file - assert_raises(MissingSourceFile) { require_dependency("missing_service") } + assert_raise(MissingSourceFile) { require_dependency("missing_service") } end def test_missing_association_raises_nothing @@ -136,10 +136,10 @@ class DependenciesTest < Test::Unit::TestCase def test_non_existing_const_raises_name_error with_loading 'autoloading_fixtures' do - assert_raises(NameError) { DoesNotExist } - assert_raises(NameError) { NoModule::DoesNotExist } - assert_raises(NameError) { A::DoesNotExist } - assert_raises(NameError) { A::B::DoesNotExist } + assert_raise(NameError) { DoesNotExist } + assert_raise(NameError) { NoModule::DoesNotExist } + assert_raise(NameError) { A::DoesNotExist } + assert_raise(NameError) { A::B::DoesNotExist } end end @@ -206,8 +206,8 @@ class DependenciesTest < Test::Unit::TestCase def failing_test_access_thru_and_upwards_fails with_loading 'autoloading_fixtures' do assert ! defined?(ModuleFolder) - assert_raises(NameError) { ModuleFolder::Object } - assert_raises(NameError) { ModuleFolder::NestedClass::Object } + assert_raise(NameError) { ModuleFolder::Object } + assert_raise(NameError) { ModuleFolder::NestedClass::Object } Object.__send__ :remove_const, :ModuleFolder end end @@ -382,7 +382,7 @@ class DependenciesTest < Test::Unit::TestCase with_loading 'autoloading_fixtures' do require_dependency '././counting_loader' assert_equal 1, $counting_loaded_times - assert_raises(ArgumentError) { ActiveSupport::Dependencies.load_missing_constant Object, :CountingLoader } + assert_raise(ArgumentError) { ActiveSupport::Dependencies.load_missing_constant Object, :CountingLoader } assert_equal 1, $counting_loaded_times end end @@ -421,7 +421,7 @@ class DependenciesTest < Test::Unit::TestCase def test_nested_load_error_isnt_rescued with_loading 'dependencies' do - assert_raises(MissingSourceFile) do + assert_raise(MissingSourceFile) do RequiresNonexistent1 end end @@ -494,7 +494,7 @@ class DependenciesTest < Test::Unit::TestCase def test_unloadable_should_fail_with_anonymous_modules with_loading 'autoloading_fixtures' do m = Module.new - assert_raises(ArgumentError) { m.unloadable } + assert_raise(ArgumentError) { m.unloadable } end end @@ -584,7 +584,7 @@ class DependenciesTest < Test::Unit::TestCase end def test_new_constants_in_with_illegal_module_name_raises_correct_error - assert_raises(NameError) do + assert_raise(NameError) do ActiveSupport::Dependencies.new_constants_in("Illegal-Name") {} end end diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index d8c93dc9ae..948b6d9bb0 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -161,13 +161,13 @@ class InflectorTest < Test::Unit::TestCase assert_nothing_raised { assert_equal Ace::Base::Case, ActiveSupport::Inflector.constantize("::Ace::Base::Case") } assert_nothing_raised { assert_equal InflectorTest, ActiveSupport::Inflector.constantize("InflectorTest") } assert_nothing_raised { assert_equal InflectorTest, ActiveSupport::Inflector.constantize("::InflectorTest") } - assert_raises(NameError) { ActiveSupport::Inflector.constantize("UnknownClass") } - assert_raises(NameError) { ActiveSupport::Inflector.constantize("An invalid string") } - assert_raises(NameError) { ActiveSupport::Inflector.constantize("InvalidClass\n") } + assert_raise(NameError) { ActiveSupport::Inflector.constantize("UnknownClass") } + assert_raise(NameError) { ActiveSupport::Inflector.constantize("An invalid string") } + assert_raise(NameError) { ActiveSupport::Inflector.constantize("InvalidClass\n") } end def test_constantize_does_lexical_lookup - assert_raises(NameError) { ActiveSupport::Inflector.constantize("Ace::Base::InflectorTest") } + assert_raise(NameError) { ActiveSupport::Inflector.constantize("Ace::Base::InflectorTest") } end def test_ordinal diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb index ebd46a851e..b88a00e584 100644 --- a/activesupport/test/json/decoding_test.rb +++ b/activesupport/test/json/decoding_test.rb @@ -40,6 +40,6 @@ class TestJSONDecoding < Test::Unit::TestCase end def test_failed_json_decoding - assert_raises(ActiveSupport::JSON::ParseError) { ActiveSupport::JSON.decode(%({: 1})) } + assert_raise(ActiveSupport::JSON::ParseError) { ActiveSupport::JSON.decode(%({: 1})) } end end diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index 2c5b4d0378..7d2eedad61 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -75,7 +75,7 @@ class TestJSONEncoding < Test::Unit::TestCase def test_exception_raised_when_encoding_circular_reference a = [1] a << a - assert_raises(ActiveSupport::JSON::CircularReferenceError) { a.to_json } + assert_raise(ActiveSupport::JSON::CircularReferenceError) { a.to_json } end def test_hash_key_identifiers_are_always_quoted diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index c0b4a4658c..ed3461571a 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -33,7 +33,7 @@ class MessageEncryptorTest < Test::Unit::TestCase private def assert_not_decrypted(value) - assert_raises(ActiveSupport::MessageEncryptor::InvalidMessage) do + assert_raise(ActiveSupport::MessageEncryptor::InvalidMessage) do @encryptor.decrypt(value) end end diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 2190308856..57c4ce841e 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -18,7 +18,7 @@ class MessageVerifierTest < Test::Unit::TestCase end def assert_not_verified(message) - assert_raises(ActiveSupport::MessageVerifier::InvalidSignature) do + assert_raise(ActiveSupport::MessageVerifier::InvalidSignature) do @verifier.verify(message) end end diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 0644dbe603..661b33cc57 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -26,7 +26,7 @@ class MultibyteCharsTest < Test::Unit::TestCase assert_nothing_raised do @chars.__method_for_multibyte_testing end - assert_raises NoMethodError do + assert_raise NoMethodError do @chars.__unknown_method end end @@ -71,7 +71,7 @@ class MultibyteCharsTest < Test::Unit::TestCase end def test_unpack_raises_encoding_error_on_broken_strings - assert_raises(ActiveSupport::Multibyte::EncodingError) do + assert_raise(ActiveSupport::Multibyte::EncodingError) do @proxy_class.u_unpack(BYTE_STRING) end end @@ -209,8 +209,8 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase end def test_insert_throws_index_error - assert_raises(IndexError) { @chars.insert(-12, 'わ')} - assert_raises(IndexError) { @chars.insert(12, 'わ') } + assert_raise(IndexError) { @chars.insert(-12, 'わ')} + assert_raise(IndexError) { @chars.insert(12, 'わ') } end def test_should_know_if_one_includes_the_other @@ -222,7 +222,7 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase end def test_include_raises_type_error_when_nil_is_passed - assert_raises(TypeError) do + assert_raise(TypeError) do @chars.include?(nil) end end @@ -257,22 +257,22 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase def test_indexed_insert_should_raise_on_index_overflow before = @chars.to_s - assert_raises(IndexError) { @chars[10] = 'a' } - assert_raises(IndexError) { @chars[10, 4] = 'a' } - assert_raises(IndexError) { @chars[/ii/] = 'a' } - assert_raises(IndexError) { @chars[/()/, 10] = 'a' } + assert_raise(IndexError) { @chars[10] = 'a' } + assert_raise(IndexError) { @chars[10, 4] = 'a' } + assert_raise(IndexError) { @chars[/ii/] = 'a' } + assert_raise(IndexError) { @chars[/()/, 10] = 'a' } assert_equal before, @chars end def test_indexed_insert_should_raise_on_range_overflow before = @chars.to_s - assert_raises(RangeError) { @chars[10..12] = 'a' } + assert_raise(RangeError) { @chars[10..12] = 'a' } assert_equal before, @chars end def test_rjust_should_raise_argument_errors_on_bad_arguments - assert_raises(ArgumentError) { @chars.rjust(10, '') } - assert_raises(ArgumentError) { @chars.rjust } + assert_raise(ArgumentError) { @chars.rjust(10, '') } + assert_raise(ArgumentError) { @chars.rjust } end def test_rjust_should_count_characters_instead_of_bytes @@ -289,8 +289,8 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase end def test_ljust_should_raise_argument_errors_on_bad_arguments - assert_raises(ArgumentError) { @chars.ljust(10, '') } - assert_raises(ArgumentError) { @chars.ljust } + assert_raise(ArgumentError) { @chars.ljust(10, '') } + assert_raise(ArgumentError) { @chars.ljust } end def test_ljust_should_count_characters_instead_of_bytes @@ -307,8 +307,8 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase end def test_center_should_raise_argument_errors_on_bad_arguments - assert_raises(ArgumentError) { @chars.center(10, '') } - assert_raises(ArgumentError) { @chars.center } + assert_raise(ArgumentError) { @chars.center(10, '') } + assert_raise(ArgumentError) { @chars.center } end def test_center_should_count_charactes_instead_of_bytes @@ -440,7 +440,7 @@ class MultibyteCharsExtrasTest < Test::Unit::TestCase if RUBY_VERSION >= '1.9' def test_tidy_bytes_is_broken_on_1_9_0 - assert_raises(ArgumentError) do + assert_raise(ArgumentError) do assert_equal_codepoints [0xfffd].pack('U'), chars("\xef\xbf\xbd").tidy_bytes end end diff --git a/activesupport/test/string_inquirer_test.rb b/activesupport/test/string_inquirer_test.rb index dda7850e6b..7f11f667df 100644 --- a/activesupport/test/string_inquirer_test.rb +++ b/activesupport/test/string_inquirer_test.rb @@ -10,6 +10,6 @@ class StringInquirerTest < Test::Unit::TestCase end def test_missing_question_mark - assert_raises(NoMethodError) { ActiveSupport::StringInquirer.new("production").production } + assert_raise(NoMethodError) { ActiveSupport::StringInquirer.new("production").production } end end diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 6dec6a8f34..b01f62460a 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -244,7 +244,7 @@ class TimeZoneTest < Test::Unit::TestCase assert_nil ActiveSupport::TimeZone["bogus"] assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone["Central Time (US & Canada)"] assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone[8] - assert_raises(ArgumentError) { ActiveSupport::TimeZone[false] } + assert_raise(ArgumentError) { ActiveSupport::TimeZone[false] } end def test_new -- cgit v1.2.3 From 822c41d69d9228c9912d29ac45155d3a16bb5c50 Mon Sep 17 00:00:00 2001 From: Bart ten Brinke Date: Thu, 26 Feb 2009 00:24:42 +0100 Subject: XmlMini supports different backend parsers, starting with libxml [#2084 state:committed] Signed-off-by: Jeremy Kemper --- activesupport/CHANGELOG | 5 + activesupport/lib/active_support/xml_mini.rb | 110 ++--------------- .../lib/active_support/xml_mini/libxml.rb | 131 +++++++++++++++++++++ activesupport/lib/active_support/xml_mini/rexml.rb | 106 +++++++++++++++++ 4 files changed, 251 insertions(+), 101 deletions(-) create mode 100644 activesupport/lib/active_support/xml_mini/libxml.rb create mode 100644 activesupport/lib/active_support/xml_mini/rexml.rb (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index bbece6349a..1d42000867 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,3 +1,8 @@ +*Edge* + +* XmlMini supports libxml if available. #2084 [Bart ten Brinke] + + *2.3.1 [RC2] (March 5, 2009)* * Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda] diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index ce3f50620d..8ae8e7cefe 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -1,113 +1,21 @@ # = XmlMini -# This is a derivitive work of XmlSimple 1.0.11 -# Author:: Joseph Holsten -# Copyright:: Copyright (c) 2008 Joseph Holsten -# Copyright:: Copyright (c) 2003-2006 Maik Schmidt -# License:: Distributes under the same terms as Ruby. module ActiveSupport module XmlMini extend self CONTENT_KEY = '__content__'.freeze - # Parse an XML Document string into a simple hash - # - # Same as XmlSimple::xml_in but doesn't shoot itself in the foot, - # and uses the defaults from ActiveSupport - # - # string:: - # XML Document string to parse - def parse(string) - require 'rexml/document' unless defined?(REXML::Document) - doc = REXML::Document.new(string) - merge_element!({}, doc.root) - end - - private - # Convert an XML element and merge into the hash - # - # hash:: - # Hash to merge the converted element into. - # element:: - # XML element to merge into hash - def merge_element!(hash, element) - merge!(hash, element.name, collapse(element)) - end - - # Actually converts an XML document element into a data structure. - # - # element:: - # The document element to be collapsed. - def collapse(element) - hash = get_attributes(element) - - if element.has_elements? - element.each_element {|child| merge_element!(hash, child) } - merge_texts!(hash, element) unless empty_content?(element) - hash - else - merge_texts!(hash, element) - end - end - - # Merge all the texts of an element into the hash - # - # hash:: - # Hash to add the converted emement to. - # element:: - # XML element whose texts are to me merged into the hash - def merge_texts!(hash, element) - unless element.has_text? - hash - else - # must use value to prevent double-escaping - merge!(hash, CONTENT_KEY, element.texts.sum(&:value)) - end - end - - # Adds a new key/value pair to an existing Hash. If the key to be added - # already exists and the existing value associated with key is not - # an Array, it will be wrapped in an Array. Then the new value is - # appended to that Array. - # - # hash:: - # Hash to add key/value pair to. - # key:: - # Key to be added. - # value:: - # Value to be associated with key. - def merge!(hash, key, value) - if hash.has_key?(key) - if hash[key].instance_of?(Array) - hash[key] << value - else - hash[key] = [hash[key], value] - end - elsif value.instance_of?(Array) - hash[key] = [value] - else - hash[key] = value - end - hash + # Hook the correct parser into XmlMini + def hook_parser + begin + require 'xml/libxml' unless defined? LibXML + require "active_support/xml_mini/libxml.rb" + rescue MissingSourceFile => e + require "active_support/xml_mini/rexml.rb" end + end - # Converts the attributes array of an XML element into a hash. - # Returns an empty Hash if node has no attributes. - # - # element:: - # XML element to extract attributes from. - def get_attributes(element) - attributes = {} - element.attributes.each { |n,v| attributes[n] = v } - attributes - end + hook_parser - # Determines if a document element has text content - # - # element:: - # XML element to be checked. - def empty_content?(element) - element.texts.join.blank? - end end end \ No newline at end of file diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb new file mode 100644 index 0000000000..dd271dc587 --- /dev/null +++ b/activesupport/lib/active_support/xml_mini/libxml.rb @@ -0,0 +1,131 @@ +# = XML Mini Libxml implementation +module ActiveSupport + module XmlMini + extend self + + # Parse an XML Document string into a simple hash using libxml. + # string:: + # XML Document string to parse + def parse(string) + require 'xml/libxml' unless defined? LibXML + + string.strip! + XML.default_keep_blanks = false + + return {} if string.blank? + return XML::Parser.string(string).parse.to_hash + end + + end +end + +module XML + module Conversions + module Document + def to_hash + root.to_hash + end + end + + module Node + CONTENT_ROOT = '__content__' + LIB_XML_LIMIT = 30000000 # Hardcoded LibXML limit + + # Convert XML document to hash + # + # hash:: + # Hash to merge the converted element into. + def to_hash(hash={}) + if text? + raise RuntimeError if content.length >= LIB_XML_LIMIT + hash[CONTENT_ROOT] = content + else + sub_hash = insert_name_into_hash(hash, name) + attributes_to_hash(sub_hash) + if array? + children_array_to_hash(sub_hash) + elsif yaml? + children_yaml_to_hash(sub_hash) + else + children_to_hash(sub_hash) + end + end + hash + end + + protected + + # Insert name into hash + # + # hash:: + # Hash to merge the converted element into. + # name:: + # name to to merge into hash + def insert_name_into_hash(hash, name) + sub_hash = {} + if hash[name] + if !hash[name].kind_of? Array + hash[name] = [hash[name]] + end + hash[name] << sub_hash + else + hash[name] = sub_hash + end + sub_hash + end + + # Insert children into hash + # + # hash:: + # Hash to merge the children into. + def children_to_hash(hash={}) + each { |child| child.to_hash(hash) } + attributes_to_hash(hash) + hash + end + + # Convert xml attributes to hash + # + # hash:: + # Hash to merge the attributes into + def attributes_to_hash(hash={}) + each_attr { |attr| hash[attr.name] = attr.value } + hash + end + + # Convert array into hash + # + # hash:: + # Hash to merge the array into + def children_array_to_hash(hash={}) + hash[child.name] = map do |child| + returning({}) { |sub_hash| child.children_to_hash(sub_hash) } + end + hash + end + + # Convert yaml into hash + # + # hash:: + # Hash to merge the yaml into + def children_yaml_to_hash(hash = {}) + hash[CONTENT_ROOT] = content unless content.blank? + hash + end + + # Check if child is of type array + def array? + child? && child.next? && child.name == child.next.name + end + + # Check if child is of type yaml + def yaml? + attributes.collect{|x| x.value}.include?('yaml') + end + + end + end +end + +XML::Document.send(:include, XML::Conversions::Document) +XML::Node.send(:include, XML::Conversions::Node) \ No newline at end of file diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb new file mode 100644 index 0000000000..655eff168c --- /dev/null +++ b/activesupport/lib/active_support/xml_mini/rexml.rb @@ -0,0 +1,106 @@ +# = XmlMini ReXML implementation +module ActiveSupport + module XmlMini + extend self + + # Parse an XML Document string into a simple hash + # + # Same as XmlSimple::xml_in but doesn't shoot itself in the foot, + # and uses the defaults from ActiveSupport + # + # string:: + # XML Document string to parse + def parse(string) + require 'rexml/document' unless defined?(REXML::Document) + doc = REXML::Document.new(string) + merge_element!({}, doc.root) + end + + private + # Convert an XML element and merge into the hash + # + # hash:: + # Hash to merge the converted element into. + # element:: + # XML element to merge into hash + def merge_element!(hash, element) + merge!(hash, element.name, collapse(element)) + end + + # Actually converts an XML document element into a data structure. + # + # element:: + # The document element to be collapsed. + def collapse(element) + hash = get_attributes(element) + + if element.has_elements? + element.each_element {|child| merge_element!(hash, child) } + merge_texts!(hash, element) unless empty_content?(element) + hash + else + merge_texts!(hash, element) + end + end + + # Merge all the texts of an element into the hash + # + # hash:: + # Hash to add the converted emement to. + # element:: + # XML element whose texts are to me merged into the hash + def merge_texts!(hash, element) + unless element.has_text? + hash + else + # must use value to prevent double-escaping + merge!(hash, CONTENT_KEY, element.texts.sum(&:value)) + end + end + + # Adds a new key/value pair to an existing Hash. If the key to be added + # already exists and the existing value associated with key is not + # an Array, it will be wrapped in an Array. Then the new value is + # appended to that Array. + # + # hash:: + # Hash to add key/value pair to. + # key:: + # Key to be added. + # value:: + # Value to be associated with key. + def merge!(hash, key, value) + if hash.has_key?(key) + if hash[key].instance_of?(Array) + hash[key] << value + else + hash[key] = [hash[key], value] + end + elsif value.instance_of?(Array) + hash[key] = [value] + else + hash[key] = value + end + hash + end + + # Converts the attributes array of an XML element into a hash. + # Returns an empty Hash if node has no attributes. + # + # element:: + # XML element to extract attributes from. + def get_attributes(element) + attributes = {} + element.attributes.each { |n,v| attributes[n] = v } + attributes + end + + # Determines if a document element has text content + # + # element:: + # XML element to be checked. + def empty_content?(element) + element.texts.join.blank? + end + end +end \ No newline at end of file -- cgit v1.2.3 From a995a738ca10f9bef023689df70d26aad8931b9a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 9 Mar 2009 19:00:21 +0100 Subject: Revert "XmlMini supports different backend parsers, starting with libxml" Spews a ton undefined method `default_keep_blanks=' for XML:Module errors. This reverts commit 822c41d69d9228c9912d29ac45155d3a16bb5c50. --- activesupport/CHANGELOG | 5 - activesupport/lib/active_support/xml_mini.rb | 110 +++++++++++++++-- .../lib/active_support/xml_mini/libxml.rb | 131 --------------------- activesupport/lib/active_support/xml_mini/rexml.rb | 106 ----------------- 4 files changed, 101 insertions(+), 251 deletions(-) delete mode 100644 activesupport/lib/active_support/xml_mini/libxml.rb delete mode 100644 activesupport/lib/active_support/xml_mini/rexml.rb (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 1d42000867..bbece6349a 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,8 +1,3 @@ -*Edge* - -* XmlMini supports libxml if available. #2084 [Bart ten Brinke] - - *2.3.1 [RC2] (March 5, 2009)* * Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda] diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index 8ae8e7cefe..ce3f50620d 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -1,21 +1,113 @@ # = XmlMini +# This is a derivitive work of XmlSimple 1.0.11 +# Author:: Joseph Holsten +# Copyright:: Copyright (c) 2008 Joseph Holsten +# Copyright:: Copyright (c) 2003-2006 Maik Schmidt +# License:: Distributes under the same terms as Ruby. module ActiveSupport module XmlMini extend self CONTENT_KEY = '__content__'.freeze - # Hook the correct parser into XmlMini - def hook_parser - begin - require 'xml/libxml' unless defined? LibXML - require "active_support/xml_mini/libxml.rb" - rescue MissingSourceFile => e - require "active_support/xml_mini/rexml.rb" - end + # Parse an XML Document string into a simple hash + # + # Same as XmlSimple::xml_in but doesn't shoot itself in the foot, + # and uses the defaults from ActiveSupport + # + # string:: + # XML Document string to parse + def parse(string) + require 'rexml/document' unless defined?(REXML::Document) + doc = REXML::Document.new(string) + merge_element!({}, doc.root) end - hook_parser + private + # Convert an XML element and merge into the hash + # + # hash:: + # Hash to merge the converted element into. + # element:: + # XML element to merge into hash + def merge_element!(hash, element) + merge!(hash, element.name, collapse(element)) + end + + # Actually converts an XML document element into a data structure. + # + # element:: + # The document element to be collapsed. + def collapse(element) + hash = get_attributes(element) + + if element.has_elements? + element.each_element {|child| merge_element!(hash, child) } + merge_texts!(hash, element) unless empty_content?(element) + hash + else + merge_texts!(hash, element) + end + end + + # Merge all the texts of an element into the hash + # + # hash:: + # Hash to add the converted emement to. + # element:: + # XML element whose texts are to me merged into the hash + def merge_texts!(hash, element) + unless element.has_text? + hash + else + # must use value to prevent double-escaping + merge!(hash, CONTENT_KEY, element.texts.sum(&:value)) + end + end + + # Adds a new key/value pair to an existing Hash. If the key to be added + # already exists and the existing value associated with key is not + # an Array, it will be wrapped in an Array. Then the new value is + # appended to that Array. + # + # hash:: + # Hash to add key/value pair to. + # key:: + # Key to be added. + # value:: + # Value to be associated with key. + def merge!(hash, key, value) + if hash.has_key?(key) + if hash[key].instance_of?(Array) + hash[key] << value + else + hash[key] = [hash[key], value] + end + elsif value.instance_of?(Array) + hash[key] = [value] + else + hash[key] = value + end + hash + end + # Converts the attributes array of an XML element into a hash. + # Returns an empty Hash if node has no attributes. + # + # element:: + # XML element to extract attributes from. + def get_attributes(element) + attributes = {} + element.attributes.each { |n,v| attributes[n] = v } + attributes + end + + # Determines if a document element has text content + # + # element:: + # XML element to be checked. + def empty_content?(element) + element.texts.join.blank? + end end end \ No newline at end of file diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb deleted file mode 100644 index dd271dc587..0000000000 --- a/activesupport/lib/active_support/xml_mini/libxml.rb +++ /dev/null @@ -1,131 +0,0 @@ -# = XML Mini Libxml implementation -module ActiveSupport - module XmlMini - extend self - - # Parse an XML Document string into a simple hash using libxml. - # string:: - # XML Document string to parse - def parse(string) - require 'xml/libxml' unless defined? LibXML - - string.strip! - XML.default_keep_blanks = false - - return {} if string.blank? - return XML::Parser.string(string).parse.to_hash - end - - end -end - -module XML - module Conversions - module Document - def to_hash - root.to_hash - end - end - - module Node - CONTENT_ROOT = '__content__' - LIB_XML_LIMIT = 30000000 # Hardcoded LibXML limit - - # Convert XML document to hash - # - # hash:: - # Hash to merge the converted element into. - def to_hash(hash={}) - if text? - raise RuntimeError if content.length >= LIB_XML_LIMIT - hash[CONTENT_ROOT] = content - else - sub_hash = insert_name_into_hash(hash, name) - attributes_to_hash(sub_hash) - if array? - children_array_to_hash(sub_hash) - elsif yaml? - children_yaml_to_hash(sub_hash) - else - children_to_hash(sub_hash) - end - end - hash - end - - protected - - # Insert name into hash - # - # hash:: - # Hash to merge the converted element into. - # name:: - # name to to merge into hash - def insert_name_into_hash(hash, name) - sub_hash = {} - if hash[name] - if !hash[name].kind_of? Array - hash[name] = [hash[name]] - end - hash[name] << sub_hash - else - hash[name] = sub_hash - end - sub_hash - end - - # Insert children into hash - # - # hash:: - # Hash to merge the children into. - def children_to_hash(hash={}) - each { |child| child.to_hash(hash) } - attributes_to_hash(hash) - hash - end - - # Convert xml attributes to hash - # - # hash:: - # Hash to merge the attributes into - def attributes_to_hash(hash={}) - each_attr { |attr| hash[attr.name] = attr.value } - hash - end - - # Convert array into hash - # - # hash:: - # Hash to merge the array into - def children_array_to_hash(hash={}) - hash[child.name] = map do |child| - returning({}) { |sub_hash| child.children_to_hash(sub_hash) } - end - hash - end - - # Convert yaml into hash - # - # hash:: - # Hash to merge the yaml into - def children_yaml_to_hash(hash = {}) - hash[CONTENT_ROOT] = content unless content.blank? - hash - end - - # Check if child is of type array - def array? - child? && child.next? && child.name == child.next.name - end - - # Check if child is of type yaml - def yaml? - attributes.collect{|x| x.value}.include?('yaml') - end - - end - end -end - -XML::Document.send(:include, XML::Conversions::Document) -XML::Node.send(:include, XML::Conversions::Node) \ No newline at end of file diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb deleted file mode 100644 index 655eff168c..0000000000 --- a/activesupport/lib/active_support/xml_mini/rexml.rb +++ /dev/null @@ -1,106 +0,0 @@ -# = XmlMini ReXML implementation -module ActiveSupport - module XmlMini - extend self - - # Parse an XML Document string into a simple hash - # - # Same as XmlSimple::xml_in but doesn't shoot itself in the foot, - # and uses the defaults from ActiveSupport - # - # string:: - # XML Document string to parse - def parse(string) - require 'rexml/document' unless defined?(REXML::Document) - doc = REXML::Document.new(string) - merge_element!({}, doc.root) - end - - private - # Convert an XML element and merge into the hash - # - # hash:: - # Hash to merge the converted element into. - # element:: - # XML element to merge into hash - def merge_element!(hash, element) - merge!(hash, element.name, collapse(element)) - end - - # Actually converts an XML document element into a data structure. - # - # element:: - # The document element to be collapsed. - def collapse(element) - hash = get_attributes(element) - - if element.has_elements? - element.each_element {|child| merge_element!(hash, child) } - merge_texts!(hash, element) unless empty_content?(element) - hash - else - merge_texts!(hash, element) - end - end - - # Merge all the texts of an element into the hash - # - # hash:: - # Hash to add the converted emement to. - # element:: - # XML element whose texts are to me merged into the hash - def merge_texts!(hash, element) - unless element.has_text? - hash - else - # must use value to prevent double-escaping - merge!(hash, CONTENT_KEY, element.texts.sum(&:value)) - end - end - - # Adds a new key/value pair to an existing Hash. If the key to be added - # already exists and the existing value associated with key is not - # an Array, it will be wrapped in an Array. Then the new value is - # appended to that Array. - # - # hash:: - # Hash to add key/value pair to. - # key:: - # Key to be added. - # value:: - # Value to be associated with key. - def merge!(hash, key, value) - if hash.has_key?(key) - if hash[key].instance_of?(Array) - hash[key] << value - else - hash[key] = [hash[key], value] - end - elsif value.instance_of?(Array) - hash[key] = [value] - else - hash[key] = value - end - hash - end - - # Converts the attributes array of an XML element into a hash. - # Returns an empty Hash if node has no attributes. - # - # element:: - # XML element to extract attributes from. - def get_attributes(element) - attributes = {} - element.attributes.each { |n,v| attributes[n] = v } - attributes - end - - # Determines if a document element has text content - # - # element:: - # XML element to be checked. - def empty_content?(element) - element.texts.join.blank? - end - end -end \ No newline at end of file -- cgit v1.2.3 From 146511e0181a8c6703dcff7b5236d81b64841dd5 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 9 Mar 2009 12:39:20 -0700 Subject: Revert "Revert "XmlMini supports different backend parsers, starting with libxml"" Will change to require a known-working libxml-ruby. This reverts commit a995a738ca10f9bef023689df70d26aad8931b9a. --- activesupport/CHANGELOG | 5 + activesupport/lib/active_support/xml_mini.rb | 110 ++--------------- .../lib/active_support/xml_mini/libxml.rb | 131 +++++++++++++++++++++ activesupport/lib/active_support/xml_mini/rexml.rb | 106 +++++++++++++++++ 4 files changed, 251 insertions(+), 101 deletions(-) create mode 100644 activesupport/lib/active_support/xml_mini/libxml.rb create mode 100644 activesupport/lib/active_support/xml_mini/rexml.rb (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index bbece6349a..1d42000867 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,3 +1,8 @@ +*Edge* + +* XmlMini supports libxml if available. #2084 [Bart ten Brinke] + + *2.3.1 [RC2] (March 5, 2009)* * Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda] diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index ce3f50620d..8ae8e7cefe 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -1,113 +1,21 @@ # = XmlMini -# This is a derivitive work of XmlSimple 1.0.11 -# Author:: Joseph Holsten -# Copyright:: Copyright (c) 2008 Joseph Holsten -# Copyright:: Copyright (c) 2003-2006 Maik Schmidt -# License:: Distributes under the same terms as Ruby. module ActiveSupport module XmlMini extend self CONTENT_KEY = '__content__'.freeze - # Parse an XML Document string into a simple hash - # - # Same as XmlSimple::xml_in but doesn't shoot itself in the foot, - # and uses the defaults from ActiveSupport - # - # string:: - # XML Document string to parse - def parse(string) - require 'rexml/document' unless defined?(REXML::Document) - doc = REXML::Document.new(string) - merge_element!({}, doc.root) - end - - private - # Convert an XML element and merge into the hash - # - # hash:: - # Hash to merge the converted element into. - # element:: - # XML element to merge into hash - def merge_element!(hash, element) - merge!(hash, element.name, collapse(element)) - end - - # Actually converts an XML document element into a data structure. - # - # element:: - # The document element to be collapsed. - def collapse(element) - hash = get_attributes(element) - - if element.has_elements? - element.each_element {|child| merge_element!(hash, child) } - merge_texts!(hash, element) unless empty_content?(element) - hash - else - merge_texts!(hash, element) - end - end - - # Merge all the texts of an element into the hash - # - # hash:: - # Hash to add the converted emement to. - # element:: - # XML element whose texts are to me merged into the hash - def merge_texts!(hash, element) - unless element.has_text? - hash - else - # must use value to prevent double-escaping - merge!(hash, CONTENT_KEY, element.texts.sum(&:value)) - end - end - - # Adds a new key/value pair to an existing Hash. If the key to be added - # already exists and the existing value associated with key is not - # an Array, it will be wrapped in an Array. Then the new value is - # appended to that Array. - # - # hash:: - # Hash to add key/value pair to. - # key:: - # Key to be added. - # value:: - # Value to be associated with key. - def merge!(hash, key, value) - if hash.has_key?(key) - if hash[key].instance_of?(Array) - hash[key] << value - else - hash[key] = [hash[key], value] - end - elsif value.instance_of?(Array) - hash[key] = [value] - else - hash[key] = value - end - hash + # Hook the correct parser into XmlMini + def hook_parser + begin + require 'xml/libxml' unless defined? LibXML + require "active_support/xml_mini/libxml.rb" + rescue MissingSourceFile => e + require "active_support/xml_mini/rexml.rb" end + end - # Converts the attributes array of an XML element into a hash. - # Returns an empty Hash if node has no attributes. - # - # element:: - # XML element to extract attributes from. - def get_attributes(element) - attributes = {} - element.attributes.each { |n,v| attributes[n] = v } - attributes - end + hook_parser - # Determines if a document element has text content - # - # element:: - # XML element to be checked. - def empty_content?(element) - element.texts.join.blank? - end end end \ No newline at end of file diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb new file mode 100644 index 0000000000..dd271dc587 --- /dev/null +++ b/activesupport/lib/active_support/xml_mini/libxml.rb @@ -0,0 +1,131 @@ +# = XML Mini Libxml implementation +module ActiveSupport + module XmlMini + extend self + + # Parse an XML Document string into a simple hash using libxml. + # string:: + # XML Document string to parse + def parse(string) + require 'xml/libxml' unless defined? LibXML + + string.strip! + XML.default_keep_blanks = false + + return {} if string.blank? + return XML::Parser.string(string).parse.to_hash + end + + end +end + +module XML + module Conversions + module Document + def to_hash + root.to_hash + end + end + + module Node + CONTENT_ROOT = '__content__' + LIB_XML_LIMIT = 30000000 # Hardcoded LibXML limit + + # Convert XML document to hash + # + # hash:: + # Hash to merge the converted element into. + def to_hash(hash={}) + if text? + raise RuntimeError if content.length >= LIB_XML_LIMIT + hash[CONTENT_ROOT] = content + else + sub_hash = insert_name_into_hash(hash, name) + attributes_to_hash(sub_hash) + if array? + children_array_to_hash(sub_hash) + elsif yaml? + children_yaml_to_hash(sub_hash) + else + children_to_hash(sub_hash) + end + end + hash + end + + protected + + # Insert name into hash + # + # hash:: + # Hash to merge the converted element into. + # name:: + # name to to merge into hash + def insert_name_into_hash(hash, name) + sub_hash = {} + if hash[name] + if !hash[name].kind_of? Array + hash[name] = [hash[name]] + end + hash[name] << sub_hash + else + hash[name] = sub_hash + end + sub_hash + end + + # Insert children into hash + # + # hash:: + # Hash to merge the children into. + def children_to_hash(hash={}) + each { |child| child.to_hash(hash) } + attributes_to_hash(hash) + hash + end + + # Convert xml attributes to hash + # + # hash:: + # Hash to merge the attributes into + def attributes_to_hash(hash={}) + each_attr { |attr| hash[attr.name] = attr.value } + hash + end + + # Convert array into hash + # + # hash:: + # Hash to merge the array into + def children_array_to_hash(hash={}) + hash[child.name] = map do |child| + returning({}) { |sub_hash| child.children_to_hash(sub_hash) } + end + hash + end + + # Convert yaml into hash + # + # hash:: + # Hash to merge the yaml into + def children_yaml_to_hash(hash = {}) + hash[CONTENT_ROOT] = content unless content.blank? + hash + end + + # Check if child is of type array + def array? + child? && child.next? && child.name == child.next.name + end + + # Check if child is of type yaml + def yaml? + attributes.collect{|x| x.value}.include?('yaml') + end + + end + end +end + +XML::Document.send(:include, XML::Conversions::Document) +XML::Node.send(:include, XML::Conversions::Node) \ No newline at end of file diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb new file mode 100644 index 0000000000..655eff168c --- /dev/null +++ b/activesupport/lib/active_support/xml_mini/rexml.rb @@ -0,0 +1,106 @@ +# = XmlMini ReXML implementation +module ActiveSupport + module XmlMini + extend self + + # Parse an XML Document string into a simple hash + # + # Same as XmlSimple::xml_in but doesn't shoot itself in the foot, + # and uses the defaults from ActiveSupport + # + # string:: + # XML Document string to parse + def parse(string) + require 'rexml/document' unless defined?(REXML::Document) + doc = REXML::Document.new(string) + merge_element!({}, doc.root) + end + + private + # Convert an XML element and merge into the hash + # + # hash:: + # Hash to merge the converted element into. + # element:: + # XML element to merge into hash + def merge_element!(hash, element) + merge!(hash, element.name, collapse(element)) + end + + # Actually converts an XML document element into a data structure. + # + # element:: + # The document element to be collapsed. + def collapse(element) + hash = get_attributes(element) + + if element.has_elements? + element.each_element {|child| merge_element!(hash, child) } + merge_texts!(hash, element) unless empty_content?(element) + hash + else + merge_texts!(hash, element) + end + end + + # Merge all the texts of an element into the hash + # + # hash:: + # Hash to add the converted emement to. + # element:: + # XML element whose texts are to me merged into the hash + def merge_texts!(hash, element) + unless element.has_text? + hash + else + # must use value to prevent double-escaping + merge!(hash, CONTENT_KEY, element.texts.sum(&:value)) + end + end + + # Adds a new key/value pair to an existing Hash. If the key to be added + # already exists and the existing value associated with key is not + # an Array, it will be wrapped in an Array. Then the new value is + # appended to that Array. + # + # hash:: + # Hash to add key/value pair to. + # key:: + # Key to be added. + # value:: + # Value to be associated with key. + def merge!(hash, key, value) + if hash.has_key?(key) + if hash[key].instance_of?(Array) + hash[key] << value + else + hash[key] = [hash[key], value] + end + elsif value.instance_of?(Array) + hash[key] = [value] + else + hash[key] = value + end + hash + end + + # Converts the attributes array of an XML element into a hash. + # Returns an empty Hash if node has no attributes. + # + # element:: + # XML element to extract attributes from. + def get_attributes(element) + attributes = {} + element.attributes.each { |n,v| attributes[n] = v } + attributes + end + + # Determines if a document element has text content + # + # element:: + # XML element to be checked. + def empty_content?(element) + element.texts.join.blank? + end + end +end \ No newline at end of file -- cgit v1.2.3 From 87d82ef76e88d7ce97cfc09151b677b552f2840a Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Mon, 9 Mar 2009 12:46:06 -0700 Subject: Require libxml-ruby 0.9.4 or 0.9.7 pending a segfault bugfix for 1.0. Delegate parsing to a switchable backend. --- activesupport/lib/active_support/xml_mini.rb | 26 ++++++++++------------ .../lib/active_support/xml_mini/libxml.rb | 14 ++++++------ activesupport/lib/active_support/xml_mini/rexml.rb | 6 +++-- activesupport/test/core_ext/hash_ext_test.rb | 3 ++- 4 files changed, 25 insertions(+), 24 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index 8ae8e7cefe..d2a882b685 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -1,21 +1,19 @@ -# = XmlMini module ActiveSupport + # = XmlMini module XmlMini extend self + delegate :parse, :to => :@backend - CONTENT_KEY = '__content__'.freeze - - # Hook the correct parser into XmlMini - def hook_parser - begin - require 'xml/libxml' unless defined? LibXML - require "active_support/xml_mini/libxml.rb" - rescue MissingSourceFile => e - require "active_support/xml_mini/rexml.rb" - end + def backend=(name) + require "active_support/xml_mini/#{name.to_s.downcase}.rb" + @backend = ActiveSupport.const_get("XmlMini_#{name}") end + end - hook_parser - + begin + gem 'libxml-ruby', '=0.9.4', '=0.9.7' + XmlMini.backend = 'LibXML' + rescue Gem::LoadError + XmlMini.backend = 'REXML' end -end \ No newline at end of file +end diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb index dd271dc587..e1549d8c58 100644 --- a/activesupport/lib/active_support/xml_mini/libxml.rb +++ b/activesupport/lib/active_support/xml_mini/libxml.rb @@ -1,19 +1,19 @@ # = XML Mini Libxml implementation module ActiveSupport - module XmlMini + module XmlMini_LibXML #:nodoc: extend self # Parse an XML Document string into a simple hash using libxml. # string:: # XML Document string to parse def parse(string) - require 'xml/libxml' unless defined? LibXML - - string.strip! XML.default_keep_blanks = false - return {} if string.blank? - return XML::Parser.string(string).parse.to_hash + if string.blank? + {} + else + XML::Parser.string(string.strip).parse.to_hash + end end end @@ -128,4 +128,4 @@ module XML end XML::Document.send(:include, XML::Conversions::Document) -XML::Node.send(:include, XML::Conversions::Node) \ No newline at end of file +XML::Node.send(:include, XML::Conversions::Node) diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb index 655eff168c..a8fdeca967 100644 --- a/activesupport/lib/active_support/xml_mini/rexml.rb +++ b/activesupport/lib/active_support/xml_mini/rexml.rb @@ -1,8 +1,10 @@ # = XmlMini ReXML implementation module ActiveSupport - module XmlMini + module XmlMini_REXML #:nodoc: extend self + CONTENT_KEY = '__content__'.freeze + # Parse an XML Document string into a simple hash # # Same as XmlSimple::xml_in but doesn't shoot itself in the foot, @@ -103,4 +105,4 @@ module ActiveSupport element.texts.join.blank? end end -end \ No newline at end of file +end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index f1f1f15426..2285d5a724 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -884,7 +884,8 @@ class QueryTest < Test::Unit::TestCase end def test_expansion_count_is_limited - assert_raise RuntimeError do + expected = defined?(LibXML) ? LibXML::XML::Error : RuntimeError + assert_raise expected do attack_xml = <<-EOT Date: Mon, 9 Mar 2009 13:42:42 -0700 Subject: Use the REXML parser by default. XmlMini.backend = 'LibXML' to use libxml-ruby. --- activesupport/lib/active_support/xml_mini.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb index d2a882b685..99158e4ff7 100644 --- a/activesupport/lib/active_support/xml_mini.rb +++ b/activesupport/lib/active_support/xml_mini.rb @@ -1,5 +1,9 @@ module ActiveSupport # = XmlMini + # + # To use the much faster libxml parser: + # gem 'libxml-ruby', '=0.9.7' + # XmlMini.backend = 'LibXML' module XmlMini extend self delegate :parse, :to => :@backend @@ -10,10 +14,5 @@ module ActiveSupport end end - begin - gem 'libxml-ruby', '=0.9.4', '=0.9.7' - XmlMini.backend = 'LibXML' - rescue Gem::LoadError - XmlMini.backend = 'REXML' - end + XmlMini.backend = 'REXML' end -- cgit v1.2.3