|  | Commit message (Collapse) | Author | Age | Files | Lines | 
|---|
| | 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| | Currently `type.serialize` and `connection.{quote|type_cast}` for a time
object always does `time.getutc` call regardless of whether it is
already utc time object or not, that duplicated proccess
(`connection.type_cast(type.serialize(time))`) allocates extra/useless
time objects for each type casting.
This avoids that redundant `time.getutc` call if it is already utc time
object. In the case of a model has timestamps (`created_at` and
`updated_at`), it avoids 6,000 time objects allocation for 1,000 times
`model.save`.
```ruby
ObjectSpace::AllocationTracer.setup(%i{path line type})
pp ObjectSpace::AllocationTracer.trace {
  1_000.times { User.create }
}.select { |k, _| k[0].end_with?("quoting.rb", "time_value.rb") }
```
Before (c104bfe424e6cebe9c8e85a38515327a6c88b1f8):
```
{["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  203,
  :T_ARRAY]=>[1004, 0, 778, 0, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  220,
  :T_STRING]=>[2, 0, 2, 1, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  209,
  :T_ARRAY]=>[8, 0, 8, 1, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  57,
  :T_ARRAY]=>[4, 0, 4, 1, 1, 0],
 ["~/rails/activemodel/lib/active_model/type/helpers/time_value.rb",
  17,
  :T_DATA]=>[4000, 0, 3096, 0, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  120,
  :T_DATA]=>[2000, 0, 1548, 0, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  126,
  :T_STRING]=>[4000, 0, 3096, 0, 1, 0]}
```
After (this change):
```
{["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  203,
  :T_ARRAY]=>[1004, 0, 823, 0, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  220,
  :T_STRING]=>[2, 0, 2, 1, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  209,
  :T_ARRAY]=>[8, 0, 8, 1, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  57,
  :T_ARRAY]=>[4, 0, 4, 1, 1, 0],
 ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb",
  126,
  :T_STRING]=>[2000, 0, 1638, 0, 1, 0]}
``` | 
| | 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| | We sometimes say "✂️ newline after `private`" in a code review (e.g.
https://github.com/rails/rails/pull/18546#discussion_r23188776,
https://github.com/rails/rails/pull/34832#discussion_r244847195).
Now `Layout/EmptyLinesAroundAccessModifier` cop have new enforced style
`EnforcedStyle: only_before` (https://github.com/rubocop-hq/rubocop/pull/7059).
That cop and enforced style will reduce the our code review cost. | 
| | 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| 
| | Currently, if `:datetime` type has a precision, type casting always does
round off subseconds regardless of whether necessary or not, it is a bit
slow.
Since #34970, `t.timestamps` with `precision: 6` by default, so
`pluck(:created_at)` in newly created app will always be affected by the
round off.
This avoids the round off if possible, it makes `pluck(:created_at)`
about 25% faster.
https://gist.github.com/kamipo/e029539f2632aee9f5e711fe66fc8842
Before (0a87d7c9ddb95cf7568baf889ff4091469ba9af4 with postgresql adapter):
```
Warming up --------------------------------------
    users.pluck(:id)      344.000  i/100ms
  users.pluck(:name)      336.000  i/100ms
users.pluck(:created_at)  206.000  i/100ms
Calculating -------------------------------------
    users.pluck(:id)      3.620k (± 8.5%) i/s -     18.232k in   5.077316s
  users.pluck(:name)      3.579k (± 9.4%) i/s -     17.808k in   5.020230s
users.pluck(:created_at)  2.069k (± 8.0%) i/s -     10.300k in   5.019284s
```
Before (0a87d7c9ddb95cf7568baf889ff4091469ba9af4 with mysql2 adapter):
```
Warming up --------------------------------------
    users.pluck(:id)      245.000  i/100ms
  users.pluck(:name)      240.000  i/100ms
users.pluck(:created_at)  180.000  i/100ms
Calculating -------------------------------------
    users.pluck(:id)      2.548k (± 9.4%) i/s -     12.740k in   5.066574s
  users.pluck(:name)      2.513k (± 8.0%) i/s -     12.480k in   5.011260s
users.pluck(:created_at)  1.771k (±11.2%) i/s -      8.820k in   5.084473s
```
After (this change with postgresql adapter):
```
Warming up --------------------------------------
    users.pluck(:id)      348.000  i/100ms
  users.pluck(:name)      357.000  i/100ms
users.pluck(:created_at)  254.000  i/100ms
Calculating -------------------------------------
    users.pluck(:id)      3.628k (± 8.2%) i/s -     18.096k in   5.024748s
  users.pluck(:name)      3.624k (±12.4%) i/s -     17.850k in   5.020959s
users.pluck(:created_at)  2.567k (± 7.0%) i/s -     12.954k in   5.081153s
```
After (this change with mysql2 adapter):
```
Warming up --------------------------------------
    users.pluck(:id)      268.000  i/100ms
  users.pluck(:name)      265.000  i/100ms
users.pluck(:created_at)  207.000  i/100ms
Calculating -------------------------------------
    users.pluck(:id)      2.586k (±10.9%) i/s -     12.864k in   5.050546s
  users.pluck(:name)      2.543k (±10.2%) i/s -     12.720k in   5.067726s
users.pluck(:created_at)  2.263k (±14.5%) i/s -     10.971k in   5.004039s
``` | 
| |\  
| | 
| | | Improve doc for :root option in as_json() | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | 
| | | Remove trailing whitespace [ci skip]
Reword
Root value should be string [ci skip] | 
| | | 
| | 
| | 
| | | This reverts commit 9c9c950d02af83742a5f76302d0faa99508f242c. | 
| |/  
|   
|   
| | Otherwise we get deprecation warnings in the generated scaffold template files | 
| | 
| 
| 
| 
| 
| 
| 
| | instead of 6.0 (#36087)
* Change the deprecation for Enumerating ActiveModel::Errors to Rails 6.1 instead of 6.0
* Changed the deprecation message for ActiveModel::Errors methods: slice, values, keys and to_xml | 
| |\  
| | 
| | | Model error as object | 
| | | 
| | 
| | 
| | | maintaining behavior errors.details[:foo].any? | 
| | | |  | 
| | | |  | 
| | | |  | 
| | | |  | 
| | | 
| | 
| | 
| | 
| | 
| | | Fix double wrapping issue
Revert messages_for wrapping. It's a new method so no need to put
deprecation warnings. | 
| | | 
| | 
| | 
| | | Revert some tests to ensure back compatibility | 
| | | |  | 
| | | 
| | 
| | 
| | | To keep the same as SHA dcafe995bfe51e53dd04607956be9b54073e9cb6 | 
| | | |  | 
| | | 
| | 
| | 
| | 
| | | autosave duplicate errors can be removed
See SHA 7550f0a016ee6647aaa76c0c0ae30bebc3867288 | 
| | | |  | 
| | | 
| | 
| | 
| | | This is because we try to accommodate old hash behavior, so `first` and `last` now does not return Error object. | 
| | | 
| | 
| | 
| | 
| | | All enumerable methods must go through the `each` so it retain old hash behavior.
Revert this after Rails 6.1 in order to speed up enumerable methods. | 
| | | 
| | 
| | 
| | 
| | 
| | | Many operations need grouping of errors by attributes, e.g. ActiveRecord::AutosaveAssociation#association_valid?
Refactor other methods using group_by_attribute | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | | Allow `each` to behave in new way if block arity is 1
Ensure dumped marshal from Rails 5 can be loaded
Make errors compatible with marshal and YAML dumps from previous versions of Rails
Add deprecation warnings
Ensure each behave like the past, sorted by attribute | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | | Add initialize_dup to deep dup.
Move proc eval and flexible message position out to Errors,
because proc eval is needed for Errors#added? and Errors#delete | 
| | | |  | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | | If we want to get alias resolved attribute finally, we can use
`attribute_alias` directly.
For that purpose, avoiding redundant `attribute_alias?` makes alias
attribute access 40% faster.
https://gist.github.com/kamipo/e427f080a27b46f50bc508fae3612a0e
Before (2c0729d8):
```
Warming up --------------------------------------
          user['id']   102.668k i/100ms
      user['new_id']    80.660k i/100ms
        user['name']    99.368k i/100ms
    user['new_name']    81.626k i/100ms
Calculating -------------------------------------
          user['id']      1.431M (± 4.0%) i/s -      7.187M in   5.031985s
      user['new_id']      1.042M (± 4.2%) i/s -      5.243M in   5.039858s
        user['name']      1.406M (± 5.6%) i/s -      7.055M in   5.036743s
    user['new_name']      1.074M (± 3.6%) i/s -      5.387M in   5.024152s
```
After (this change):
```
Warming up --------------------------------------
          user['id']   109.775k i/100ms
      user['new_id']   103.303k i/100ms
        user['name']   105.988k i/100ms
    user['new_name']    99.618k i/100ms
Calculating -------------------------------------
          user['id']      1.520M (± 6.7%) i/s -      7.574M in   5.011496s
      user['new_id']      1.485M (± 6.2%) i/s -      7.438M in   5.036252s
        user['name']      1.538M (± 5.4%) i/s -      7.737M in   5.049765s
    user['new_name']      1.516M (± 4.6%) i/s -      7.571M in   5.007293s
``` | 
| |\ \  
| | | 
| | | | Update comment in attribute_method_matchers_matching | 
| | | | 
| | | 
| | | 
| | | 
| | | 
| | | 
| | | 
| | | 
| | | 
| | | 
| | | | The current comment here is from 2011 and its original context has
changed completely. The plain matcher will not "match every time"
anymore since the code now filters all matchers, and only selects those
for which the captured attribute is valid.
To avoid confusion, I updated the comment. For more discussion, see:
https://github.com/rails/rails/pull/36005 | 
| |/ /  
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| | | This adds `.attribute_names` and `#attribute_names` to
`ActiveModel::Attributes` along the same lines as the corresponding
methods in `ActiveRecord::AttributeMethods` (see
[`.attribute_names`][class_method] and
[`#attribute_names`][instance_method].
While I was here I also added documentation for '#attributes', which I
added in 043ce35b186. The whole class is still `#:nodoc:` so I don't
think this will have any effect for now.
[class_method]: https://github.com/rails/rails/blob/cc834db1d0815744cfa173813c05d928e008e167/activerecord/lib/active_record/attribute_methods.rb#L154-L160
[instance_method]: https://github.com/rails/rails/blob/cc834db1d0815744cfa173813c05d928e008e167/activerecord/lib/active_record/attribute_methods.rb#L299-L301 | 
| | | 
| | 
| | 
| | 
| | 
| | | Most of the time, these methods are called from actual methods defined
from columns in the schema, not from method_missing, so the current
wording is misleading. | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | | The target of matchers is used in two contexts: to define attribute
methods which dispatch to handlers like attribute_was, and to match
method calls in method_missing and dispatch to those same handler
methods.
Only in the latter context does the term "method_missing_target" make
any sense; in the former context it is just confusing. "target" is not
ideal as a term but at least it avoids this confusion. | 
| | | |  | 
| | | |  | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | | Currently, although using both dirty tracking (ivar backed and
attributes backed) on one model is not supported (doesn't fully work at
least), both dirty tracking are being performed, that is very slow.
As long as attributes backed dirty tracking is used, ivar backed dirty
tracking should not need to be performed.
I've refactored to extract new `ForcedMutationTracker` which only tracks
`force_change` to be performed for ivar backed dirty tracking, that
makes dirty tracking on Active Record 2x ~ 30x faster.
https://gist.github.com/kamipo/971dfe0891f0fe1ec7db8ab31f016435
Before:
```
Warming up --------------------------------------
            changed?     4.467k i/100ms
             changed     5.134k i/100ms
             changes     3.023k i/100ms
  changed_attributes     4.358k i/100ms
        title_change     3.185k i/100ms
           title_was     3.381k i/100ms
Calculating -------------------------------------
            changed?     42.197k (±28.5%) i/s -    187.614k in   5.050446s
             changed     50.481k (±16.0%) i/s -    246.432k in   5.045759s
             changes     30.799k (± 7.2%) i/s -    154.173k in   5.030765s
  changed_attributes     51.530k (±14.2%) i/s -    252.764k in   5.041106s
        title_change     44.667k (± 9.0%) i/s -    222.950k in   5.040646s
           title_was     44.635k (±16.6%) i/s -    216.384k in   5.051098s
```
After:
```
Warming up --------------------------------------
            changed?    24.130k i/100ms
             changed    13.503k i/100ms
             changes     6.511k i/100ms
  changed_attributes     9.226k i/100ms
        title_change    48.221k i/100ms
           title_was    96.060k i/100ms
Calculating -------------------------------------
            changed?    245.478k (±16.1%) i/s -      1.182M in   5.015837s
             changed    157.641k (± 4.9%) i/s -    796.677k in   5.066734s
             changes     70.633k (± 5.7%) i/s -    358.105k in   5.086553s
  changed_attributes     95.155k (±13.6%) i/s -    470.526k in   5.082841s
        title_change    566.481k (± 3.5%) i/s -      2.845M in   5.028852s
           title_was      1.487M (± 3.9%) i/s -      7.493M in   5.046774s
``` | 
| | | 
| | 
| | 
| | 
| | 
| | | Follow up of #26764 and #35700.
And add test case for #35700. | 
| |\ \  
| |/  
|/| | Reintroduce support for overriding `has_secure_password` attributes | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | | In Rails 5.2.x calling `has_secure_password` would define attribute
readers and writers on the superclass of the model, which meant that you
could override these attributes in a model and call the superclass for
example:
```
class Dog < ApplicationRecord
  has_secure_password
  def password=(new_password)
    @password_set = new_password.present?
    super
  end
end
```
However this behaviour was broken in Rails 6 when the ability to
customise the name of the attribute was introduced [1] since they are no
longer being defined on the superclass you will now see the following
error:
```
NoMethodError:
super: no superclass method `password=' for #<Dog:0x00007ffbbc7ce290>
Did you mean?  password
```
In order to resolve this issue and retain support for setting a custom
attribute name we can define these attribute readers/writers in a module
and then ensure that the module is included in the inheritance chain.
[1] https://www.github.com/rails/rails/commit/86a48b4da3
    https://www.github.com/rails/rails/commit/9b63bf1dfd | 
| |\ \  
| | | 
| | | | Type cast falsy boolean symbols on boolean attribute as false | 
| | |/  
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| |   
| | | Before 34cc301, type casting by boolean attribute when querying is a
no-op, so finding by truthy boolean string (i.e.
`where(value: "true") # => value = 'true'`) didn't work as expected
(matches it to FALSE in MySQL #32624). By type casting is ensured, a
value on boolean attribute is always serialized to TRUE or FALSE.
In PostgreSQL, `where(value: :false) # => value = 'false'` was a valid
SQL, so 34cc301 is a regresson for PostgreSQL since all symbol values
are serialized as TRUE.
I'd say using `:false` is mostly a developer's mistake (user's input
basically comes as a string), but `:false` on boolean attribute is
serialized as TRUE is not a desirable behavior for anybody.
This allows falsy boolean symbols as false, i.e.
`klass.create(value: :false).value? # => false` and
`where(value: :false) # => value = FALSE`.
Fixes #35676. | 
| |/  
|   
|   
|   
|   
| | - I feel `i18n_customize_full_messages` explains the meaning of the
  config better.
- Followup of https://github.com/rails/rails/pull/32956 | 
| |\  
| | 
| | 
| | | v6.0.0.beta3 release | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | | * Update RAILS_VERSION
* Bundle
* rake update_versions
* rake changelog:header | 
| |/ |  | 
| | |  | 
| |\  
| | 
| | 
| | 
| | | kamipo/dont_allow_non_numeric_string_matches_to_zero
Don't allow `where` with non numeric string matches to 0 values | 
| | | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | 
| | | This is a follow-up of #35310.
Currently `Topic.find_by(id: "not-a-number")` matches to a `id = 0`
record. That is considered as silently leaking information.
If non numeric string is given to find by an integer column, it should
not be matched to any record.
Related #12793. | 
| |/  
|   
|   
|   
|   
|   
|   
|   
|   
|   
| | This reverts commit 52fddcc653458456f98b3683dffd781cf00b35fe.
52fddcc was to short-circuit `ensure_in_range` in `cast_value`. But that
caused a regression for empty string deserialization.
Since 7c6f393, `ensure_in_range` is moved into `serialize`. As 52fddcc
said, the absolute gain is quite small. So I've reverted that commit to
fix the regression. | 
| | 
| 
| 
| 
| 
| 
| 
| 
| | That is considered as silently leaking information.
If type casting doesn't return any actual value, it should not be
matched to any record.
Fixes #33624.
Closes #33946. |