activesupport 5.0.0.rc1 → 5.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 58f6288e3a1b4e7c9d9bab4be5d3cc168bdd70a4
4
- data.tar.gz: e78cdf5761abaabe30b2c8282066e5b694824bc2
3
+ metadata.gz: 9f3c6d59a6e4308dab74700a6dda2698d36dc434
4
+ data.tar.gz: 1aa6d12354a195b9d5a7d087d516b1747c64e032
5
5
  SHA512:
6
- metadata.gz: 55f8870bcd0d114e8fdf0715300f6b051b3db8e18a5be7072e9fd43c073c7d4b8589e7e855065fd881dfac2ff8594a28ca4d6356afc01a7642842bcf9f89fb7a
7
- data.tar.gz: 9c29a71fe2e96a02319ab4f52a400764d3e472894062af0eaac342f95dc0496318dfc349cb6f95b2f3655ce37ad8947f56fec1122133a30ec00801de35983a30
6
+ metadata.gz: c35c9b59e15764243d8a9ab178785a291c65bc45c32440bfe5c94b68038d218f6bbe4f465403c8a0b6c73ba94b79a9d56db2fec8f47dbea68058d490cbbcc246
7
+ data.tar.gz: 7513136a18f2d448899d598fc4a26179ea13e497448ae25345e5fdf01bbdb6e44068273f6d8f31746650e1f592a3380b05044a01d82648b7d9c339f334f90cbf
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## Rails 5.0.0.rc2 (June 22, 2016) ##
2
+
3
+ * `Date.to_s` doesn't produce too many spaces. For example, `to_s(:short)`
4
+ will now produce `01 Feb` instead of ` 1 Feb`.
5
+
6
+ Fixes #25251.
7
+
8
+ *Sean Griffin*
9
+
10
+ * Rescuable: If a handler doesn't match the exception, check for handlers
11
+ matching the exception's cause.
12
+
13
+ *Jeremy Daer*
14
+
15
+
1
16
  ## Rails 5.0.0.rc1 (May 06, 2016) ##
2
17
 
3
18
  * `ActiveSupport::Duration` supports weeks and hours.
@@ -20,6 +35,7 @@
20
35
 
21
36
  *Andrey Novikov*
22
37
 
38
+
23
39
  ## Rails 5.0.0.beta4 (April 27, 2016) ##
24
40
 
25
41
  * Time zones: Ensure that the UTC offset reflects DST changes that occurred
@@ -656,6 +672,25 @@
656
672
 
657
673
  *George Claghorn*
658
674
 
675
+ * Added ability to `TaggedLogging` to allow loggers to be instantiated multiple times
676
+ so that they don't share tags with each other.
677
+
678
+ Rails.logger = Logger.new(STDOUT)
679
+
680
+ # Before
681
+ custom_logger = ActiveSupport::TaggedLogging.new(Rails.logger)
682
+ custom_logger.push_tags "custom_tag"
683
+ custom_logger.info "test" # => "[custom_tag] [custom_tag] test"
684
+ Rails.logger.info "test" # => "[custom_tag] [custom_tag] test"
685
+
686
+ # After
687
+ custom_logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
688
+ custom_logger.push_tags "custom_tag"
689
+ custom_logger.info "test" # => "[custom_tag] test"
690
+ Rails.logger.info "test" # => "test"
691
+
692
+ *Alexander Staubo*
693
+
659
694
  * Change the default test order from `:sorted` to `:random`.
660
695
 
661
696
  *Rafael Mendonça França*
@@ -730,6 +765,10 @@
730
765
 
731
766
  *Rafael Mendonça França*
732
767
 
768
+ * Remove `Object#itself` as it is implemented in Ruby 2.2.
769
+
770
+ *Cristian Bica*
771
+
733
772
  * Add support for error dispatcher classes in `ActiveSupport::Rescuable`.
734
773
  Now it acts closer to Ruby's rescue.
735
774
 
@@ -26,8 +26,6 @@ class Class
26
26
 
27
27
  # Returns an array with the direct children of +self+.
28
28
  #
29
- # Integer.subclasses # => [Fixnum, Bignum]
30
- #
31
29
  # class Foo; end
32
30
  # class Bar < Foo; end
33
31
  # class Baz < Bar; end
@@ -5,15 +5,15 @@ require 'active_support/core_ext/module/remove_method'
5
5
 
