CHANGELOG.md 18.9 KB
Newer Older
1 2 3 4 5 6 7
*   Fixed bug in `DateAndTime::Compatibility#to_time` that caused it to
    raise `RuntimeError: can't modify frozen Time` when called on any frozen `Time`.
    Properly pass through the frozen `Time` or `ActiveSupport::TimeWithZone` object
    when calling `#to_time`.

    *Kevin McPhillips* & *Andrew White*

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
*   Remove implicit coercion deprecation of durations

    In #28204 we deprecated implicit conversion of durations to a numeric which
    represented the number of seconds in the duration because of unwanted side
    effects with calculations on durations and dates. This unfortunately had
    the side effect of forcing a explicit cast when configuring third-party
    libraries like expiration in Redis, e.g:

        redis.expire("foo", 5.minutes)

    To work around this we've removed the deprecation and added a private class
    that wraps the numeric and can perform calculation involving durations and
    ensure that they remain a duration irrespective of the order of operations.

    *Andrew White*

24
*   Update `titleize` regex to allow apostrophes
25

26
    In 4b685aa the regex in `titleize` was updated to not match apostrophes to
J
Jon Moss 已提交
27
    better reflect the nature of the transformation. Unfortunately, this had the
28 29 30 31 32 33 34 35 36 37 38 39
    side effect of breaking capitalization on the first word of a sub-string, e.g:

        >> "This was 'fake news'".titleize
        => "This Was 'fake News'"

    This is fixed by extending the look-behind to also check for a word
    character on the other side of the apostrophe.

    Fixes #28312.

    *Andrew White*

40 41 42 43 44 45
*   Add `rfc3339` aliases to `xmlschema` for `Time` and `ActiveSupport::TimeWithZone`

    For naming consistency when using the RFC 3339 profile of ISO 8601 in applications.

    *Andrew White*

A
Andrew White 已提交
46 47
*   Add `Time.rfc3339` parsing method

J
Jon Moss 已提交
48
    `Time.xmlschema` and consequently its alias `iso8601` accepts timestamps
A
Andrew White 已提交
49 50 51 52 53
    without a offset in contravention of the RFC 3339 standard. This method
    enforces that constraint and raises an `ArgumentError` if it doesn't.

    *Andrew White*

54 55
*   Add `ActiveSupport::TimeZone.rfc3339` parsing method

J
Jon Moss 已提交
56
    Previously, there was no way to get a RFC 3339 timestamp into a specific
57 58 59 60 61 62 63 64
    timezone without either using `parse` or chaining methods. The new method
    allows parsing directly into the timezone, e.g:

        >> Time.zone = "Hawaii"
        => "Hawaii"
        >> Time.zone.rfc3339("1999-12-31T14:00:00Z")
        => Fri, 31 Dec 1999 14:00:00 HST -10:00

J
Jon Moss 已提交
65
    This new method has stricter semantics than the current `parse` method,
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    and will raise an `ArgumentError` instead of returning nil, e.g:

        >> Time.zone = "Hawaii"
        => "Hawaii"
        >> Time.zone.rfc3339("foobar")
        ArgumentError: invalid date
        >> Time.zone.parse("foobar")
        => nil

    It will also raise an `ArgumentError` when either the time or offset
    components are missing, e.g:

        >> Time.zone = "Hawaii"
        => "Hawaii"
        >> Time.zone.rfc3339("1999-12-31")
        ArgumentError: invalid date
        >> Time.zone.rfc3339("1999-12-31T14:00:00")
        ArgumentError: invalid date

    *Andrew White*

87 88
*   Add `ActiveSupport::TimeZone.iso8601` parsing method

J
Jon Moss 已提交
89
    Previously, there was no way to get a ISO 8601 timestamp into a specific
90 91 92 93 94 95 96 97
    timezone without either using `parse` or chaining methods. The new method
    allows parsing directly into the timezone, e.g:

        >> Time.zone = "Hawaii"
        => "Hawaii"
        >> Time.zone.iso8601("1999-12-31T14:00:00Z")
        => Fri, 31 Dec 1999 14:00:00 HST -10:00

J
Jon Moss 已提交
98
    If the timestamp is a ISO 8601 date (YYYY-MM-DD), then the time is set
99 100 101 102 103 104 105
    to midnight, e.g:

        >> Time.zone = "Hawaii"
        => "Hawaii"
        >> Time.zone.iso8601("1999-12-31")
        => Fri, 31 Dec 1999 00:00:00 HST -10:00

