| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This bug occurs when an attribute of an ActiveRecord model is an
ActiveRecord::Type::Integer type or a ActiveRecord::Type::Decimal type (or any
other type that includes the ActiveRecord::Type::Numeric module. When the value
of the attribute is negative and is set to the same negative value, it is marked
as changed.
Take the following example of a Person model with the integer attribute age:
class Person < ActiveRecord::Base
# age :integer(4)
end
The following will produce the error:
person = Person.new(age: -1)
person.age = -1
person.changes
=> { "age" => [-1, -1] }
person.age_changed?
=> true
The problematic line is here:
module ActiveRecord
module Type
module Numeric
...
def non_numeric_string?(value)
# 'wibble'.to_i will give zero, we want to make sure
# that we aren't marking int zero to string zero as
# changed.
value.to_s !~ /\A\d+\.?\d*\z/
end
end
end
end
The regex match doesn't accept numbers with a leading '-'.
|
|
|
|
| |
Fixes #18122
|
| |
|
| |
|
|
|
|
|
| |
Thanks to @thedarkone for pointing out that an instance of this object
is used in a shared context.
|
| |
|
|
|
|
|
|
|
| |
It doesn't make sense for the subclass to implement this method, and not
have it on the parent. We can also DRY up the implementation of
`#lookup` to be defined in terms of fetch, which will give us a single
point of entry
|
|
|
|
| |
This reverts commit da99a2a2982d35f670ad9647463e09bfe9032b70.
|
|
|
|
|
|
|
|
| |
We don't have the check the range when the value is coming from the DB,
so override type_cast_from_database to short-circuit the extra work.
The difference is huge but the absolute gain is quite small. That being
said this is a hotspot and it showed up on the radar when benchmarking
discourse.
|
|
|
|
|
|
| |
This reverts commit 6f7910a and 52c70d4.
Query params are type cased through the same method, so this approach doesn't work.
|
|
|
|
| |
See comment on 6f7910a
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We don't have the check the range when the value is coming from the DB, so
override type_cast_from_database to short-circuit the extra work.
type_cast_from_database (small) 3437507.5 (±29.2%) i/s - 14223135 in 4.996973s
type_cast_from_database (large) 3158588.7 (±28.3%) i/s - 13265628 in 4.992121s
type_cast (small) 481984.8 (±14.2%) i/s - 2352012 in 5.005694s
type_cast (large) 477331.8 (±14.2%) i/s - 2332824 in 5.012365s
Comparison:
type_cast_from_database (small): 3437507.5 i/s
type_cast_from_database (large): 3158588.7 i/s - 1.09x slower
type_cast (small): 481984.8 i/s - 7.13x slower
type_cast (large): 477331.8 i/s - 7.20x slower
The difference is huge but the absolute gain is quite small. That being said
this is a hotspot and it showed up on the radar when benchmarking discourse.
|
| |
|
|
|
|
| |
There is a significant performance difference between the two. Closes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Why are people assigning booleans to string columns? >_>
We unintentionally changed the behavior on Sqlite3 and PostgreSQL.
Boolean values should cast to the database's representation of true and
false. This is 't' and 'f' by default, and "1" and "0" on Mysql. The
implementation to make the connection adapter specific behavior is hacky
at best, and should be re-visted once we decide how we actually want to
separate the concerns related to things that should change based on the
database adapter.
That said, this isn't something I'd expect to change based on my
database adapter. We're storing a string, so the way the database
represents a boolean should be irrelevant. It also seems strange for us
to give booleans special behavior at all in string columns. Why is
`to_s` not sufficient? It's inconsistent and confusing. Perhaps we
should consider deprecating in the future.
Fixes #17571
|
|
|
|
|
| |
We had accidentally gone one power of two too far. In addition, we need
to handle minimum values as well as the maximum.
|
|
|
|
|
|
|
|
|
|
|
| |
Sufficiently large integers cause `find` and `find_by` to raise
`StatementInvalid` instead of `RecordNotFound` or just returning `nil`.
Given that we can't cast to `nil` for `Integer` like we would with junk
data for other types, we raise a `RangeError` instead, and rescue in
places where it would be highly unexpected to get an exception from
casting.
Fixes #17380
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
In Rails 5.0, we'd like to change the behavior of boolean columns in
Rails to be closer to Ruby's semantics. Currently we have a small set
of values which are "truthy", and all others are "falsy". In Rails 5.0,
we will reverse this to have a small number of values which are "falsy",
and all others will become "truthy".
In the interim, all values which are ambiguous must emit a deprecation
warning.
|
| |
|
|
|
|
| |
Fixes #16701
|
|
|
|
|
| |
This was a small self contained piece of the refactoring that I am
working on, which required these objects to be comparable.
|
| |
|
|\
| |
| |
| |
| |
| |
| |
| |
| | |
joker1007/fix_decimal_cast_from_float_with_large_precision
Fix type casting to Decimal from Float with large precision
Conflicts:
activerecord/CHANGELOG.md
|
| |
| |
| |
| |
| | |
When I defines large precision column at RDBMS,
I assigns float value, raise ArgumentError (precision too large).
|
|/
|
|
| |
Ruby generally does not use the is_* prefix on predicate methods.
|
|
|
|
|
| |
One of the branches is using a proc to check if the value respond_to a
method so it is better to not do case comparations
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
| |
This was only used for uniqueness validations. The first usage was in
conjunction with `limit`. Types which cast to string, but are not
considered text cannot have a limit. The second case was only with an
explicit `:case_sensitive => true` option given by the user.
|
| |
|
| |
|
|\
| |
| |
| | |
Detect in-place modifications on Strings
|
| | |
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| | |
We previously only did this if the old value was zero, to make sure
numericality validations run and failed if the user gave 'wibble' as the
value, which would be type cast to 0. However, numericality validations
will fail if there are any non-numeric characters in the string, so 5 ->
'5wibble' should also be marked as changed.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Adding `# :nodoc:` to the parent `class` / `module` is not going
to ignore nested classes or modules.
There is a modifier `# :nodoc: all` but sadly the containing class
or module will continue to be in the docs.
/cc @sgrif
|
| | |
|
|/
|
|
|
|
|
| |
`Type::Integer.new.type_cast('') # => nil`, we do not need a special
case to handle this, `nil => ''` already returns false. The only case we
need to handle is `0 => 'wibble'` should be changed, while `0 => '0'`
should not.
|
|
|
|
|
|
|
|
|
| |
The case where we have a column object, but don't have a type cast
method involves type casting the default value when changing the schema.
We get one of the column definition structs instead. That is a case that
I'm trying to remove overall, but in the short term, we can achieve the
same behavior without needing to pass the adapter to the array type by
creating a fake type that proxies to the adapter.
|
| |
|
|
|
|
|
|
| |
We have several mutable types on Active Record now. (Serialized, JSON,
HStore). We need to be able to detect if these have been modified in
place.
|
|
|
|
|
| |
On MySQL and PostgreSQL, the adapter does not type cast virtual columns
for us.
|
|
|
|
|
|
|
|
| |
In some cases there is a difference between the two, we should always
be doing one or the other. For convenience, `type_cast` is still a
private method on type, so new types that do not need different behavior
don't need to implement two methods, but it has been moved to private so
it cannot be used accidentally.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- The following is now true for all types, all the time
- `model.attribute_before_type_cast == given_value`
- `model.attribute == model.save_and_reload.attribute`
- `model.attribute == model.dup.attribute`
- `model.attribute == YAML.load(YAML.dump(model)).attribute`
- Removes the remaining types implementing `type_cast_for_write`
- Simplifies the implementation of time zone aware attributes
- Brings tz aware attributes closer to being implemented as an attribute
decorator
- Adds additional point of control for custom types
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The definition of `write_attribute` in dirty checking ultimately leads
to the columns calling `type_cast` on the value to perform the
comparison. However, this is a potentially expensive computation that we
cache when it occurs in `read_attribute`. The only case that we need the
non-type-cast form is for numeric, so we pass that through as well
(something I'm looking to remove in the future).
This also reduces the number of places that manually access various
stages in an attribute's type casting lifecycle, which will aid in one
of the larger refactorings that I'm working on.
|
|
|
|
| |
Only `Date` and `Time` are handled.
|