| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
* 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
|
| | | |
| | | |
| | | |
| | | | |
It is not a test case.
|
| | | | |
|
| | | | |
|
| | | | |
|
| | | | |
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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
|
| | | | |
|
| | | |
| | | |
| | | |
| | | | |
I believe that this was caused by a copy/paste mistake.
|
| |_|/
|/| |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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"]
```
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
`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]
```
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
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.
|
|\ \ \
| | | |
| | | | |
fix bug on added? method
|
| | | |
| | | |
| | | |
| | | | |
fix rubocop issues
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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`.
|
|/ / /
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Currently, executing the test with only `attribute_set_test.rb` results in an error.
```
./bin/test -w test/cases/attribute_set_test.rb
Run options: --seed 33470
# Running:
E
Error:
ActiveModel::AttributeSetTest#test_#map_returns_a_new_attribute_set_with_the_changes_applied:
NameError: uninitialized constant ActiveModel::AttributeSetTest::AttributeSet
Did you mean? ActiveModel::Attributes
ActiveModel::Attribute
activemodel/test/cases/attribute_set_test.rb:235:in `block in <class:AttributeSetTest>'
bin/test test/cases/attribute_set_test.rb:234
```
Added a missing require to fix this.
Also, I suspect that this is the cause of failures in CI.
Ref: https://travis-ci.org/rails/rails/jobs/299994708
|
| | |
| | |
| | |
| | |
| | | |
Use these to back the attributes API. Stop automatically including
ActiveModel::Dirty in ActiveModel::Attributes, and make it optional.
|
|\ \ \
| | | |
| | | |
| | | |
| | | | |
bogdanvlviv/test-if-unless-options-for-validations
Add cases to test combining validation conditions
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
- Test condition that is defined by array of conditions
- Test condition that is defined by combining :if and :unless
- Test local condition that is defined by :if
- Test local condition that is defined by :unless
See http://edgeguides.rubyonrails.org/active_record_validations.html#combining-validation-conditions
|
|/ / /
| | |
| | |
| | | |
`false`
|
| | |
| | |
| | |
| | |
| | | |
This brings the Length validator in line with the Numericality
validator, which currently supports Proc & Symbol arguments
|
|\ \ \
| | | |
| | | | |
Start bringing attributes API to AM
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
This is the first PR of a WIP to bring the attributes API to
ActiveModel. It is not yet ready for public API.
The `attributes_dirty_test.rb` file was created based on `dirty_test.rb`,
and the simplifications in the diff do much to motivate this change.
```
diff activemodel/test/cases/dirty_test.rb activemodel/test/cases/attributes_dirty_test.rb
3a4
> require "active_model/attributes"
5c6
< class DirtyTest < ActiveModel::TestCase
---
> class AttributesDirtyTest < ActiveModel::TestCase
7,41c8,12
< include ActiveModel::Dirty
< define_attribute_methods :name, :color, :size
<
< def initialize
< @name = nil
< @color = nil
< @size = nil
< end
<
< def name
< @name
< end
<
< def name=(val)
< name_will_change!
< @name = val
< end
<
< def color
< @color
< end
<
< def color=(val)
< color_will_change! unless val == @color
< @color = val
< end
<
< def size
< @size
< end
<
< def size=(val)
< attribute_will_change!(:size) unless val == @size
< @size = val
< end
---
> include ActiveModel::Model
> include ActiveModel::Attributes
> attribute :name, :string
> attribute :color, :string
> attribute :size, :integer
```
|
|/ / / |
|
|\ \ \
| | | |
| | | | |
Remove unused `Mutex_m` in Active Model
|
| | | |
| | | |
| | | |
| | | | |
Because `generated_attribute_methods` is an internal API.
|
|/ / / |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
ActiveModel::Errors#merge! allows ActiveModel::Errors to append errors from
a separate ActiveModel::Errors instance onto their own.
Example:
person = Person.new
person.errors.add(:name, :blank)
errors = ActiveModel::Errors.new(Person.new)
errors.add(:name, :invalid)
person.errors.merge!(errors)
puts person.errors.messages
# => { name: ["can't be blank", "is invalid"] }
|
| | |
| | |
| | |
| | |
| | | |
This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing
changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
|
|\ \ \
| | | |
| | | |
| | | | |
Enforce frozen string in Rubocop
|
| | | | |
|
|/ / /
| | |
| | |
| | | |
Includes two external changes because they're referenced within the ActiveModel test suite.
|
| | |
| | |
| | |
| | | |
\Z was a mistake of \z. Replace \Z to \z to prevent newly \Z added.
|
| | |
| | |
| | |
| | | |
[ci skip]
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
See 34321e4a433bb7eef48fd743286601403f8f7d82 for background on
ImmutableString vs String.
Our String type cannot delegate typecasting to ImmutableString, because
the latter freezes its input: duplicating the value after that gives us
an unfrozen result, but still mutates the originally passed object.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Before:
person.errors.keys # => []
person.errors.values # => []
person.errors[:name] # => []
person.errors.keys # => [:name]
person.errors.values # => [[]]
After:
person.errors.keys # => []
person.errors.values # => []
person.errors[:name] # => []
person.errors.keys # => []
person.errors.values # => []
Related to #23468
|
|\ \ \
| |/ /
|/| |
| | | |
Avoid converting integer as a string into float
|
| | | |
|
|/ /
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
In Ruby 2.4, BigDecimal(), as used by the Decimal cast, was changed so
that it will raise ArgumentError when passed an invalid string, in order
to be more consistent with Integer(), Float(), etc. The other numeric
types use ex. to_i and to_f.
Unfortunately, we can't simply change BigDecimal() to to_d. String#to_d
raises errors like BigDecimal(), unlike all the other to_* methods (this
should probably be filed as a ruby bug).
Instead, this simulates the existing behaviour and the behaviour of the
other to_* methods by finding a numeric string at the start of the
passed in value, and parsing that using BigDecimal().
See also
https://bugs.ruby-lang.org/issues/10286
https://github.com/ruby/bigdecimal/commit/3081a627cebdc1fc119425c7a9f009dbb6bec8e8
|
| | |
|
|\ \
| | |
| | |
| | |
| | | |
kamipo/remove_deprecated_passing_string_to_define_callback
Remove deprecated passing string to define callback
|
| | |
| | |
| | |
| | | |
`set_callback` and `skip_callback`
|
| | |
| | |
| | |
| | | |
And raise `ArgumentError` when passing string to define callback.
|
|/ /
| |
| |
| |
| |
| | |
`ActiveModel::TestCase` is used only for the test of Active Model.
Also, it is a private API and can not be used in applications.
Therefore, it is not necessary to include it in lib.
|
| |
| |
| |
| | |
we call them only in the tests
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
| |
| |
| |
| |
| |
| | |
If a Error object was serialized in the database as YAML in the Rails
4.2 version, if we load in the Rails 5.0 version it will miss the
@details instance variable so methods like #clear and #add will start to
fail.
|