1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
Commit graph

8 commits

Author SHA1 Message Date
Xavier Noria
80e66cc4d9 normalizes indentation and whitespace across the project 2016-08-06 20:16:27 +02:00
Xavier Noria
4df2b779dd applies new string literal convention in activerecord/lib
The current code base is not uniform. After some discussion,
we have chosen to go with double quotes by default.
2016-08-06 18:26:45 +02:00
Sean Griffin
ba06dab545 Memoize user provided defaults before type casting
When a proc is given as a default value, the form builder ends up
displaying `Proc#to_s` when the default is used. That's because we
didn't handle the proc until type casting. This issue technically can
occur any time that a proc is the value before type casting, but in
reality the only place that will occur is when a proc default is
provided through the attributes API, so the best place to handle this
edge case is there.

I've opted to memoize instead of just moving the `Proc#call` up, as this
made me realize that it could potentially interact very poorly with
dirty checking.

The code here is a little redundant, but I don't want to rely on how
`value_before_type_cast` is implemented in the super class, even if it's
just an `attr_reader`.

Fixes #24249

Close #24306
2016-03-24 14:58:23 -06:00
Yves Senn
9d02a25d59 nodoc ActiveRecord::Attribute::UserProvidedDefault. [ci skip] 2015-10-13 13:24:07 +02:00
Sean Griffin
07723c23a7 Further encapsulate dirty checking on Attribute
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.
2015-10-02 08:03:11 -04:00
Sean Griffin
8e633e5058 Clean up the implementation of AR::Dirty
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
2015-09-24 14:06:59 -06:00
Sean Griffin
2f9d88954c Persist user provided default values, even if unchanged
This is a usability change to fix a quirk from our definition of partial
writes. By default, we only persist changed attributes. When creating a
new record, this is assumed that the default values came from the
database. However, if the user provided a default, it will not be
persisted, since we didn't see it as "changed". Since this is a very
specific case, I wanted to isolate it with the other quirks that come
from user provided default values. The number of edge cases which are
presenting themselves are starting to make me wonder if we should just
remove the ability to assign a default, in favor of overriding
`initialize`. For the time being, this is required for the attributes
API to not have confusing behavior.

We had to delete one test, since this actually changes the meaning of
`.changed?` on Active Record models. It now specifically means
`changed_from_database?`. While I think this will make the attributes
API more ergonomic to use, it is a subtle change in definition (though
not a backwards incompatible one). We should probably figure out the
right place to document this. (Feel free to open a PR doing that if
you're reading this).

/cc @rafaelfranca @kirs @senny

This is an alternate implementation of #19921.

Close #19921.

[Sean Griffin & Kir Shatrov]
2015-05-28 16:40:26 -06:00
Sean Griffin
a6e3cdae0c Allow proc defaults with the Attributes API
This is a variant implementation of the changes proposed in #19914.
Unlike that PR, the change in behavior is isolated in its own class.
This is to prevent wonky behavior if a Proc is assigned outside of the
default, and it is a natural place to place the behavior required by #19921
as well.

Close #19914.

[Sean Griffin & Kir Shatrov]
2015-05-28 16:26:49 -06:00