6
6
  class Date
7
7
  DATE_FORMATS = {
8
- :short => '%e %b',
9
- :long => '%B %e, %Y',
8
+ :short => '%d %b',
9
+ :long => '%B %d, %Y',
10
10
  :db => '%Y-%m-%d',
11
11
  :number => '%Y%m%d',
12
12
  :long_ordinal => lambda { |date|
13
13
  day_format = ActiveSupport::Inflector.ordinalize(date.day)
14
14
  date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
15
15
  },
16
- :rfc822 => '%e %b %Y',
16
+ :rfc822 => '%d %b %Y',
17
17
  :iso8601 => lambda { |date| date.iso8601 }
18
18
  }
19
19
 
@@ -55,8 +55,7 @@ class Hash
55
55
  #
56
56
  # XML_TYPE_NAMES = {
57
57
  # "Symbol" => "symbol",
58
- # "Fixnum" => "integer",
59
- # "Bignum" => "integer",
58
+ # "Integer" => "integer",
60
59
  # "BigDecimal" => "decimal",
61
60
  # "Float" => "float",
62
61
  # "TrueClass" => "boolean",
@@ -165,8 +165,8 @@ class Module
165
165
  ''
166
166
  end
167
167
 
168
- file, line = caller(1, 1).first.split(':'.freeze, 2)
169
- line = line.to_i
168
+ location = caller_locations(1, 1).first
169
+ file, line = location.path, location.lineno
170
170
 
171
171
  to = to.to_s
172
172
  to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
@@ -134,6 +134,12 @@ module ActiveSupport::NumericWithFormat
134
134
  deprecate to_formatted_s: :to_s
135
135
  end
136
136
 
137
- [Fixnum, Bignum, Float, BigDecimal].each do |klass|
138
- klass.prepend(ActiveSupport::NumericWithFormat)
137
+ # Ruby 2.4+ unifies Fixnum & Bignum into Integer.
138
+ if Integer == Fixnum
139
+ Integer.prepend ActiveSupport::NumericWithFormat
140
+ else
141
+ Fixnum.prepend ActiveSupport::NumericWithFormat
142
+ Bignum.prepend ActiveSupport::NumericWithFormat
139
143
  end
144
+ Float.prepend ActiveSupport::NumericWithFormat
145
+ BigDecimal.prepend ActiveSupport::NumericWithFormat
@@ -70,7 +70,7 @@ class Numeric
70
70
  # Numbers are not duplicable:
71
71
  #
72
72
  # 3.duplicable? # => false
73
- # 3.dup # => TypeError: can't dup Fixnum
73
+ # 3.dup # => TypeError: can't dup Integer
74
74
  def duplicable?
75
75
  false
76
76
  end
@@ -99,7 +99,7 @@ class Object
99
99
  #
100
100
  # "a".try!(:upcase) # => "A"
101
101
  # nil.try!(:upcase) # => nil
102
- # 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Fixnum
102
+ # 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
103
103
  end
104
104
 
105
105
  class Delegator
@@ -1,5 +1,5 @@
1
1
  class String
2
- # If you pass a single Fixnum, returns a substring of one character at that
2
+ # If you pass a single integer, returns a substring of one character at that
3
3
  # position. The first character of the string is at position 0, the next at
4
4
  # position 1, and so on. If a range is supplied, a substring containing
5
5
  # characters at offsets given by the range is returned. In both cases, if an
@@ -3,6 +3,33 @@ require 'pathname'
3
3
  require 'concurrent/atomic/atomic_boolean'
4
4
 
5
5
  module ActiveSupport
6
+ # Allows you to "listen" to changes in a file system.
7
+ # The evented file updater does not hit disk when checking for updates
8
+ # instead it uses platform specific file system events to trigger a change
9
+ # in state.
10
+ #
11
+ # The file checker takes an array of files to watch or a hash specifying directories
12
+ # and file extensions to watch. It also takes a block that is called when
13
+ # EventedFileUpdateChecker#execute is run or when EventedFileUpdateChecker#execute_if_updated
14
+ # is run and there have been changes to the file system.
15
+ #
16
+ # Note: Forking will cause the first call to `updated?` to return `true`.
17
+ #
18
+ # Example:
19
+ #
20
+ # checker = EventedFileUpdateChecker.new(["/tmp/foo"], -> { puts "changed" })
21
+ # checker.updated?
22
+ # # => false
23
+ # checker.execute_if_updated
24
+ # # => nil
25
+ #
26
+ # FileUtils.touch("/tmp/foo")
27
+ #
28
+ # checker.updated?
29
+ # # => true
30
+ # checker.execute_if_updated
31
+ # # => "changed"
32
+ #
6
33
  class EventedFileUpdateChecker #:nodoc: all
