aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib/active_model/dirty.rb
Commit message (Collapse)AuthorAgeFilesLines
* PERF: 2x ~ 30x faster dirty trackingRyuta Kamizono2019-04-111-91/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently, although using both dirty tracking (ivar backed and attributes backed) on one model is not supported (doesn't fully work at least), both dirty tracking are being performed, that is very slow. As long as attributes backed dirty tracking is used, ivar backed dirty tracking should not need to be performed. I've refactored to extract new `ForcedMutationTracker` which only tracks `force_change` to be performed for ivar backed dirty tracking, that makes dirty tracking on Active Record 2x ~ 30x faster. https://gist.github.com/kamipo/971dfe0891f0fe1ec7db8ab31f016435 Before: ``` Warming up -------------------------------------- changed? 4.467k i/100ms changed 5.134k i/100ms changes 3.023k i/100ms changed_attributes 4.358k i/100ms title_change 3.185k i/100ms title_was 3.381k i/100ms Calculating ------------------------------------- changed? 42.197k (±28.5%) i/s - 187.614k in 5.050446s changed 50.481k (±16.0%) i/s - 246.432k in 5.045759s changes 30.799k (± 7.2%) i/s - 154.173k in 5.030765s changed_attributes 51.530k (±14.2%) i/s - 252.764k in 5.041106s title_change 44.667k (± 9.0%) i/s - 222.950k in 5.040646s title_was 44.635k (±16.6%) i/s - 216.384k in 5.051098s ``` After: ``` Warming up -------------------------------------- changed? 24.130k i/100ms changed 13.503k i/100ms changes 6.511k i/100ms changed_attributes 9.226k i/100ms title_change 48.221k i/100ms title_was 96.060k i/100ms Calculating ------------------------------------- changed? 245.478k (±16.1%) i/s - 1.182M in 5.015837s changed 157.641k (± 4.9%) i/s - 796.677k in 5.066734s changes 70.633k (± 5.7%) i/s - 358.105k in 5.086553s changed_attributes 95.155k (±13.6%) i/s - 470.526k in 5.082841s title_change 566.481k (± 3.5%) i/s - 2.845M in 5.028852s title_was 1.487M (± 3.9%) i/s - 7.493M in 5.046774s ```
* Re-add changes_applied docGannon McGibbon2018-11-161-1/+3
| | | | [ci skip]
* Fix grammar in changed? docs [ci skip]Alberto Almagro2018-10-281-1/+1
| | | | See https://english.stackexchange.com/questions/23218/anyone-has-or-anyone-have-seen-them
* Shorter code: remove unnecessary conditionclaudiob2018-07-051-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | See https://github.com/rails/rails/commit/136fc65c9b8b66e1fb56f3a17f0d1fddff9b4bd0#r28897107 I _think_ that this method can now be rewritten from: ```ruby def attribute_previous_change(attr) previous_changes[attr] if attribute_previously_changed?(attr) end ``` to: ```ruby def attribute_previous_change(attr) previous_changes[attr] end ``` without losing performance. --- Calling ```ruby previous_changes[attr] if attribute_previously_changed?(attr) ``` is equivalent to calling ```ruby previous_changes[attr] if previous_changes.include?(attr) ``` When this commit 136fc65c9b was made, Active Record had its own `previous_changes` method, added here below. However, that method has been recently removed from the codebase, so `previous_changes` is now only the method defined in Active Model as: ```ruby def previous_changes @previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new @previously_changed.merge(mutations_before_last_save.changes) end ``` Since we are dealing with a memoized Hash, there is probably no need to check `if .include?(attr_name)` before trying to fetch `[attr]` for it. Does that make sense? Did I miss anything? Thanks!
* Don't call changes in `changes_applied` unless requiredSean Griffin2018-03-061-1/+3
| | | | | | This is an alternate implementation of #31698. That PR makes assumptions that I do not want in the code base. We can fix the performance regression with a much simpler patch.
* Revert "PERF: Recover `changes_applied` performance (#31698)"Sean Griffin2018-03-061-39/+67
| | | | This reverts commit a19e91f0fab13cca61acdb1f33e27be2323b9786.
* PERF: Recover `changes_applied` performance (#31698)Ryuta Kamizono2018-01-221-67/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | #30985 caused `object.save` performance regression since calling `changes` in `changes_applied` is very slow. We don't need to call the expensive method in `changes_applied` as long as `@attributes` is tracked by mutation tracker. https://gist.github.com/kamipo/1a9f4f3891803b914fc72ede98268aa2 Before: ``` Warming up -------------------------------------- create_string_columns 73.000 i/100ms Calculating ------------------------------------- create_string_columns 722.256 (± 5.8%) i/s - 3.650k in 5.073031s ``` After: ``` Warming up -------------------------------------- create_string_columns 96.000 i/100ms Calculating ------------------------------------- create_string_columns 950.224 (± 7.7%) i/s - 4.800k in 5.084837s ```
* Fix "warning: instance variable @attributes not initialized"yuuji.yaginuma2017-11-101-2/+2
|
* Move Attribute and AttributeSet to ActiveModelLisa Ugray2017-11-091-56/+121
| | | | | Use these to back the attributes API. Stop automatically including ActiveModel::Dirty in ActiveModel::Attributes, and make it optional.
* Use frozen string literal in activemodel/Kir Shatrov2017-07-161-0/+2
|
* Revert "Merge pull request #29540 from kirs/rubocop-frozen-string"Matthew Draper2017-07-021-1/+0
| | | | | This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
* Enforce frozen string in RubocopKir Shatrov2017-07-011-0/+1
|
* Move around AR::Dirty and fix _attribute methodAaron Patterson2017-04-141-8/+4
| | | | | | We already have a _read_attribute method that can get the value we need from the model. Lets define that method in AM::Dirty and use the existing one from AR::Dirty rather than introducing a new method.
* Fix inconsistency with changed attributes when overriding AR attribute readerbogdanvlviv2017-04-121-4/+8
|
* Update ActiveModel::Dirty Doc [ci skip]Louis-Michel Couture2016-09-161-8/+8
|
* Update ActiveModel::Dirty Doc [ci skip]Louis-Michel Couture2016-09-151-1/+1
| | | Fix potentially misleading example.
* applies new string literal convention in activemodel/libXavier Noria2016-08-061-5/+5
| | | | | The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
* Fixed bug introduced in #24519. Makes build green againBogdan Gusiev2016-04-131-1/+1
|
* Use keyword arguments to cleanup without droping performanceBogdan Gusiev2016-04-131-8/+8
|
* prevent 'attribute_changed?' from returning nilSen-Zhang2016-04-111-1/+1
|
* set default parameter to nil to speed up attribute_changed?Lihan Li2016-04-111-3/+5
| | | | | | | | | | | Benchmark results: Warming up -------------------------------------- old code 32.176k i/100ms new code 34.837k i/100ms Calculating ------------------------------------- old code 1.595M (± 3.5%) i/s - 7.947M new code 1.942M (± 3.9%) i/s - 9.685M
* Merge pull request #22333 from harrykiselev/patch-3Yves Senn2015-11-211-1/+5
|\ | | | | | | [ci skip] Update dirty.rb: documentation fix.
| * Update dirty.rb: documentation fix.Harry V. Kiselev2015-11-191-1/+5
|/ | | ActiveModel::Dirty module documentation fix.
* Improve the performance of `save` and friendsSean Griffin2015-09-241-2/+2
| | | | | | | | | | | | | | | | | | | | | | 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
* minor rdoc syntax fix [ci skip]Gourav Tiwari2015-05-081-2/+2
|
* Add `ActiveModel::Dirty#[attr_name]_previously_changed?` andFernando Tapia Rico2015-04-211-2/+21
| | | | | | | | `ActiveModel::Dirty#[attr_name]_previous_change` to improve access to recorded changes after the model has been saved. It makes the dirty-attributes query methods consistent before and after saving.
* Merge branch 'master' of github.com:rails/docrailsVijay Dev2015-02-141-8/+9
|\
| * AM#Dirty doc fixesVipul A M2015-02-011-8/+9
| | | | | | | | | | | | - Grammar fixes - Add doc for changes_include? - implemntations => implementations
* | revises AM:Dirty example [Godfrey Chan & Xavier Noria]Xavier Noria2015-02-061-6/+2
| | | | | | | | | | | | | | | | | | | | The existing example seems somewhat forced: is it realistic to have a model that accepts state in its initializer but considers it has not been changed? By allowing state changes to happen only via accessors it seems more natural that new instances are considered to be unchanged (as they are in AR). [ci skip]
* | use parentheses here, for the beard of the Prophet! [ci skip]Xavier Noria2015-02-061-1/+1
| |
* | applies guidelines to dirty.rb [ci skip]Xavier Noria2015-02-061-11/+11
| |
* | Wrap method arguments with parentheses in docsCarlos Antonio da Silva2015-02-031-1/+1
| | | | | | | | As per Rails general coding conventions. Related to #18794 [ci skip]
* | Person class doesn't contain finder methods, hence usage of Person.find_by ↵Vipul A M2015-02-031-1/+5
| | | | | | | | | | | | | | is wrong. Added simple initialize and made use of Person.new instead of Person.find_by to clarify the docs. [ci skip]
* | Don't calculate in-place changes on attribute assignmentSean Griffin2015-01-181-0/+1
|/ | | | | | | | | | | When an attribute is assigned, we determine if it was already marked as changed so we can determine if we need to clear the changes, or mark it as changed. Since this only affects the `attributes_changed_by_setter` hash, in-place changes are irrelevant to this process. Since calculating in-place changes can be expensive, we can just skip it here. I also added a test for the only edge case I could think of that would be affected by this change.
* Remove unneeded requiresRafael Mendonça França2015-01-041-1/+0
| | | | These requires were added only to change deprecation message
* Remove deprecated `ActiveModel::Dirty#reset_#{attribute}` and ↵Rafael Mendonça França2015-01-041-20/+0
| | | | `ActiveModel::Dirty#reset_changes`.
* Merge branch 'master' of github.com:rails/docrailsVijay Dev2015-01-031-1/+1
|\
| * Use Active Model, not ActiveModel in plain Englishclaudiob2015-01-021-1/+1
| | | | | | | | | | | | | | Also prevents the word "Model" from linking to the documentation of ActiveModel::Model because that's not intended. [ci skip]
* | Don't calculate all in-place changes to determine if attribute_changed?Sean Griffin2014-12-221-1/+5
|/ | | | | | | | | Calling `changed_attributes` will ultimately check if every mutable attribute has changed in place. Since this gets called whenever an attribute is assigned, it's extremely slow. Instead, we can avoid this calculation until we actually need it. Fixes #18029
* add brackets around attribute_name_tiii2014-12-081-1/+1
| | | | | | since 'attr_name_will_change!' is not an actual method it should be clearer that you have to insert the attribute name as in line 104 [ci skip]
* [Enh] Changed the visibility of the ↵Daniele Di Bernardo2014-11-061-1/+1
| | | | | | | | | ActiveModel::Dirty#clear_attribute_changes method In Rails 4.2 it is impossible to define a custom default value for a model's attribute without making it appear as _changed?, especially when the model is first initialized. Making this method publicly visible will allow such a behaviour, without the need to use private APIs.
* edit pass over all warningsXavier Noria2014-10-281-2/+10
| | | | | | | | | | | | | | | This patch uniformizes warning messages. I used the most common style already present in the code base: * Capitalize the first word. * End the message with a full stop. * "Rails 5" instead of "Rails 5.0". * Backticks for method names and inline code. Also, converted a few long strings into the new heredoc convention.
* Don't expose these new APIs yet (added in 877ea78 / #16189)Godfrey Chan2014-08-161-14/+15
| | | | | | | WARNING: don't use them! They might change or go away between future beta/RC/ patch releases! Also added a CHANGELOG entry for this.
* Implement `_was` and `changes` for in-place mutations of AR attributesSean Griffin2014-08-161-3/+16
|
* Make restore_attributes publicRafael Mendonça França2014-07-171-5/+5
| | | | | | | Also make it accept a list of attributes to be changed. This will make possible to restore only a subset of the changed attributes. Closes #16203
* Deprecate `reset_#{attribute}` in favor of `restore_#{attribute}`.Rafael Mendonça França2014-07-151-4/+12
| | | | | | | | | These methods may cause confusion with the `reset_changes` that behaves differently of them. Also rename undo_changes to restore_changes to match this new set of methods.
* Deprecate ActiveModel::Dirty#reset_changes in favor of ↵Rafael Mendonça França2014-07-151-4/+12
| | | | | | | | | #clear_changes_information This method name is causing confusion with the `reset_#{attribute}` methods. While `reset_name` set the value of the name attribute for the previous value the `reset_changes` only discard the changes and previous changes.
* Rename rollback_changes to undo_changesRafael Mendonça França2014-06-301-3/+3
| | | | To avoid overload with database rollback
* Add CHANGELOG entry for #14861 and document private methods on the APIRafael Mendonça França2014-06-301-5/+5
|
* Merge pull request #14861 from igor04/dirty-rollbackRafael Mendonça França2014-06-301-0/+17
|\ | | | | | | Added rollback method to ActiveModel::Dirty