diff options
Diffstat (limited to 'activesupport')
28 files changed, 289 insertions, 75 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 3508ec0f34..63f406cd9f 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,9 @@ *Rails 3.2.0 (unreleased)* +* Added safe_constantize that constantizes a string but returns nil instead of an exception if the constant (or part of it) does not exist [Ryan Oblak] + +* ActiveSupport::OrderedHash is now marked as extractable when using Array#extract_options! [Prem Sichanugrist] + * Added Array#prepend as an alias for Array#unshift and Array#append as an alias for Array#<< [DHH] * The definition of blank string for Ruby 1.9 has been extended to Unicode whitespace. @@ -18,7 +22,7 @@ Also, in 1.8 the ideographic space U+3000 is considered to be whitespace. [Akira * ActiveSupport::OrderedHash now has different behavior for #each and #each_pair when given a block accepting its parameters with a splat. [Andrew Radev] -*Rails 3.1.0 (unreleased)* +*Rails 3.1.0 (August 30, 2011)* * ActiveSupport::Dependencies#load and ActiveSupport::Dependencies#require now return the value from `super` [Aaron Patterson] diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index f7c01948b4..b431041b76 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -13,6 +13,7 @@ module ActiveSupport attr_reader :cache_path DIR_FORMATTER = "%03X" + FILENAME_MAX_SIZE = 230 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write) def initialize(cache_path, options = nil) super(options) @@ -129,15 +130,13 @@ module ActiveSupport hash, dir_1 = hash.divmod(0x1000) dir_2 = hash.modulo(0x1000) fname_paths = [] - # Make sure file name is < 255 characters so it doesn't exceed file system limits. - if fname.size <= 255 - fname_paths << fname - else - while fname.size <= 255 - fname_path << fname[0, 255] - fname = fname[255, -1] - end - end + + # Make sure file name doesn't exceed file system limits. + begin + fname_paths << fname[0, FILENAME_MAX_SIZE] + fname = fname[FILENAME_MAX_SIZE..-1] + end until fname.blank? + File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, *fname_paths) end @@ -162,6 +161,7 @@ module ActiveSupport end def search_dir(dir, &callback) + return if !File.exist?(dir) Dir.foreach(dir) do |d| next if d == "." || d == ".." name = File.join(dir, d) diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index ddb4f3012f..9343bb7106 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -97,7 +97,7 @@ module Enumerable end # Returns true if the enumerable has more than 1 element. Functionally equivalent to enum.to_a.size > 1. - # Can be called with a block too, much like any?, so people.many? { |p| p.age > 26 } returns true if more than 1 person is over 26. + # Can be called with a block too, much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns true if more than one person is over 26. def many? cnt = 0 if block_given? @@ -110,7 +110,7 @@ module Enumerable end end - # The negative of the Enumerable#include?. Returns true if the collection does not include the object. + # The negative of the <tt>Enumerable#include?</tt>. Returns true if the collection does not include the object. def exclude?(object) !include?(object) end diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb index 0b368fe7b7..f4cb445444 100644 --- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb +++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb @@ -2,7 +2,7 @@ require 'active_support/hash_with_indifferent_access' class Hash - # Returns an +ActiveSupport::HashWithIndifferentAccess+ out of its receiver: + # Returns an <tt>ActiveSupport::HashWithIndifferentAccess</tt> out of its receiver: # # {:a => 1}.with_indifferent_access["a"] # => 1 # diff --git a/activesupport/lib/active_support/core_ext/module/reachable.rb b/activesupport/lib/active_support/core_ext/module/reachable.rb index 443d2c3d53..5d3d0e9851 100644 --- a/activesupport/lib/active_support/core_ext/module/reachable.rb +++ b/activesupport/lib/active_support/core_ext/module/reachable.rb @@ -3,8 +3,6 @@ require 'active_support/core_ext/string/inflections' class Module def reachable? #:nodoc: - !anonymous? && name.constantize.equal?(self) - rescue NameError - false + !anonymous? && name.safe_constantize.equal?(self) end end diff --git a/activesupport/lib/active_support/core_ext/object/to_query.rb b/activesupport/lib/active_support/core_ext/object/to_query.rb index 3f1540f685..5d5fcf00e0 100644 --- a/activesupport/lib/active_support/core_ext/object/to_query.rb +++ b/activesupport/lib/active_support/core_ext/object/to_query.rb @@ -7,7 +7,7 @@ class Object # Note: This method is defined as a default implementation for all Objects for Hash#to_query to work. def to_query(key) require 'cgi' unless defined?(CGI) && defined?(CGI::escape) - "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}" + "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}" end end diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb index 002688d6c0..c7ceeb9de4 100644 --- a/activesupport/lib/active_support/core_ext/string/inflections.rb +++ b/activesupport/lib/active_support/core_ext/string/inflections.rb @@ -33,14 +33,27 @@ class String # +constantize+ tries to find a declared constant with the name specified # in the string. It raises a NameError when the name is not in CamelCase - # or is not initialized. + # or is not initialized. See ActiveSupport::Inflector.constantize # # Examples - # "Module".constantize # => Module - # "Class".constantize # => Class + # "Module".constantize # => Module + # "Class".constantize # => Class + # "blargle".constantize # => NameError: wrong constant name blargle def constantize ActiveSupport::Inflector.constantize(self) end + + # +safe_constantize+ tries to find a declared constant with the name specified + # in the string. It returns nil when the name is not in CamelCase + # or is not initialized. See ActiveSupport::Inflector.safe_constantize + # + # Examples + # "Module".safe_constantize # => Module + # "Class".safe_constantize # => Class + # "blargle".safe_constantize # => nil + def safe_constantize + ActiveSupport::Inflector.safe_constantize(self) + end # By default, +camelize+ converts strings to UpperCamelCase. If the argument to camelize # is set to <tt>:lower</tt> then camelize produces lowerCamelCase. diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index f111c8e5a3..2daf4016cd 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -20,7 +20,7 @@ class ERB if s.html_safe? s else - s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<").html_safe + s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<").html_safe end end @@ -142,12 +142,12 @@ module ActiveSupport #:nodoc: end UNSAFE_STRING_METHODS.each do |unsafe_method| - class_eval <<-EOT, __FILE__, __LINE__ - def #{unsafe_method}(*args, &block) # def gsub(*args, &block) - to_str.#{unsafe_method}(*args, &block) # to_str.gsub(*args, &block) + class_eval <<-EOT, __FILE__, __LINE__ + 1 + def #{unsafe_method}(*args, &block) # def capitalize(*args, &block) + to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block) end # end - def #{unsafe_method}!(*args) # def gsub!(*args) + def #{unsafe_method}!(*args) # def capitalize!(*args) @dirty = true # @dirty = true super # super end # end diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 59ffd24698..636f019cd5 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -112,7 +112,7 @@ module ActiveSupport end end - # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash + # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash. # Does not overwrite the existing hash. def merge(hash) self.dup.update(hash) diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 423b5abd20..934529d496 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -224,6 +224,39 @@ module ActiveSupport end end + # Tries to find a constant with the name specified in the argument string: + # + # "Module".safe_constantize # => Module + # "Test::Unit".safe_constantize # => Test::Unit + # + # The name is assumed to be the one of a top-level constant, no matter whether + # it starts with "::" or not. No lexical context is taken into account: + # + # C = 'outside' + # module M + # C = 'inside' + # C # => 'inside' + # "C".safe_constantize # => 'outside', same as ::C + # end + # + # nil is returned when the name is not in CamelCase or the constant (or part of it) is + # unknown. + # + # "blargle".safe_constantize # => nil + # "UnknownModule".safe_constantize # => nil + # "UnknownModule::Foo::Bar".safe_constantize # => nil + # + def safe_constantize(camel_cased_word) + begin + constantize(camel_cased_word) + rescue NameError => e + raise unless e.message =~ /uninitialized constant #{const_regexp(camel_cased_word)}$/ || + e.name.to_s == camel_cased_word.to_s + rescue ArgumentError => e + raise unless e.message =~ /not missing constant #{const_regexp(camel_cased_word)}\!$/ + end + end + # Turns a number into an ordinal string used to denote the position in an # ordered sequence such as 1st, 2nd, 3rd, 4th. # @@ -246,5 +279,18 @@ module ActiveSupport end end end + + private + + # Mount a regular expression that will match part by part of the constant. + # For instance, Foo::Bar::Baz will generate Foo(::Bar(::Baz)?)? + def const_regexp(camel_cased_word) #:nodoc: + parts = camel_cased_word.split("::") + last = parts.pop + + parts.reverse.inject(last) do |acc, part| + part.empty? ? acc : "#{part}(::#{acc})?" + end + end end end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 67698c1cff..469ae69258 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -38,7 +38,7 @@ module ActiveSupport attr_reader :options def initialize(options = nil) - @options = options + @options = options || {} @seen = Set.new end @@ -59,7 +59,7 @@ module ActiveSupport def options_for(value) if value.is_a?(Array) || value.is_a?(Hash) # hashes and arrays need to get encoder in the options, so that they can detect circular references - (options || {}).merge(:encoder => self) + options.merge(:encoder => self) else options end diff --git a/activesupport/lib/active_support/log_subscriber/test_helper.rb b/activesupport/lib/active_support/log_subscriber/test_helper.rb index 3e54134c5c..dcfcf0b63c 100644 --- a/activesupport/lib/active_support/log_subscriber/test_helper.rb +++ b/activesupport/lib/active_support/log_subscriber/test_helper.rb @@ -18,8 +18,8 @@ module ActiveSupport # Developer.all # wait # assert_equal 1, @logger.logged(:debug).size - # assert_match /Developer Load/, @logger.logged(:debug).last - # assert_match /SELECT \* FROM "developers"/, @logger.logged(:debug).last + # assert_match(/Developer Load/, @logger.logged(:debug).last) + # assert_match(/SELECT \* FROM "developers"/, @logger.logged(:debug).last) # end # end # diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 4f7cd12d48..e14386a85d 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -13,9 +13,15 @@ module ActiveSupport class InvalidMessage < StandardError; end OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError - def initialize(secret, cipher = 'aes-256-cbc') + def initialize(secret, options = {}) + unless options.is_a?(Hash) + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :cipher => 'algorithm' to specify the cipher algorithm." + options = { :cipher => options } + end + @secret = secret - @cipher = cipher + @cipher = options[:cipher] || 'aes-256-cbc' + @serializer = options[:serializer] || Marshal end def encrypt(value) @@ -27,7 +33,7 @@ module ActiveSupport cipher.key = @secret cipher.iv = iv - encrypted_data = cipher.update(Marshal.dump(value)) + encrypted_data = cipher.update(@serializer.dump(value)) encrypted_data << cipher.final [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--") @@ -44,7 +50,7 @@ module ActiveSupport decrypted_data = cipher.update(encrypted_data) decrypted_data << cipher.final - Marshal.load(decrypted_data) + @serializer.load(decrypted_data) rescue OpenSSLCipherError, TypeError raise InvalidMessage end diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 8f3946325a..9d7c81142a 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -18,12 +18,23 @@ module ActiveSupport # self.current_user = User.find(id) # end # + # By default it uses Marshal to serialize the message. If you want to use another + # serialization method, you can set the serializer attribute to something that responds + # to dump and load, e.g.: + # + # @verifier.serializer = YAML class MessageVerifier class InvalidSignature < StandardError; end - def initialize(secret, digest = 'SHA1') + def initialize(secret, options = {}) + unless options.is_a?(Hash) + ActiveSupport::Deprecation.warn "The second parameter should be an options hash. Use :digest => 'algorithm' to specify the digest algorithm." + options = { :digest => options } + end + @secret = secret - @digest = digest + @digest = options[:digest] || 'SHA1' + @serializer = options[:serializer] || Marshal end def verify(signed_message) @@ -31,14 +42,14 @@ module ActiveSupport data, digest = signed_message.split("--") if data.present? && digest.present? && secure_compare(digest, generate_digest(data)) - Marshal.load(ActiveSupport::Base64.decode64(data)) + @serializer.load(ActiveSupport::Base64.decode64(data)) else raise InvalidSignature end end def generate(value) - data = ActiveSupport::Base64.encode64s(Marshal.dump(value)) + data = ActiveSupport::Base64.encode64s(@serializer.dump(value)) "#{data}--#{generate_digest(data)}" end diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index 7f70628933..0264133581 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -47,6 +47,11 @@ module ActiveSupport self end + # Returns true to make sure that this hash is extractable via <tt>Array#extract_options!</tt> + def extractable_options? + true + end + # Hash is ordered in Ruby 1.9! if RUBY_VERSION < '1.9' diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index ec2c717942..63279d0e6d 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -12,7 +12,7 @@ module ActiveSupport # # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00 - # Time.zone.parse('2007-02-01 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00 + # Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00 # Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00 # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00 # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00 diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 4fb487ade1..35f400f9df 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -371,7 +371,7 @@ module ActiveSupport protected def require_tzinfo - require 'tzinfo' + require 'tzinfo' unless defined?(::TZInfo) rescue LoadError $stderr.puts "You don't have tzinfo installed in your application. Please add it to your Gemfile and run bundle install" raise diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 6bb13ec9b8..cb5362525f 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -357,7 +357,7 @@ module CacheStoreBehavior def test_really_long_keys key = "" - 1000.times{key << "x"} + 900.times{key << "x"} assert_equal true, @cache.write(key, "bar") assert_equal "bar", @cache.read(key) assert_equal "bar", @cache.fetch(key) @@ -557,6 +557,23 @@ class FileStoreTest < ActiveSupport::TestCase key = @cache_with_pathname.send(:key_file_path, "views/index?id=1") assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key) end + + # Because file systems have a maximum filename size, filenames > max size should be split in to directories + # If filename is 'AAAAB', where max size is 4, the returned path should be AAAA/B + def test_key_transformation_max_filename_size + key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}B" + path = @cache.send(:key_file_path, key) + assert path.split('/').all? { |dir_name| dir_name.size <= ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE} + assert_equal 'B', File.basename(path) + end + + # If nothing has been stored in the cache, there is a chance the cache directory does not yet exist + # Ensure delete_matched gracefully handles this case + def test_delete_matched_when_cache_directory_does_not_exist + assert_nothing_raised(Exception) do + ActiveSupport::Cache::FileStore.new('/test/cache/directory').delete_matched(/does_not_exist/) + end + end end class MemoryStoreTest < ActiveSupport::TestCase diff --git a/activesupport/test/constantize_test_cases.rb b/activesupport/test/constantize_test_cases.rb new file mode 100644 index 0000000000..81d200a0c8 --- /dev/null +++ b/activesupport/test/constantize_test_cases.rb @@ -0,0 +1,37 @@ +module Ace + module Base + class Case + end + end +end + +module ConstantizeTestCases + def run_constantize_tests_on + assert_nothing_raised { assert_equal Ace::Base::Case, yield("Ace::Base::Case") } + assert_nothing_raised { assert_equal Ace::Base::Case, yield("::Ace::Base::Case") } + assert_nothing_raised { assert_equal ConstantizeTestCases, yield("ConstantizeTestCases") } + assert_nothing_raised { assert_equal ConstantizeTestCases, yield("::ConstantizeTestCases") } + assert_raise(NameError) { yield("UnknownClass") } + assert_raise(NameError) { yield("UnknownClass::Ace") } + assert_raise(NameError) { yield("UnknownClass::Ace::Base") } + assert_raise(NameError) { yield("An invalid string") } + assert_raise(NameError) { yield("InvalidClass\n") } + assert_raise(NameError) { yield("Ace::ConstantizeTestCases") } + assert_raise(NameError) { yield("Ace::Base::ConstantizeTestCases") } + end + + def run_safe_constantize_tests_on + assert_nothing_raised { assert_equal Ace::Base::Case, yield("Ace::Base::Case") } + assert_nothing_raised { assert_equal Ace::Base::Case, yield("::Ace::Base::Case") } + assert_nothing_raised { assert_equal ConstantizeTestCases, yield("ConstantizeTestCases") } + assert_nothing_raised { assert_equal ConstantizeTestCases, yield("::ConstantizeTestCases") } + assert_nothing_raised { assert_equal nil, yield("UnknownClass") } + assert_nothing_raised { assert_equal nil, yield("UnknownClass::Ace") } + assert_nothing_raised { assert_equal nil, yield("UnknownClass::Ace::Base") } + assert_nothing_raised { assert_equal nil, yield("An invalid string") } + assert_nothing_raised { assert_equal nil, yield("InvalidClass\n") } + assert_nothing_raised { assert_equal nil, yield("blargle") } + assert_nothing_raised { assert_equal nil, yield("Ace::ConstantizeTestCases") } + assert_nothing_raised { assert_equal nil, yield("Ace::Base::ConstantizeTestCases") } + end +end
\ No newline at end of file diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 1813ba2a4d..fa800eada2 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -9,7 +9,7 @@ require 'active_support/inflections' class HashExtTest < Test::Unit::TestCase class IndifferentHash < HashWithIndifferentAccess end - + class SubclassingArray < Array end @@ -272,14 +272,14 @@ class HashExtTest < Test::Unit::TestCase hash = { "urls" => { "url" => [ { "address" => "1" }, { "address" => "2" } ] }}.with_indifferent_access assert_equal "1", hash[:urls][:url].first[:address] end - + def test_should_preserve_array_subclass_when_value_is_array array = SubclassingArray.new array << { "address" => "1" } hash = { "urls" => { "url" => array }}.with_indifferent_access assert_equal SubclassingArray, hash[:urls][:url].class end - + def test_should_preserve_array_class_when_hash_value_is_frozen_array array = SubclassingArray.new array << { "address" => "1" } @@ -543,7 +543,7 @@ class HashExtToParamTests < Test::Unit::TestCase end def test_to_param_hash - assert_equal 'custom2=param2-1&custom=param-1', {ToParam.new('custom') => ToParam.new('param'), ToParam.new('custom2') => ToParam.new('param2')}.to_param + assert_equal 'custom-1=param-1&custom2-1=param2-1', {ToParam.new('custom') => ToParam.new('param'), ToParam.new('custom2') => ToParam.new('param2')}.to_param end def test_to_param_hash_escapes_its_keys_and_values @@ -955,13 +955,13 @@ class HashToXmlTest < Test::Unit::TestCase hash = Hash.from_xml(xml) assert_equal "bacon is the best", hash['blog']['name'] end - + def test_empty_cdata_from_xml xml = "<data><![CDATA[]]></data>" - + assert_equal "", Hash.from_xml(xml)["data"] end - + def test_xsd_like_types_from_xml bacon_xml = <<-EOT <bacon> @@ -1004,7 +1004,7 @@ class HashToXmlTest < Test::Unit::TestCase assert_equal expected_product_hash, Hash.from_xml(product_xml)["product"] end - + def test_should_use_default_value_for_unknown_key hash_wia = HashWithIndifferentAccess.new(3) assert_equal 3, hash_wia[:new_key] diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index 449d3810e2..f11bf3dc69 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -183,8 +183,9 @@ class ModuleTest < Test::Unit::TestCase someone.foo rescue NoMethodError => e file_and_line = "#{__FILE__}:#{Someone::FAILED_DELEGATE_LINE}" - assert e.backtrace.first.include?(file_and_line), - "[#{e.backtrace.first}] did not include [#{file_and_line}]" + # We can't simply check the first line of the backtrace, because JRuby reports the call to __send__ in the backtrace. + assert e.backtrace.any?{|a| a.include?(file_and_line)}, + "[#{e.backtrace.inspect}] did not include [#{file_and_line}]" end def test_delegation_exception_backtrace_with_allow_nil @@ -192,8 +193,9 @@ class ModuleTest < Test::Unit::TestCase someone.bar rescue NoMethodError => e file_and_line = "#{__FILE__}:#{Someone::FAILED_DELEGATE_LINE_2}" - assert e.backtrace.first.include?(file_and_line), - "[#{e.backtrace.first}] did not include [#{file_and_line}]" + # We can't simply check the first line of the backtrace, because JRuby reports the call to __send__ in the backtrace. + assert e.backtrace.any?{|a| a.include?(file_and_line)}, + "[#{e.backtrace.inspect}] did not include [#{file_and_line}]" end def test_parent diff --git a/activesupport/test/core_ext/object/to_query_test.rb b/activesupport/test/core_ext/object/to_query_test.rb index 84da52f4bf..c146f6cc9b 100644 --- a/activesupport/test/core_ext/object/to_query_test.rb +++ b/activesupport/test/core_ext/object/to_query_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'active_support/ordered_hash' require 'active_support/core_ext/object/to_query' +require 'active_support/core_ext/string/output_safety.rb' class ToQueryTest < Test::Unit::TestCase def test_simple_conversion @@ -11,6 +12,14 @@ class ToQueryTest < Test::Unit::TestCase assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d' end + def test_html_safe_parameter_key + assert_query_equal 'a%3Ab=c+d', 'a:b'.html_safe => 'c d' + end + + def test_html_safe_parameter_value + assert_query_equal 'a=%5B10%5D', 'a' => '[10]'.html_safe + end + def test_nil_parameter_value empty = Object.new def empty.to_param; nil end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 81a284dded..5c1dddaf96 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -2,6 +2,7 @@ require 'date' require 'abstract_unit' require 'inflector_test_cases' +require 'constantize_test_cases' require 'active_support/inflector' require 'active_support/core_ext/string' @@ -9,9 +10,17 @@ require 'active_support/time' require 'active_support/core_ext/string/strip' require 'active_support/core_ext/string/output_safety' +module Ace + module Base + class Case + end + end +end + class StringInflectionsTest < Test::Unit::TestCase include InflectorTestCases - + include ConstantizeTestCases + def test_erb_escape string = [192, 60].pack('CC') expected = 192.chr + "<" @@ -292,6 +301,18 @@ class StringInflectionsTest < Test::Unit::TestCase "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8').truncate(10) end end + + def test_constantize + run_constantize_tests_on do |string| + string.constantize + end + end + + def test_safe_constantize + run_safe_constantize_tests_on do |string| + string.safe_constantize + end + end end class StringBehaviourTest < Test::Unit::TestCase diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index b9e299af75..5c956e0075 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -2,16 +2,11 @@ require 'abstract_unit' require 'active_support/inflector' require 'inflector_test_cases' - -module Ace - module Base - class Case - end - end -end +require 'constantize_test_cases' class InflectorTest < Test::Unit::TestCase include InflectorTestCases + include ConstantizeTestCases def test_pluralize_plurals assert_equal "plurals", ActiveSupport::Inflector.pluralize("plurals") @@ -282,17 +277,15 @@ class InflectorTest < Test::Unit::TestCase end def test_constantize - assert_nothing_raised { assert_equal Ace::Base::Case, ActiveSupport::Inflector.constantize("Ace::Base::Case") } - 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_raise(NameError) { ActiveSupport::Inflector.constantize("UnknownClass") } - assert_raise(NameError) { ActiveSupport::Inflector.constantize("An invalid string") } - assert_raise(NameError) { ActiveSupport::Inflector.constantize("InvalidClass\n") } + run_constantize_tests_on do |string| + ActiveSupport::Inflector.constantize(string) + end end - - def test_constantize_does_lexical_lookup - assert_raise(NameError) { ActiveSupport::Inflector.constantize("Ace::Base::InflectorTest") } + + def test_safe_constantize + run_safe_constantize_tests_on do |string| + ActiveSupport::Inflector.safe_constantize(string) + end end def test_ordinal diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index e45d5ecd59..83a19f8106 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -8,8 +8,20 @@ rescue LoadError, NameError else require 'active_support/time' +require 'active_support/json' -class MessageEncryptorTest < Test::Unit::TestCase +class MessageEncryptorTest < ActiveSupport::TestCase + + class JSONSerializer + def dump(value) + ActiveSupport::JSON.encode(value) + end + + def load(value) + ActiveSupport::JSON.decode(value) + end + end + def setup @encryptor = ActiveSupport::MessageEncryptor.new(SecureRandom.hex(64)) @data = { :some => "data", :now => Time.local(2010) } @@ -38,8 +50,19 @@ class MessageEncryptorTest < Test::Unit::TestCase message = @encryptor.encrypt_and_sign(@data) assert_equal @data, @encryptor.decrypt_and_verify(message) end + + def test_alternative_serialization_method + encryptor = ActiveSupport::MessageEncryptor.new(SecureRandom.hex(64), :serializer => JSONSerializer.new) + message = encryptor.encrypt_and_sign({ :foo => 123, 'bar' => Time.utc(2010) }) + assert_equal encryptor.decrypt_and_verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } + end - + def test_digest_algorithm_as_second_parameter_deprecation + assert_deprecated(/options hash/) do + ActiveSupport::MessageEncryptor.new(SecureRandom.hex(64), 'aes-256-cbc') + end + end + private def assert_not_decrypted(value) assert_raise(ActiveSupport::MessageEncryptor::InvalidMessage) do diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 4821311244..35747abe5b 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -8,8 +8,20 @@ rescue LoadError, NameError else require 'active_support/time' +require 'active_support/json' -class MessageVerifierTest < Test::Unit::TestCase +class MessageVerifierTest < ActiveSupport::TestCase + + class JSONSerializer + def dump(value) + ActiveSupport::JSON.encode(value) + end + + def load(value) + ActiveSupport::JSON.decode(value) + end + end + def setup @verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!") @data = { :some => "data", :now => Time.local(2010) } @@ -31,6 +43,18 @@ class MessageVerifierTest < Test::Unit::TestCase assert_not_verified("#{data}--#{hash.reverse}") assert_not_verified("purejunk") end + + def test_alternative_serialization_method + verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!", :serializer => JSONSerializer.new) + message = verifier.generate({ :foo => 123, 'bar' => Time.utc(2010) }) + assert_equal verifier.verify(message), { "foo" => 123, "bar" => "2010-01-01T00:00:00Z" } + end + + def test_digest_algorithm_as_second_parameter_deprecation + assert_deprecated(/options hash/) do + ActiveSupport::MessageVerifier.new("secret", "SHA1") + end + end def assert_not_verified(message) assert_raise(ActiveSupport::MessageVerifier::InvalidSignature) do diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index bf851dbcbc..0b5f912dc4 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -329,4 +329,9 @@ class OrderedHashTest < Test::Unit::TestCase assert_equal expected, @ordered_hash.invert assert_equal @values.zip(@keys), @ordered_hash.invert.to_a end + + def test_extractable + @ordered_hash[:rails] = "snowman" + assert_equal @ordered_hash, [1, 2, @ordered_hash].extract_options! + end end diff --git a/activesupport/test/rescuable_test.rb b/activesupport/test/rescuable_test.rb index bf4f5265ef..c28ffa50f2 100644 --- a/activesupport/test/rescuable_test.rb +++ b/activesupport/test/rescuable_test.rb @@ -70,7 +70,7 @@ class CoolStargate < Stargate end -class RescueableTest < Test::Unit::TestCase +class RescuableTest < Test::Unit::TestCase def setup @stargate = Stargate.new @cool_stargate = CoolStargate.new |