| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
If a parent association was accessed in an `after_find` or
`after_initialize` callback, it would always end up loading the
association, and then immediately overwriting the association we just
loaded. If this occurred in a way that the parent's `current_scope` was
set to eager load the child, this would result in an infinite loop and
eventually overflow the stack.
For records that are created with `.new`, we have a mechanism to
perform an action before the callbacks are run. I've introduced the same
code path for records created with `instantiate`, and updated all code
which sets inverse instances on newly loaded associations to use this
block instead.
Fixes #26320.
|
| |
|
|
|
|
|
| |
The current code base is not uniform. After some discussion,
we have chosen to go with double quotes by default.
|
| |
|
|
|
|
|
|
| |
The current error message only indicates that a touch can fail because the record is new. In practice, we saw cases where touches were failing because the record had been destroyed. `persisted?` checks `new_record?` *and* `destroyed?`. It was confusing to get a message about a new record when in reality we were destroying records.
I also included a helpful tip for users to consider using `persisted?`, `new_record?`, or `destroyed?` before touching.
|
|
|
|
|
|
|
|
| |
See the end of [this] page.
[ci skip]
[this]: http://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create
|
|
|
|
|
|
|
|
|
|
|
| |
won't update a record if validation fails.
- Also fixed `update` method's documention to be uniform about this statement.
Fixes #20821
[ci skip]
[Vipul A M & pseidemann ]
|
|\
| |
| | |
Improvement in ActiveRecord::Persistence doc [ci skip]
|
| | |
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The problem was that when saving an object, we would
call touch_later on the parent which wont be saved immediteally, and
it wont call any callbacks. That was working one level up because
we were calling touch, during the touch_later commit phase. However that still
didnt solve the problem when you have a 3+ levels of parents to be touched,
as calling touch would affect the parent, but it would be too late to run callbacks
on its grand-parent.
The solution for this, is instead, call touch_later upwards when the first
touch_later is called. So we make sure all the timestamps are updated without relying
on callbacks.
This also removed the hard dependency BelongsTo builder had with the TouchLater module.
So we can still have the old behaviour if TouchLater module is not included.
[fixes 5f5e6d924973003c105feb711cefdb726f312768]
[related #19324]
|
| | |
|
|\ \
| |/
|/| |
Add example for AR::Persistence#toggle
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
|\ \
| | |
| | |
| | | |
Make AR#increment! and #decrement! concurrency-safe
|
| | | |
|
|/ /
| |
| |
| |
| | |
For reads, we never need to construct this object. The double `defined?`
check is to avoid errors in tests
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|