J
Jon Moss 已提交
106
    This new method has stricter semantics than the current `parse` method,
107 108 109 110 111 112 113 114 115 116 117
    and will raise an `ArgumentError` instead of returning nil, e.g:

        >> Time.zone = "Hawaii"
        => "Hawaii"
        >> Time.zone.iso8601("foobar")
        ArgumentError: invalid date
        >> Time.zone.parse("foobar")
        => nil

    *Andrew White*

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
*   Deprecate implicit coercion of `ActiveSupport::Duration`

    Currently `ActiveSupport::Duration` implicitly converts to a seconds
    value when used in a calculation except for the explicit examples of
    addition and subtraction where the duration is the receiver, e.g:

        >> 2 * 1.day
        => 172800

    This results in lots of confusion especially when using durations
    with dates because adding/subtracting a value from a date treats
    integers as a day and not a second, e.g:

        >> Date.today
        => Wed, 01 Mar 2017
        >> Date.today + 2 * 1.day
        => Mon, 10 Apr 2490

    To fix this we're implementing `coerce` so that we can provide a
    deprecation warning with the intent of removing the implicit coercion
    in Rails 5.2, e.g:

        >> 2 * 1.day
        DEPRECATION WARNING: Implicit coercion of ActiveSupport::Duration
        to a Numeric is deprecated and will raise a TypeError in Rails 5.2.
        => 172800

    In Rails 5.2 it will raise `TypeError`, e.g:

        >> 2 * 1.day
        TypeError: ActiveSupport::Duration can't be coerced into Integer

    This is the same behavior as with other types in Ruby, e.g:

        >> 2 * "foo"
        TypeError: String can't be coerced into Integer
        >> "foo" * 2
        => "foofoo"

    As part of this deprecation add `*` and `/` methods to `AS::Duration`
    so that calculations that keep the duration as the receiver work
    correctly whether the final receiver is a `Date` or `Time`, e.g:

        >> Date.today
        => Wed, 01 Mar 2017
        >> Date.today + 1.day * 2
        => Fri, 03 Mar 2017

    Fixes #27457.

    *Andrew White*

170 171 172 173 174 175 176 177 178 179 180 181
*   Update `DateTime#change` to support `:usec` and `:nsec` options.

    Adding support for these options now allows us to update the `DateTime#end_of`
    methods to match the equivalent `Time#end_of` methods, e.g:

        datetime = DateTime.now.end_of_day
        datetime.nsec == 999999999 # => true

    Fixes #21424.

    *Dan Moore*, *Andrew White*

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
*   Add `ActiveSupport::Duration#before` and `#after` as aliases for `#until` and `#since`

    These read more like English and require less mental gymnastics to read and write.

    Before:

        2.weeks.since(customer_start_date)
        5.days.until(today)

    After:

        2.weeks.after(customer_start_date)
        5.days.before(today)

    *Nick Johnstone*

198
*   Soft-deprecated the top-level `HashWithIndifferentAccess` constant.
199 200
    `ActiveSupport::HashWithIndifferentAccess` should be used instead.

J
Jon Moss 已提交
201 202 203
    Fixes #28157.

    *Robin Dupret*
204

205
*   In Core Extensions, make `MarshalWithAutoloading#load` pass through the second, optional
206
    argument for `Marshal#load( source [, proc] )`. This way we don't have to do
V
Vipul A M 已提交
207
    `Marshal.method(:load).super_method.call(source, proc)` just to be able to pass a proc.
208 209 210

    *Jeff Latz*

211 212 213 214
*   `ActiveSupport::Gzip.decompress` now checks checksum and length in footer.

    *Dylan Thacker-Smith*

215 216 217

## Rails 5.1.0.beta1 (February 23, 2017) ##

A
Andrew White 已提交
218 219 220 221
*   Cache `ActiveSupport::TimeWithZone#to_datetime` before freezing.

    *Adam Rice*

V
Vipul A M 已提交
222
*   Deprecate `ActiveSupport.halt_callback_chains_on_return_false`.
223 224 225

    *Rafael Mendonça França*

226 227 228 229
*   Remove deprecated behavior that halts callbacks when the return is false.

    *Rafael Mendonça França*

230 231 232 233 234
*   Deprecate passing string to `:if` and `:unless` conditional options
    on `set_callback` and `skip_callback`.

    *Ryuta Kamizono*

