- Pass object to I18n helper so that when calling message proc, it will
pass that object as argument to the proc and we can generate custom
error messages based on current record being validated.
- Based on https://github.com/rails/rails/issues/856.
[Łukasz Bandzarewicz, Prathamesh Sonpatki]
Since precision is always larger than scale, it can actually change
rounding behavior. Given a precision of 5 and a scale of 3, when you
apply the precision of 5 to `1.25047`, the result is `1.2505`, which
when the scale is applied would be `1.251` instead of the expected
`1.250`.
This issue appears to only occur with floats, as scale doesn't apply to
other numeric types, and the bigdecimal constructor actually ignores
precision entirely when working with strings. There's no way we could
handle this for the "unknown object which responds to `to_d`" case, as
we can't assume an interface for applying the scale.
Fixes#24235
From: https://github.com/rails/rails/issues/24279
Problem:
By doing `record.errors.include? :foo`, it adds a new key to the
@messages hash that defaults to an empty array.
This happens because of a combination of these 2 commits:
b97035df64
(Added in Rails 4.1)
and
6ec8ba16d8 (diff-fdcf8b65b5fb954372c6fe1ddf284c78R76)
(Rails 5.0)
By adding the default proc that returns an array for non-existing keys,
ruby adds that key to the hash.
Solution:
Change `#include?` to check with `has_key?` and then check if that value is
`present?`.
Add test case for ActiveModels::Errors#include?
Ok, this explains why the branch showed as green. We don't run files in
isolation for PRs, only for master. Active Support monkeypatches
`BigDecimal#to_s`, so the generated error message was different
depending on if the file was run in isolation
The error message when asserting `greater_than: BigDecimal.new` will
give an error message based on how BigDecimal displays itself. Big
decimal appears to always use scientific notation. This might not be the
best error message for the general case, but the general case wouldn't
use big decimal for the validation. And if they do, they likely need
this level of precision.
This type adds an escape hatch to apps for which string duping causes
unacceptable memory growth. The reason we are duping them is in order to
detect mutation, which was a feature added to 4.2 in #15674. The string
type was modified to support this behavior in #15788.
Memory growth is really only a concern for string types, as it's the
only mutable type where the act of coersion does not create a new object
regardless (as we're usually returning an object of a different class).
I do feel strongly that if we are going to support detecting mutation,
we should do it universally for any type which is mutable. While it is
less common and ideomatic to mutate strings than arrays or hashes, there
shouldn't be rules or gotchas to understanding our behavior.
However, I also appreciate that for apps which are using a lot of string
columns, this would increase the number of allocations by a large
factor. To ensure that we keep our contract, if you'd like to opt out of
mutation detection on strings, you'll also be option out of mutation of
those strings.
I'm not completely married to the thought that strings coming out of
this actually need to be frozen -- and I think the name is correct
either way, as the purpose of this is to provide a string type which
does not detect mutation.
In the new implementation, I'm only overriding `cast_value`. I did not
port over the duping in `serialize`. I cannot think of a reason we'd
need to dup the string there, and the tests pass without it.
Unfortunately that line was introduced at a time where I was not nearly
as good about writing my commit messages, so I have no context as to
why I added it. Thanks past Sean. You are a jerk.
Any tests for a type which is not overridden by Active Record, and does
not test the specifics of the attributes API interacting in more complex
ways have no reason to be in the Active Record suite. Doing this
revealed that the implementation of the date and time types in AM was
actually completely broken, and incapable of returning any value other
than `nil`.
Things like decorations, overrides, and priorities only matter for
Active Record, so the Active Model registry can be implemented much more
simply. At this point, I wonder if having Active Record's registry
inherit from Active Model's is even worth the trouble?
The Active Model class was also missing test cases, which have been
backfilled.
This removes the error when two types are registered with the same name,
but given that Active Model is meant to be significantly more generic, I
do not think this is an issue for now. If we want, we can raise an error
at the point that someone tries to register it.
Example:
```ruby
class Person
include ActiveModel::Validations
attr_reader :name, :title
validates_presence_of :name, on: :create
validates_presence_of :title, on: :update
end
person = Person.new
person.valid?([:create, :update]) # => true
person.errors.messages # => {:name=>["can't be blank"], :title=>["can't be blank"]}
```
This reverts commit 51dd2588433457960cca592d5b5dac6e0537feac, reversing
changes made to ecb4e4b21b3222b823fa24d4a0598b1f2f63ecfb.
This broke Active Record tests
Example:
```ruby
class Person
include ActiveModel::Validations
attr_reader :name, :title
validates_presence_of :name, on: :create
validates_presence_of :title, on: :update
end
person = Person.new
person.valid?([:create, :update]) # => true
person.errors.messages # => {:name=>["can't be blank"], :title=>["can't be blank"]}
```
This fixes the issue where you may be comparing (using a numeric
validator such as `greater_than`) numbers of a specific Numeric type
such as `BigDecimal`.
Previous behavior took the numeric value to be validated and
unconditionally converted to Float. For example, due to floating point
precision, this can cause issues when comparing a Float to a BigDecimal.
Consider the following:
```
validates :sub_total, numericality: {
greater_than: BigDecimal('97.18')
}
```
If the `:sub_total` value BigDecimal.new('97.18') was validated against
the above, the following would be valid since `:sub_total` is converted
to a Float regardless of its original type. The result therefore becomes
Kernel.Float(97.18) > BigDecimal.new('97.18')
The above illustrated behavior is corrected with this patch by
conditionally converting the value to validate to float.
Use the post-type-cast version of the attribute to validate numericality
[Roque Pinel & Trevor Wistaff]
The test was skipped because of an issue that, in the meantime,
has been fixed: https://github.com/rubinius/rubinius/issues/3328.
Using the latest Rubinius (the one currently on Travis CI), this
is the result:
```sh
$ ruby --version
rubinius 2.5.3 (2.1.0 2482b093 2015-05-10 3.5.1 JI) [x86_64-darwin14.3.0]
```
**Before this PR**
```sh
$ ruby -Itest test/cases/attribute_assignment_test.rb
Run options: --seed 58569
.....S...
Finished in 0.048278s, 186.4203 runs/s, 269.2738 assertions/s.
9 runs, 13 assertions, 0 failures, 0 errors, 1 skips
You have skipped tests. Run with --verbose for details.
```
**After this PR**
$ ruby -Itest test/cases/attribute_assignment_test.rb
Run options: --seed 35720
.........
Finished in 0.029441s, 305.6961 runs/s, 475.5273 assertions/s.
9 runs, 14 assertions, 0 failures, 0 errors, 0 skips
```
`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.
As demonstrated by #19570, this option is severely limited, and
satisfies an extremely specific use case. Realistically, there's not
much reason for this option to exist. Its functionality can be trivially
replicated with a normal Ruby method. Let's deprecate this option, in
favor of the simpler solution.
Rails 5.0 changes to ActiveModel::Errors include addition of `details`
that also accidentally changed the return value of `delete`. Since
there was no test for that behavior it went unnoticed. This commit
adds a test and fixes the regression.
Small improvements to comments have also been made. Since `get` is
getting deprecated it is better to use `[]` in other methods' code
examples. Also, in the module usage example, `def Person.method`
was replaced with a more commonly used `def self.method` code style.