aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/CHANGELOG.md
blob: db9c7e96f3f6193ef8b893b2e382fa6e1881814d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
*   In `:zeitwerk` mode, eager load directories in engines and applications only
    if present in their respective `config.eager_load_paths`.

    A common use case for this is adding `lib` to `config.autoload_paths`, but
    not to `config.eager_load_paths`. In that configuration, for example, files
    in the `lib` directory should not be eager loaded.

    *Xavier Noria*

*   Fix bug in Range comparisons when comparing to an excluded-end Range

    Before:

        (1..10).cover?(1...11) # => false

    After:

        (1..10).cover?(1...11) # => true

    With the same change for `Range#include?` and `Range#===`.

    *Owen Stephens*

*   Use weak references in descendants tracker to allow anonymous subclasses to
    be garbage collected.

    *Edgars Beigarts*

*   Update `ActiveSupport::Notifications::Instrumenter#instrument` to make
    passing a block optional. This will let users use
    `ActiveSupport::Notifications` messaging features outside of
    instrumentation.

    *Ali Ibrahim*

*   Fix `Time#advance` to work with dates before 1001-03-07

    Before:

        Time.utc(1001, 3, 6).advance(years: -1) # => 1000-03-05 00:00:00 UTC

    After

        Time.utc(1001, 3, 6).advance(years: -1) # => 1000-03-06 00:00:00 UTC

    Note that this doesn't affect `DateTime#advance` as that doesn't use a proleptic calendar.

    *Andrew White*

*   In Zeitwerk mode, engines are now managed by the `main` autoloader. Engines may reference application constants, if the application is reloaded and we do not reload engines, they won't use the reloaded application code.

    *Xavier Noria*

*   Add support for supplying `locale` to `transliterate` and `parameterize`.

        I18n.backend.store_translations(:de, i18n: { transliterate: { rule: { "ü" => "ue" } } })

        ActiveSupport::Inflector.transliterate("ü", locale: :de) # => "ue"
        "Fünf autos".parameterize(locale: :de) # => "fuenf-autos"
        ActiveSupport::Inflector.parameterize("Fünf autos", locale: :de) # => "fuenf-autos"

    *Kaan Ozkan*, *Sharang Dashputre*

*   Allow `Array#excluding` and `Enumerable#excluding` to deal with a passed array gracefully.

        [ 1, 2, 3, 4, 5 ].excluding([4, 5]) # => [ 1, 2, 3 ]

    *DHH*

*   Renamed `Array#without` and `Enumerable#without` to `Array#excluding` and `Enumerable#excluding`, to create parity with
    `Array#including` and `Enumerable#including`. Retained the old names as aliases.

    *DHH*