235 236 237 238
*   Raise `ArgumentError` when passing string to define callback.

    *Ryuta Kamizono*

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
*   Updated Unicode version to 9.0.0

    Now we can handle new emojis such like "👩‍👩‍👧‍👦" ("\u{1F469}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}").

    version 8.0.0

        "👩‍👩‍👧‍👦".mb_chars.grapheme_length # => 4
        "👩‍👩‍👧‍👦".mb_chars.reverse # => "👦👧‍👩‍👩‍"

    version 9.0.0

        "👩‍👩‍👧‍👦".mb_chars.grapheme_length # => 1
        "👩‍👩‍👧‍👦".mb_chars.reverse # => "👩‍👩‍👧‍👦"

    *Fumiaki MATSUSHIMA*

255 256 257 258 259
*   Changed `ActiveSupport::Inflector#transliterate` to raise `ArgumentError` when it receives
    anything except a string.

    *Kevin McPhillips*

260 261
*   Fixed bugs that `StringInquirer#respond_to_missing?` and
    `ArrayInquirer#respond_to_missing?` do not fallback to `super`.
262 263 264

    *Akira Matsuda*

265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
*   Fix inconsistent results when parsing large durations and constructing durations from code

        ActiveSupport::Duration.parse('P3Y') == 3.years # It should be true

    Duration parsing made independent from any moment of time:
    Fixed length in seconds is assigned to each duration part during parsing.

    Changed duration of months and years in seconds to more accurate and logical:

     1. The value of 365.2425 days in Gregorian year is more accurate
        as it accounts for every 400th non-leap year.

     2. Month's length is bound to year's duration, which makes
        sensible comparisons like `12.months == 1.year` to be `true`
        and nonsensical ones like `30.days == 1.month` to be `false`.

    Calculations on times and dates with durations shouldn't be affected as
    duration's numeric value isn't used in calculations, only parts are used.

    Methods on `Numeric` like `2.days` now use these predefined durations
V
Vipul A M 已提交
285
    to avoid duplication of duration constants through the codebase and
286 287
    eliminate creation of intermediate durations.

288
    *Andrey Novikov*, *Andrew White*
289

U
utilum 已提交
290 291 292 293 294
*   Change return value of `Rational#duplicable?`, `ComplexClass#duplicable?`
    to false.

    *utilum*

295 296 297 298 299 300
*   Change return value of `NilClass#duplicable?`, `FalseClass#duplicable?`,
    `TrueClass#duplicable?`, `Symbol#duplicable?` and `Numeric#duplicable?`
    to true with Ruby 2.4+. These classes can dup with Ruby 2.4+.

    *Yuji Yaginuma*

301
*   Remove deprecated class `ActiveSupport::Concurrency::Latch`.
302 303 304

    *Andrew White*

305
*   Remove deprecated separator argument from `parameterize`.
306 307 308

    *Andrew White*

309
*   Remove deprecated method `Numeric#to_formatted_s`.
310 311 312

    *Andrew White*

313
*   Remove deprecated method `alias_method_chain`.
314 315 316

    *Andrew White*

317
*   Remove deprecated constant `MissingSourceFile`.
318 319 320

    *Andrew White*

321
*   Remove deprecated methods `Module.qualified_const_defined?`,
322
    `Module.qualified_const_get` and `Module.qualified_const_set`.
323 324 325

    *Andrew White*

326
*   Remove deprecated `:prefix` option from `number_to_human_size`.
A
Andrew White 已提交
327 328 329

    *Andrew White*

330
*   Remove deprecated method `ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default`.
A
Andrew White 已提交
331 332 333

    *Andrew White*

334
*   Remove deprecated file `active_support/core_ext/time/marshal.rb`.
A
Andrew White 已提交
335 336 337

    *Andrew White*

338
*   Remove deprecated file `active_support/core_ext/struct.rb`.
A
Andrew White 已提交
339 340 341

    *Andrew White*

342
*   Remove deprecated file `active_support/core_ext/module/method_transplanting.rb`.
A
Andrew White 已提交
343 344 345

    *Andrew White*

346
*   Remove deprecated method `Module.local_constants`.
A
Andrew White 已提交
347 348 349

    *Andrew White*

350
*   Remove deprecated file `active_support/core_ext/kernel/debugger.rb`.
A
Andrew White 已提交
351 352 353

    *Andrew White*