7
34
  def initialize(files, dirs = {}, &block)
8
35
  @ph = PathHelper.new
@@ -13,11 +40,13 @@ module ActiveSupport
13
40
  @dirs[@ph.xpath(dir)] = Array(exts).map { |ext| @ph.normalize_extension(ext) }
14
41
  end
15
42
 
16
- @block = block
17
- @updated = Concurrent::AtomicBoolean.new(false)
18
- @lcsp = @ph.longest_common_subpath(@dirs.keys)
43
+ @block = block
44
+ @updated = Concurrent::AtomicBoolean.new(false)
45
+ @lcsp = @ph.longest_common_subpath(@dirs.keys)
46
+ @pid = Process.pid
47
+ @boot_mutex = Mutex.new
19
48
 
20
- if (dtw = directories_to_watch).any?
49
+ if (@dtw = directories_to_watch).any?
21
50
  # Loading listen triggers warnings. These are originated by a legit
22
51
  # usage of attr_* macros for private attributes, but adds a lot of noise
23
52
  # to our test suite. Thus, we lazy load it and disable warnings locally.
@@ -28,11 +57,18 @@ module ActiveSupport
28
57
  raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
29
58
  end
30
59
  end
31
- Listen.to(*dtw, &method(:changed)).start
32
60
  end
61
+ boot!
33
62
  end
34
63
 
35
64
  def updated?
65
+ @boot_mutex.synchronize do
66
+ if @pid != Process.pid
67
+ boot!
68
+ @pid = Process.pid
69
+ @updated.make_true
70
+ end
71
+ end
36
72
  @updated.true?
37
73
  end
38
74
 
@@ -50,6 +86,9 @@ module ActiveSupport
50
86
  end
51
87
 
52
88
  private
89
+ def boot!
90
+ Listen.to(*@dtw, &method(:changed)).start
91
+ end
53
92
 
54
93
  def changed(modified, added, removed)
55
94
  unless updated?
@@ -8,7 +8,7 @@ module ActiveSupport
8
8
  MAJOR = 5
9
9
  MINOR = 0
10
10
  TINY = 0
11
- PRE = "rc1"
11
+ PRE = "rc2"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -55,6 +55,24 @@ module ActiveSupport
55
55
  logger.local_level = level if logger.respond_to?(:local_level=)
56
56
  super(level) if respond_to?(:local_level=)
57
57
  end
58
+
59
+ define_method(:silence) do |level = Logger::ERROR, &block|
60
+ if logger.respond_to?(:silence)
61
+ logger.silence(level) do
62
+ if respond_to?(:silence)
63
+ super(level, &block)
64
+ else
65
+ block.call(self)
66
+ end
67
+ end
68
+ else
69
+ if respond_to?(:silence)
70
+ super(level, &block)
71
+ else
72
+ block.call(self)
73
+ end
74
+ end
75
+ end
58
76
  end
59
77
  end
60
78
 
@@ -97,7 +97,7 @@ module ActiveSupport
97
97
  end
98
98
 
99
99
  def new_cipher
100
- OpenSSL::Cipher::Cipher.new(@cipher)
100
+ OpenSSL::Cipher.new(@cipher)
101
101
  end
102
102
 
103
103
  def verifier
@@ -1,7 +1,6 @@
1
1
  require 'active_support/concern'
2
2
  require 'active_support/core_ext/class/attribute'
3
3
  require 'active_support/core_ext/string/inflections'
4
- require 'active_support/core_ext/array/extract_options'
5
4
 
6
5
  module ActiveSupport
7
6
  # Rescuable module adds support for easier exception handling.
@@ -48,14 +47,12 @@ module ActiveSupport
48
47
  # end
49
48
  #
50
49
  # Exceptions raised inside exception handlers are not propagated up.
51
- def rescue_from(*klasses, &block)
52
- options = klasses.extract_options!
53
-
54
- unless options.has_key?(:with)
50
+ def rescue_from(*klasses, with: nil, &block)
51
+ unless with
55
52
  if block_given?
