| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|\
| |
| | |
Improve the performance of writing attributes
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Using a similar approach to 08576b94ad4f19dfc368619d7751e211d23dcad8,
this change adds a new internal `_write_attribute` method which bypasses
the code that checks for attribute aliases and custom primary keys.
We can use this method instead of `write_attribute` when we know that we
have the name of the actual column to be updated and not an alias.
This makes writing an attribute with `attribute=` about 18% faster.
Benchmark:
```
begin
require "bundler/inline"
rescue LoadError => e
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
raise e
end
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails"
gem "arel", github: "rails/arel"
gem "sqlite3"
gem "benchmark-ips"
end
require "active_record"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Schema.define do
create_table :posts, force: true do |t|
end
end
class Post < ActiveRecord::Base
end
post = Post.new(id: 1)
Benchmark.ips do |x|
x.report("attribute=") { post.id = post.id + 1 }
end
```
Before:
Warming up --------------------------------------
attribute= 25.889k i/100ms
Calculating -------------------------------------
attribute= 290.946k (± 3.1%) i/s - 1.476M in 5.077036s
After:
Warming up --------------------------------------
attribute= 30.056k i/100ms
Calculating -------------------------------------
attribute= 345.088k (± 4.8%) i/s - 1.743M in 5.064264s
|
|\ \
| |/
|/|
| |
| | |
kamipo/use_timestamp_attributes_for_update_in_model
Use `timestamp_attributes_for_update_in_model` rather than `timestamp_attributes_for_update`
|
| |
| |
| |
| | |
`timestamp_attributes_for_update`
|
|/
|
|
|
|
|
|
|
|
|
|
| |
* Allow a default value to be declared for class_attribute
* Convert to using class_attribute default rather than explicit setter
* Removed instance_accessor option by mistake
* False is a valid default value
* Documentation
|
|
|
|
|
|
| |
to class method
Actually these methods don't need instantiation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`timestamp_attributes_for_{create,update}` is defined as symbol but
always used as string with `to_s`. This allocates extra strings. To
avoid extra allocation, change the definitions from symbol to string.
```ruby
pp ObjectSpace::AllocationTracer.trace {
1_000.times { |i|
Post.create!
}
}
```
Before:
```
["~/rails/activerecord/lib/active_record/timestamp.rb", 121]=>[1002, 0, 750, 0, 1, 18528],
["~/rails/activerecord/lib/active_record/timestamp.rb", 105]=>[1002, 0, 750, 0, 1, 7720],
["~/rails/activerecord/lib/active_record/timestamp.rb", 101]=>[1002, 0, 750, 0, 1, 7720],
["~/rails/activerecord/lib/active_record/timestamp.rb", 109]=>[1002, 0, 750, 0, 1, 13896],
["~/rails/activerecord/lib/active_record/timestamp.rb", 61]=>[4008, 0, 3000, 0, 1, 30880],
```
After:
```
["~/rails/activerecord/lib/active_record/timestamp.rb", 120]=>[1000, 0, 756, 0, 1, 17184],
["~/rails/activerecord/lib/active_record/timestamp.rb", 104]=>[1000, 0, 756, 0, 1, 7160],
["~/rails/activerecord/lib/active_record/timestamp.rb", 100]=>[1000, 0, 756, 0, 1, 7160],
["~/rails/activerecord/lib/active_record/timestamp.rb", 108]=>[1000, 0, 756, 0, 1, 12888],
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
|
|
|
|
|
| |
[ci skip]
@sgrif can you review when you have time? Thanks!
|
| |
|
|
|
|
| |
timestamps. [#18202]
|
| |
|
|
|
|
|
|
| |
I've been trying to reduce the number of places that care about
`attributes`, and its existence. We have a method for this check, let's
use it instead.
|
|\
| |
| |
| |
| |
| |
| |
| |
| | |
greyblake/dont_write_timestamps_if_they_are_not_attributes
Write timestamps only if there are timestamps columns
Conflicts:
activerecord/CHANGELOG.md
|
| | |
|
| | |
|
| |
| |
| |
| | |
`[].max # => nil`
|
|/
|
|
|
|
| |
This is to ensure that they are not accidentally called by the app code.
They are renamed to _create_record and _update_record respectively.
Closes #11645
|
|
|
| |
Move serialization dirty into serialization.rb
|
| |
|
|
|
|
|
| |
Reuse the already existing logic used for grabbing this information from
the updated columns.
|
| |
|
|
|
|
|
| |
- Extract max timestamp retrieval for cache_key
- Update changelog for cache_key changes
|
| |
|
|
|
|
|
| |
These were removed with ActiveRecord::Model in
https://github.com/rails/rails/commit/9e4c41c903e8e58721f2c41776a8c60ddba7a0a9#L15L156
|
|
|
|
|
|
|
|
|
|
| |
In the end I think the pain of implementing this seamlessly was not
worth the gain provided.
The intention was that it would allow plain ruby objects that might not
live in your main application to be subclassed and have persistence
mixed in. But I've decided that the benefit of doing that is not worth
the amount of complexity that the implementation introduced.
|
|
|
|
| |
This reverts commit 83846838252397b3781eed165ca301e05db39293.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I think it's going to be too much pain to try to transition the
:active_record load hook from executing against Base to executing
against Model.
For example, after Model is included in Base, and modules included in
Model will no longer get added to the ancestors of Base.
So plugins which wish to be compatible with both Model and Base should
use the :active_record_model load hook which executes *before* Base gets
loaded.
In general, ActiveRecord::Model is an advanced feature at the moment and
probably most people will continue to inherit from ActiveRecord::Base
for the time being.
|
|
|
|
| |
This reflects the fact that it now impact inserts as well as updates.
|
|
|
|
| |
dup'ed object (call ActiveModel::Validations#initialize_dup). Closes #7291
|
| |
|
| |
|
|
|
|
|
| |
Get rid of ActiveModel::Configuration, make better use of
ActiveSupport::Concern + class_attribute, etc.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The problem: We need to be able to specify configuration in a way that
can be inherited to models that include ActiveRecord::Model. So it is
no longer sufficient to put 'top level' config on ActiveRecord::Base,
but we do want configuration specified on ActiveRecord::Base and
descendants to continue to work.
So we need something like class_attribute that can be defined on a
module but that is inherited when ActiveRecord::Model is included.
The solution: added ActiveModel::Configuration module which provides a
config_attribute macro. It's a bit specific hence I am not putting this
in Active Support or making it a 'public API' at present.
|
| |
|
|
|
|
|
|
|
|
|
| |
Previously we would just silently write the attribute. This can lead to
subtle bugs (for example, see the change in AutosaveAssociation where a
through association would wrongly gain an attribute.
Also, ensuring that we never gain any new attributes after
initialization will allow me to reduce our dependence on method_missing.
|
|
|
|
| |
(and this call to super is no essential, so easiest to simply remove)
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Change ActiveRecord::Base.xyz to config.active_record.xyz in docs.
Remove <tt> from code samples.
Update skip_time_zone_conversion_for_attributes code sample: put the call in the model class.
Clarify that skip_time_zone_conversion_for_attributes skips converion when reading.
|
|
|
|
| |
Signed-off-by: Santiago Pastorino <santiago@wyeworks.com>
|
|
|
|
| |
Signed-off-by: Santiago Pastorino <santiago@wyeworks.com>
|
| |
|
|
|
|
|
|
| |
inheritable has been changed to class_attribute. class inheritable attributes has been deprecated.
Signed-off-by: José Valim <jose.valim@gmail.com>
|
| |
|
|
|
|
| |
state:resolved]
|
|
|
|
| |
intrinsic to its implementation.
|