354
*   Remove deprecated method `ActiveSupport::Cache::Store#namespaced_key`.
A
Andrew White 已提交
355 356 357

    *Andrew White*

358
*   Remove deprecated method `ActiveSupport::Cache::Strategy::LocalCache::LocalStore#set_cache_value`.
A
Andrew White 已提交
359 360 361

    *Andrew White*

362
*   Remove deprecated method `ActiveSupport::Cache::MemCacheStore#escape_key`.
A
Andrew White 已提交
363 364 365

    *Andrew White*

366
*   Remove deprecated method `ActiveSupport::Cache::FileStore#key_file_path`.
A
Andrew White 已提交
367 368 369

    *Andrew White*

370
*   Ensure duration parsing is consistent across DST changes.
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389

    Previously `ActiveSupport::Duration.parse` used `Time.current` and
    `Time#advance` to calculate the number of seconds in the duration
    from an arbitrary collection of parts. However as `advance` tries to
    be consistent across DST boundaries this meant that either the
    duration was shorter or longer depending on the time of year.

    This was fixed by using an absolute reference point in UTC which
    isn't subject to DST transitions. An arbitrary date of Jan 1st, 2000
    was chosen for no other reason that it seemed appropriate.

    Additionally, duration parsing should now be marginally faster as we
    are no longer creating instances of `ActiveSupport::TimeWithZone`
    every time we parse a duration string.

    Fixes #26941.

    *Andrew White*

390 391 392 393 394
*   Use `Hash#compact` and `Hash#compact!` from Ruby 2.4. Old Ruby versions
    will continue to get these methods from Active Support as before.

    *Prathamesh Sonpatki*

395 396 397 398 399 400 401
*   Fix `ActiveSupport::TimeZone#strptime`.
    Support for timestamps in format of seconds (%s) and milliseconds (%Q).

    Fixes #26840.

    *Lev Denisov*

402 403 404 405 406 407
*   Fix `DateAndTime::Calculations#copy_time_to`. Copy `nsec` instead of `usec`.

    Jumping forward or backward between weeks now preserves nanosecond digits.

    *Josua Schmid*

408 409 410 411 412 413 414 415 416 417
*   Fix `ActiveSupport::TimeWithZone#in` across DST boundaries.

    Previously calls to `in` were being sent to the non-DST aware
    method `Time#since` via `method_missing`. It is now aliased to
    the DST aware `ActiveSupport::TimeWithZone#+` which handles
    transitions across DST boundaries, e.g:

        Time.zone = "US/Eastern"

        t = Time.zone.local(2016,11,6,1)
418
        # => Sun, 06 Nov 2016 01:00:00 EDT -05:00
419 420

        t.in(1.hour)
421
        # => Sun, 06 Nov 2016 01:00:00 EST -05:00
422 423 424 425 426

    Fixes #26580.

    *Thomas Balthazar*

427 428 429 430 431 432
*   Remove unused parameter `options = nil` for `#clear` of
    `ActiveSupport::Cache::Strategy::LocalCache::LocalStore` and
    `ActiveSupport::Cache::Strategy::LocalCache`.

    *Yosuke Kabuto*

433
*   Fix `thread_mattr_accessor` subclass no longer overwrites parent.
434

435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
    Assigning a value to a subclass using `thread_mattr_accessor` no
    longer changes the value of the parent class. This brings the
    behavior inline with the documentation.

    Given:

        class Account
          thread_mattr_accessor :user
        end

        class Customer < Account
        end

        Account.user = "DHH"
        Customer.user = "Rafael"

    Before:

        Account.user  # => "Rafael"

    After:

        Account.user  # => "DHH"
458 459 460

    *Shinichi Maeshima*

461 462 463 464 465 466 467 468
*   Since weeks are no longer converted to days, add `:weeks` to the list of
    parts that `ActiveSupport::TimeWithZone` will recognize as possibly being
    of variable duration to take account of DST transitions.

    Fixes #26039.

    *Andrew White*

X
Xavier Noria 已提交
469
*   Defines `Regexp.match?` for Ruby versions prior to 2.4. The predicate
470
    has the same interface, but it does not have the performance boost. Its
X
Xavier Noria 已提交
471 472 473 474
    purpose is to be able to write 2.4 compatible code.

    *Xavier Noria*

V
Vipul A M 已提交
475
*   Allow `MessageEncryptor` to take advantage of authenticated encryption modes.
476 477

    AEAD modes like `aes-256-gcm` provide both confidentiality and data
