| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
| |
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Deep down in the association internals, we're calling `destroy!` rather
than `destroy` when handling things like `dependent` or autosave
association callbacks. Unfortunately, due to the structure of the code
(e.g. it uses callbacks for everything), it's nearly impossible to pass
whether to call `destroy` or `destroy!` down to where we actually need
it.
As such, we have to do some legwork to handle this. Since the callbacks
are what actually raise the exception, we need to rescue it in
`ActiveRecord::Callbacks`, rather than `ActiveRecord::Persistence` where
it matters. (As an aside, if this code wasn't so callback heavy, it
would handling this would likely be as simple as changing `destroy` to
call `destroy!` instead of the other way around).
Since we don't want to lose the exception when `destroy!` is called (in
particular, we don't want the value of the `record` field to change to
the parent class), we have to do some additional legwork to hold onto it
where we can use it.
Again, all of this is ugly and there is definitely a better way to do
this. However, barring a much more significant re-architecting for what
I consider to be a reletively minor improvement, I'm willing to take
this small hit to the flow of this code (begrudgingly).
|
| |
|
|\
| |
| |
| | |
Cause ActiveRecord::Base::reload to also ignore the QueryCache.
|
| | |
|
| |
| |
| |
| |
| |
| |
| | |
When `AR::Base.save!` or `AR::Base.destroy!` is called and an exception
is raised, the exception doesn't have any error message or has a weird
message like `#<FailedBulb:0x0000000907b4b8>`. Give a better message so
we can easily understand why it's failing to save/destroy.
|
| | |
|
|\ \
| |/
|/|
| | |
Add note about sti column value to becomes method [ci skip]
|
|/ |
|
|
|
|
|
|
|
|
|
| |
This will avoid the indirection of having calling id since we already
know which is the primary key column.
Also this will make explicit the behavior since it is not clear that id
gets the right primary key value and not just the value of the "id"
column.
|
|
|
|
|
|
|
|
|
|
| |
Fixes #19776
change test variable names and use more verbose on method
less verbose
use _read_attribute instead of send
|
|
|
|
|
|
|
|
|
|
| |
[fixes #18606]
Make belongs_to use touch over touch_later when running the callbacks.
Add more tests and small method rename
Thanks Jeremy for the feedback.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
directly
calling `sync_with_transaction_state` is not fast, so if we call it
once, we can improve the performance of the `persisted?` method. This
is important because every call to `url_for(model)` will call
`persisted?`, so we want that to be fast.
Here is the benchmark:
```ruby
require 'active_record'
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
ActiveRecord::Base.connection.instance_eval do
create_table(:articles)
end
class Article < ActiveRecord::Base; end
article = Article.new.tap(&:save!)
Benchmark.ips do |x|
x.report("persisted?") do
article.persisted?
end
end
```
Before this patch:
```
$ bundle exec ruby -rbenchmark/ips persisted.rb
Calculating -------------------------------------
persisted? 3.333k i/100ms
-------------------------------------------------
persisted? 51.037k (± 8.2%) i/s - 253.308k
```
After:
```
$ bundle exec ruby -rbenchmark/ips persisted.rb
Calculating -------------------------------------
persisted? 7.172k i/100ms
-------------------------------------------------
persisted? 120.730k (± 5.1%) i/s - 602.448k
```
|
|\
| |
| |
| | |
Isolate access to @associations_cache and @aggregations_cache to the Associations and Aggregations modules, respectively.
|
| |
| |
| |
| |
| |
| |
| |
| | |
Associations and Aggregations modules, respectively.
This includes replacing the `association_cache` accessor with a more
limited `association_cached?` accessor and making `clear_association_cache`
and `clear_aggregation_cache` private.
|
|\ \
| | |
| | |
| | | |
Always reset changed attributes in becomes
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
When ```becomes``` changes @attributes it should also change
@changed_attributes. Otherwise we'll experience a kind of split head situation
where attributes are coming from ```self```, but changed_attributes is coming
from ```klass.new```. This affects the inheritance_colmn as it's changed by new
for example.
Fixes #16881
|
|/ /
| |
| |
| |
| |
| | |
Fixes #18905. `#touch` now takes time as an option. Setting the option
saves the record with the updated_at/on attributes set to the current time
or the time specified. Updated tests and documentation accordingly.
|
| | |
|
| | |
|
| |
| |
| |
| |
| | |
- This is based on https://github.com/rails/rails/issues/18400 but
tackling same issue with update_attribute method instead of update method.
|
| |
| |
| |
| |
| |
| | |
Building the Arel AST, and manipulating the relation manually like this
is prone to errors and breakage as implementation details change from
underneath it.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Before this commit, returning `false` in an ActiveRecord `before_` callback
such as `before_create` would halt the callback chain.
After this commit, the behavior is deprecated: will still work until
the next release of Rails but will also display a deprecation warning.
The preferred way to halt a callback chain is to explicitly `throw(:abort)`.
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
ActiveRecord::Base `save` and `save!` take an option boolean
`:touch` parameter since #18225 (stems from #18202).
This commit document that parameter.
[ci skip]
|
| |
| |
| |
| | |
timestamps. [#18202]
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| | |
[ci skip]
This is due to the fact that `.delete` is directly translated to SQL.
It tries to follow the same rules as `.delete_all` which is not able
to verify that records are `#readonly?`.
|
| |
| |
| |
| |
| |
| | |
Since 3e30c5d, it started ignoring the given error message. This commit
changes the behavior of AR::RecordNotSaved#initialize so that it no
longer loses the given error message.
|
| |
| |
| |
| | |
This allows these exceptions to be handled generically in conjunction with RecordInvalid.
|
| |
| |
| |
| | |
Oh hey, we got to remove some code because of that!
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
This reverts commit 8fee923888192a658d8823b31e77ed0683dfd665.
Conflicts:
activerecord/lib/active_record/attribute_set/builder.rb
This solution sucks, and is hard to actually apply across the board.
Going to try other solutions
|
| |
| |
| |
| |
| |
| |
| | |
Currently, there is no messages which get printed out. Convoluted system
may have hooks that create other objects in which case we only fail with
no messages. This commit changes this information allowing you to know
which object is the one that actually raised the error.
|
|/
|
|
|
|
|
| |
We introduced a performance hit by adding an additional iteration
through a model's attributes on creation. We don't actually need the
values from `Result` to be a hash, we can separate the columns and
values and zip them up ourself during the iteration that we have to do.
|
| |
|
| |
|
|
|
|
|
|
| |
`#create!` regarding validations in contrast to the behavior of
`#create`. Also describe creating multiple objects using an array of
hashes as the +attributes+ parameter. [ci skip] /cc #16384
|
|
|
|
| |
for rdoc
|
| |
|
| |
|
|
|
|
| |
This was used more previously, but other uses have been removed.
|
|
|
|
|
|
| |
`reload` is meant to put a record in the same state it would be if you
were to do `Post.find(post.id)`. This means we should fully replace the
attributes hash.
|
|
|
|
|
| |
Mostly delegation to start, but we can start moving a lot of behavior in
bulk to this object.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
There's a lot more that can be moved to these, but this felt like a good
place to introduce the object. Plans are:
- Remove all knowledge of type casting from the columns, beyond a
reference to the cast_type
- Move type_cast_for_database to these objects
- Potentially make them mutable, introduce a state machine, and have
dirty checking handled here as well
- Move `attribute`, `decorate_attribute`, and anything else that
modifies types to mess with this object, not the columns hash
- Introduce a collection object to manage these, reduce allocations, and
not require serializing the types
|
|
|
|
|
|
|
| |
We never want result types to override column types, and
`decorate_columns` can only affect column types. No need to go through
the decoration multiple times, we can just exclude the column types from
the result types instead.
|
|
|
|
|
| |
Reduces the number of things outside of attribute methods that cares
about the details of how we store and type cast attributes
|
|
|
|
|
| |
`@raw_attributes` should not contain the type-cast, mutable version of
the value.
|
| |
|
|
|
|
|
|
|
|
|
| |
`@attributes` was actually used for `_before_type_cast` and friends,
while `@attributes_cache` is the type cast version (and caching is the
wrong word there, but I'm working on removing the conditionals around
that). I opted for `@raw_attributes`, because `_before_type_cast` is
also semantically misleading. The values in said hash are in the state
given by the form builder or database, so raw seemed to be a good word.
|