56
- options[:with] = block
53
+ with = block
57
54
  else
58
- raise ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument."
55
+ raise ArgumentError, 'Need a handler. Pass the with: keyword argument or provide a block.'
59
56
  end
60
57
  end
61
58
 
@@ -65,65 +62,104 @@ module ActiveSupport
65
62
  elsif klass.is_a?(String)
66
63
  klass
67
64
  else
68
- raise ArgumentError, "#{klass} is neither an Exception nor a String"
65
+ raise ArgumentError, "#{klass.inspect} must be an Exception class or a String referencing an Exception class"
69
66
  end
70
67
 
71
68
  # Put the new handler at the end because the list is read in reverse.
72
- self.rescue_handlers += [[key, options[:with]]]
69
+ self.rescue_handlers += [[key, with]]
73
70
  end
74
71
  end
75
- end
76
72
 
77
- # Tries to rescue the exception by looking up and calling a registered handler.
78
- def rescue_with_handler(exception)
79
- if handler = handler_for_rescue(exception)
80
- handler.arity != 0 ? handler.call(exception) : handler.call
81
- true # don't rely on the return value of the handler
73
+ # Matches an exception to a handler based on the exception class.
74
+ #
75
+ # If no handler matches the exception, check for a handler matching the
76
+ # (optional) exception.cause. If no handler matches the exception or its
77
+ # cause, this returns nil so you can deal with unhandled exceptions.
78
+ # Be sure to re-raise unhandled exceptions if this is what you expect.
79
+ #
80
+ # begin
81
+ # …
82
+ # rescue => exception
83
+ # rescue_with_handler(exception) || raise
84
+ # end
85
+ #
86
+ # Returns the exception if it was handled and nil if it was not.
87
+ def rescue_with_handler(exception, object: self)
88
+ if handler = handler_for_rescue(exception, object: object)
89
+ handler.call exception
90
+ exception
91
+ end
82
92
  end
83
- end
84
93
 
85
- def handler_for_rescue(exception)
86
- # We go from right to left because pairs are pushed onto rescue_handlers
87
- # as rescue_from declarations are found.
88
- _, rescuer = self.class.rescue_handlers.reverse.detect do |klass_name, handler|
89
- # The purpose of allowing strings in rescue_from is to support the
90
- # declaration of handler associations for exception classes whose
91
- # definition is yet unknown.
92
- #
93
- # Since this loop needs the constants it would be inconsistent to
94
- # assume they should exist at this point. An early raised exception
95
- # could trigger some other handler and the array could include
96
- # precisely a string whose corresponding constant has not yet been
97
- # seen. This is why we are tolerant to unknown constants.
98
- #
99
- # Note that this tolerance only matters if the exception was given as
100
- # a string, otherwise a NameError will be raised by the interpreter
101
- # itself when rescue_from CONSTANT is executed.
102
- klass = self.class.const_get(klass_name) rescue nil
103
- klass ||= (klass_name.constantize rescue nil)
104
- klass === exception if klass
94
+ def handler_for_rescue(exception, object: self) #:nodoc:
95
+ case rescuer = find_rescue_handler(exception)
96
+ when Symbol
97
+ method = object.method(rescuer)
98
+ if method.arity == 0
99
+ -> e { method.call }
100
+ else
101
+ method
102
+ end
103
+ when Proc
104
+ if rescuer.arity == 0
105
+ -> e { object.instance_exec(&rescuer) }
106
+ else
107
+ -> e { object.instance_exec(e, &rescuer) }
108
+ end
109
+ end
105
110
  end
106
111
 
