aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
Commit message (Collapse)AuthorAgeFilesLines
* Merge pull request #32498 from eugeneius/mutation_tracker_merge_changesRyuta Kamizono2018-04-101-1/+1
|\ | | | | Prevent changes_to_save from mutating attributes
| * Prevent changes_to_save from mutating attributesEugene Kenny2018-04-081-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | When an array of hashes is added to a `HashWithIndifferentAccess`, the hashes are replaced with HWIAs by mutating the array in place. If an attribute's value is an array of hashes, `changes_to_save` will convert it to an array of HWIAs as a side-effect of adding it to the changes hash. Using `merge!` instead of `[]=` fixes the problem, as `merge!` copies any array values in the provided hash instead of mutating them.
* | Avoid generating full changes hash on every saveEugene Kenny2018-04-081-0/+8
|/ | | | | | | | | | `changed_attribute_names_to_save` is called in `keys_for_partial_write`, which is called on every save when partial writes are enabled. We can avoid generating the full changes hash by asking the mutation tracker for just the names of the changed attributes. At minimum this saves one array allocation per attribute, but will also avoid calling `Attribute#original_value` which is expensive for serialized attributes.
* Merge pull request #32220 from rails/fix-time-columns-on-sqlite3Andrew White2018-03-151-6/+2
|\ | | | | Time column improvements
| * Normalize date component when writing to time columnsAndrew White2018-03-111-5/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | For legacy reasons Rails stores time columns on sqlite as full timestamp strings. However because the date component wasn't being normalized this meant that when they were read back they were being prefixed with 2001-01-01 by ActiveModel::Type::Time. This had a twofold result - first it meant that the fast code path wasn't being used because the string was invalid and second it was corrupting the second fractional component being read by the Date._parse code path. Fix this by a combination of normalizing the timestamps on writing and also changing Active Model to be more lenient when detecting whether a string starts with a date component before creating the dummy time value for parsing.
| * Apply time column precision on assignmentAndrew White2018-03-111-1/+1
| | | | | | | | | | | | | | In #20317, datetime columns had their precision applied on assignment but that behaviour wasn't applied to time columns - this commit fixes that. Fixes #30301.
* | Remove changelog header for unreleased versionRafael Mendonça França2018-03-131-2/+0
|/ | | | | | We only add the header when releasing to avoid some conflicts. [ci skip]
* 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-062-43/+70
| | | | This reverts commit a19e91f0fab13cca61acdb1f33e27be2323b9786.
* Ruby 2.4: take advantage of String#unpack1Jeremy Daer2018-03-012-2/+2
| | | | | https://bugs.ruby-lang.org/issues/12752 https://ruby-doc.org/core-2.4.0/String.html#method-i-unpack1
* Remove CHANGELOG entries which were backported to 5-2-stableRyuta Kamizono2018-02-281-4/+0
|
* Alias `assign_attributes` to `attributes=` for `AttributeAssignment`Ryuta Kamizono2018-02-282-0/+10
| | | | There is no reason `attributes=` doesn't take `assign_attributes`.
* Merge pull request #31926 from composerinteralia/am-attributesRafael França2018-02-282-0/+24
|\ | | | | Add ActiveModel::Attributes#attributes
| * Add ActiveModel::Attributes#attributesDaniel Colson2018-02-072-0/+24
| | | | | | | | | | | | This starts to fix #31832. ActiveModel::Attributes includes ActiveModel::AttributeMethods, which requires an `#attributes` method that returns a hash with string keys.
* | Merge pull request #28270 from mmangino/dont_ignore_seralization_optionsRyuta Kamizono2018-02-273-1/+12
|\ \ | | | | | | | | | Don't accidentally lose includes in serialization
| * | Fix styleMike Mangino2017-03-031-1/+1
| | |
| * | Don't accidentally lose includes in serializationMike Mangino2017-03-033-4/+13
| | |
* | | Active Model: Use private attr_readerRyuta Kamizono2018-02-264-11/+6
| | | | | | | | | | | | Follow up of 6d63b5e49a399fe246afcebad45c3c962de268fa.
* | | PostgreSQL: Allow BC dates like datetime consistentlyRyuta Kamizono2018-02-231-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | BC dates are supported by both date and datetime types. https://www.postgresql.org/docs/current/static/datatype-datetime.html Since #1097, new datetime allows year zero as 1 BC, but new date does not. It should be allowed even in new date consistently.
* | | Rails 6 requires Ruby 2.4.1+Jeremy Daer2018-02-172-1/+6
| | | | | | | | | | | | | | | | | | Skipping over 2.4.0 to sidestep the `"symbol_from_string".to_sym.dup` bug. References #32028
* | | Rails 6 requires Ruby 2.3+Jeremy Daer2018-02-176-33/+7
| | |
* | | Remove usage of strip_heredoc in the framework in favor of <<~Rafael Mendonça França2018-02-161-2/+1
| | | | | | | | | | | | | | | Some places we can't remove because Ruby still don't have a method equivalent to strip_heredoc to be called in an already existent string.
* | | Remove support to Ruby 2.2Rafael Mendonça França2018-02-161-1/+1
| |/ |/| | | | | Rails 6 will only support Ruby >= 2.3.
* | PERF: Recover marshaling dump/load performance (#31827)Ryuta Kamizono2018-02-022-9/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * PERF: Recover marshaling dump/load performance This performance regression which is described in #30680 was caused by f0ddf87 due to force materialized `LazyAttributeHash`. Since 95b86e5, default proc has been removed in the class, so it is no longer needed that force materialized. Avoiding force materialized will recover marshaling dump/load performance. Benchmark: https://gist.github.com/blimmer/1360ea51cd3147bae8aeb7c6d09bff17 Before: ``` it took 0.6248569069430232 seconds to unmarshal the objects Total allocated: 38681544 bytes (530060 objects) allocated memory by class ----------------------------------- 12138848 Hash 10542384 String 7920000 ActiveModel::Attribute::Uninitialized 5600000 ActiveModel::Attribute::FromDatabase 1200000 Foo 880000 ActiveModel::LazyAttributeHash 400000 ActiveModel::AttributeSet 80 Integer 72 ActiveRecord::ConnectionAdapters::SQLite3Adapter::SQLite3Integer 40 ActiveModel::Type::String 40 ActiveRecord::Type::DateTime 40 Object 40 Range allocated objects by class ----------------------------------- 250052 String 110000 ActiveModel::Attribute::Uninitialized 70001 Hash 70000 ActiveModel::Attribute::FromDatabase 10000 ActiveModel::AttributeSet 10000 ActiveModel::LazyAttributeHash 10000 Foo 2 Integer 1 ActiveModel::Type::String 1 ActiveRecord::ConnectionAdapters::SQLite3Adapter::SQLite3Integer 1 ActiveRecord::Type::DateTime 1 Object 1 Range ``` After: ``` it took 0.1660824950085953 seconds to unmarshal the objects Total allocated: 13883811 bytes (220090 objects) allocated memory by class ----------------------------------- 5743371 String 4940008 Hash 1200000 Foo 880000 ActiveModel::LazyAttributeHash 720000 Array 400000 ActiveModel::AttributeSet 80 ActiveModel::Attribute::FromDatabase 80 Integer 72 ActiveRecord::ConnectionAdapters::SQLite3Adapter::SQLite3Integer 40 ActiveModel::Type::String 40 ActiveModel::Type::Value 40 ActiveRecord::Type::DateTime 40 Object 40 Range allocated objects by class ----------------------------------- 130077 String 50004 Hash 10000 ActiveModel::AttributeSet 10000 ActiveModel::LazyAttributeHash 10000 Array 10000 Foo 2 Integer 1 ActiveModel::Attribute::FromDatabase 1 ActiveModel::Type::String 1 ActiveModel::Type::Value 1 ActiveRecord::ConnectionAdapters::SQLite3Adapter::SQLite3Integer 1 ActiveRecord::Type::DateTime 1 Object 1 Range ``` Fixes #30680. * Keep the `@delegate_hash` to avoid to lose any mutations that have been made to the record
* | Start Rails 6.0 development!!!Rafael Mendonça França2018-01-302-68/+4
| | | | | | | | :tada::tada::tada:
* | Don't expose `attributes_with_uninitialized_key` utility methodRyuta Kamizono2018-01-301-5/+6
| | | | | | | | It is not a test case.
* | Use assert_empty and assert_not_emptyDaniel Colson2018-01-254-14/+14
| |
* | Use assert_predicate and assert_not_predicateDaniel Colson2018-01-2519-361/+361
| |
* | Change refute to assert_notDaniel Colson2018-01-251-3/+3
| |
* | Use respond_to test helpersDaniel Colson2018-01-254-21/+21
| |
* | Allow attributes with a proc default to be marshalledSean Griffin2018-01-233-0/+38
| | | | | | | | | | | | | | | | | | | | | | | | | | | | We don't implement much custom marshalling logic for these objects, but the proc default case needs to be handled separately. Unfortunately there's no way to just say "do what you would have done but with this value for one ivar", so we have to manually implement `marshal_load` as well. The test case is a little bit funky, but I'd really like an equality test in there, and there's no easy way to add one now that this is out of AR (since the `attributes` method isn't here) Fixes #31216
* | Use singular define_attribute_methodDaniel Colson2018-01-211-1/+1
| | | | | | | | | | | | | | | | `define_attribute_methods` splats the arguments, then calls out to `define_attribute_method` for each. When defining a singule attribute, using the singular version of the method saves us an array and an extra method call.
* | PERF: Recover `changes_applied` performance (#31698)Ryuta Kamizono2018-01-222-70/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | #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 ```
* | More exercise `ActiveModel::Dirty` testsRyuta Kamizono2018-01-201-3/+24
| |
* | Change test case name to FormatValidationTestPatrik Bóna2018-01-141-1/+1
| | | | | | | | I believe that this was caused by a copy/paste mistake.
* | `deep_dup` is used in `AttributeSet#deep_dup`Ryuta Kamizono2018-01-132-1/+1
| |
* | Merge pull request #29018 from willbryant/missing_attributes_after_saveRyuta Kamizono2018-01-031-0/+4
|\ \ | | | | | | | | | fix the dirty tracking code's save hook overwriting missing attribute…
* | | Refactor to `Array(options[:on])` only once in defining validationsRyuta Kamizono2018-01-012-11/+13
| | |
* | | Bump license years for 2018Yoshiyuki Hirano2017-12-312-2/+2
| | |
* | | Fix validation callbacks on multiple contextYoshiyuki Hirano2017-12-203-9/+60
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I found a bug that validation callbacks don't fire on multiple context. So I've fixed it. Example: ```ruby class Dog include ActiveModel::Validations include ActiveModel::Validations::Callbacks attr_accessor :history def initialize @history = [] end before_validation :set_before_validation_on_a, on: :a before_validation :set_before_validation_on_b, on: :b after_validation :set_after_validation_on_a, on: :a after_validation :set_after_validation_on_b, on: :b def set_before_validation_on_a; history << "before_validation on a"; end def set_before_validation_on_b; history << "before_validation on b"; end def set_after_validation_on_a; history << "after_validation on a" ; end def set_after_validation_on_b; history << "after_validation on b" ; end end ``` Before: ``` d = Dog.new d.valid?([:a, :b]) d.history # [] ``` After: ``` d = Dog.new d.valid?([:a, :b]) d.history # ["before_validation on a", "before_validation on b", "after_validation on a", "after_validation on b"] ```
* | | Suppress `warning: BigDecimal.new is deprecated` in Active ModelYasuo Honda2017-12-143-23/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `BigDecimal.new` has been deprecated in BigDecimal 1.3.3 which will be a default for Ruby 2.5. Refer ruby/bigdecimal@5337373 * This commit has been made as follows: ```ruby $ cd activemodel/ $ git grep -l BigDecimal.new | grep \.rb | xargs sed -i -e "s/BigDecimal.new/BigDecimal/g" ``` * This commit has been tested with these Ruby versions: ``` ruby 2.5.0dev (2017-12-15 trunk 61262) [x86_64-linux] ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux] ruby 2.3.5p376 (2017-09-14 revision 59905) [x86_64-linux] ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-linux] ```
* | | Fix doc typo [ci skip]Tom Copeland2017-12-121-1/+1
| | |
* | | Update validates.rbLonre Wang2017-12-101-1/+1
| | |
* | | Preparing for 5.2.0.beta2 releaseRafael Mendonça França2017-11-282-1/+6
| | |
* | | Fix typos and add a few suggestionsFatos Morina2017-11-281-2/+2
| | |
* | | Change how `AttributeSet::Builder` receives its defaultsSean Griffin2017-11-273-16/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There are two concerns which are both being combined into one here, but both have the same goal. There are certain attributes which we want to always consider initialized. Previously, they were handled separately. The primary key (which is assumed to be backed by a database column) needs to be initialized, because there is a ton of code in Active Record that assumes `foo.id` will never raise. Additionally, we want attributes which aren't backed by a database column to always be initialized, since we would never receive a database value for them. Ultimately these two concerns can be combined into one. The old implementation hid a lot of inherent complexity, and is hard to optimize from the outside. We can simplify things significantly by just passing in a hash. This has slightly different semantics from the old behavior, in that `Foo.select(:bar).first.id` will return the default value for the primary key, rather than `nil` unconditionally -- however, the default value is always `nil` in practice.
* | | Preparing for 5.2.0.beta1 releaseRafael Mendonça França2017-11-272-1/+3
| | |
* | | Merge pull request #31117 from renuo/fix_errors_addedRafael França2017-11-132-3/+14
|\ \ \ | | | | | | | | fix bug on added? method
| * | | fix bug on added? methodAlessandro Rodi2017-11-132-3/+14
| | | | | | | | | | | | | | | | fix rubocop issues
* | | | Add missing autoload `Type` (#31123)Ryuta Kamizono2017-11-1117-16/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Attribute modules (`Attribute`, `Attributes`, `AttributeSet`) uses `Type`, but referencing `Type` before the modules still fail. ``` % ./bin/test -w test/cases/attribute_test.rb -n test_with_value_from_user_validates_the_value Run options: -n test_with_value_from_user_validates_the_value --seed 31876 E Error: ActiveModel::AttributeTest#test_with_value_from_user_validates_the_value: NameError: uninitialized constant ActiveModel::AttributeTest::Type /Users/kamipo/src/github.com/rails/rails/activemodel/test/cases/attribute_test.rb:233:in `block in <class:AttributeTest>' bin/test test/cases/attribute_test.rb:232 Finished in 0.002985s, 335.0479 runs/s, 335.0479 assertions/s. 1 runs, 1 assertions, 0 failures, 1 errors, 0 skips ``` Probably we need more autoloading at least `Type`.