diff options
Diffstat (limited to 'activesupport')
27 files changed, 168 insertions, 475 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index ed30c7de70..912b0287af 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,388 +1,9 @@ -* The decorated `load` and `require` methods are now kept private. +* Added `#verified` and `#valid_message?` methods to `ActiveSupport::MessageVerifier` - Fixes #17553. + Previously, the only way to decode a message with `ActiveSupport::MessageVerifier` was to use `#verify`, which would raise an exception on invalid messages. Now `#verified` can also be used, which returns `nil` on messages that cannot be decoded. - *Xavier Noria* + Previously, there was no way to check if a message's format was valid without attempting to decode it. `#valid_message?` is a boolean convenience method that checks whether the message is valid without actually decoding it. -* `String#remove` and `String#remove!` accept multiple arguments. + *Logan Leger* - *Pavel Pravosud* - -* `TimeWithZone#strftime` now delegates every directive to `Time#strftime` except for '%Z', - it also now correctly handles escaped '%' characters placed just before time zone related directives. - - *Pablo Herrero* - -* Corrected `Inflector#underscore` handling of multiple successive acroynms. - - *James Le Cuirot* - -* Delegation now works with ruby reserved words passed to `:to` option. - - Fixes #16956. - - *Agis Anastasopoulos* - -* Added method `#eql?` to `ActiveSupport::Duration`, in addition to `#==`. - - Currently, the following returns `false`, contrary to expectation: - - 1.minute.eql?(1.minute) - - Adding method `#eql?` will make this behave like expected. Method `#eql?` is - just a bit stricter than `#==`, as it checks whether the argument is also a duration. Their - parts may be different though. - - 1.minute.eql?(60.seconds) # => true - 1.minute.eql?(60) # => false - - *Joost Lubach* - -* `Time#change` can now change nanoseconds (`:nsec`) as a higher-precision - alternative to microseconds (`:usec`). - - *Agis Anastasooulos* - -* `MessageVerifier.new` raises an appropriate exception if the secret is `nil`. - This prevents `MessageVerifier#generate` from raising a cryptic error later on. - - *Kostiantyn Kahanskyi* - -* Introduced new configuration option `active_support.test_order` for - specifying the order in which test cases are executed. This option currently defaults - to `:sorted` but will be changed to `:random` in Rails 5.0. - - *Akira Matsuda*, *Godfrey Chan* - -* Fixed a bug in `Inflector#underscore` where acroynms in nested constant names - are incorrectly parsed as camelCase. - - Fixes #8015. - - *Fred Wu*, *Matthew Draper* - -* Make `Time#change` throw an exception if the `:usec` option is out of range and - the time has an offset other than UTC or local. - - *Agis Anastasopoulos* - -* `Method` objects now report themselves as not `duplicable?`. This allows - hashes and arrays containing `Method` objects to be `deep_dup`ed. - - *Peter Jaros* - -* `determine_constant_from_test_name` does no longer shadow `NameError`s - which happens during constant autoloading. - - Fixes #9933. - - *Guo Xiang Tan* - -* Added instance_eval version to Object#try and Object#try!, so you can do this: - - person.try { name.first } - - instead of: - - person.try { |person| person.name.first } - - *DHH*, *Ari Pollak* - -* Fix the `ActiveSupport::Duration#instance_of?` method to return the right - value with the class itself since it was previously delegated to the - internal value. - - *Robin Dupret* - -* Fix rounding errors with `#travel_to` by resetting the usec on any passed time to zero, so we only travel - with per-second precision, not anything deeper than that. - - *DHH* - -* Fix DateTime comparison with `DateTime::Infinity` object. - - *Rafael Mendonça França* - -* Added Object#itself which returns the object itself. Useful when dealing with a chaining scenario, like Active Record scopes: - - Event.public_send(state.presence_in([ :trashed, :drafted ]) || :itself).order(:created_at) - - *DHH* - -* `Object#with_options` executes block in merging option context when - explicit receiver in not passed. - - *Pavel Pravosud* - -* Fixed a compatibility issue with the `Oj` gem when cherry-picking the file - `active_support/core_ext/object/json` without requiring `active_support/json`. - - Fixes #16131. - - *Godfrey Chan* - -* Make `Hash#with_indifferent_access` copy the default proc too. - - *arthurnn*, *Xanders* - -* Add `String#truncate_words` to truncate a string by a number of words. - - *Mohamed Osama* - -* Deprecate `capture` and `quietly`. - - These methods are not thread safe and may cause issues when used in threaded environments. - To avoid problems we are deprecating them. - - *Tom Meier* - -* `DateTime#to_f` now preserves the fractional seconds instead of always - rounding to `.0`. - - Fixes #15994. - - *John Paul Ashenfelter* - -* Add `Hash#transform_values` to simplify a common pattern where the values of a - hash must change, but the keys are left the same. - - *Sean Griffin* - -* Always instrument `ActiveSupport::Cache`. - - Since `ActiveSupport::Notifications` only instruments items when there - are attached subscribers, we don't need to disable instrumentation. - - *Peter Wagenet* - -* Make the `apply_inflections` method case-insensitive when checking - whether a word is uncountable or not. - - *Robin Dupret* - -* Make Dependencies pass a name to NameError error. - - *arthurnn* - -* Fixed `ActiveSupport::Cache::FileStore` exploding with long paths. - - *Adam Panzer*, *Michael Grosser* - -* Fixed `ActiveSupport::TimeWithZone#-` so precision is not unnecessarily lost - when working with objects with a nanosecond component. - - `ActiveSupport::TimeWithZone#-` should return the same result as if we were - using `Time#-`: - - Time.now.end_of_day - Time.now.beginning_of_day # => 86399.999999999 - - Before: - - Time.zone.now.end_of_day.nsec # => 999999999 - Time.zone.now.end_of_day - Time.zone.now.beginning_of_day # => 86400.0 - - After: - - Time.zone.now.end_of_day - Time.zone.now.beginning_of_day - # => 86399.999999999 - - *Gordon Chan* - -* Fixed precision error in NumberHelper when using Rationals. - - Before: - - ActiveSupport::NumberHelper.number_to_rounded Rational(1000, 3), precision: 2 - # => "330.00" - - After: - - ActiveSupport::NumberHelper.number_to_rounded Rational(1000, 3), precision: 2 - # => "333.33" - - See #15379. - - *Juanjo Bazán* - -* Removed deprecated `Numeric#ago` and friends - - Replacements: - - 5.ago => 5.seconds.ago - 5.until => 5.seconds.until - 5.since => 5.seconds.since - 5.from_now => 5.seconds.from_now - - See #12389 for the history and rationale behind this. - - *Godfrey Chan* - -* DateTime `advance` now supports partial days. - - Before: - - DateTime.now.advance(days: 1, hours: 12) - - After: - - DateTime.now.advance(days: 1.5) - - Fixes #12005. - - *Shay Davidson* - -* `Hash#deep_transform_keys` and `Hash#deep_transform_keys!` now transform hashes - in nested arrays. This change also applies to `Hash#deep_stringify_keys`, - `Hash#deep_stringify_keys!`, `Hash#deep_symbolize_keys` and - `Hash#deep_symbolize_keys!`. - - *OZAWA Sakuro* - -* Fixed confusing `DelegationError` in `Module#delegate`. - - See #15186. - - *Vladimir Yarotsky* - -* Fixed `ActiveSupport::Subscriber` so that no duplicate subscriber is created - when a subscriber method is redefined. - - *Dennis Schön* - -* Remove deprecated string based terminators for `ActiveSupport::Callbacks`. - - *Eileen M. Uchitelle* - -* Fixed an issue when using - `ActiveSupport::NumberHelper::NumberToDelimitedConverter` to - convert a value that is an `ActiveSupport::SafeBuffer` introduced - in 2da9d67. - - See #15064. - - *Mark J. Titorenko* - -* `TimeZone#parse` defaults the day of the month to '1' if any other date - components are specified. This is more consistent with the behavior of - `Time#parse`. - - *Ulysse Carion* - -* `humanize` strips leading underscores, if any. - - Before: - - '_id'.humanize # => "" - - After: - - '_id'.humanize # => "Id" - - *Xavier Noria* - -* Fixed backward compatibility issues introduced in 326e652. - - Empty Hash or Array should not be present in serialization result. - - {a: []}.to_query # => "" - {a: {}}.to_query # => "" - - For more info see #14948. - - *Bogdan Gusiev* - -* Add `Digest::UUID::uuid_v3` and `Digest::UUID::uuid_v5` to support stable - UUID fixtures on PostgreSQL. - - *Roderick van Domburg* - -* Fixed `ActiveSupport::Duration#eql?` so that `1.second.eql?(1.second)` is - true. - - This fixes the current situation of: - - 1.second.eql?(1.second) # => false - - `eql?` also requires that the other object is an `ActiveSupport::Duration`. - This requirement makes `ActiveSupport::Duration`'s behavior consistent with - the behavior of Ruby's numeric types: - - 1.eql?(1.0) # => false - 1.0.eql?(1) # => false - - 1.second.eql?(1) # => false (was true) - 1.eql?(1.second) # => false - - { 1 => "foo", 1.0 => "bar" } - # => { 1 => "foo", 1.0 => "bar" } - - { 1 => "foo", 1.second => "bar" } - # now => { 1 => "foo", 1.second => "bar" } - # was => { 1 => "bar" } - - And though the behavior of these hasn't changed, for reference: - - 1 == 1.0 # => true - 1.0 == 1 # => true - - 1 == 1.second # => true - 1.second == 1 # => true - - *Emily Dobervich* - -* `ActiveSupport::SafeBuffer#prepend` acts like `String#prepend` and modifies - instance in-place, returning self. `ActiveSupport::SafeBuffer#prepend!` is - deprecated. - - *Pavel Pravosud* - -* `HashWithIndifferentAccess` better respects `#to_hash` on objects it - receives. In particular, `.new`, `#update`, `#merge`, and `#replace` accept - objects which respond to `#to_hash`, even if those objects are not hashes - directly. - - *Peter Jaros* - -* Deprecate `Class#superclass_delegating_accessor`, use `Class#class_attribute` instead. - - *Akshay Vishnoi* - -* Ensure classes which `include Enumerable` get `#to_json` in addition to - `#as_json`. - - *Sammy Larbi* - -* Change the signature of `fetch_multi` to return a hash rather than an - array. This makes it consistent with the output of `read_multi`. - - *Parker Selbert* - -* Introduce `Concern#class_methods` as a sleek alternative to clunky - `module ClassMethods`. Add `Kernel#concern` to define at the toplevel - without chunky `module Foo; extend ActiveSupport::Concern` boilerplate. - - # app/models/concerns/authentication.rb - concern :Authentication do - included do - after_create :generate_private_key - end - - class_methods do - def authenticate(credentials) - # ... - end - end - - def generate_private_key - # ... - end - end - - # app/models/user.rb - class User < ActiveRecord::Base - include Authentication - end - - *Jeremy Kemper* - -Please check [4-1-stable](https://github.com/rails/rails/blob/4-1-stable/activesupport/CHANGELOG.md) for previous changes. +Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/activesupport/CHANGELOG.md) for previous changes. diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec index 80d1d35888..f86f5133fc 100644 --- a/activesupport/activesupport.gemspec +++ b/activesupport/activesupport.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |s| s.summary = 'A toolkit of support libraries and Ruby core extensions extracted from the Rails framework.' s.description = 'A toolkit of support libraries and Ruby core extensions extracted from the Rails framework. Rich support for multibyte strings, internationalization, time zones, and testing.' - s.required_ruby_version = '>= 1.9.3' + s.required_ruby_version = '>= 2.1.0' s.license = 'MIT' diff --git a/activesupport/bin/generate_tables b/activesupport/bin/generate_tables index f39e89b7d0..71a6b78652 100755 --- a/activesupport/bin/generate_tables +++ b/activesupport/bin/generate_tables @@ -55,7 +55,7 @@ module ActiveSupport codepoint.combining_class = Integer($4) #codepoint.bidi_class = $5 codepoint.decomp_type = $7 - codepoint.decomp_mapping = ($8=='') ? nil : $8.split.collect { |element| element.hex } + codepoint.decomp_mapping = ($8=='') ? nil : $8.split.collect(&:hex) #codepoint.bidi_mirrored = ($13=='Y') ? true : false codepoint.uppercase_mapping = ($16=='') ? 0 : $16.hex codepoint.lowercase_mapping = ($17=='') ? 0 : $17.hex diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index 76ffd23ed1..080e3b5ef7 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -92,7 +92,7 @@ class Array if empty? 'null' else - collect { |element| element.id }.join(',') + collect(&:id).join(',') end else to_default_s diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb index 843c592669..234283e792 100644 --- a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb +++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb @@ -3,14 +3,13 @@ require 'bigdecimal/util' class BigDecimal DEFAULT_STRING_FORMAT = 'F' - def to_formatted_s(*args) - if args[0].is_a?(Symbol) - super + alias_method :to_default_s, :to_s + + def to_s(format = nil, options = nil) + if format.is_a?(Symbol) + to_formatted_s(format, options || {}) else - format = args[0] || DEFAULT_STRING_FORMAT - _original_to_s(format) + to_default_s(format || DEFAULT_STRING_FORMAT) end end - alias_method :_original_to_s, :to_s - alias_method :to_s, :to_formatted_s end diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb index f4105f66b0..9297a59c46 100644 --- a/activesupport/lib/active_support/core_ext/hash/keys.rb +++ b/activesupport/lib/active_support/core_ext/hash/keys.rb @@ -31,13 +31,13 @@ class Hash # hash.stringify_keys # # => {"name"=>"Rob", "age"=>"28"} def stringify_keys - transform_keys{ |key| key.to_s } + transform_keys(&:to_s) end # Destructively convert all keys to strings. Same as # +stringify_keys+, but modifies +self+. def stringify_keys! - transform_keys!{ |key| key.to_s } + transform_keys!(&:to_s) end # Returns a new hash with all keys converted to symbols, as long as @@ -105,14 +105,14 @@ class Hash # hash.deep_stringify_keys # # => {"person"=>{"name"=>"Rob", "age"=>"28"}} def deep_stringify_keys - deep_transform_keys{ |key| key.to_s } + deep_transform_keys(&:to_s) end # Destructively convert all keys to strings. # This includes the keys from the root hash and from all # nested hashes and arrays. def deep_stringify_keys! - deep_transform_keys!{ |key| key.to_s } + deep_transform_keys!(&:to_s) end # Returns a new hash with all keys converted to symbols, as long as diff --git a/activesupport/lib/active_support/core_ext/numeric/conversions.rb b/activesupport/lib/active_support/core_ext/numeric/conversions.rb index 6d3635c69a..0c8ff79237 100644 --- a/activesupport/lib/active_support/core_ext/numeric/conversions.rb +++ b/activesupport/lib/active_support/core_ext/numeric/conversions.rb @@ -118,18 +118,28 @@ class Numeric end end - [Float, Fixnum, Bignum, BigDecimal].each do |klass| - klass.send(:alias_method, :to_default_s, :to_s) - - klass.send(:define_method, :to_s) do |*args| - if args[0].is_a?(Symbol) - format = args[0] - options = args[1] || {} + [Fixnum, Bignum].each do |klass| + klass.class_eval do + alias_method :to_default_s, :to_s + def to_s(base_or_format = 10, options = nil) + if base_or_format.is_a?(Symbol) + to_formatted_s(base_or_format, options || {}) + else + to_default_s(base_or_format) + end + end + end + end - self.to_formatted_s(format, options) + Float.class_eval do + alias_method :to_default_s, :to_s + def to_s(*args) + if args.empty? + to_default_s else - to_default_s(*args) + to_formatted_s(*args) end end end + end diff --git a/activesupport/lib/active_support/core_ext/object/deep_dup.rb b/activesupport/lib/active_support/core_ext/object/deep_dup.rb index 2e99f4a1b8..0191d2e973 100644 --- a/activesupport/lib/active_support/core_ext/object/deep_dup.rb +++ b/activesupport/lib/active_support/core_ext/object/deep_dup.rb @@ -25,7 +25,7 @@ class Array # array[1][2] # => nil # dup[1][2] # => 4 def deep_dup - map { |it| it.deep_dup } + map(&:deep_dup) end end diff --git a/activesupport/lib/active_support/core_ext/object/instance_variables.rb b/activesupport/lib/active_support/core_ext/object/instance_variables.rb index 755e1c6b16..593a7a4940 100644 --- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb +++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb @@ -23,6 +23,6 @@ class Object # # C.new(0, 1).instance_variable_names # => ["@y", "@x"] def instance_variable_names - instance_variables.map { |var| var.to_s } + instance_variables.map(&:to_s) 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 ccd568bbf5..ec5ace4e16 100644 --- a/activesupport/lib/active_support/core_ext/object/to_query.rb +++ b/activesupport/lib/active_support/core_ext/object/to_query.rb @@ -38,7 +38,7 @@ class Array # Calls <tt>to_param</tt> on all its elements and joins the result with # slashes. This is used by <tt>url_for</tt> in Action Pack. def to_param - collect { |e| e.to_param }.join '/' + collect(&:to_param).join '/' end # Converts an array into a string suitable for use as a URL query string, diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 65a370dd30..ff8c0fd310 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -742,7 +742,7 @@ module ActiveSupport #:nodoc: protected def log_call(*args) if log_activity? - arg_str = args.collect { |arg| arg.inspect } * ', ' + arg_str = args.collect(&:inspect) * ', ' /in `([a-z_\?\!]+)'/ =~ caller(1).first selector = $1 || '<unknown>' log "called #{selector}(#{arg_str})" diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb index bc7933e38b..7068f09d87 100644 --- a/activesupport/lib/active_support/gem_version.rb +++ b/activesupport/lib/active_support/gem_version.rb @@ -5,10 +5,10 @@ module ActiveSupport end module VERSION - MAJOR = 4 - MINOR = 2 + MAJOR = 5 + MINOR = 0 TINY = 0 - PRE = "beta4" + PRE = "alpha" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index a8a8de5672..d16c1c629b 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -34,22 +34,78 @@ module ActiveSupport @serializer = options[:serializer] || Marshal end - def verify(signed_message) - raise InvalidSignature if signed_message.blank? + # Checks if a signed message could have been generated by signing an object + # with the +MessageVerifier+'s secret. + # + # verifier = ActiveSupport::MessageVerifier.new 's3Krit' + # signed_message = verifier.generate 'a private message' + # verifier.valid_message?(signed_message) # => true + # + # tampered_message = signed_message.chop # editing the message invalidates the signature + # verifier.valid_message?(tampered_message) # => false + def valid_message?(signed_message) + return if signed_message.blank? data, digest = signed_message.split("--") - if data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data)) + data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data)) + end + + # Decodes the signed message using the +MessageVerifier+'s secret. + # + # verifier = ActiveSupport::MessageVerifier.new 's3Krit' + # + # signed_message = verifier.generate 'a private message' + # verifier.verified(signed_message) # => 'a private message' + # + # Returns +nil+ if the message was not signed with the same secret. + # + # other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit' + # other_verifier.verified(signed_message) # => nil + # + # Returns +nil+ if the message is not Base64-encoded. + # + # invalid_message = "f--46a0120593880c733a53b6dad75b42ddc1c8996d" + # verifier.verified(invalid_message) # => nil + # + # Raises any error raised while decoding the signed message. + # + # incompatible_message = "test--dad7b06c94abba8d46a15fafaef56c327665d5ff" + # verifier.verified(incompatible_message) # => TypeError: incompatible marshal file format + def verified(signed_message) + if valid_message?(signed_message) begin + data = signed_message.split("--")[0] @serializer.load(decode(data)) rescue ArgumentError => argument_error - raise InvalidSignature if argument_error.message =~ %r{invalid base64} + return if argument_error.message =~ %r{invalid base64} raise end - else - raise InvalidSignature end end + # Decodes the signed message using the +MessageVerifier+'s secret. + # + # verifier = ActiveSupport::MessageVerifier.new 's3Krit' + # signed_message = verifier.generate 'a private message' + # + # verifier.verify(signed_message) # => 'a private message' + # + # Raises +InvalidSignature+ if the message was not signed with the same + # secret or was not Base64-encoded. + # + # other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit' + # other_verifier.verified(signed_message) # => ActiveSupport::MessageVerifier::InvalidSignature + def verify(signed_message) + verified(signed_message) || raise(InvalidSignature) + end + + # Generates a signed message for the provided value. + # + # The message is signed with the +MessageVerifier+'s secret. Without knowing + # the secret, the original value cannot be extracted from the message. + # + # verifier = ActiveSupport::MessageVerifier.new 's3Krit' + # verifier.generate 'a private message' # => "BAhJIhRwcml2YXRlLW1lc3NhZ2UGOgZFVA==--e2d724331ebdee96a10fb99b089508d1c72bd772" def generate(value) data = encode(@serializer.dump(value)) "#{data}--#{generate_digest(data)}" diff --git a/activesupport/lib/active_support/number_helper/number_to_human_converter.rb b/activesupport/lib/active_support/number_helper/number_to_human_converter.rb index 9a3dc526ae..6940beb318 100644 --- a/activesupport/lib/active_support/number_helper/number_to_human_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_human_converter.rb @@ -59,7 +59,7 @@ module ActiveSupport translate_in_locale("human.decimal_units.units", raise: true) else raise ArgumentError, ":units must be a Hash or String translation scope." - end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by { |e| -e } + end.keys.map { |e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by(&:-@) end end end diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb index 11cca82995..8b649c193f 100644 --- a/activesupport/lib/active_support/testing/assertions.rb +++ b/activesupport/lib/active_support/testing/assertions.rb @@ -66,7 +66,7 @@ module ActiveSupport exps = expressions.map { |e| e.respond_to?(:call) ? e : lambda { eval(e, block.binding) } } - before = exps.map { |e| e.call } + before = exps.map(&:call) yield diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index dbee145196..9703fb6d28 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -121,16 +121,25 @@ module ActiveSupport utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon) end - # Time uses +zone+ to display the time zone abbreviation, so we're - # duck-typing it. + # Returns the time zone abbreviation. + # + # Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)" + # Time.zone.now.zone # => "EST" def zone period.zone_identifier.to_s end + # Returns a string of the object's date, time, zone and offset from UTC. + # + # Time.zone.now.httpdate # => "Thu, 04 Dec 2014 11:00:25 EST -05:00" def inspect "#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}" end + # Returns a string of the object's date and time in the ISO 8601 standard + # format. + # + # Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00" def xmlschema(fraction_digits = 0) fraction = if fraction_digits.to_i > 0 (".%06i" % time.usec)[0, fraction_digits.to_i + 1] @@ -303,15 +312,27 @@ module ActiveSupport [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone] end + # Returns the object's date and time as a floating point number of seconds + # since the Epoch (January 1, 1970 00:00 UTC). + # + # Time.zone.now.to_f # => 1417709320.285418 def to_f utc.to_f end + # Returns the object's date and time as an integer number of seconds + # since the Epoch (January 1, 1970 00:00 UTC). + # + # Time.zone.now.to_i # => 1417709320 def to_i utc.to_i end alias_method :tv_sec, :to_i + # Returns the object's date and time as a rational number of seconds + # since the Epoch (January 1, 1970 00:00 UTC). + # + # Time.zone.now.to_r # => (708854548642709/500000) def to_r utc.to_r end diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 55533a5d40..fd05a5459c 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -237,7 +237,7 @@ module ActiveSupport case arg when String begin - @lazy_zones_map[arg] ||= create(arg).tap { |tz| tz.utc_offset } + @lazy_zones_map[arg] ||= create(arg).tap(&:utc_offset) rescue TZInfo::InvalidTimezoneIdentifier nil end diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb index 27c64c4dca..f303daa1a7 100644 --- a/activesupport/lib/active_support/xml_mini/jdom.rb +++ b/activesupport/lib/active_support/xml_mini/jdom.rb @@ -141,7 +141,7 @@ module ActiveSupport (0...attributes.length).each do |i| attribute_hash[CONTENT_KEY] ||= '' attribute_hash[attributes.item(i).name] = attributes.item(i).value - end + end attribute_hash end diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index 6fcf6e8743..346dc3d208 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -71,14 +71,14 @@ class EnumerableTests < ActiveSupport::TestCase def test_index_by payments = GenericEnumerable.new([ Payment.new(5), Payment.new(15), Payment.new(10) ]) assert_equal({ 5 => Payment.new(5), 15 => Payment.new(15), 10 => Payment.new(10) }, - payments.index_by { |p| p.price }) + payments.index_by(&:price)) assert_equal Enumerator, payments.index_by.class if Enumerator.method_defined? :size assert_equal nil, payments.index_by.size assert_equal 42, (1..42).index_by.size end assert_equal({ 5 => Payment.new(5), 15 => Payment.new(15), 10 => Payment.new(10) }, - payments.index_by.each { |p| p.price }) + payments.index_by.each(&:price)) end def test_many diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 5e9fdfd872..3d2f50ce49 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -365,7 +365,7 @@ class HashExtTest < ActiveSupport::TestCase :member? => true } hashes.each do |name, hash| - method_map.sort_by { |m| m.to_s }.each do |meth, expected| + method_map.sort_by(&:to_s).each do |meth, expected| assert_equal(expected, hash.__send__(meth, 'a'), "Calling #{name}.#{meth} 'a'") assert_equal(expected, hash.__send__(meth, :a), diff --git a/activesupport/test/core_ext/object/try_test.rb b/activesupport/test/core_ext/object/try_test.rb index efc6beaf02..89438675c1 100644 --- a/activesupport/test/core_ext/object/try_test.rb +++ b/activesupport/test/core_ext/object/try_test.rb @@ -52,11 +52,11 @@ class ObjectTryTest < ActiveSupport::TestCase end def test_try_only_block - assert_equal @string.reverse, @string.try { |s| s.reverse } + assert_equal @string.reverse, @string.try(&:reverse) end def test_try_only_block_bang - assert_equal @string.reverse, @string.try! { |s| s.reverse } + assert_equal @string.reverse, @string.try!(&:reverse) end def test_try_only_block_nil diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index e32c178951..0af207fae9 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -281,15 +281,11 @@ class StringInflectionsTest < ActiveSupport::TestCase end def test_constantize - run_constantize_tests_on do |string| - string.constantize - end + run_constantize_tests_on(&:constantize) end def test_safe_constantize - run_safe_constantize_tests_on do |string| - string.safe_constantize - end + run_safe_constantize_tests_on(&:safe_constantize) end end diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index b6c0a08b05..eb71369397 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -1,12 +1,5 @@ require 'abstract_unit' - -begin - require 'openssl' - OpenSSL::Digest::SHA1 -rescue LoadError, NameError - $stderr.puts "Skipping MessageEncryptor test: broken OpenSSL install" -else - +require 'openssl' require 'active_support/time' require 'active_support/json' @@ -97,5 +90,3 @@ class MessageEncryptorTest < ActiveSupport::TestCase ::Base64.strict_encode64(bits) end end - -end diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 28035bc428..6c3519df9a 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -1,12 +1,5 @@ require 'abstract_unit' - -begin - require 'openssl' - OpenSSL::Digest::SHA1 -rescue LoadError, NameError - $stderr.puts "Skipping MessageVerifier test: broken OpenSSL install" -else - +require 'openssl' require 'active_support/time' require 'active_support/json' @@ -27,21 +20,29 @@ class MessageVerifierTest < ActiveSupport::TestCase @data = { :some => "data", :now => Time.local(2010) } end + def test_valid_message + data, hash = @verifier.generate(@data).split("--") + assert !@verifier.valid_message?(nil) + assert !@verifier.valid_message?("") + assert !@verifier.valid_message?("#{data.reverse}--#{hash}") + assert !@verifier.valid_message?("#{data}--#{hash.reverse}") + assert !@verifier.valid_message?("purejunk") + end + def test_simple_round_tripping message = @verifier.generate(@data) + assert_equal @data, @verifier.verified(message) assert_equal @data, @verifier.verify(message) end - def test_missing_signature_raises - assert_not_verified(nil) - assert_not_verified("") + def test_verified_returns_false_on_invalid_message + assert !@verifier.verified("purejunk") end - def test_tampered_data_raises - data, hash = @verifier.generate(@data).split("--") - assert_not_verified("#{data.reverse}--#{hash}") - assert_not_verified("#{data}--#{hash.reverse}") - assert_not_verified("purejunk") + def test_verify_exception_on_invalid_message + assert_raise(ActiveSupport::MessageVerifier::InvalidSignature) do + @verifier.verify("purejunk") + end end def test_alternative_serialization_method @@ -50,6 +51,7 @@ class MessageVerifierTest < ActiveSupport::TestCase verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!", :serializer => JSONSerializer.new) message = verifier.generate({ :foo => 123, 'bar' => Time.utc(2010) }) exp = { "foo" => 123, "bar" => "2010-01-01T00:00:00.000Z" } + assert_equal exp, verifier.verified(message) assert_equal exp, verifier.verify(message) ensure ActiveSupport.use_standard_json_time_format = prev @@ -63,6 +65,11 @@ class MessageVerifierTest < ActiveSupport::TestCase # valid_message = "BAh7BjoIZm9vbzonTWVzc2FnZVZlcmlmaWVyVGVzdDo6QXV0b2xvYWRDbGFzcwY6CUBmb29JIghmb28GOgZFVA==--f3ef39a5241c365083770566dc7a9eb5d6ace914" exception = assert_raise(ArgumentError, NameError) do + @verifier.verified(valid_message) + end + assert_includes ["uninitialized constant MessageVerifierTest::AutoloadClass", + "undefined class/module MessageVerifierTest::AutoloadClass"], exception.message + exception = assert_raise(ArgumentError, NameError) do @verifier.verify(valid_message) end assert_includes ["uninitialized constant MessageVerifierTest::AutoloadClass", @@ -75,12 +82,4 @@ class MessageVerifierTest < ActiveSupport::TestCase end assert_equal exception.message, 'Secret should not be nil.' end - - def assert_not_verified(message) - assert_raise(ActiveSupport::MessageVerifier::InvalidSignature) do - @verifier.verify(message) - end - end -end - end diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index feca013675..94748dd991 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -182,7 +182,7 @@ class MultibyteCharsUTF8BehaviourTest < ActiveSupport::TestCase end def test_sortability - words = %w(builder armor zebra).sort_by { |s| s.mb_chars } + words = %w(builder armor zebra).sort_by(&:mb_chars) assert_equal %w(armor builder zebra), words end diff --git a/activesupport/test/multibyte_conformance_test.rb b/activesupport/test/multibyte_conformance_test.rb index aba81b8248..f7bd21c8ab 100644 --- a/activesupport/test/multibyte_conformance_test.rb +++ b/activesupport/test/multibyte_conformance_test.rb @@ -115,7 +115,7 @@ class MultibyteConformanceTest < ActiveSupport::TestCase next if (line.empty? || line =~ /^\#/) cols, comment = line.split("#") - cols = cols.split(";").map{|e| e.strip}.reject{|e| e.empty? } + cols = cols.split(";").map(&:strip).reject(&:empty?) next unless cols.length == 5 # codepoints are in hex in the test suite, pack wants them as integers diff --git a/activesupport/test/rescuable_test.rb b/activesupport/test/rescuable_test.rb index ec9d231125..b8af888f7c 100644 --- a/activesupport/test/rescuable_test.rb +++ b/activesupport/test/rescuable_test.rb @@ -93,13 +93,13 @@ class RescuableTest < ActiveSupport::TestCase def test_rescues_defined_later_are_added_at_end_of_the_rescue_handlers_array expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon"] - result = @stargate.send(:rescue_handlers).collect {|e| e.first} + result = @stargate.send(:rescue_handlers).collect(&:first) assert_equal expected, result end def test_children_should_inherit_rescue_definitions_from_parents_and_child_rescue_should_be_appended expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "CoolError"] - result = @cool_stargate.send(:rescue_handlers).collect {|e| e.first} + result = @cool_stargate.send(:rescue_handlers).collect(&:first) assert_equal expected, result end end |