V
Vipul A M 已提交
478
    authenticity, eliminating the need to use `MessageVerifier` to check if the
479 480 481 482 483
    encrypted data has been tampered with. This speeds up encryption/decryption
    and results in shorter cipher text.

    *Bart de Water*

484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
*   Introduce `assert_changes` and `assert_no_changes`.

    `assert_changes` is a more general `assert_difference` that works with any
    value.

        assert_changes 'Error.current', from: nil, to: 'ERR' do
          expected_bad_operation
        end

    Can be called with strings, to be evaluated in the binding (context) of
    the block given to the assertion, or a lambda.

        assert_changes -> { Error.current }, from: nil, to: 'ERR' do
          expected_bad_operation
        end

    The `from` and `to` arguments are compared with the case operator (`===`).

        assert_changes 'Error.current', from: nil, to: Error do
          expected_bad_operation
        end

    This is pretty useful, if you need to loosely compare a value. For example,
    you need to test a token has been generated and it has that many random
    characters.

        user = User.start_registration
        assert_changes 'user.token', to: /\w{32}/ do
          user.finish_registration
        end

    *Genadi Samokovarov*

517 518 519 520 521 522 523 524 525
*   Fix `ActiveSupport::TimeZone#strptime`. Now raises `ArgumentError` when the
    given time doesn't match the format. The error is the same as the one given
    by Ruby's `Date.strptime`. Previously it raised
    `NoMethodError: undefined method empty? for nil:NilClass.` due to a bug.

    Fixes #25701.

    *John Gesimondo*

X
Xavier Noria 已提交
526
*   `travel/travel_to` travel time helpers, now raise on nested calls,
527
    as this can lead to confusing time stubbing.
528

529
    Instead of:
530

531 532 533 534 535 536
        travel_to 2.days.from_now do
          # 2 days from today
          travel_to 3.days.from_now do
            # 5 days from today
          end
        end
537

538
    preferred way to achieve above is:
539

540 541 542
        travel 2.days do
          # 2 days from today
        end
543

544 545 546
        travel 5.days do
          # 5 days from today
        end
547

548
    *Vipul A M*
549

550 551 552 553 554 555
*   Support parsing JSON time in ISO8601 local time strings in
    `ActiveSupport::JSON.decode` when `parse_json_times` is enabled.
    Strings in the format of `YYYY-MM-DD hh:mm:ss` (without a `Z` at
    the end) will be parsed in the local timezone (`Time.zone`). In
    addition, date strings (`YYYY-MM-DD`) are now parsed into `Date`
    objects.
556 557 558

    *Grzegorz Witek*

K
Kevin McPhillips 已提交
559 560 561 562 563 564
*   Fixed `ActiveSupport::Logger.broadcast` so that calls to `#silence` now
    properly delegate to all loggers. Silencing now properly suppresses logging
    to both the log and the console.

    *Kevin McPhillips*

565 566 567 568
*   Remove deprecated arguments in `assert_nothing_raised`.

    *Rafel Mendonça França*

569 570 571 572 573 574 575
*   `Date.to_s` doesn't produce too many spaces. For example, `to_s(:short)`
    will now produce `01 Feb` instead of ` 1 Feb`.

    Fixes #25251.

    *Sean Griffin*

V
Vipul A M 已提交
576
*   Introduce `Module#delegate_missing_to`.
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622

    When building a decorator, a common pattern emerges:

        class Partition
          def initialize(first_event)
            @events = [ first_event ]
          end

          def people
            if @events.first.detail.people.any?
              @events.collect { |e| Array(e.detail.people) }.flatten.uniq
            else
              @events.collect(&:creator).uniq
            end
          end

          private
            def respond_to_missing?(name, include_private = false)
              @events.respond_to?(name, include_private)
            end

            def method_missing(method, *args, &block)
              @events.send(method, *args, &block)
            end
        end

    With `Module#delegate_missing_to`, the above is condensed to:

        class Partition
          delegate_missing_to :@events

          def initialize(first_event)
            @events = [ first_event ]
          end

          def people
            if @events.first.detail.people.any?
              @events.collect { |e| Array(e.detail.people) }.flatten.uniq
            else
              @events.collect(&:creator).uniq
            end
          end
        end

    *Genadi Samokovarov*, *DHH*

623 624 625 626
*   Rescuable: If a handler doesn't match the exception, check for handlers
    matching the exception's cause.

    *Jeremy Daer*
627

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