| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
| |
Actually, private methods cannot be called with `self.`, so it's not just redundant, it's a bad habit in Ruby
|
|\
| |
| | |
Add missing `emit_warning_if_needed` for `changed?`
|
| | |
|
|/ |
|
|
|
|
|
|
| |
Some methods were added to public API in
5b14129d8d4ad302b4e11df6bd5c7891b75f393c and they should be not part of
the public API.
|
| |
|
|
|
|
| |
- If aliased, then use the aliased attribute name.
|
|
|
|
|
| |
- If aliased, then use the aliased attribute name.
- Fixes #26417.
|
|
|
|
| |
I had pointed the messages at the new behavior, not the old.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
callbacks
We pretty frequently get bug reports that "dirty is broken inside of
after callbacks". Intuitively they are correct. You'd expect
`Model.after_save { puts changed? }; model.save` to do the same thing as
`model.save; puts model.changed?`, but it does not.
However, changing this goes much farther than just making the behavior
more intuitive. There are a _ton_ of places inside of AR that can be
drastically simplified with this change. Specifically, autosave
associations, timestamps, touch, counter cache, and just about anything
else in AR that works with callbacks have code to try to avoid "double
save" bugs which we will be able to flat out remove with this change.
We introduce two new sets of methods, both with names that are meant to
be more explicit than dirty. The first set maintains the old behavior,
and their names are meant to center that they are about changes that
occurred during the save that just happened. They are equivalent to
`previous_changes` when called outside of after callbacks, or once the
deprecation cycle moves.
The second set is the new behavior. Their names imply that they are
talking about changes from the database representation. The fact that
this is what we really care about became clear when looking at
`BelongsTo.touch_record` when tests were failing. I'm unsure that this
set of methods should be in the public API. Outside of after callbacks,
they are equivalent to the existing methods on dirty.
Dirty itself is not deprecated, nor are the methods inside of it. They
will only emit the warning when called inside of after callbacks. The
scope of this breakage is pretty large, but the migration path is
simple. Given how much this can improve our codebase, and considering
that it makes our API more intuitive, I think it's worth doing.
|
|
|
|
|
|
|
|
|
| |
delegation
Following off of https://github.com/rails/rails/issues/15945, I realized that super
needs to be the first thing that is called in an AbstractModel's inherited method.
I was receiving errors within the inherited method of time_zone_conversion, so I tested
locally by moving super to the top of the method declaration. All exceptions went away.
|
|
|
|
|
|
| |
This reverts commit 671eb742eec77b5c8281ac2a2e3976ef32a6e424.
This is not a change we would like moving forward.
|
|
|
|
|
|
|
|
| |
ActiveModel::Type)
Some code was previously referring to ActiveModel::Type::*. This could
cause issues in the future if any of the ActiveRecord::Type classes were
overridden in the future.
|
| |
|
|
|
|
|
|
| |
All indentation was normalized by rubocop auto-correct at 80e66cc4d90bf8c15d1a5f6e3152e90147f00772.
But comments was still kept absolute position. This commit aligns
comments with method definitions for consistency.
|
|
|
|
|
|
| |
All indentation was normalized by rubocop auto-correct at 80e66cc4d90bf8c15d1a5f6e3152e90147f00772.
But heredocs was still kept absolute position. This commit aligns
heredocs indentation for consistency.
|
|
|
|
|
|
|
|
|
| |
A few have been left for aesthetic reasons, but have made a pass
and removed most of them.
Note that if the method `foo` returns an array, `foo << 1`
is a regular push, nothing to do with assignments, so
no self required.
|
|
|
|
| |
Some case expressions remain, need to think about those ones.
|
| |
|
| |
|
|
|
|
|
| |
The current code base is not uniform. After some discussion,
we have chosen to go with double quotes by default.
|
|\
| |
| |
| |
| | |
kamipo/move_warning_about_composite_primary_key_to_attribute_methods_primary_key
Move the warning about composite primary key to `AttributeMethods::PrimaryKey`
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Actually schema dumper/creation supports composite primary key (#21614).
Therefore it should not show the warning about composite primary key in
connection adapter.
This change moves the warning to `AttributeMethods::PrimaryKey` and
suppress the warning for habtm join table.
Fixes #25388.
|
|/
|
|
| |
and invalid params
|
|
|
|
|
|
|
|
| |
Ruby 2.4 unifies Fixnum and Bignum into Integer: https://bugs.ruby-lang.org/issues/12005
* Forward compat with new unified Integer class in Ruby 2.4+.
* Backward compat with separate Fixnum/Bignum in Ruby 2.2 & 2.3.
* Drops needless Fixnum distinction in docs, preferring Integer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I have hit this deprecation in a newly created Rails 5 application and
the suggested tip lead me to a `NoMethodError`.
It's not trivial to actually make the following work, because of the
ActiveRecord::Base class attributes setting dance in the Active Record
railtie.
config.active_record.time_zone_aware_types << :time
Decided to suggest setting it explicitly to the values we need.
[ci skip]
|
|\
| |
| | |
Remove unused ReaderMethodCache and WriterMethodCache constants from ActiveRecord
|
| | |
|
| | |
|
| |
| |
| |
| | |
There was a typo in the variable name leading to infinite recursion
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We had previously updated this to attempt to map over whatever was
passed in, so that additional types like range and array could benefit
from this behavior without the time zone converter having to deal with
every known type.
However, the default behavior of a type is to just yield the given value
to `map`, which means that if we don't actually know how to handle a
value, we'll just recurse infinitely. Since both uses of `map` in this
case occur in cases where we know receiving the same object will
recurse, we can just break on reference equality.
Fixes #23241.
|
|
|
|
|
|
| |
This is really strange, as it passes on Travis for 2.3, and it passes
for me locally on 2.2. But on travis w/ 2.2, passing `Float::INFINITY`
in is resulting in an infinite loop. This should resolve it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is an alternate implementation to #22875, that generalizes a lot of
the logic that type decorators are going to need, in order to have them
work with arrays, ranges, etc. The types have the ability to map over a
value, with the default implementation being to just yield that given
value. Array and Range give more appropriate definitions.
This does not automatically make ranges time zone aware, as they need to
be added to the `time_zone_aware` types config, but we could certainly
make that change if we feel it is appropriate. I do think this would be
a breaking change however, and should at least have a deprecation cycle.
Closes #22875.
/cc @matthewd
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
```
# before
DEPRECATION WARNING: Time columns will become time zone aware in Rails 5.1. This
still causes `String`s to be parsed as if they were in `Time.zone`,
and `Time`s to be converted to `Time.zone`.
To keep the old behavior, you must add the following to your initializer:
config.active_record.time_zone_aware_types = [:datetime]
To silence this deprecation warning, add the following:
config.active_record.time_zone_aware_types << :time
```
```
# after
DEPRECATION WARNING: Time columns will become time zone aware in Rails 5.1. This
still causes `String`s to be parsed as if they were in `Time.zone`,
and `Time`s to be converted to `Time.zone`.
To keep the old behavior, you must add the following to your initializer:
config.active_record.time_zone_aware_types = [:datetime]
To silence this deprecation warning, add the following:
config.active_record.time_zone_aware_types << :time
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The focus of this change is to make the API more accessible.
References to method and classes should be linked to make it easy to
navigate around.
This patch makes exzessiv use of `rdoc-ref:` to provide more readable
docs. This makes it possible to document `ActiveRecord::Base#save` even
though the method is within a separate module
`ActiveRecord::Persistence`. The goal here is to bring the API closer to
the actual code that you would write.
This commit only deals with Active Record. The other gems will be
updated accordingly but in different commits. The pass through Active
Record is not completely finished yet. A follow up commit will change
the spots I haven't yet had the time to update.
/cc @fxn
|
|
|
|
| |
to reduce allocation of same object
|
|
|
|
|
| |
For reads, we never need to construct this object. The double `defined?`
check is to avoid errors in tests
|
|
|
|
|
| |
There were a few places where I missed a `create` vs `new`
before_type_cast check, and the semantics of `reload` became wrong.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We can skip the allocation of a full `AttributeSet` by changing the
semantics of how we structure things. Instead of comparing two separate
`AttributeSet` objects, and `Attribute` is now a singly linked list of
every change that has happened to it. Since the attribute objects are
immutable, to apply the changes we simply need to copy the head of the
list.
It's worth noting that this causes one subtle change in the behavior of
AR. When a record is saved successfully, the `before_type_cast` version
of everything will be what was sent to the database. I honestly think
these semantics make more sense, as we could have just as easily had the
DB do `RETURNING *` and updated the record with those if we had things
like timestamps implemented at the DB layer.
This brings our performance closer to 4.2, but we're still not quite
there.
|
|
|
|
|
|
|
|
|
|
|
| |
I'm looking to move towards a tree-like structure for dirty checking
that involves an attribute holding onto the attribute that it was
created from. This means that `changed?` can be fully encapsulated on
that object. Since the objects are immutable, in `changes_applied`, we
can simply perform a shallow dup, instead of a deep one.
I'm not sure if that will actually end up in a performance boost, but
I'd like to semantically separate these concepts regardless
|
|
|
|
|
|
|
|
|
|
|
| |
When a time object was assigned to a datetime column, the decorator for
TZ aware attributes wouldn't call super, so when using a database
without support for subsecond precision, the nanosecond would not be
truncated, leading to the value being marked as changed.
Interestingly, this also shows our new implementation of dirty checking
to be more robust than the old one (with less code and better
performance! :tada:!!!)
|
|
|
|
|
|
| |
When I removed the call to `super` to avoid the setting of
`@previous_changes`, I forgot to duplicate the other part of that
behavior, which led to failing tests
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The biggest source of the performance regression in these methods
occurred because dirty tracking required eagerly materializing and type
casting the assigned values. In the previous commits, I've changed dirty
tracking to perform the comparisons lazily. However, all of this is moot
when calling `save`, since `changes_applied` will be called, which just
ends up eagerly materializing everything, anyway. With the new mutation
tracker, it's easy to just compare the previous two hashes in the same
lazy fashion.
We will not have aliasing issues with this setup, which is proven by the
fact that we're able to detect nested mutation.
Before:
User.create! 2.007k (± 7.1%) i/s - 10.098k
After:
User.create! 2.557k (± 3.5%) i/s - 12.789k
Fixes #19859
|
|
|
|
|
|
|
|
|
| |
In order to improve the performance of dirty checking, we're going to
need to duplicate all of the `previous_` methods in Active Model.
However, these methods are basically the same as their non-previous
counterparts, but comparing `@original_attributes` to
`@previous_original_attributes` instead of `@attributes` and
`@original_attributes`. This will help reduce that duplication.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This moves a bit more of the logic required for dirty checking into the
attribute objects. I had hoped to remove the `with_value_from_database`
stuff, but unfortunately just calling `dup` on the attribute objects
isn't enough, since the values might contain deeply nested data
structures. I think this can be cleaned up further.
This makes most dirty checking become lazy, and reduces the number of
object allocations and amount of CPU time when assigning a value. This
opens the door (but doesn't quite finish) to improving the performance
of writes to a place comparable to 4.1
|
|
|
|
| |
The first step of bringing typecasting to ActiveModel
|
|\
| |
| | |
nodoc raw_write_attribute
|
| |
| |
| |
| |
| | |
Is this supposed to be public API? If so, I can document it instead.
:memo:
|