*   Added `Array#including` and `Enumerable#including` to conveniently enlarge a collection with more members using a method rather than an operator:

        [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
        post.authors.including(Current.person) # => All the authors plus the current person!

    *DHH*


## Rails 6.0.0.beta3 (March 11, 2019) ##

*   No changes.


## Rails 6.0.0.beta2 (February 25, 2019) ##

*   New autoloading based on [Zeitwerk](https://github.com/fxn/zeitwerk).

    *Xavier Noria*

*   Revise `ActiveSupport::Notifications.unsubscribe` to correctly handle Regex or other multiple-pattern subscribers.

    *Zach Kemp*

*   Add `before_reset` callback to `CurrentAttributes` and define `after_reset` as an alias of `resets` for symmetry.

    *Rosa Gutierrez*

*   Remove the `` Kernel#` `` override that suppresses ENOENT and accidentally returns nil on Unix systems.

    *Akinori Musha*

*   Add `ActiveSupport::HashWithIndifferentAccess#assoc`.

    `assoc` can now be called with either a string or a symbol.

    *Stefan Schüßler*

*   Add `Hash#deep_transform_values`, and `Hash#deep_transform_values!`.

    *Guillermo Iguaran*


## Rails 6.0.0.beta1 (January 18, 2019) ##

*   Remove deprecated `Module#reachable?` method.

    *Rafael Mendonça França*

*   Remove deprecated `#acronym_regex` method from `Inflections`.

    *Rafael Mendonça França*

*   Fix `String#safe_constantize` throwing a `LoadError` for incorrectly cased constant references.

    *Keenan Brock*

*   Preserve key order passed to `ActiveSupport::CacheStore#fetch_multi`.

    `fetch_multi(*names)` now returns its results in the same order as the `*names` requested, rather than returning cache hits followed by cache misses.

    *Gannon McGibbon*

*   If the same block is `included` multiple times for a Concern, an exception is no longer raised.

    *Mark J. Titorenko*, *Vlad Bokov*

*   Fix bug where `#to_options` for `ActiveSupport::HashWithIndifferentAccess`
    would not act as alias for `#symbolize_keys`.

    *Nick Weiland*

*   Improve the logic that detects non-autoloaded constants.

    *Jan Habermann*, *Xavier Noria*

*   Deprecate `ActiveSupport::Multibyte::Unicode#pack_graphemes(array)` and `ActiveSuppport::Multibyte::Unicode#unpack_graphemes(string)`
    in favor of `array.flatten.pack("U*")` and `string.scan(/\X/).map(&:codepoints)`, respectively.

    *Francesco Rodríguez*

*   Deprecate `ActiveSupport::Multibyte::Chars.consumes?` in favor of `String#is_utf8?`.

    *Francesco Rodríguez*

*   Fix duration being rounded to a full second.
    ```
      time = DateTime.parse("2018-1-1")
      time += 0.51.seconds
    ```
    Will now correctly add 0.51 second and not 1 full second.

    *Edouard Chin*

*   Deprecate `ActiveSupport::Multibyte::Unicode#normalize` and `ActiveSuppport::Multibyte::Chars#normalize`
    in favor of `String#unicode_normalize`

    *Francesco Rodríguez*

*   Deprecate `ActiveSupport::Multibyte::Unicode#downcase/upcase/swapcase` in favor of
    `String#downcase/upcase/swapcase`.

    *Francesco Rodríguez*

*   Add `ActiveSupport::ParameterFilter`.

    *Yoshiyuki Kinjo*

*   Rename `Module#parent`, `Module#parents`, and `Module#parent_name` to
    `module_parent`, `module_parents`, and `module_parent_name`.

    *Gannon McGibbon*

*   Deprecate the use of `LoggerSilence` in favor of `ActiveSupport::LoggerSilence`

    *Edouard Chin*

*   Deprecate using negative limits in `String#first` and `String#last`.

    *Gannon McGibbon*, *Eric Turner*

*   Fix bug where `#without` for `ActiveSupport::HashWithIndifferentAccess` would fail
    with symbol arguments

    *Abraham Chan*

*   Treat `#delete_prefix`, `#delete_suffix` and `#unicode_normalize` results as non-`html_safe`.
    Ensure safety of arguments for `#insert`, `#[]=` and `#replace` calls on `html_safe` Strings.

    *Janosch Müller*

*   Changed `ActiveSupport::TaggedLogging.new` to return a new logger instance instead
    of mutating the one received as parameter.

    *Thierry Joyal*

*   Define `unfreeze_time` as an alias of `travel_back` in `ActiveSupport::Testing::TimeHelpers`.

    The alias is provided for symmetry with `freeze_time`.

    *Ryan Davidson*

*   Add support for tracing constant autoloads. Just throw

        ActiveSupport::Dependencies.logger = Rails.logger
        ActiveSupport::Dependencies.verbose = true

    in an initializer.

    *Xavier Noria*

*   Maintain `html_safe?` on html_safe strings when sliced.

        string = "<div>test</div>".html_safe
        string[-1..1].html_safe? # => true

    *Elom Gomez*, *Yumin Wong*

*   Add `Array#extract!`.

    The method removes and returns the elements for which the block returns a true value.
    If no block is given, an Enumerator is returned instead.

        numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
        numbers # => [0, 2, 4, 6, 8]

    *bogdanvlviv*

*   Support not to cache `nil` for `ActiveSupport::Cache#fetch`.

        cache.fetch('bar', skip_nil: true) { nil }
        cache.exist?('bar') # => false

    *Martin Hong*

*   Add "event object" support to the notification system.
    Before this change, end users were forced to create hand made artisanal
    event objects on their own, like this:

        ActiveSupport::Notifications.subscribe('wait') do |*args|
          @event = ActiveSupport::Notifications::Event.new(*args)
        end

        ActiveSupport::Notifications.instrument('wait') do
          sleep 1
        end

        @event.duration # => 1000.138

    After this change, if the block passed to `subscribe` only takes one
    parameter, the framework will yield an event object to the block.  Now
    end users are no longer required to make their own:

        ActiveSupport::Notifications.subscribe('wait') do |event|
          @event = event
        end

        ActiveSupport::Notifications.instrument('wait') do
          sleep 1
        end

        p @event.allocations # => 7
        p @event.cpu_time    # => 0.256
        p @event.idle_time   # => 1003.2399

    Now you can enjoy event objects without making them yourself.  Neat!

    *Aaron "t.lo" Patterson*

*   Add cpu_time, idle_time, and allocations to Event.

    *Eileen M. Uchitelle*, *Aaron Patterson*

*   RedisCacheStore: support key expiry in increment/decrement.

    Pass `:expires_in` to `#increment` and `#decrement` to set a Redis EXPIRE on the key.

    If the key is already set to expire, RedisCacheStore won't extend its expiry.

        Rails.cache.increment("some_key", 1, expires_in: 2.minutes)

    *Jason Lee*

*   Allow `Range#===` and `Range#cover?` on Range.

    `Range#cover?` can now accept a range argument like `Range#include?` and
    `Range#===`. `Range#===` works correctly on Ruby 2.6. `Range#include?` is moved
    into a new file, with these two methods.

    *Requiring active_support/core_ext/range/include_range is now deprecated.*
    *Use `require "active_support/core_ext/range/compare_range"` instead.*

    *utilum*

*   Add `index_with` to Enumerable.

    Allows creating a hash from an enumerable with the value from a passed block
    or a default argument.

        %i( title body ).index_with { |attr| post.public_send(attr) }
        # => { title: "hey", body: "what's up?" }

        %i( title body ).index_with(nil)
        # => { title: nil, body: nil }

    Closely linked with `index_by`, which creates a hash where the keys are extracted from a block.

    *Kasper Timm Hansen*

*   Fix bug where `ActiveSupport::TimeZone.all` would fail when tzinfo data for
    any timezone defined in `ActiveSupport::TimeZone::MAPPING` is missing.

    *Dominik Sander*

*   Redis cache store: `delete_matched` no longer blocks the Redis server.
    (Switches from evaled Lua to a batched SCAN + DEL loop.)

    *Gleb Mazovetskiy*

*   Fix bug where `ActiveSupport::Cache` will massively inflate the storage
    size when compression is enabled (which is true by default). This patch
    does not attempt to repair existing data: please manually flush the cache
    to clear out the problematic entries.

    *Godfrey Chan*

*   Fix bug where `URI.unescape` would fail with mixed Unicode/escaped character input:

        URI.unescape("\xe3\x83\x90")  # => "バ"
        URI.unescape("%E3%83%90")  # => "バ"
        URI.unescape("\xe3\x83\x90%E3%83%90")  # => Encoding::CompatibilityError

    *Ashe Connor*, *Aaron Patterson*

*   Add `before?` and `after?` methods to `Date`, `DateTime`,
    `Time`, and `TimeWithZone`.

    *Nick Holden*

*   `ActiveSupport::Inflector#ordinal` and `ActiveSupport::Inflector#ordinalize` now support
    translations through I18n.

        # locale/fr.rb

        {
          fr: {
            number: {
              nth: {
                ordinals: lambda do |_key, number:, **_options|
                  if number.to_i.abs == 1
                    'er'
                  else
                    'e'
                  end
                end,

                ordinalized: lambda do |_key, number:, **_options|
                  "#{number}#{ActiveSupport::Inflector.ordinal(number)}"
                end
              }
            }
          }
        }


    *Christian Blais*

*   Add `:private` option to ActiveSupport's `Module#delegate`
    in order to delegate methods as private:

        class User < ActiveRecord::Base
          has_one :profile
          delegate :date_of_birth, to: :profile, private: true

          def age
            Date.today.year - date_of_birth.year
          end
        end

        # User.new.age  # => 29
        # User.new.date_of_birth
        # => NoMethodError: private method `date_of_birth' called for #<User:0x00000008221340>

    *Tomas Valent*

*   `String#truncate_bytes` to truncate a string to a maximum bytesize without
    breaking multibyte characters or grapheme clusters like 👩‍👩‍👦‍👦.

    *Jeremy Daer*

*   `String#strip_heredoc` preserves frozenness.

        "foo".freeze.strip_heredoc.frozen?  # => true

    Fixes that frozen string literals would inadvertently become unfrozen:

        # frozen_string_literal: true

        foo = <<-MSG.strip_heredoc
          la la la
        MSG

        foo.frozen?  # => false !??

    *Jeremy Daer*

*   Rails 6 requires Ruby 2.5.0 or newer.

    *Jeremy Daer*, *Kasper Timm Hansen*

*   Adds parallel testing to Rails.

    Parallelize your test suite with forked processes or threads.

    *Eileen M. Uchitelle*, *Aaron Patterson*


Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/activesupport/CHANGELOG.md) for previous changes.