diff options
Diffstat (limited to 'activesupport/lib/active_support/core_ext')
45 files changed, 359 insertions, 389 deletions
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb index caa499dfa2..ca66d806ef 100644 --- a/activesupport/lib/active_support/core_ext/array/access.rb +++ b/activesupport/lib/active_support/core_ext/array/access.rb @@ -20,7 +20,11 @@ class Array # %w( a b c d ).to(-2) # => ["a", "b", "c"] # %w( a b c ).to(-10) # => [] def to(position) - self[0..position] + if position >= 0 + take position + 1 + else + self[0..position] + end end # Equal to <tt>self[1]</tt>. 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/big_decimal/yaml_conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/yaml_conversions.rb deleted file mode 100644 index 46ba93ead4..0000000000 --- a/activesupport/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +++ /dev/null @@ -1,14 +0,0 @@ -ActiveSupport::Deprecation.warn 'core_ext/big_decimal/yaml_conversions is deprecated and will be removed in the future.' - -require 'bigdecimal' -require 'yaml' -require 'active_support/core_ext/big_decimal/conversions' - -class BigDecimal - YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' } - - def encode_with(coder) - string = to_s - coder.represent_scalar(nil, YAML_MAPPING[string] || string) - end -end diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb index f2a221c396..f2b7bb3ef1 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute.rb @@ -116,12 +116,4 @@ class Class attr_writer name if instance_writer end end - - private - - unless respond_to?(:singleton_class?) - def singleton_class? - ancestors.first != self - end - end end diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb index b85e49aca5..9525c10112 100644 --- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb @@ -9,15 +9,26 @@ module DateAndTime :saturday => 5, :sunday => 6 } + WEEKEND_DAYS = [ 6, 0 ] # Returns a new date/time representing yesterday. def yesterday - advance(:days => -1) + advance(days: -1) + end + + # Returns a new date/time representing the previous day. + def prev_day + advance(days: -1) end # Returns a new date/time representing tomorrow. def tomorrow - advance(:days => 1) + advance(days: 1) + end + + # Returns a new date/time representing the next day. + def next_day + advance(days: 1) end # Returns true if the date/time is today. @@ -35,6 +46,11 @@ module DateAndTime self > self.class.current end + # Returns true if the date/time falls on a Saturday or Sunday. + def on_weekend? + WEEKEND_DAYS.include?(wday) + end + # Returns a new date/time the specified number of days ago. def days_ago(days) advance(:days => -days) @@ -111,9 +127,19 @@ module DateAndTime # Returns a new date/time representing the given day in the next week. # The +given_day_in_next_week+ defaults to the beginning of the week # which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+ - # when set. +DateTime+ objects have their time set to 0:00. - def next_week(given_day_in_next_week = Date.beginning_of_week) - first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week))) + # when set. +DateTime+ objects have their time set to 0:00 unless +same_time+ is true. + def next_week(given_day_in_next_week = Date.beginning_of_week, same_time: false) + result = first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week))) + same_time ? copy_time_to(result) : result + end + + # Returns a new date/time representing the next weekday. + def next_weekday + if next_day.on_weekend? + next_week(:monday, same_time: true) + else + next_day + end end # Short-hand for months_since(1). @@ -134,12 +160,23 @@ module DateAndTime # Returns a new date/time representing the given day in the previous week. # Week is assumed to start on +start_day+, default is # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. - # DateTime objects have their time set to 0:00. - def prev_week(start_day = Date.beginning_of_week) - first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day))) + # DateTime objects have their time set to 0:00 unless +same_time+ is true. + def prev_week(start_day = Date.beginning_of_week, same_time: false) + result = first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day))) + same_time ? copy_time_to(result) : result end alias_method :last_week, :prev_week + # Returns a new date/time representing the previous weekday. + def prev_weekday + if prev_day.on_weekend? + copy_time_to(beginning_of_week(:friday)) + else + prev_day + end + end + alias_method :last_weekday, :prev_weekday + # Short-hand for months_ago(1). def prev_month months_ago(1) @@ -235,17 +272,20 @@ module DateAndTime end private + def first_hour(date_or_time) + date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time + end - def first_hour(date_or_time) - date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time - end + def last_hour(date_or_time) + date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time + end - def last_hour(date_or_time) - date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time - end + def days_span(day) + (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7 + end - def days_span(day) - (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7 - end + def copy_time_to(other) + other.change(hour: hour, min: min, sec: sec, usec: try(:usec)) + end end end diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb index dc4e767e9d..55ad384f4f 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -10,7 +10,11 @@ class DateTime end end - # Seconds since midnight: DateTime.now.seconds_since_midnight. + # Returns the number of seconds since 00:00:00. + # + # DateTime.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0 + # DateTime.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296 + # DateTime.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399 def seconds_since_midnight sec + (min * 60) + (hour * 3600) end diff --git a/activesupport/lib/active_support/core_ext/file/atomic.rb b/activesupport/lib/active_support/core_ext/file/atomic.rb index 0e7e3ba378..fad6fa8d9d 100644 --- a/activesupport/lib/active_support/core_ext/file/atomic.rb +++ b/activesupport/lib/active_support/core_ext/file/atomic.rb @@ -20,7 +20,7 @@ class File temp_file = Tempfile.new(basename(file_name), temp_dir) temp_file.binmode - yield temp_file + return_val = yield temp_file temp_file.close if File.exist?(file_name) @@ -40,7 +40,10 @@ class File chown(old_stat.uid, old_stat.gid, file_name) # This operation will affect filesystem ACL's chmod(old_stat.mode, file_name) - rescue Errno::EPERM + + # Make sure we return the result of the yielded block + return_val + rescue Errno::EPERM, Errno::EACCES # Changing file ownership failed, moving on. end end diff --git a/activesupport/lib/active_support/core_ext/hash/compact.rb b/activesupport/lib/active_support/core_ext/hash/compact.rb index 6566215a4d..5dc9a05ec7 100644 --- a/activesupport/lib/active_support/core_ext/hash/compact.rb +++ b/activesupport/lib/active_support/core_ext/hash/compact.rb @@ -1,6 +1,6 @@ class Hash # Returns a hash with non +nil+ values. - # + # # hash = { a: true, b: false, c: nil} # hash.compact # => { a: true, b: false} # hash # => { a: true, b: false, c: nil} @@ -8,9 +8,9 @@ class Hash def compact self.select { |_, value| !value.nil? } end - + # Replaces current hash with non +nil+ values. - # + # # hash = { a: true, b: false, c: nil} # hash.compact! # => { a: true, b: false} # hash # => { a: true, b: false} diff --git a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb index 763d563231..9c9faf67ea 100644 --- a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb +++ b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb @@ -4,7 +4,7 @@ class Hash # h1 = { a: true, b: { c: [1, 2, 3] } } # h2 = { a: false, b: { x: [3, 4, 5] } } # - # h1.deep_merge(h2) #=> { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } } + # h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } } # # Like with Hash#merge in the standard library, a block can be provided # to merge values: diff --git a/activesupport/lib/active_support/core_ext/hash/except.rb b/activesupport/lib/active_support/core_ext/hash/except.rb index 682d089881..6e397abf51 100644 --- a/activesupport/lib/active_support/core_ext/hash/except.rb +++ b/activesupport/lib/active_support/core_ext/hash/except.rb @@ -1,13 +1,19 @@ class Hash - # Returns a hash that includes everything but the given keys. This is useful for - # limiting a set of parameters to everything but a few known toggles: + # Returns a hash that includes everything but the given keys. + # hash = { a: true, b: false, c: nil} + # hash.except(:c) # => { a: true, b: false} + # hash # => { a: true, b: false, c: nil} # + # This is useful for limiting a set of parameters to everything but a few known toggles: # @person.update(params[:person].except(:admin)) def except(*keys) dup.except!(*keys) end # Replaces the hash without the given keys. + # hash = { a: true, b: false, c: nil} + # hash.except!(:c) # => { a: true, b: false} + # hash # => { a: true, b: false } def except!(*keys) keys.each { |key| delete(key) } self 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/hash/slice.rb b/activesupport/lib/active_support/core_ext/hash/slice.rb index 8ad600b171..41b2279013 100644 --- a/activesupport/lib/active_support/core_ext/hash/slice.rb +++ b/activesupport/lib/active_support/core_ext/hash/slice.rb @@ -1,6 +1,12 @@ class Hash - # Slice a hash to include only the given keys. This is useful for - # limiting an options hash to valid keys before passing to a method: + # Slice a hash to include only the given keys. Returns a hash containing + # the given keys. + # + # { a: 1, b: 2, c: 3, d: 4 }.slice(:a, :b) + # # => {:a=>1, :b=>2} + # + # This is useful for limiting an options hash to valid keys before + # passing to a method: # # def search(criteria = {}) # criteria.assert_valid_keys(:mass, :velocity, :time) diff --git a/activesupport/lib/active_support/core_ext/kernel.rb b/activesupport/lib/active_support/core_ext/kernel.rb index 293a3b2619..364ed9d65f 100644 --- a/activesupport/lib/active_support/core_ext/kernel.rb +++ b/activesupport/lib/active_support/core_ext/kernel.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/kernel/agnostics' require 'active_support/core_ext/kernel/concern' -require 'active_support/core_ext/kernel/debugger' if RUBY_VERSION < '2.0.0' require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/kernel/singleton_class' diff --git a/activesupport/lib/active_support/core_ext/kernel/debugger.rb b/activesupport/lib/active_support/core_ext/kernel/debugger.rb index 2073cac98d..1fde3db070 100644 --- a/activesupport/lib/active_support/core_ext/kernel/debugger.rb +++ b/activesupport/lib/active_support/core_ext/kernel/debugger.rb @@ -1,10 +1,3 @@ -module Kernel - unless respond_to?(:debugger) - # Starts a debugging session if the +debugger+ gem has been loaded (call rails server --debugger to do load it). - def debugger - message = "\n***** Debugger requested, but was not available (ensure the debugger gem is listed in Gemfile/installed as gem): Start server with --debugger to enable *****\n" - defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message) - end - alias breakpoint debugger unless respond_to?(:breakpoint) - end -end +require 'active_support/deprecation' + +ActiveSupport::Deprecation.warn("This file is deprecated and will be removed in Rails 5.1 with no replacement.") diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb index 80c531b694..9189e6d977 100644 --- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb +++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb @@ -1,4 +1,3 @@ -require 'rbconfig' require 'tempfile' module Kernel @@ -29,34 +28,6 @@ module Kernel $VERBOSE = old_verbose end - # For compatibility - def silence_stderr #:nodoc: - ActiveSupport::Deprecation.warn( - "#silence_stderr is deprecated and will be removed in the next release" - ) #not thread-safe - silence_stream(STDERR) { yield } - end - - # Deprecated : this method is not thread safe - # Silences any stream for the duration of the block. - # - # silence_stream(STDOUT) do - # puts 'This will never be seen' - # end - # - # puts 'But this will' - # - # This method is not thread-safe. - def silence_stream(stream) - old_stream = stream.dup - stream.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null') - stream.sync = true - yield - ensure - stream.reopen(old_stream) - old_stream.close - end - # Blocks and ignores any exception passed as argument if raised within the block. # # suppress(ZeroDivisionError) do @@ -69,56 +40,4 @@ module Kernel yield rescue *exception_classes end - - # Captures the given stream and returns it: - # - # stream = capture(:stdout) { puts 'notice' } - # stream # => "notice\n" - # - # stream = capture(:stderr) { warn 'error' } - # stream # => "error\n" - # - # even for subprocesses: - # - # stream = capture(:stdout) { system('echo notice') } - # stream # => "notice\n" - # - # stream = capture(:stderr) { system('echo error 1>&2') } - # stream # => "error\n" - def capture(stream) - ActiveSupport::Deprecation.warn( - "#capture(stream) is deprecated and will be removed in the next release" - ) #not thread-safe - stream = stream.to_s - captured_stream = Tempfile.new(stream) - stream_io = eval("$#{stream}") - origin_stream = stream_io.dup - stream_io.reopen(captured_stream) - - yield - - stream_io.rewind - return captured_stream.read - ensure - captured_stream.close - captured_stream.unlink - stream_io.reopen(origin_stream) - end - alias :silence :capture - - # Silences both STDOUT and STDERR, even for subprocesses. - # - # quietly { system 'bundle install' } - # - # This method is not thread-safe. - def quietly - ActiveSupport::Deprecation.warn( - "#quietly is deprecated and will be removed in the next release" - ) #not thread-safe - silence_stream(STDOUT) do - silence_stream(STDERR) do - yield - end - end - end end diff --git a/activesupport/lib/active_support/core_ext/load_error.rb b/activesupport/lib/active_support/core_ext/load_error.rb index 768b980f21..d9fb392752 100644 --- a/activesupport/lib/active_support/core_ext/load_error.rb +++ b/activesupport/lib/active_support/core_ext/load_error.rb @@ -1,3 +1,5 @@ +require 'active_support/deprecation/proxy_wrappers' + class LoadError REGEXPS = [ /^no such file to load -- (.+)$/i, @@ -25,4 +27,4 @@ class LoadError end end -MissingSourceFile = LoadError +MissingSourceFile = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('MissingSourceFile', 'LoadError') diff --git a/activesupport/lib/active_support/core_ext/module/aliasing.rb b/activesupport/lib/active_support/core_ext/module/aliasing.rb index 580cb80413..0a6fadf928 100644 --- a/activesupport/lib/active_support/core_ext/module/aliasing.rb +++ b/activesupport/lib/active_support/core_ext/module/aliasing.rb @@ -19,9 +19,9 @@ class Module # alias_method :foo_without_feature?, :foo? # alias_method :foo?, :foo_with_feature? # - # so you can safely chain foo, foo?, and foo! with the same feature. + # so you can safely chain foo, foo?, foo! and/or foo= with the same feature. def alias_method_chain(target, feature) - # Strip out punctuation on predicates or bang methods since + # Strip out punctuation on predicates, bang or writer methods since # e.g. target?_without_feature is not a valid method name. aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1 yield(aliased_target, punctuation) if block_given? diff --git a/activesupport/lib/active_support/core_ext/module/attr_internal.rb b/activesupport/lib/active_support/core_ext/module/attr_internal.rb index 67f0e0335d..93fb598650 100644 --- a/activesupport/lib/active_support/core_ext/module/attr_internal.rb +++ b/activesupport/lib/active_support/core_ext/module/attr_internal.rb @@ -27,11 +27,8 @@ class Module def attr_internal_define(attr_name, type) internal_name = attr_internal_ivar_name(attr_name).sub(/\A@/, '') - # class_eval is necessary on 1.9 or else the methods are made private - class_eval do - # use native attr_* methods as they are faster on some Ruby implementations - send("attr_#{type}", internal_name) - end + # use native attr_* methods as they are faster on some Ruby implementations + send("attr_#{type}", internal_name) attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer alias_method attr_name, internal_name remove_method internal_name diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb index d317df5079..d4e6b5a1ac 100644 --- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb @@ -203,7 +203,7 @@ class Module # include HairColors # end # - # Person.class_variable_get("@@hair_colors") #=> [:brown, :black, :blonde, :red] + # Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red] def mattr_accessor(*syms, &blk) mattr_reader(*syms, &blk) mattr_writer(*syms, &blk) diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 570585b89a..a5f4d03256 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -17,7 +17,7 @@ class Module # ==== Options # * <tt>:to</tt> - Specifies the target object # * <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix - # * <tt>:allow_nil</tt> - if set to true, prevents a +NoMethodError+ to be raised + # * <tt>:allow_nil</tt> - if set to true, prevents a +NoMethodError+ from being raised # # The macro receives one or more method names (specified as symbols or # strings) and the name of the target object via the <tt>:to</tt> option @@ -185,19 +185,31 @@ class Module # On the other hand it could be that the target has side-effects, # whereas conceptually, from the user point of view, the delegator should # be doing one call. - - exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") - - method_def = [ - "def #{method_prefix}#{method}(#{definition})", - " _ = #{to}", - " if !_.nil? || nil.respond_to?(:#{method})", - " _.#{method}(#{definition})", - " else", - " #{exception unless allow_nil}", - " end", + if allow_nil + method_def = [ + "def #{method_prefix}#{method}(#{definition})", + "_ = #{to}", + "if !_.nil? || nil.respond_to?(:#{method})", + " _.#{method}(#{definition})", + "end", "end" - ].join ';' + ].join ';' + else + exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") + + method_def = [ + "def #{method_prefix}#{method}(#{definition})", + " _ = #{to}", + " _.#{method}(#{definition})", + "rescue NoMethodError => e", + " if _.nil? && e.name == :#{method}", + " #{exception}", + " else", + " raise", + " end", + "end" + ].join ';' + end module_eval(method_def, file, line) end diff --git a/activesupport/lib/active_support/core_ext/module/method_transplanting.rb b/activesupport/lib/active_support/core_ext/module/method_transplanting.rb index b1097cc83b..1fde3db070 100644 --- a/activesupport/lib/active_support/core_ext/module/method_transplanting.rb +++ b/activesupport/lib/active_support/core_ext/module/method_transplanting.rb @@ -1,11 +1,3 @@ -class Module - ### - # TODO: remove this after 1.9 support is dropped - def methods_transplantable? # :nodoc: - x = Module.new { def foo; end } - Module.new { define_method :bar, x.instance_method(:foo) } - true - rescue TypeError - false - end -end +require 'active_support/deprecation' + +ActiveSupport::Deprecation.warn("This file is deprecated and will be removed in Rails 5.1 with no replacement.") diff --git a/activesupport/lib/active_support/core_ext/module/remove_method.rb b/activesupport/lib/active_support/core_ext/module/remove_method.rb index 719071d1c2..8a2569a7d0 100644 --- a/activesupport/lib/active_support/core_ext/module/remove_method.rb +++ b/activesupport/lib/active_support/core_ext/module/remove_method.rb @@ -1,10 +1,13 @@ class Module + # Remove the named method, if it exists. def remove_possible_method(method) if method_defined?(method) || private_method_defined?(method) undef_method(method) end end + # Replace the existing method definition, if there is one, with the contents + # of the block. def redefine_method(method, &block) remove_possible_method(method) define_method(method, &block) diff --git a/activesupport/lib/active_support/core_ext/name_error.rb b/activesupport/lib/active_support/core_ext/name_error.rb index e1ebd4f91c..6b447d772b 100644 --- a/activesupport/lib/active_support/core_ext/name_error.rb +++ b/activesupport/lib/active_support/core_ext/name_error.rb @@ -1,5 +1,12 @@ class NameError # Extract the name of the missing constant from the exception message. + # + # begin + # HelloWorld + # rescue NameError => e + # e.missing_name + # end + # # => "HelloWorld" def missing_name if /undefined local variable or method/ !~ message $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message @@ -7,10 +14,16 @@ class NameError end # Was this exception raised because the given name was missing? + # + # begin + # HelloWorld + # rescue NameError => e + # e.missing_name?("HelloWorld") + # end + # # => true def missing_name?(name) if name.is_a? Symbol - last_name = (missing_name || '').split('::').last - last_name == name.to_s + self.name == name else missing_name == name.to_s end diff --git a/activesupport/lib/active_support/core_ext/numeric/bytes.rb b/activesupport/lib/active_support/core_ext/numeric/bytes.rb index deea8e9358..dfbca32474 100644 --- a/activesupport/lib/active_support/core_ext/numeric/bytes.rb +++ b/activesupport/lib/active_support/core_ext/numeric/bytes.rb @@ -7,36 +7,56 @@ class Numeric EXABYTE = PETABYTE * 1024 # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes + # + # 2.bytes # => 2 def bytes self end alias :byte :bytes + # Returns the number of bytes equivalent to the kilobytes provided. + # + # 2.kilobytes # => 2048 def kilobytes self * KILOBYTE end alias :kilobyte :kilobytes + # Returns the number of bytes equivalent to the megabytes provided. + # + # 2.megabytes # => 2_097_152 def megabytes self * MEGABYTE end alias :megabyte :megabytes + # Returns the number of bytes equivalent to the gigabytes provided. + # + # 2.gigabytes # => 2_147_483_648 def gigabytes self * GIGABYTE end alias :gigabyte :gigabytes + # Returns the number of bytes equivalent to the terabytes provided. + # + # 2.terabytes # => 2_199_023_255_552 def terabytes self * TERABYTE end alias :terabyte :terabytes + # Returns the number of bytes equivalent to the petabytes provided. + # + # 2.petabytes # => 2_251_799_813_685_248 def petabytes self * PETABYTE end alias :petabyte :petabytes + # Returns the number of bytes equivalent to the exabytes provided. + # + # 2.exabytes # => 2_305_843_009_213_693_952 def exabytes self * EXABYTE end 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/numeric/time.rb b/activesupport/lib/active_support/core_ext/numeric/time.rb index 689fae4830..98716383f4 100644 --- a/activesupport/lib/active_support/core_ext/numeric/time.rb +++ b/activesupport/lib/active_support/core_ext/numeric/time.rb @@ -1,6 +1,8 @@ require 'active_support/duration' require 'active_support/core_ext/time/calculations' require 'active_support/core_ext/time/acts_like' +require 'active_support/core_ext/date/calculations' +require 'active_support/core_ext/date/acts_like' class Numeric # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years. @@ -36,33 +38,51 @@ class Numeric end alias :second :seconds + # Returns a Duration instance matching the number of minutes provided. + # + # 2.minutes # => 120 seconds def minutes ActiveSupport::Duration.new(self * 60, [[:seconds, self * 60]]) end alias :minute :minutes + # Returns a Duration instance matching the number of hours provided. + # + # 2.hours # => 7_200 seconds def hours ActiveSupport::Duration.new(self * 3600, [[:seconds, self * 3600]]) end alias :hour :hours + # Returns a Duration instance matching the number of days provided. + # + # 2.days # => 2 days def days ActiveSupport::Duration.new(self * 24.hours, [[:days, self]]) end alias :day :days + # Returns a Duration instance matching the number of weeks provided. + # + # 2.weeks # => 14 days def weeks ActiveSupport::Duration.new(self * 7.days, [[:days, self * 7]]) end alias :week :weeks + # Returns a Duration instance matching the number of fortnights provided. + # + # 2.fortnights # => 28 days def fortnights ActiveSupport::Duration.new(self * 2.weeks, [[:days, self * 14]]) end alias :fortnight :fortnights + # Returns the number of milliseconds equivalent to the seconds provided. # Used with the standard time durations, like 1.hour.in_milliseconds -- # so we can feed them to JavaScript functions like getTime(). + # + # 2.in_milliseconds # => 2_000 def in_milliseconds self * 1000 end diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb index f1106cca9b..f4f9152d6a 100644 --- a/activesupport/lib/active_support/core_ext/object.rb +++ b/activesupport/lib/active_support/core_ext/object.rb @@ -2,7 +2,6 @@ require 'active_support/core_ext/object/acts_like' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/duplicable' require 'active_support/core_ext/object/deep_dup' -require 'active_support/core_ext/object/itself' require 'active_support/core_ext/object/try' require 'active_support/core_ext/object/inclusion' 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/duplicable.rb b/activesupport/lib/active_support/core_ext/object/duplicable.rb index 665cb0f96d..620f7b6561 100644 --- a/activesupport/lib/active_support/core_ext/object/duplicable.rb +++ b/activesupport/lib/active_support/core_ext/object/duplicable.rb @@ -19,7 +19,7 @@ class Object # Can you safely dup this object? # - # False for +nil+, +false+, +true+, symbol, number and BigDecimal(in 1.9.x) objects; + # False for +nil+, +false+, +true+, symbol, number objects; # true otherwise. def duplicable? true @@ -78,17 +78,8 @@ end require 'bigdecimal' class BigDecimal - # Needed to support Ruby 1.9.x, as it doesn't allow dup on BigDecimal, instead - # raises TypeError exception. Checking here on the runtime whether BigDecimal - # will allow dup or not. - begin - BigDecimal.new('4.56').dup - - def duplicable? - true - end - rescue TypeError - # can't dup, so use superclass implementation + def duplicable? + true 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/itself.rb b/activesupport/lib/active_support/core_ext/object/itself.rb deleted file mode 100644 index d71cea6674..0000000000 --- a/activesupport/lib/active_support/core_ext/object/itself.rb +++ /dev/null @@ -1,15 +0,0 @@ -class Object - # TODO: Remove this file when we drop support for Ruby < 2.2 - unless respond_to?(:itself) - # Returns the object itself. - # - # Useful for chaining methods, such as Active Record scopes: - # - # Event.public_send(state.presence_in([ :trashed, :drafted ]) || :itself).order(:created_at) - # - # @return Object - def itself - self - end - 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/core_ext/object/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb index 31919474ed..e0f70b9caa 100644 --- a/activesupport/lib/active_support/core_ext/object/try.rb +++ b/activesupport/lib/active_support/core_ext/object/try.rb @@ -9,7 +9,23 @@ class Object # # instead of # - # @person ? @person.name : nil + # @person.name if @person + # + # +try+ calls can be chained: + # + # @person.try(:spouse).try(:name) + # + # instead of + # + # @person.spouse.name if @person && @person.spouse + # + # +try+ will also return +nil+ if the receiver does not respond to the method: + # + # @person.try(:non_existing_method) # => nil + # + # instead of + # + # @person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil # # +try+ returns +nil+ when called on +nil+ regardless of whether it responds # to the method: @@ -24,7 +40,7 @@ class Object # # The number of arguments in the signature must match. If the object responds # to the method the call is attempted and +ArgumentError+ is still raised - # otherwise. + # in case of argument mismatch. # # If +try+ is called without arguments it yields the receiver to a given # block unless it is +nil+: @@ -38,12 +54,22 @@ class Object # # @person.try { upcase.truncate(50) } # - # Please also note that +try+ is defined on +Object+, therefore it won't work + # Please also note that +try+ is defined on +Object+. Therefore, it won't work # with instances of classes that do not have +Object+ among their ancestors, # like direct subclasses of +BasicObject+. For example, using +try+ with # +SimpleDelegator+ will delegate +try+ to the target instead of calling it on - # delegator itself. + # the delegator itself. def try(*a, &b) + try!(*a, &b) if a.empty? || respond_to?(a.first) + end + + # Same as #try, but raises a NoMethodError exception if the receiver is + # not +nil+ and does not implement the tried method. + # + # "a".try!(:upcase) # => "A" + # nil.try!(:upcase) # => nil + # 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Fixnum + def try!(*a, &b) if a.empty? && block_given? if b.arity.zero? instance_eval(&b) @@ -51,16 +77,6 @@ class Object yield self end else - public_send(*a, &b) if respond_to?(a.first) - end - end - - # Same as #try, but will raise a NoMethodError exception if the receiving is not nil and - # does not implement the tried method. - def try!(*a, &b) - if a.empty? && block_given? - yield self - else public_send(*a, &b) end end @@ -68,12 +84,12 @@ end class NilClass # Calling +try+ on +nil+ always returns +nil+. - # It becomes specially helpful when navigating through associations that may return +nil+. + # It becomes especially helpful when navigating through associations that may return +nil+. # # nil.try(:name) # => nil # # Without +try+ - # @person && !@person.children.blank? && @person.children.first.name + # @person && @person.children.any? && @person.children.first.name # # With +try+ # @person.try(:children).try(:first).try(:name) @@ -81,6 +97,9 @@ class NilClass nil end + # Calling +try!+ on +nil+ always returns +nil+. + # + # nil.try!(:name) # => nil def try!(*args) nil end diff --git a/activesupport/lib/active_support/core_ext/object/with_options.rb b/activesupport/lib/active_support/core_ext/object/with_options.rb index 42e87c4424..7d38e1d134 100644 --- a/activesupport/lib/active_support/core_ext/object/with_options.rb +++ b/activesupport/lib/active_support/core_ext/object/with_options.rb @@ -47,7 +47,21 @@ class Object # end # # <tt>with_options</tt> can also be nested since the call is forwarded to its receiver. - # Each nesting level will merge inherited defaults in addition to their own. + # + # NOTE: Each nesting level will merge inherited defaults in addition to their own. + # + # class Post < ActiveRecord::Base + # with_options if: :persisted?, length: { minimum: 50 } do + # validates :content, if: -> { content.present? } + # end + # end + # + # The code is equivalent to: + # + # validates :content, length: { minimum: 50 }, if: -> { content.present? } + # + # Hence the inherited default for `if` key is ignored. + # def with_options(options, &block) option_merger = ActiveSupport::OptionMerger.new(self, options) block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger) diff --git a/activesupport/lib/active_support/core_ext/securerandom.rb b/activesupport/lib/active_support/core_ext/securerandom.rb new file mode 100644 index 0000000000..6cdbea1f37 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/securerandom.rb @@ -0,0 +1,23 @@ +require 'securerandom' + +module SecureRandom + BASE58_ALPHABET = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a - ['0', 'O', 'I', 'l'] + # SecureRandom.base58 generates a random base58 string. + # + # The argument _n_ specifies the length, of the random string to be generated. + # + # If _n_ is not specified or is nil, 16 is assumed. It may be larger in the future. + # + # The result may contain alphanumeric characters except 0, O, I and l + # + # p SecureRandom.base58 #=> "4kUgL2pdQMSCQtjE" + # p SecureRandom.base58(24) #=> "77TMHrHJFvFDwodq8w7Ev2m7" + # + def self.base58(n = 16) + SecureRandom.random_bytes(n).unpack("C*").map do |byte| + idx = byte % 64 + idx = SecureRandom.random_number(58) if idx >= 58 + BASE58_ALPHABET[idx] + end.join + end +end diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb index 2b1583d4ac..096292dc58 100644 --- a/activesupport/lib/active_support/core_ext/string/filters.rb +++ b/activesupport/lib/active_support/core_ext/string/filters.rb @@ -13,6 +13,9 @@ class String end # Performs a destructive squish. See String#squish. + # str = " foo bar \n \t boo" + # str.squish! # => "foo bar boo" + # str # => "foo bar boo" def squish! gsub!(/\A[[:space:]]+/, '') gsub!(/[[:space:]]+\z/, '') @@ -20,14 +23,24 @@ class String self end - # Returns a new string with all occurrences of the pattern removed. Short-hand for String#gsub(pattern, ''). - def remove(pattern) - gsub pattern, '' + # Returns a new string with all occurrences of the patterns removed. + # str = "foo bar test" + # str.remove(" test") # => "foo bar" + # str # => "foo bar test" + def remove(*patterns) + dup.remove!(*patterns) end - # Alters the string by removing all occurrences of the pattern. Short-hand for String#gsub!(pattern, ''). - def remove!(pattern) - gsub! pattern, '' + # Alters the string by removing all occurrences of the patterns. + # str = "foo bar test" + # str.remove!(" test") # => "foo bar" + # str # => "foo bar" + def remove!(*patterns) + patterns.each do |pattern| + gsub! pattern, "" + end + + self end # Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>: diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb index a124202936..2eedd4fdb1 100644 --- a/activesupport/lib/active_support/core_ext/string/multibyte.rb +++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb @@ -1,4 +1,3 @@ -# encoding: utf-8 require 'active_support/multibyte' class String 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 c761325108..bae4e206e6 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -1,6 +1,5 @@ require 'erb' require 'active_support/core_ext/kernel/singleton_class' -require 'active_support/deprecation' class ERB module Util @@ -86,6 +85,11 @@ class ERB # automatically flag the result as HTML safe, since the raw value is unsafe to # use inside HTML attributes. # + # If your JSON is being used downstream for insertion into the DOM, be aware of + # whether or not it is being inserted via +html()+. Most JQuery plugins do this. + # If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated + # content returned by your JSON. + # # If you need to output JSON elsewhere in your HTML, you can just do something # like this, as any unsafe characters (including quotation marks) will be # automatically escaped for you: @@ -150,7 +154,11 @@ module ActiveSupport #:nodoc: else if html_safe? new_safe_buffer = super - new_safe_buffer.instance_eval { @html_safe = true } + + if new_safe_buffer + new_safe_buffer.instance_variable_set :@html_safe, true + end + new_safe_buffer else to_str[*args] @@ -186,11 +194,6 @@ module ActiveSupport #:nodoc: super(html_escape_interpolated_argument(value)) end - def prepend!(value) - ActiveSupport::Deprecation.deprecation_warning "ActiveSupport::SafeBuffer#prepend!", :prepend - prepend value - end - def +(other) dup.concat(other) end @@ -219,7 +222,7 @@ module ActiveSupport #:nodoc: end def encode_with(coder) - coder.represent_scalar nil, to_str + coder.represent_object nil, to_str end UNSAFE_STRING_METHODS.each do |unsafe_method| @@ -247,6 +250,11 @@ module ActiveSupport #:nodoc: end class String + # Marks a string as trusted safe. It will be inserted into HTML with no + # additional escaping performed. It is your responsibilty to ensure that the + # string contains no malicious content. This method is equivalent to the + # `raw` helper in views. It is recommended that you use `sanitize` instead of + # this method. It should never be called on user input. def html_safe ActiveSupport::SafeBuffer.new(self) end diff --git a/activesupport/lib/active_support/core_ext/struct.rb b/activesupport/lib/active_support/core_ext/struct.rb index c2c30044f2..1fde3db070 100644 --- a/activesupport/lib/active_support/core_ext/struct.rb +++ b/activesupport/lib/active_support/core_ext/struct.rb @@ -1,6 +1,3 @@ -# Backport of Struct#to_h from Ruby 2.0 -class Struct # :nodoc: - def to_h - Hash[members.zip(values)] - end -end unless Struct.instance_methods.include?(:to_h) +require 'active_support/deprecation' + +ActiveSupport::Deprecation.warn("This file is deprecated and will be removed in Rails 5.1 with no replacement.") diff --git a/activesupport/lib/active_support/core_ext/thread.rb b/activesupport/lib/active_support/core_ext/thread.rb deleted file mode 100644 index 4cd6634558..0000000000 --- a/activesupport/lib/active_support/core_ext/thread.rb +++ /dev/null @@ -1,86 +0,0 @@ -class Thread - LOCK = Mutex.new # :nodoc: - - # Returns the value of a thread local variable that has been set. Note that - # these are different than fiber local values. - # - # Thread local values are carried along with threads, and do not respect - # fibers. For example: - # - # Thread.new { - # Thread.current.thread_variable_set("foo", "bar") # set a thread local - # Thread.current["foo"] = "bar" # set a fiber local - # - # Fiber.new { - # Fiber.yield [ - # Thread.current.thread_variable_get("foo"), # get the thread local - # Thread.current["foo"], # get the fiber local - # ] - # }.resume - # }.join.value # => ['bar', nil] - # - # The value <tt>"bar"</tt> is returned for the thread local, where +nil+ is returned - # for the fiber local. The fiber is executed in the same thread, so the - # thread local values are available. - def thread_variable_get(key) - _locals[key.to_sym] - end - - # Sets a thread local with +key+ to +value+. Note that these are local to - # threads, and not to fibers. Please see Thread#thread_variable_get for - # more information. - def thread_variable_set(key, value) - _locals[key.to_sym] = value - end - - # Returns an array of the names of the thread-local variables (as Symbols). - # - # thr = Thread.new do - # Thread.current.thread_variable_set(:cat, 'meow') - # Thread.current.thread_variable_set("dog", 'woof') - # end - # thr.join # => #<Thread:0x401b3f10 dead> - # thr.thread_variables # => [:dog, :cat] - # - # Note that these are not fiber local variables. Please see Thread#thread_variable_get - # for more details. - def thread_variables - _locals.keys - end - - # Returns <tt>true</tt> if the given string (or symbol) exists as a - # thread-local variable. - # - # me = Thread.current - # me.thread_variable_set(:oliver, "a") - # me.thread_variable?(:oliver) # => true - # me.thread_variable?(:stanley) # => false - # - # Note that these are not fiber local variables. Please see Thread#thread_variable_get - # for more details. - def thread_variable?(key) - _locals.has_key?(key.to_sym) - end - - # Freezes the thread so that thread local variables cannot be set via - # Thread#thread_variable_set, nor can fiber local variables be set. - # - # me = Thread.current - # me.freeze - # me.thread_variable_set(:oliver, "a") #=> RuntimeError: can't modify frozen thread locals - # me[:oliver] = "a" #=> RuntimeError: can't modify frozen thread locals - def freeze - _locals.freeze - super - end - - private - - def _locals - if defined?(@_locals) - @_locals - else - LOCK.synchronize { @_locals ||= {} } - end - end -end unless Thread.instance_methods.include?(:thread_variable_set) diff --git a/activesupport/lib/active_support/core_ext/time.rb b/activesupport/lib/active_support/core_ext/time.rb index 32cffe237d..72c3234630 100644 --- a/activesupport/lib/active_support/core_ext/time.rb +++ b/activesupport/lib/active_support/core_ext/time.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/time/acts_like' require 'active_support/core_ext/time/calculations' require 'active_support/core_ext/time/conversions' -require 'active_support/core_ext/time/marshal' require 'active_support/core_ext/time/zones' diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index ab8307429a..13610ba19f 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -69,7 +69,7 @@ class Time # and minute is passed, then sec, usec and nsec is set to 0. The +options+ # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt> - # <tt>:nsec</tt>. Path either <tt>:usec</tt> or <tt>:nsec</tt>, not both. + # <tt>:nsec</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both. # # Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0) # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0) @@ -162,7 +162,7 @@ class Time alias :at_noon :middle_of_day alias :at_middle_of_day :middle_of_day - # Returns a new Time representing the end of the day, 23:59:59.999999 (.999999999 in ruby1.9) + # Returns a new Time representing the end of the day, 23:59:59.999999 def end_of_day change( :hour => 23, @@ -179,7 +179,7 @@ class Time end alias :at_beginning_of_hour :beginning_of_hour - # Returns a new Time representing the end of the hour, x:59:59.999999 (.999999999 in ruby1.9) + # Returns a new Time representing the end of the hour, x:59:59.999999 def end_of_hour change( :min => 59, @@ -195,7 +195,7 @@ class Time end alias :at_beginning_of_minute :beginning_of_minute - # Returns a new Time representing the end of the minute, x:xx:59.999999 (.999999999 in ruby1.9) + # Returns a new Time representing the end of the minute, x:xx:59.999999 def end_of_minute change( :sec => 59, diff --git a/activesupport/lib/active_support/core_ext/time/marshal.rb b/activesupport/lib/active_support/core_ext/time/marshal.rb index 497c4c3fb8..467bad1726 100644 --- a/activesupport/lib/active_support/core_ext/time/marshal.rb +++ b/activesupport/lib/active_support/core_ext/time/marshal.rb @@ -1,30 +1,3 @@ -# Ruby 1.9.2 adds utc_offset and zone to Time, but marshaling only -# preserves utc_offset. Preserve zone also, even though it may not -# work in some edge cases. -if Time.local(2010).zone != Marshal.load(Marshal.dump(Time.local(2010))).zone - class Time - class << self - alias_method :_load_without_zone, :_load - def _load(marshaled_time) - time = _load_without_zone(marshaled_time) - time.instance_eval do - if zone = defined?(@_zone) && remove_instance_variable('@_zone') - ary = to_a - ary[0] += subsec if ary[0] == sec - ary[-1] = zone - utc? ? Time.utc(*ary) : Time.local(*ary) - else - self - end - end - end - end +require 'active_support/deprecation' - alias_method :_dump_without_zone, :_dump - def _dump(*args) - obj = dup - obj.instance_variable_set('@_zone', zone) - obj.send :_dump_without_zone, *args - end - end -end +ActiveSupport::Deprecation.warn("This is deprecated and will be removed in Rails 5.1 with no replacement.") diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb index bbda04d60c..0668eadb1e 100644 --- a/activesupport/lib/active_support/core_ext/time/zones.rb +++ b/activesupport/lib/active_support/core_ext/time/zones.rb @@ -1,4 +1,5 @@ require 'active_support/time_with_zone' +require 'active_support/core_ext/time/acts_like' require 'active_support/core_ext/date_and_time/zones' class Time @@ -50,7 +51,16 @@ class Time end end - # Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones. + # Returns a TimeZone instance matching the time zone provided. + # Accepts the time zone in any format supported by <tt>Time.zone=</tt>. + # Raises an ArgumentError for invalid time zones. + # + # Time.find_zone! "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...> + # Time.find_zone! "EST" # => #<ActiveSupport::TimeZone @name="EST" ...> + # Time.find_zone! -5.hours # => #<ActiveSupport::TimeZone @name="Bogota" ...> + # Time.find_zone! nil # => nil + # Time.find_zone! false # => false + # Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE def find_zone!(time_zone) if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone) time_zone @@ -71,6 +81,12 @@ class Time raise ArgumentError, "Invalid Timezone: #{time_zone}" end + # Returns a TimeZone instance matching the time zone provided. + # Accepts the time zone in any format supported by <tt>Time.zone=</tt>. + # Returns +nil+ for invalid time zones. + # + # Time.find_zone "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...> + # Time.find_zone "NOT-A-TIMEZONE" # => nil def find_zone(time_zone) find_zone!(time_zone) rescue nil end |