107
- case rescuer
108
- when Symbol
109
- method(rescuer)
110
- when Proc
111
- if rescuer.arity == 0
112
- Proc.new { instance_exec(&rescuer) }
113
- else
114
- Proc.new { |_exception| instance_exec(_exception, &rescuer) }
112
+ private
113
+ def find_rescue_handler(exception)
114
+ if exception
115
+ # Handlers are in order of declaration but the most recently declared
116
+ # is the highest priority match, so we search for matching handlers
117
+ # in reverse.
118
+ _, handler = rescue_handlers.reverse_each.detect do |class_or_name, _|
119
+ if klass = constantize_rescue_handler_class(class_or_name)
120
+ klass === exception
121
+ end
122
+ end
123
+
124
+ handler || find_rescue_handler(exception.cause)
125
+ end
126
+ end
127
+
128
+ def constantize_rescue_handler_class(class_or_name)
129
+ case class_or_name
130
+ when String, Symbol
131
+ begin
132
+ # Try a lexical lookup first since we support
133
+ #
134
+ # class Super
135
+ # rescue_from 'Error', with: …
136
+ # end
137
+ #
138
+ # class Sub
139
+ # class Error < StandardError; end
140
+ # end
141
+ #
142
+ # so an Error raised in Sub will hit the 'Error' handler.
143
+ const_get class_or_name
144
+ rescue NameError
145
+ class_or_name.safe_constantize
146
+ end
147
+ else
148
+ class_or_name
149
+ end
115
150
  end
116
- end
117
151
  end
118
152
 
119
- def index_of_handler_for_rescue(exception)
120
- handlers = self.class.rescue_handlers.reverse_each.with_index
121
- _, index = handlers.detect do |(klass_name, _), _|
122
- klass = self.class.const_get(klass_name) rescue nil
123
- klass ||= (klass_name.constantize rescue nil)
124
- klass === exception if klass
125
- end
126
- index
153
+ # Delegates to the class method, but uses the instance as the subject for
154
+ # rescue_from handlers (method calls, instance_exec blocks).
155
+ def rescue_with_handler(exception)
156
+ self.class.rescue_with_handler exception, object: self
157
+ end
158
+
159
+ # Internal handler lookup. Delegates to class method. Some libraries call
160
+ # this directly, so keeping it around for compatibility.
161
+ def handler_for_rescue(exception) #:nodoc:
162
+ self.class.handler_for_rescue exception, object: self
127
163
  end
128
164
  end
129
165
  end
@@ -20,11 +20,9 @@ module ActiveSupport
20
20
  data = StringIO.new(data || '')
21
21
  end
22
22
 
23
- char = data.getc
24
- if char.nil?
23
+ if data.eof?
25
24
  {}
26
25
  else
27
- data.ungetc(char)
28
26
  silence_warnings { require 'rexml/document' } unless defined?(REXML::Document)
29
27
  doc = REXML::Document.new(data)
30
28
 
@@ -32,20 +32,25 @@ module ActiveSupport
32
32
  "binary" => "base64"
33
33
  } unless defined?(DEFAULT_ENCODINGS)
34
34
 
35
- TYPE_NAMES = {
36
- "Symbol" => "symbol",
37
- "Fixnum" => "integer",
38
- "Bignum" => "integer",
39
- "BigDecimal" => "decimal",
40
- "Float" => "float",
41
- "TrueClass" => "boolean",
42
- "FalseClass" => "boolean",
43
- "Date" => "date",
44
- "DateTime" => "dateTime",
45
- "Time" => "dateTime",
46
- "Array" => "array",
47
- "Hash" => "hash"
48
- } unless defined?(TYPE_NAMES)
35
+ unless defined?(TYPE_NAMES)
36
+ TYPE_NAMES = {
37
+ "Symbol" => "symbol",
38
+ "Integer" => "integer",
39
+ "BigDecimal" => "decimal",
40
+ "Float" => "float",
41
+ "TrueClass" => "boolean",
42
+ "FalseClass" => "boolean",
43
+ "Date" => "date",
44
+ "DateTime" => "dateTime",
45
+ "Time" => "dateTime",
46
+ "Array" => "array",
47
+ "Hash" => "hash"
48
+ }
49
+
50
+ # No need to map these on Ruby 2.4+
51
+ TYPE_NAMES["Fixnum"] = "integer" unless Fixnum == Integer
52
+ TYPE_NAMES["Bignum"] = "integer" unless Bignum == Integer
53
+ end
49
54
 
50
55
  FORMATTING = {
51
56
  "symbol" => Proc.new { |symbol| symbol.to_s },
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activesupport
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.rc1
4
+ version: 5.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-06 00:00:00.000000000 Z
11
+ date: 2016-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -336,7 +336,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
336
336
  version: 1.3.1
337
337
  requirements: []
338
338
  rubyforge_project:
339
- rubygems_version: 2.5.1
339
+ rubygems_version: 2.6.4
340
340
  signing_key:
341
341
  specification_version: 4
342
342
  summary: A toolkit of support libraries and Ruby core extensions extracted from the