Commit Graph

2664 Commits

Author SHA1 Message Date
Jonathan Hefner
9dbf7a58a2 Fix formatting of parameters doc [ci-skip] 2022-02-21 11:11:11 -06:00
Jonathan Hefner
e37adfed4e Add Oxford commas [ci-skip] 2022-02-21 11:11:11 -06:00
Jonathan Hefner
0d3effc97e Replace "overwrite" with "override" [ci-skip]
"Overwrite" means "destructively replace", and is more suitable when,
for example, talking about writing data to a location.

"Override" means "supersede", and is more suitable when, for example,
talking about redifining methods in a subclass.
2022-02-21 11:11:11 -06:00
Jonathan Hefner
5fdbd217d1 Fix typos [ci-skip] 2022-02-21 11:11:11 -06:00
Usman
3324cbdff5 Update ActiveModel::Attributes examples in docs 2022-02-11 01:19:49 +05:00
Jonathan Hefner
61468079b6
Merge pull request #44306 from volmer/attributes-docs
Documentation for Active Model Attributes [ci-skip]
2022-02-09 14:33:09 -06:00
Volmer Campos Soares
07a5584999 Documentation for Active Model Attributes
This commit adds documentation to the constants and methods that are
part of Active Model's Attributes API. So far this API has been hidden
with the :nodoc: flag since its inception in Active Record and
subsequent move to Active Model (#30920 and #30985); as the API matures
and gets ready for public usage, visible documentation for its endpoints
becomes necessary.

The classes and modules being documented and publicized by this commit
are the main `Attributes` module, the `Type` namespace, and all the
standard attribute type classes included in the current API, which users
will be able to extend and replicate to suit their customization needs.

Some private modules are also receiving documetation, although they will
continue using the :nodoc: flag. Those are `Attribute` and
`AttributeSet`. Although they remain private I found useful to add some
comments to describe their responsibilities.
2022-02-09 14:17:18 -05:00
Chris Salzberg
fd415ef98d Rename target -> proxy_target 2022-02-09 10:55:10 +09:00
Chris Salzberg
251445601e Rename AttributeMethodMatcher to AttributeMethodPattern 2022-02-09 10:41:02 +09:00
David Heinemeier Hansson
41478f7074 Make #to_fs the default replacement for #to_s(:format)
#to_formatted_s is too cumbersome.
2022-02-07 12:41:21 +01:00
Ryuta Kamizono
ed4d81caf7
Merge pull request #44299 from jonathanhefner/model_name-human-performance
Improve `ActiveModel::Name#human` performance
2022-02-04 07:58:17 +09:00
Chris Salzberg
81519dec1a Use different namespace for proxy calls 2022-02-03 10:10:07 +01:00
Jonathan Hefner
acbc39b663 Improve human_attribute_name performance
This reduces allocations and improves performance by ~35% when a
translation is defined and ~50% when a translation is not defined.

Benchmark script:

```ruby
require "benchmark/memory"
require "benchmark/ips"

class BaseModel
  extend ActiveModel::Translation
end

Person = Class.new(BaseModel)

module A
  Person = Class.new(BaseModel)

  module B
    Person = Class.new(BaseModel)
  end
end

I18n.backend.store_translations "en",
  activemodel: { attributes: { person: { has_translation: "translated" } } }

Benchmark.memory do |x|
  x.report("warmup") do
    Person.human_attribute_name("first_name")
    A::Person.human_attribute_name("first_name")
    A::B::Person.human_attribute_name("first_name")
    Person.human_attribute_name("has_translation")
  end

  x.report("no namespace") { Person.human_attribute_name("first_name") }
  x.report("1 namespace")  { A::Person.human_attribute_name("first_name") }
  x.report("2 namespaces") { A::B::Person.human_attribute_name("first_name") }

  x.report("has translation") { Person.human_attribute_name("has_translation") }
end

Benchmark.ips do |x|
  x.report("no namespace") { Person.human_attribute_name("first_name") }
  x.report("1 namespace")  { A::Person.human_attribute_name("first_name") }
  x.report("2 namespaces") { A::B::Person.human_attribute_name("first_name") }

  x.report("has translation") { Person.human_attribute_name("has_translation") }
end
```

Before:

```
Calculating -------------------------------------
              warmup   988.923k memsize (    24.587k retained)
                         2.441k objects (   339.000  retained)
                        50.000  strings (    50.000  retained)
        no namespace     6.416k memsize (     0.000  retained)
                        58.000  objects (     0.000  retained)
                        18.000  strings (     0.000  retained)
         1 namespace     6.416k memsize (     0.000  retained)
                        58.000  objects (     0.000  retained)
                        18.000  strings (     0.000  retained)
        2 namespaces     6.416k memsize (     0.000  retained)
                        58.000  objects (     0.000  retained)
                        18.000  strings (     0.000  retained)
     has translation     4.501k memsize (     0.000  retained)
                        46.000  objects (     0.000  retained)
                        18.000  strings (     0.000  retained)

Warming up --------------------------------------
        no namespace   567.000  i/100ms
         1 namespace   563.000  i/100ms
        2 namespaces   565.000  i/100ms
     has translation   839.000  i/100ms
Calculating -------------------------------------
        no namespace      5.642k (± 0.9%) i/s -     28.350k in   5.025255s
         1 namespace      5.652k (± 0.9%) i/s -     28.713k in   5.080325s
        2 namespaces      5.662k (± 1.1%) i/s -     28.815k in   5.090226s
     has translation      8.391k (± 1.6%) i/s -     42.789k in   5.100484s
```

After:

```
Calculating -------------------------------------
              warmup   982.803k memsize (    24.587k retained)
                         2.385k objects (   339.000  retained)
                        50.000  strings (    50.000  retained)
        no namespace     4.712k memsize (     0.000  retained)
                        44.000  objects (     0.000  retained)
                        13.000  strings (     0.000  retained)
         1 namespace     4.712k memsize (     0.000  retained)
                        44.000  objects (     0.000  retained)
                        12.000  strings (     0.000  retained)
        2 namespaces     4.712k memsize (     0.000  retained)
                        44.000  objects (     0.000  retained)
                        12.000  strings (     0.000  retained)
     has translation     3.493k memsize (     0.000  retained)
                        32.000  objects (     0.000  retained)
                        11.000  strings (     0.000  retained)

Warming up --------------------------------------
        no namespace   850.000  i/100ms
         1 namespace   846.000  i/100ms
        2 namespaces   842.000  i/100ms
     has translation     1.127k i/100ms
Calculating -------------------------------------
        no namespace      8.389k (± 0.9%) i/s -     42.500k in   5.066296s
         1 namespace      8.412k (± 0.6%) i/s -     42.300k in   5.028401s
        2 namespaces      8.423k (± 0.6%) i/s -     42.942k in   5.098322s
     has translation     11.303k (± 1.1%) i/s -     57.477k in   5.085568s
```
2022-02-02 11:50:29 -06:00
Jonathan Hefner
b2f49f27ad Improve ActiveModel::Name#human performance
This refactors `ActiveModel::Name#human` to reduce allocations and
improve performance by ~2x when a translation is not defined.

Benchmark script:

```ruby
require "benchmark/memory"
require "benchmark/ips"

class BaseModel
  extend ActiveModel::Translation
end

BlogPost = Class.new(BaseModel)

Benchmark.memory do |x|
  x.report("warmup") { BlogPost.model_name.human }
  x.report("human")  { BlogPost.model_name.human }
end

Benchmark.ips do |x|
  x.report("human")  { BlogPost.model_name.human }
end
```

Before:

```
Calculating -------------------------------------
              warmup   964.242k memsize (    23.575k retained)
                         2.157k objects (   310.000  retained)
                        50.000  strings (    50.000  retained)
               human     4.144k memsize (     0.000  retained)
                        32.000  objects (     0.000  retained)
                         6.000  strings (     0.000  retained)

Warming up --------------------------------------
               human   870.000  i/100ms
Calculating -------------------------------------
               human      8.434k (± 0.8%) i/s -     42.630k in   5.054943s
```

After:

```
Calculating -------------------------------------
              warmup   962.418k memsize (    23.607k retained)
                         2.143k objects (   310.000  retained)
                        50.000  strings (    50.000  retained)
               human     2.112k memsize (     0.000  retained)
                        16.000  objects (     0.000  retained)
                         1.000  strings (     0.000  retained)

Warming up --------------------------------------
               human     1.851k i/100ms
Calculating -------------------------------------
               human     18.492k (± 0.7%) i/s -     92.550k in   5.005100s
```
2022-02-02 11:11:56 -06:00
Ryuta Kamizono
65766ebcc8 Bump license years to 2022 [ci-skip] 2022-01-01 15:22:15 +09:00
Orhan Toy
318d6905e2 Add only_numeric option to numericality validator 2021-12-16 22:21:14 +01:00
Rafael Mendonça França
83d85b2207
Start Rails 7.1 development 2021-12-07 15:52:30 +00:00
Rafael Mendonça França
c2e12e0191
Use to_formatted_s(:db) instead of to_s(:db) internally
Ruby 3.1 introduced an optimization to string interpolation for some
core classes in b08dacfea3.

But since we override `to_s` in some of those core classes to add behavior
like `to_s(:db)`, all Rails applications will not be able to take advantage
of that improvement.

Since we can use the `to_formatted_s` alias for the Rails specific behavior
it is best for us to deprecate the `to_s` core extension and allow Rails
applications to get the proformace improvement.

This commit starts removing all the `to_s(:db)` calls inside the framework
so we can deprecate the core extension in the next commit.
2021-12-06 19:22:04 +00:00
Rafael Mendonça França
6f2c4027e8
Use assert_equal 2021-11-29 22:49:39 +00:00
Zoran Pesic
1de55c3596
don't import errors if attempting to merge with self
Prior to this change, attempting to merge an `ActiveModel::Error` instance
with itself would result in an endless loop where `ActiveModel::NestedError`s
would continue to be imported on the instance until interrupted. Though the
merging of identical objects is less likely to happen in practice, this method
should still be able to handle such a case gracefully. This change ensures
that instances attempting to merge on themselves return early rather than
hanging indefinitely.

Addresses https://github.com/rails/rails/issues/43737
2021-11-29 10:17:36 -08:00
Rafael Mendonça França
902e829914
Merge pull request #43284 from mibradev/password-digest-nil
Prevent error when authenticating user with a blank password digest
2021-11-25 13:59:42 -05:00
Rafael Mendonça França
ad96027f4c
Make sure errors.messages works in the same way as Rails 6.1
When there are no errors for a given attribute we were returning empty
arrays. We should continue to do that.
2021-11-25 18:15:27 +00:00
Rafael Mendonça França
50ec25b506
Remove duplicated tests 2021-11-19 23:15:59 +00:00
Rafael Mendonça França
1f3cfb272c
Remove support to Marshal load Rails 5.x ActiveModel::AttributeSet format 2021-11-17 21:51:32 +00:00
Rafael Mendonça França
2996732089
Remove support to Marshal and YAML load Rails 5.x error format 2021-11-17 21:51:31 +00:00
Rafael Mendonça França
70dc990ad2
Remove deprecated support to use []= in ActiveModel::Errors#messages 2021-11-17 21:51:30 +00:00
Rafael Mendonça França
bab78b5d54
Remove deprecated support delete errors from ActiveModel::Errors#messages 2021-11-17 21:51:29 +00:00
Rafael Mendonça França
b2db6f390c
Implement each using a delegator and make sure all enumerable methods are available 2021-11-17 21:51:28 +00:00
Rafael Mendonça França
93edfaa7b4
Remove unnecessary class 2021-11-17 21:51:27 +00:00
Rafael Mendonça França
ef40a92c1c
Remove deprecated support clear errors from ActiveModel::Errors#messages 2021-11-17 21:51:26 +00:00
Rafael Mendonça França
884c97fad0
Remove deprecated support concat errors to ActiveModel::Errors#messages 2021-11-17 21:51:25 +00:00
Rafael Mendonça França
8a5e217b47
Remove unused method 2021-11-17 21:51:24 +00:00
Rafael Mendonça França
73872c7220
Remove deprecated ActiveModel::Errors#to_xml 2021-11-17 21:51:23 +00:00
Rafael Mendonça França
edc4e7dfb5
Remove deprecated ActiveModel::Errors#keys 2021-11-17 21:51:22 +00:00
Rafael Mendonça França
6fed53b694
Remove deprecated ActiveModel::Errors#values 2021-11-17 21:51:21 +00:00
Rafael Mendonça França
362e17e899
Remove deprecated ActiveModel::Errors#slice! 2021-11-17 21:51:20 +00:00
Rafael Mendonça França
a743656ae4
Remove deprecated ActiveModel::Errors#to_h 2021-11-17 21:51:19 +00:00
Rafael Mendonça França
05b18d2694
Remove deprecated enumeration of ActiveModel::Errors instances as a Hash 2021-11-17 21:51:18 +00:00
Rafael Mendonça França
1fde031e89 Fix gemspec 2021-11-15 21:06:21 +00:00
Rafael Mendonça França
9195b7fd0a
Require MFA to release rails 2021-11-15 20:37:42 +00:00
Jean Boussier
bf33510d86 Optimize CurrentAttributes method generation
The bulk of the optimization is to generate code rather than use
`define_method` with a closure.

```
Warming up --------------------------------------
            original   207.468k i/100ms
      code-generator   340.849k i/100ms
Calculating -------------------------------------
            original      2.127M (± 1.1%) i/s -     10.788M in   5.073860s
      code-generator      3.426M (± 0.9%) i/s -     17.383M in   5.073965s

Comparison:
      code-generator:  3426241.0 i/s
            original:  2126539.2 i/s - 1.61x  (± 0.00) slower
```

```ruby

require 'benchmark/ips'
require 'active_support/all'

class Original < ActiveSupport::CurrentAttributes
  attribute :foo
end

class CodeGen < ActiveSupport::CurrentAttributes
  class << self
    def attribute(*names)
      ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
        names.each do |name|
          owner.define_cached_method(name, namespace: :current_attributes) do |batch|
            batch <<
              "def #{name}" <<
              "attributes[:#{name}]" <<
              "end"
          end
          owner.define_cached_method("#{name}=", namespace: :current_attributes) do |batch|
            batch <<
              "def #{name}=(value)" <<
              "attributes[:#{name}] = value" <<
              "end"
          end
        end
      end

      ActiveSupport::CodeGenerator.batch(singleton_class, __FILE__, __LINE__) do |owner|
        names.each do |name|
          owner.define_cached_method(name, namespace: :current_attributes_delegation) do |batch|
            batch <<
              "def #{name}" <<
              "instance.#{name}" <<
              "end"
          end
          owner.define_cached_method("#{name}=", namespace: :current_attributes_delegation) do |batch|
            batch <<
              "def #{name}=(value)" <<
              "instance.#{name} = value" <<
              "end"
          end
        end
      end
    end
  end
  attribute :foo
end

Benchmark.ips do |x|
  x.report('original') { Original.foo }
  x.report('code-generator') { CodeGen.foo }
  x.compare!
end
```
2021-11-02 15:52:25 +01:00
Rafael Mendonça França
3b5db8e8c9
Merge pull request #43378 from Stellenticket/set_empty_secure_password
clear secure password cache if password is set to `nil`
2021-10-14 17:59:25 -04:00
Markus Doits
9bd186a0e8
clear secure password cache if password is set to nil
```rb
# before:
user.password = 'something'
user.password = nil

user.password # => 'something'

# now:
user.password = 'something'
user.password = nil

user.password # => nil
```
2021-10-10 11:54:35 +02:00
Daniel Colson
26351067c1
Replace more ableist language
Along the same lines as ccb3cb573b, this commit removes unnecessary
references to mental health.

As in that commit, I think many of these are more descriptive than what
we had before.

The commit changes only tests and documentation.
2021-10-07 11:47:28 -04:00
Muhammad Muhammad Ibrahim
d1d4a54c23 Prevent error when authenticating user with a blank password digest
Co-authored-by: Petrik de Heus <petrik@deheus.net>
2021-09-24 09:28:10 +02:00
Jesse van der Pluijm
4862c2faf6 Fix typo: integer numbers (not integral) 2021-09-18 10:21:42 +02:00
Rafael Mendonça França
d177551c30
Preparing for 7.0.0.alpha2 release 2021-09-15 18:22:51 -04:00
Rafael Mendonça França
9b7be48212
Preparing for 7.0.0.alpha1 release 2021-09-15 17:55:08 -04:00
Petrik
c477d95604 Introduce ActiveModel::API
Currently `ActiveModel::Model` is defined as the minimum API to talk
with Action Pack and Action View.
Its name suggests it can be included to create Active Record type
models, but for creating models it's probably too minimal. For example
it's very common to include ActiveModel::Attributes as well.

By moving `ActiveModel::Model`'s implementation to a new
`ActiveModel::API` we keep a definition of the minimum API to talk with
Action Pack and Action View.

For `ActiveModel::Model` we only need to include `ActiveModel::API`.
This will allow adding more funcationality to `ActiveModel::Model` while
keeping backwards compatibility.

Co-authored-by: Nathaniel Watts <1141717+thewatts@users.noreply.github.com>
2021-09-15 18:24:47 +02:00
Guillermo Iguaran
75ea828409 Don't add attribute_names to ActiveModel::Serialization public API 2021-08-28 11:56:21 -07:00
Cody Cutrer
1fbb3ddcd3 avoid calling attributes.keys in ActiveModel#serializable_hash
for ActiveRecord objects, it will force the entire attributes hash to
be constructed, which may include expensive deserialization.
ActiveModel already has a simple attribute_names method defined which
returns attributes.keys, exactly like the code we're replacing.
ActiveRecord overrides that method, and returns the names of the
attributes _without_ having to deserialize any values.

this change can save a lot of CPU if you have a serialized column
on a model that you often load from the DB because it's not worth
the effort to customize the SELECT on every relation, but
also rarely expose in any JSON serializations (i.e. have a default
except option for it).
2021-08-17 18:59:37 -06:00
Rafael Mendonça França
18707ab17f
Standardize nodoc comments 2021-07-29 21:18:07 +00:00
Ryuta Kamizono
0f001f00eb Fix to_json after changes_applied for ActiveModel::Dirty object
Follow up to #41677.

Mutation tracking variables are not only `@mutations_from_database` but
also `@mutations_before_last_save`.
2021-07-24 08:22:18 +09:00
Jonathan Hefner
baa070c3b4
Merge pull request #42839 from jonathanhefner/doc-each_validator
Remove nodoc from EachValidator [ci-skip]
2021-07-23 13:27:35 -05:00
Jean Boussier
8512118f43
Merge pull request #42832 from lulalala/slim-errors-inspect
Slimmer ActiveModel::Errors#inspect message
2021-07-23 09:05:08 +02:00
lulalala
1523838567 Slimmer ActiveModel::Errors#inspect
Only show @errors array and hide @base
2021-07-23 12:29:46 +08:00
Jonathan Hefner
79bb7d0a2b Remove nodoc from EachValidator [ci-skip]
The Active Record Validations guide recommends using `EachValidator`,
and has done so for many years.
2021-07-22 10:35:48 -05:00
Marcelo Lauxen
d1df4c100f
Fix dirty check for Float::NaN and BigDecimal::NaN
Float::NaN and BigDecimal::NaN in Ruby are [special values](https://bugs.ruby-lang.org/issues/1720) and can't be compared with `==`.
2021-07-22 09:49:16 -03:00
Ryuta Kamizono
e50b0e3ab3 Fixup CHANGELOGs [ci skip] 2021-07-21 10:08:08 +09:00
OKURA Masafumi
67adc94e00 Add :nodoc to ActiveModel::Errors
Three classes in `active_model/errors` look internal only.
2021-07-09 00:01:10 +09:00
OKURA Masafumi
f96929ae5f Add missing require to active_model/naming
Using `delegate` at L151 causes `NoMethodError`.
Adding `require` resolves this.
2021-07-08 23:02:09 +09:00
Zachary Scott
bead3221c7 ✂️ 2021-06-30 08:31:17 +09:00
Rafael França
637d386fbb
Merge pull request #41677 from anilmaurya/fix-41521
Fixes #41521, ActiveModel::Dirty fails on to_json
2021-06-24 14:10:29 -04:00
Anil Kumar Maurya
ab1a58281c Fixes #41521, ActiveModel::Dirty fails on to_json 2021-06-24 10:31:48 +00:00
Eddie Lebow
ec207a415a
Formatting markup in comment 2021-06-23 22:41:13 -04:00
Aditya Bhutani
32af6add67 [ci skip] Fixing all <x> based occurances to <x>-based 2021-06-16 19:15:12 +05:30
Chris Salzberg
caced27393 Add ActiveModel::AttributeSet#values_for_database 2021-06-08 16:39:23 +09:00
Benoit Daloze
191ee5eec9 Prefer (...) over ruby2_keywords for ActiveModel::Type.lookup
* (...) is already used in several places in Rails and looks nicer.
2021-05-25 16:06:15 +02:00
Benoit Daloze
5d86e32ae2 Fix delegation in ActiveModel::Type.lookup
* Without the change the new test fails like this:
  Failure:
  ActiveModel::TypeTest#test_registering_a_new_type [test/cases/type_test.rb:21]:
  Expected: #<struct args={}>
    Actual: #<struct args=nil>
* (*args, **kwargs)-delegation is not correct on Ruby 2.7 unless the
  target always accepts keyword arguments (not the case for `Struct.new(:args).new`).
  See https://eregon.me/blog/2021/02/13/correct-delegation-in-ruby-2-27-3.html
2021-05-25 16:01:17 +02:00
Benoit Daloze
8ccc3bfc2d Fix delegation in ActiveModel::Type::Registry
* Without the change the new test fails like this:
  Failure:
  ActiveModel::Type::RegistryTest#test_a_class_can_be_registered_for_a_symbol [test/cases/type/registry_test.rb:16]:
  Expected: [{}, {}]
    Actual: [nil, nil]
* (*args, **kwargs)-delegation is not correct on Ruby 2.7 unless the
  target always accepts keyword arguments (not the case for `Array.new`).
  See https://eregon.me/blog/2021/02/13/correct-delegation-in-ruby-2-27-3.html
2021-05-21 13:50:33 +02:00
Jean Boussier
1e56b1d115 Fix ruby-master test suite (Psych 4.0.0)
Ruby master ships with Psych 4.0.0 which makes `YAML.load`
defaults to safe mode (https://github.com/ruby/psych/pull/487).

However since these YAML files are trustworthy sources
we can parse them with `unsafe_load`.
2021-05-19 14:21:21 +02:00
John Bampton
6e85b6b86e Add spell checking with codespell as a GitHub Action
`codespell` works with a small custom dictionary and seems to find perhaps more spelling mistakes than `misspell` which really only fixes commonly misspelled English words.

Not all spell checkers can check all file types and most spell checkers can't find all the errors.

https://github.com/codespell-project/codespell
https://pypi.org/project/codespell/
2021-05-04 14:46:21 +10:00
Jean Boussier
ca5542fed3 Cache and reuse generated attribute methods 2021-05-03 09:27:59 +02:00
Ryuta Kamizono
95b45c826d Change send back to public_send
It was accidentally changed in #40095.
2021-04-26 03:23:51 +09:00
Abhay Nikam
0b0b22a46a Fixes a typo and wordsmithing in the exception message. Typo: nor -> or 2021-04-24 21:10:24 +05:30
Ashik Salman
b0241f300c Added more test coverage for comparison validator. 2021-04-24 19:36:35 +05:30
Ryuta Kamizono
aa7a8db604 Fix numericality validator :in with invalid args to raise ArgumentError 2021-04-24 14:35:35 +09:00
Ryuta Kamizono
f83dbe358e Fix error message on comparison validator 2021-04-24 14:26:08 +09:00
Ryuta Kamizono
a1afc7726b Convert \r\n to \n 2021-04-24 14:10:18 +09:00
Ryuta Kamizono
8a23c85f6e Fix "uninitialized constant ActiveModel::Validations::NumericalityValidator::Comparability (NameError)"
Somehow it isn't caused on CI, but it consistently causes on locally.

```
% bin/test -w
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:85: warning: method redefined; discarding old validates_each
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:85: warning: previous definition of validates_each was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:89: warning: already initialized constant ActiveModel::Validations::ClassMethods::VALID_OPTIONS_FOR_VALIDATE
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:89: warning: previous definition of VALID_OPTIONS_FOR_VALIDATE was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:152: warning: method redefined; discarding old validate
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:152: warning: previous definition of validate was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:192: warning: method redefined; discarding old validators
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:192: warning: previous definition of validators was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:234: warning: method redefined; discarding old clear_validators!
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:234: warning: previous definition of clear_validators! was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:254: warning: method redefined; discarding old validators_on
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:254: warning: previous definition of validators_on was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:270: warning: method redefined; discarding old attribute_method?
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:270: warning: previous definition of attribute_method? was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:275: warning: method redefined; discarding old inherited
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:275: warning: previous definition of inherited was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:283: warning: method redefined; discarding old initialize_dup
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:283: warning: previous definition of initialize_dup was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:301: warning: method redefined; discarding old errors
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:301: warning: previous definition of errors was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:373: warning: method redefined; discarding old invalid?
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:373: warning: previous definition of invalid? was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:382: warning: method redefined; discarding old validate!
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:382: warning: previous definition of validate! was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:405: warning: method redefined; discarding old run_validations!
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:405: warning: previous definition of run_validations! was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:410: warning: method redefined; discarding old raise_validation_error
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:410: warning: previous definition of raise_validation_error was here
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:426: warning: method redefined; discarding old model
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:428: warning: method redefined; discarding old initialize
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:428: warning: previous definition of initialize was here
Traceback (most recent call last):
	23: from bin/test:5:in `<main>'
	22: from bin/test:5:in `require_relative'
	21: from /Users/kamipo/src/github.com/rails/rails/tools/test.rb:18:in `<top (required)>'
	20: from /Users/kamipo/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:40:in `run'
	19: from /Users/kamipo/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:52:in `load_tests'
	18: from /Users/kamipo/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:52:in `each'
	17: from /Users/kamipo/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:52:in `block in load_tests'
	16: from /Users/kamipo/src/github.com/rails/rails/railties/lib/rails/test_unit/runner.rb:52:in `require'
	15: from /Users/kamipo/src/github.com/rails/rails/activemodel/test/cases/attributes_dirty_test.rb:5:in `<top (required)>'
	14: from /Users/kamipo/src/github.com/rails/rails/activemodel/test/cases/attributes_dirty_test.rb:6:in `<class:AttributesDirtyTest>'
	13: from /Users/kamipo/src/github.com/rails/rails/activemodel/test/cases/attributes_dirty_test.rb:7:in `<class:DirtyModel>'
	12: from /Users/kamipo/src/github.com/rails/rails/activemodel/test/cases/attributes_dirty_test.rb:7:in `require'
	11: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/model.rb:3:in `<top (required)>'
	10: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/model.rb:59:in `<module:ActiveModel>'
	 9: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/model.rb:62:in `<module:Model>'
	 8: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/model.rb:62:in `require'
	 7: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:436:in `<top (required)>'
	 6: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:436:in `each'
	 5: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:436:in `block in <top (required)>'
	 4: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations.rb:436:in `require'
	 3: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations/numericality.rb:5:in `<top (required)>'
	 2: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations/numericality.rb:6:in `<module:ActiveModel>'
	 1: from /Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations/numericality.rb:7:in `<module:Validations>'
/Users/kamipo/src/github.com/rails/rails/activemodel/lib/active_model/validations/numericality.rb:8:in `<class:NumericalityValidator>': uninitialized constant ActiveModel::Validations::NumericalityValidator::Comparability (NameError)
```
2021-04-24 13:46:45 +09:00
Matthew Draper
536a2c0011
Merge pull request #40095 from ChaelCodes/cc-comparablity-validator
Add ComparisonValidator to validate comparison of any objects
2021-04-24 13:20:57 +09:30
Ryuta Kamizono
bbbc861f71 Enable Performance/MapCompact cop
Follow up to #42053.
2021-04-23 16:33:02 +09:00
Jean Boussier
6a5fb7dbd4
Merge pull request #41911 from Shopify/simplify-proxy-call
Allow to pass the method signature when defining attribute methods
2021-04-12 22:36:32 +02:00
Rafael Mendonça França
4354e3ae49
Don't define methods using the method modifier in the same line as the method
Our style guide use block method modifiers, not inline method modifiers.
2021-04-12 18:49:54 +00:00
Jean Boussier
eece095765 Allow to pass the method signature when defining attribute methods
This saves some array allocations from avoiding `*args`, as well
as makes the Method object `arity` and `parameters` correct.

e.g. before this patch, ArgumentError would be confusing:

```ruby
>> model.name_was(1)
ArgumentError: wrong number of arguments (given 2, expected 1)
```
2021-04-11 17:03:25 +02:00
Jean Boussier
c8ea5b8615 Use alias_method rather than define_method to handle non compilable names 2021-04-11 16:10:45 +02:00
Jean Boussier
3f59640016 Stop checking if ruby2_keywords is defined 2021-04-11 13:42:02 +02:00
Étienne Barrié
81d0653f84 Simplify ActiveModel & ActiveRecord Type::Registry
ActiveRecord::Type::Registry doesn't need to inherit from
ActiveModel::Type::Registry, and it makes both classes more simple.

Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com>
2021-04-07 09:59:55 -04:00
Jean Boussier
39341de433 Remove useless include_private parameter in define_proxy_call
Since Ruby 2.7 `self.some_private_method` works fine.
So now that Ruby 2.7 is the minimal supported version,
`define_proxy_call` can always prepend `self.`
2021-03-20 14:27:53 -04:00
Ryuta Kamizono
c435af140e Don't use type.cast(value) to emulate unchecked serialized value in unboundable?
I used `type.cast(value)` to emulate unchecked serialized value in
`unboundable?`, since `RangeError` was raised only for the integer type,
so the emulation works enough for the integer type.

But since #41516, Enum types are also not always serializable, so
`type.cast(value)` may also be called for the enum types.

I've delegated `type.cast(value)` to the subtype if an unknown label is
passed to work the emulation even on Enum types in 3b6461b. But it is
strange to delegate to the subtype for the emulation only if an unknown
label is passed.

Instead of using `type.cast(value)` for the emulation, extend
`serializable?` to get unchecked serialized value if the value is not
serializable.
2021-03-15 12:23:40 +09:00
Ryuta Kamizono
4607f13c88 Use serializable? instead of rescue ::RangeError 2021-03-10 21:21:22 +09:00
Ryuta Kamizono
6ee96a8f42 Avoid extra query attribute allocation in _insert_record/_update_record
Since a `BindParam` object always has an attribute object as the value
in the Active Record usage, so `_insert_record`/`_update_record` could
be passed attribute set instead of wrapping casted value by a query
attribute.
2021-03-01 16:24:31 +09:00
Artem Yegorov
89db42b5e1
Add uncountable? method to ActiveModel::Name 2021-02-18 09:55:29 +03:00
Jonathan Hefner
167f5c8065 Fix inline code markup [ci-skip]
RDoc Markup does not support backticks the way Markdown does to mark up
inline code.  Additionally, `<tt>` must be used to mark up inline code
that includes spaces or certain punctuation characters (e.g. quotes).
2021-02-14 11:20:35 -06:00
Ryuta Kamizono
56ea638290 A value acts like time object should respond to getutc and getlocal 2021-02-11 15:05:25 +09:00
Ricardo Díaz
93cbc30f34 Use Enumerator#all? and Enumerator#any? with classes instead of iterations
These methods have changed in Ruby 2.5 to be more akin to grep:

https://bugs.ruby-lang.org/issues/11286

Using classes seems to be faster (and a bit more expressive) than iterating over
the collection items:

```
Warming up --------------------------------------
    #all? with class   504.000  i/100ms
     #all? with proc   189.000  i/100ms
Calculating -------------------------------------
    #all? with class      4.960k (± 1.6%) i/s -     25.200k in   5.082049s
     #all? with proc      1.874k (± 2.8%) i/s -      9.450k in   5.047866s

Comparison:
    #all? with class:     4959.9 i/s
     #all? with proc:     1873.8 i/s - 2.65x  (± 0.00) slower
```

Benchmark script:

```ruby
require "minitest/autorun"
require "benchmark/ips"

class BugTest < Minitest::Test
  def test_enumerators_with_classes
    arr = (1..10000).to_a << nil

    assert_equal arr.all?(Integer), arr.all? { |v| v.is_a?(Integer) }

    Benchmark.ips do |x|
      x.report("#all? with class") do
        arr.all?(Integer)
      end

      x.report("#all? with proc") do
        arr.all? { |v| v.is_a?(Integer) }
      end

      x.compare!
    end
  end
end
```
2021-02-07 01:29:50 -05:00
Ryuta Kamizono
978308ac87 Fix markup in CHANGELOGs [ci skip] 2021-02-07 05:45:53 +09:00
Rafael Mendonça França
1b455e2e9d
Rails 6.2 is now Rails 7.0
We have big plans for the next version of Rails and that
require big versions.
2021-02-04 16:47:16 +00:00
Rafael Mendonça França
6487836af8
Rails 7 requires Ruby 2.7 and prefer Ruby 3+
The code cleanup is comming in later commits but this
already remove support to Ruby < 2.7.
2021-02-04 16:34:53 +00:00
Rafael França
da418dc250
Merge pull request #41217 from Vin0uz/active-model-errors-add-doc
[ci-skip] Adding options example in ActiveModel::Errors doc
2021-02-03 16:18:26 -05:00
Kevin Vinhas
da0e869bd8 Adding options example in ActiveModel::Errors doc
Place errors with variable example under the `type is a symbol` block
Closes #41124
2021-02-03 21:55:10 +01:00
Rafael Mendonça França
9ea15f1927
Improve performance of time type cast for ISO dates
Before this patch we were appeding a new date in front of
an already existing date what was making the fast path of the
type cast to not trigger.

The following benchmark was used to drive this implementation:

https://gist.github.com/rafaelfranca/0f71c00613f924fcbcdb14b95e6f7661

Closes #41316.
2021-02-03 00:10:15 +00:00
Rachael Wright-Munn
2ed77a9577 Replace all references to invalid/valid with assert_invalid_values/assert_valid_values. 2021-01-23 21:43:19 -05:00
Rachael Wright-Munn
9a08a2f09c Add ComparisonValidator to Rails to support validations between two comparable values.
We allow for compare validations in NumericalityValidator, but these
only work on numbers. There are various comparisons people may want
to validate, from dates to strings, to custom comparisons.

```
validates_comparison_of :end_date, greater_than: :start_date
```

Refactor NumericalityValidator to share module Comparison with ComparabilityValidator
* Move creating the option_value into a reusable module
* Separate COMPARE_CHECKS which support compare functions and accept values
* Move odd/even checks to NUMBER_CHECKS as they can only be run on numbers
2021-01-23 21:24:25 -05:00
Ryuta Kamizono
ddaceddeab
Merge pull request #41166 from kamipo/raise_unknown_type_error_on_definition_time
Raise unknown type error on the definition time
2021-01-20 18:24:40 +09:00
Rafael Mendonça França
077c66d5d6
Rename master to main in all code references 2021-01-19 20:46:33 +00:00
Ryuta Kamizono
26e1fe4938 Raise unknown type error on the definition time
If unknow type is given for attribute (`attribute :foo, :unknown`),
unknown type error isn't raised on the definition time but runtime.

It should be raised on the definition time.
2021-01-19 15:52:12 +09:00
Ryuta Kamizono
e889cc55b0 Make ActiveModel's attribute behavior follow ActiveRecord's 2021-01-18 07:54:36 +09:00
Ryuta Kamizono
63835772bb
Merge pull request #41019 from intrip/40902-fix-numericality-validator
Use round(scale) in  ActiveModel NumericalityValidator
2021-01-14 17:14:31 +09:00
Jacopo
6657e3428b Change Numericaly validator to use round
f72f743 introduces truncate(scale) in the Numericality validator.
This behaviour conflicts with AR decimal type conversion,
which uses round(scale) instead.

Changes the Numericality validator in order to use
round(scale) for consistency.
2021-01-13 22:37:01 +01:00
Ryuta Kamizono
4db95d8432 Restore the ability that update/destroy optimistic locking object without default
The ability has lost due to reverted #39321 in #41049.

We should allow updating with dirty locking value to work the documented
usage, but if casted value has no difference (i.e. regarded as no dirty),
identify the object by the original (uninitialized default) value.
2021-01-12 09:27:11 +09:00
Ryuta Kamizono
8c60a2169a Add round up assertions for decimal tests 2021-01-12 06:16:21 +09:00
Ryuta Kamizono
d24dc88dad
Revert "Fix update with dirty locking column to not match latest object accidentally" 2021-01-08 18:06:05 +09:00
Michal Papis
2486e887de
Add validate numericality in range 2021-01-05 22:56:58 +01:00
Ryuta Kamizono
2b0b5a75c0 Bump license years to 2021 [ci skip] 2021-01-01 12:21:20 +09:00
Rafael Mendonça França
4740a2a02c
Add changelog entry for #40961 2020-12-29 19:25:04 +00:00
Rafael França
67a1cb6c19
Merge pull request #40961 from luk4s/add_activemodel_naming_locale_arg
change ActiveModel::Name initialize arguments to hash and add locale
2020-12-29 14:20:00 -05:00
Lukáš Pokorný
d20caa6df1
add locale argument to ActiveModel::Name initialize 2020-12-29 10:39:35 +01:00
Ryuta Kamizono
6c4306be71 Move set_options_for_callback into Callbacks::ClassMethods
https://buildkite.com/rails/rails/builds/73736#864bc31e-384d-4e38-8165-0d3256ac3f3d/968-979
2020-12-29 16:20:13 +09:00
Rafael Mendonça França
b4cab6a854
Make sure the :if options of callbacks is not mutated
In some cases, the framework was mutating the :if option of callbacks.
Since #38323, those options are frozen, so the framework could raise
exception when trying to mutate those options if they were being resued
with method like `with_options`.
2020-12-29 03:56:54 +00:00
alpaca-tc
8034a439c7 Reuse the same ActiveModel::Type::Value 2020-12-23 18:09:50 +09:00
Rafael Mendonça França
b24ed15baa
Rename the method to match what it is doing 2020-12-09 17:10:22 +00:00
Ryuta Kamizono
720a60e68c Split the options checks from read_attribute_for_validation 2020-12-09 16:43:26 +09:00
Ryuta Kamizono
1dee4990cd allow_nil should work for casted value in NumericalityValidator
It is a regression for 4cc438a1df75e4c230f19cafe9258dbab969cd27.

`NumericalityValidator` basically takes the value before typecasting,
but `allow_nil` should work for the typecasted value for the
compatibility.

Fixes #40750.
2020-12-08 23:25:56 +09:00
Rafael Mendonça França
59f7f5889e
Start Rails 6.2 development 🎉 2020-12-03 01:35:29 +00:00
alpaca-tc
3d1cb9a1f3 Handle frozen conditions in validate
Co-authored-by: Rafael França <rafael@franca.dev>
2020-11-06 12:06:03 +09:00
alpaca-tc
e4e62fbdc6 ActiveModel::Model can be frozen again 2020-11-05 20:52:27 +09:00
Rafael Mendonça França
8389f9902c
Preparing for 6.1.0.rc1 release 2020-11-02 21:12:47 +00:00
Rafael Mendonça França
7eed607b12
Fix CHANGELOG [ci skip] 2020-11-02 18:16:45 +00:00
Rafael França
af91d9a1c5
Merge pull request #40434 from filipe-sabella/pass-in-base-in-validation-messages
Pass in base to Error.human_attribute_names
2020-11-02 13:15:53 -05:00
Rafael Mendonça França
e14e78bf44
Revert "Add test to make sure this method will not be removed again"
This reverts commit d93a5d385e5bc2392a1f47dc2885e353898b62e1.

Revert "Revert "Remove unused internal methods in ActiveModel::Attributes""

This reverts commit 2d7967204e7f7d5ba846b0a6ed51088c7a7db365.

Reason: read_attribute was added in 6.1 as a performance optimization
and it is not needed anymore and write_attribute only existed to make
possible to call something that is not `attribute=` with send. We don't
need those methods internally and since they were never part of the
public API we can remove them.
2020-10-30 01:54:16 +00:00
Rafael Mendonça França
d93a5d385e
Add test to make sure this method will not be removed again 2020-10-28 21:26:39 +00:00
Rafael Mendonça França
2d7967204e
Revert "Remove unused internal methods in ActiveModel::Attributes"
This reverts commit 13bd289b448fb0186b2e932f306704ce2efb2fb6.
2020-10-28 21:26:38 +00:00
Ryuta Kamizono
e47068c3f3 Use attribute_before_type_cast in the internal
`read_attribute_before_type_cast` has become bit slower since #40395.
2020-10-27 16:38:32 +09:00
Ryuta Kamizono
13bd289b44 Remove unused internal methods in ActiveModel::Attributes 2020-10-27 16:11:24 +09:00
Akira Matsuda
fbe7bcf1d6 These test model accessors are public methods 2020-10-27 12:13:32 +09:00
Akira Matsuda
98fda672a6 *_digest is defined as a public method 2020-10-27 12:13:32 +09:00
Ryuta Kamizono
92ff708476 Re-enable Layout/SpaceAroundOperators cop
We prefer space around operators, but `Layout/SpaceAroundOperators` cop
was temporarily disabled in #36943 since that cop changed to check
alignment strictly somehow.

In RuboCop 1.0.0, that is fixed by https://github.com/rubocop-hq/rubocop/pull/8906.

Related https://github.com/rails/rails/pull/38034#discussion_r359845661,
https://github.com/rails/rails/pull/39770#discussion_r448829561.
2020-10-23 16:12:15 +09:00
Filipe Sabella
ac677fb1e3 Update CHANGELOG 2020-10-22 16:50:33 -03:00
Filipe Sabella
bc7b730891 Pass in base to Error.human_attribute_names
There are validation cases in which the human_attribute_name depends on
other fields of the base class.

For instance, an Address model that depends on the selected country to
localize the attribute name to be shown in error messages. E.g. the
:address1 and :address2 attributes can be displayed as very different
strings depending on whether the address is in the US or in Japan.
2020-10-22 16:50:00 -03:00
Chris Griego
5fe517563e
Add missing ActiveSupport require in ActiveModel::Serialization
serializable_attributes is using index_with from active_support/core_ext/enumerable
2020-10-13 14:30:24 -05:00
Akira Matsuda
a65dd81dbb 👮 2020-10-02 14:00:30 +09:00
Akira Matsuda
82ca591b4a Naming methods are defined as public methods 2020-10-02 13:50:14 +09:00
Akira Matsuda
5321f94066 Model attribute methods are publicly callable 2020-10-02 13:48:33 +09:00
Akira Matsuda
674fd96d48 Model#attribute_method_matchers is a public method 2020-10-02 13:47:39 +09:00
Akira Matsuda
ce25559c3e Comparison operator methods on Integer are public methods 2020-10-02 13:41:42 +09:00
Akira Matsuda
02ad67841c Integer#odd? and even? are public methods 2020-10-02 13:39:00 +09:00
Akira Matsuda
9d2a2c775a Add missing test for LengthValidation giving the value via Symbol 2020-10-02 13:37:08 +09:00
Akira Matsuda
c7e68d1729 ==, >=, and <= are public methods 2020-10-02 13:18:09 +09:00
Akira Matsuda
6d45be5ba0 *_confirmation is defined as a public method 2020-10-02 13:14:15 +09:00
Akira Matsuda
8d014e1058 Enumerable#include? and cover? are both public methods 2020-10-02 13:12:55 +09:00
Akira Matsuda
f2a182bf7d Time.utc and Time.local are both public methods 2020-10-02 13:06:59 +09:00
Akira Matsuda
9caf8ddb93 *_ditest and *_digest= are defined as public methods 2020-10-02 13:06:55 +09:00
Trevor John
6fba3c3be0
Allow ActiveModel::Name fields to be overriden 2020-09-23 00:17:54 -04:00
Akira Matsuda
badcaf6763 AR::Base#read_attribute_for_validation is a public_method 2020-09-16 12:15:23 +09:00
lulalala
1fee2cbc50 Rename Error#detail method as details
Plural is more expected.
2020-09-11 17:03:59 +08:00
Eugene Kenny
7af59e16a2 Use transform_values in a few more places
It's faster on Ruby 2.7+ since it avoids rehashing the keys.
2020-09-08 01:34:41 +01:00
Abhay Nikam
714f8c8068 Documents other_than option also accepts the proc or a symbol for numericality validation [skip ci] 2020-08-24 21:27:45 +05:30
Eugene Kenny
0d0eb93b16 Add missing require for Enumerable#index_with
Followup to 0adcec49541aac069600202ed5f83c8ef6f2197e.
2020-08-23 09:17:53 +01:00
Matthew Draper
843898c57a
Merge pull request #22610 from KevinSjoberg/feature/array-member-inclusion
Validate inclusion of each object in an array
2020-08-03 00:09:35 +09:30
Vipul A M
1d6daaaa56
Merge pull request #39735 from lulalala/doc-errors-update
Document ActiveModel errors methods
2020-07-31 08:54:08 +05:30
Ryuta Kamizono
4cc438a1df Extract read_attribute_for_validation for per-validator customization
The model global `read_attribute_for_validation` is not fit for some
validators (specifically for numericality validator).

To allow per-validator customization for attribute value, it extracts
`read_attribute_for_validation` in `EachValidator`.
2020-07-29 18:11:49 +09:00
lulalala
f9518dc972 Document model error methods
[ci skip]
2020-06-29 17:50:08 +08:00
Ryuta Kamizono
f870537c47 Allow ISO 8601 formatted string for fast_string_to_time
Currently `ISO_DATETIME` regexp parser doesn't allow ISO 8601 formatted
string, it fallbacks to slower `Date._parse` in `fallback_string_to_time`.

This makes `ISO_DATETIME` allows ISO 8601 formatted string for
`fast_string_to_time`, it makes ISO 8601 formatted string parsing about
3.5x faster.

```ruby
type = ActiveRecord::Type.lookup(:datetime)
local = Time.now.iso8601
utc = Time.now.utc.iso8601

Benchmark.ips do |x|
  x.report("type.cast(local)") { type.cast(local); type.cast(local) }
  x.report("type.cast(utc)")   { type.cast(utc);   type.cast(utc)   }
end
```

Before:

```
Warming up --------------------------------------
    type.cast(local)     2.198k i/100ms
      type.cast(utc)     2.443k i/100ms
Calculating -------------------------------------
    type.cast(local)     22.371k (± 5.9%) i/s -    112.098k in   5.028419s
      type.cast(utc)     23.359k (± 5.5%) i/s -    117.264k in   5.034913s
```

After:

```
Warming up --------------------------------------
    type.cast(local)     6.918k i/100ms
      type.cast(utc)     9.414k i/100ms
Calculating -------------------------------------
    type.cast(local)     71.468k (± 6.2%) i/s -    359.736k in   5.053612s
      type.cast(utc)     86.258k (± 4.5%) i/s -    433.044k in   5.029979s
```
2020-06-20 10:50:08 +09:00
Ryuta Kamizono
575f4e16a7 Do not use slower public_send in type casting
Before:

```
Warming up --------------------------------------
type.cast(usec=0len)     9.439k i/100ms
type.cast(usec=6len)     9.282k i/100ms
type.cast(usec=3len)     9.111k i/100ms
type.cast(usec=7len)     9.059k i/100ms
Calculating -------------------------------------
type.cast(usec=0len)     90.341k (± 4.2%) i/s -    453.072k in   5.023724s
type.cast(usec=6len)     84.970k (± 3.7%) i/s -    426.972k in   5.031444s
type.cast(usec=3len)     84.043k (± 4.3%) i/s -    428.217k in   5.104155s
type.cast(usec=7len)     83.443k (± 5.3%) i/s -    416.714k in   5.008011s
```

After:

```
Warming up --------------------------------------
type.cast(usec=0len)     9.829k i/100ms
type.cast(usec=6len)     9.405k i/100ms
type.cast(usec=3len)     9.315k i/100ms
type.cast(usec=7len)     9.464k i/100ms
Calculating -------------------------------------
type.cast(usec=0len)     92.918k (± 5.3%) i/s -    471.792k in   5.091504s
type.cast(usec=6len)     86.207k (± 4.4%) i/s -    432.630k in   5.027844s
type.cast(usec=3len)     86.060k (± 4.6%) i/s -    437.805k in   5.097409s
type.cast(usec=7len)     87.036k (± 4.3%) i/s -    435.344k in   5.010501s
```
2020-06-20 08:22:45 +09:00
Ryuta Kamizono
e152d3403f Make usec parsing faster
This intends to avoid extra Rational creation for usec parsing
especially in the no usec case.

This makes all usec variations faster.

```ruby
type = ActiveRecord::Type.lookup(:datetime)
time1 = "2020-06-19 19:18:43"
time2 = "2020-06-19 19:18:43.123456"
time3 = "2020-06-19 19:18:43.123"
time4 = "2020-06-19 19:18:43.1234567"

Benchmark.ips do |x|
  x.report("type.cast(usec=0len)") { type.cast(time1); type.cast(time1) }
  x.report("type.cast(usec=6len)") { type.cast(time2); type.cast(time2) }
  x.report("type.cast(usec=3len)") { type.cast(time3); type.cast(time3) }
  x.report("type.cast(usec=7len)") { type.cast(time4); type.cast(time4) }
end
```

Before:

```
Warming up --------------------------------------
type.cast(usec=0len)     7.343k i/100ms
type.cast(usec=6len)     8.993k i/100ms
type.cast(usec=3len)     8.301k i/100ms
type.cast(usec=7len)     8.209k i/100ms
Calculating -------------------------------------
type.cast(usec=0len)     85.825k (± 5.4%) i/s -    433.237k in   5.062319s
type.cast(usec=6len)     82.045k (± 4.3%) i/s -    413.678k in   5.051260s
type.cast(usec=3len)     78.659k (± 4.4%) i/s -    398.448k in   5.074891s
type.cast(usec=7len)     77.477k (± 4.4%) i/s -    394.032k in   5.095355s
```

After:

```
Warming up --------------------------------------
type.cast(usec=0len)     9.439k i/100ms
type.cast(usec=6len)     9.282k i/100ms
type.cast(usec=3len)     9.111k i/100ms
type.cast(usec=7len)     9.059k i/100ms
Calculating -------------------------------------
type.cast(usec=0len)     90.341k (± 4.2%) i/s -    453.072k in   5.023724s
type.cast(usec=6len)     84.970k (± 3.7%) i/s -    426.972k in   5.031444s
type.cast(usec=3len)     84.043k (± 4.3%) i/s -    428.217k in   5.104155s
type.cast(usec=7len)     83.443k (± 5.3%) i/s -    416.714k in   5.008011s
```
2020-06-20 08:08:31 +09:00
Ryuta Kamizono
d2cdf0be67
Merge pull request #39612 from kamipo/faster_attributes
PERF: 45% faster attributes for readonly usage
2020-06-17 20:29:47 +09:00
Ryuta Kamizono
3944fb743a Avoid to use slower define_method for AcceptsMultiparameterTime
This makes `datetime.serialize` about 10% faster.

```ruby
type = ActiveRecord::Type.lookup(:datetime)
time = Time.now.utc

Benchmark.ips do |x|
  x.report("type.serialize(time)") do
    type.serialize(time)
    type.serialize(time)
    type.serialize(time)
    type.serialize(time)
  end
end
```

Before:

```
Warming up --------------------------------------
type.serialize(time)    12.899k i/100ms
Calculating -------------------------------------
type.serialize(time)    131.293k (± 1.6%) i/s -    657.849k in   5.011870s
```

After:

```
Warming up --------------------------------------
type.serialize(time)    14.603k i/100ms
Calculating -------------------------------------
type.serialize(time)    145.941k (± 1.1%) i/s -    730.150k in   5.003639s
```
2020-06-17 19:45:00 +09:00
Ryuta Kamizono
0adcec4954 PERF: Avoid extra delegation to LazyAttributeHash
The extra delegation to `LazyAttributeHash` has non-negligible overhead.

Avoiding that delegation makes attributes access about 45% faster for
readonly (non-mutation) usage.

https://gist.github.com/kamipo/4002c96a02859d8fe6503e26d7be4ad8

Before:

```
IPS
Warming up --------------------------------------
    attribute access     1.000  i/100ms
Calculating -------------------------------------
    attribute access      3.444  (± 0.0%) i/s -     18.000  in   5.259030s
MEMORY
Calculating -------------------------------------
    attribute access    38.902M memsize (     0.000  retained)
                       350.044k objects (     0.000  retained)
                        15.000  strings (     0.000  retained)
```

After (with `immutable_strings_by_default = true`):

```
IPS
Warming up --------------------------------------
    attribute access     1.000  i/100ms
Calculating -------------------------------------
    attribute access      5.066  (±19.7%) i/s -     25.000  in   5.024650s
MEMORY
Calculating -------------------------------------
    attribute access    27.382M memsize (     0.000  retained)
                       160.044k objects (     0.000  retained)
                        15.000  strings (     0.000  retained)
```
2020-06-15 09:26:24 +09:00
Ryuta Kamizono
5090a64aa3 Lazy allocate @forced_changes
It is almost no longer used in Active Record.
2020-06-14 13:50:07 +09:00
Ryuta Kamizono
528b62e386 Address to false negative for Performance/DeletePrefix,DeleteSuffix
Follow up to c07dff72278fb7f2a3c4c71212a0773a2b25c790.

Actually it is not the cop's fault, but we mistakenly use `^`, `$`, and
`\Z` in much places, the cop doesn't correct those conservatively.

I've checked all those usage and replaced all safe ones.
2020-06-14 13:04:47 +09:00
Ryuta Kamizono
ab8b12eaf6 PERF: 35% faster attributes for readonly usage
Instantiating attributes hash from raw database values is one of the
slower part of attributes.

Why that is necessary is to detect mutations. In other words, that isn't
necessary until mutations are happened.

`LazyAttributeHash` which was introduced at 0f29c21 is to instantiate
attribute lazily until first accessing the attribute (i.e.
`Model.find(1)` isn't slow yet, but `Model.find(1).attr_name` is still
slow).

This introduces `LazyAttributeSet` to instantiate attribute more lazily,
it doesn't instantiate attribute until first assigning/dirty checking
the attribute (i.e. `Model.find(1).attr_name` is no longer slow).

It makes attributes access about 35% faster for readonly (non-mutation)
usage.

https://gist.github.com/kamipo/4002c96a02859d8fe6503e26d7be4ad8

Before:

```
IPS
Warming up --------------------------------------
    attribute access     1.000  i/100ms
Calculating -------------------------------------
    attribute access      3.444  (± 0.0%) i/s -     18.000  in   5.259030s
MEMORY
Calculating -------------------------------------
    attribute access    38.902M memsize (     0.000  retained)
                       350.044k objects (     0.000  retained)
                        15.000  strings (     0.000  retained)
```

After (with `immutable_strings_by_default = true`):

```
IPS
Warming up --------------------------------------
    attribute access     1.000  i/100ms
Calculating -------------------------------------
    attribute access      4.652  (±21.5%) i/s -     23.000  in   5.034853s
MEMORY
Calculating -------------------------------------
    attribute access    27.782M memsize (     0.000  retained)
                       170.044k objects (     0.000  retained)
                        15.000  strings (     0.000  retained)
```
2020-06-13 16:01:08 +09:00
Ryuta Kamizono
19839ff46c Fix string type cast with boolean serialization for MySQL
And benchmark with this branch for immutable string type:

```ruby
ActiveRecord::Schema.define do
  create_table :users, force: true do |t|
    t.string :name
    t.string :fast_name
  end
end

class User < ActiveRecord::Base
  attribute :fast_name, :immutable_string
end

user = User.new

Benchmark.ips do |x|
  x.report("user.name") do
    user.name = "foo"
    user.name_changed?
  end
  x.report("user.fast_name") do
    user.fast_name = "foo"
    user.fast_name_changed?
  end
end
```

```
Warming up --------------------------------------
           user.name    34.811k i/100ms
      user.fast_name    39.505k i/100ms
Calculating -------------------------------------
           user.name    343.864k (± 3.6%) i/s -      1.741M in   5.068576s
      user.fast_name    384.033k (± 2.7%) i/s -      1.936M in   5.044425s
```
2020-06-13 07:50:12 +09:00
Sean Griffin
332c3364b6 Add a setting to specify that all string columns should be immutable
In Rails 4.2 we introduced mutation detection, to remove the need to
call `attribute_will_change!` after modifying a field. One side effect
of that change was that we needed to enforce that the
`_before_type_cast` form of a value is a different object than the post
type cast value, if the value is mutable. That contract is really only
relevant for strings, but it meant we needed to dup them.

In Rails 5 we added the `ImmutableString` type, to allow people to opt
out of this duping in places where the memory usage was causing
problems, and they don't need to mutate that field.

This takes that a step further, and adds a class-level setting to
specify whether strings should be frozen by default or not. The default
value of this setting is `false` (strings are mutable), and I do not
plan on changing that.

While I think that immutable strings by default would be a reasonable
default for new applications, I do not think that we would be able to
document the value of this setting in a place that people will be
looking when they can't figure out why some string is frozen.
Realistically, the number of applications where this setting is relevant
is fairly small, so I don't think it would make sense to ever enable it
by default.
2020-06-11 15:07:06 +09:00
Ryuta Kamizono
27a1ca2bfe PERF: 15% faster attribute access
Delegating to just one line method is to not be worth it.
Avoiding the delegation makes `read_attribute` about 15% faster.

```ruby
ActiveRecord::Schema.define do
  create_table :users, force: true do |t|
    t.string :name
  end
end

class User < ActiveRecord::Base
  def fast_read_attribute(attr_name, &block)
    name = attr_name.to_s
    name = self.class.attribute_aliases[name] || name

    name = @primary_key if name == "id" && @primary_key
    @attributes.fetch_value(name, &block)
  end
end

user = User.create!(name: "user name")

Benchmark.ips do |x|
  x.report("read_attribute('id')") { user.read_attribute('id') }
  x.report("read_attribute('name')") { user.read_attribute('name') }
  x.report("fast_read_attribute('id')") { user.fast_read_attribute('id') }
  x.report("fast_read_attribute('name')") { user.fast_read_attribute('name') }
end
```

```
Warming up --------------------------------------
read_attribute('id')   165.744k i/100ms
read_attribute('name')
                       162.229k i/100ms
fast_read_attribute('id')
                       192.543k i/100ms
fast_read_attribute('name')
                       191.209k i/100ms
Calculating -------------------------------------
read_attribute('id')      1.648M (± 1.7%) i/s -      8.287M in   5.030170s
read_attribute('name')
                          1.636M (± 3.9%) i/s -      8.274M in   5.065356s
fast_read_attribute('id')
                          1.918M (± 1.8%) i/s -      9.627M in   5.021271s
fast_read_attribute('name')
                          1.928M (± 0.9%) i/s -      9.752M in   5.058820s
```
2020-06-05 09:12:21 +09:00
Ryuta Kamizono
7834363bbf Avoid redundant to_s in internal attribute API
Redundant `to_s` has a few overhead. Especially private methods are not
intend to be passed user input directly so it should be passed always
string.

Removing redundant `to_s` makes attribute methods about 10% faster.

```ruby
ActiveRecord::Schema.define do
  create_table :users, force: true do |t|
  end
end

class User < ActiveRecord::Base
  def fast_read_attribute(attr_name, &block)
    @attributes.fetch_value(attr_name, &block)
  end
end

user = User.create!

Benchmark.ips do |x|
  x.report("user._read_attribute('id')") { user._read_attribute("id") }
  x.report("user.fast_read_attribute('id')") { user.fast_read_attribute("id") }
end
```

```
Warming up --------------------------------------
user._read_attribute('id')
                       272.151k i/100ms
user.fast_read_attribute('id')
                       283.518k i/100ms
Calculating -------------------------------------
user._read_attribute('id')
                          2.699M (± 1.3%) i/s -     13.608M in   5.042846s
user.fast_read_attribute('id')
                          2.988M (± 1.2%) i/s -     15.026M in   5.029056s
```
2020-06-04 09:02:53 +09:00
Ryuta Kamizono
6f1bf2a3dd Promote clear_attribute_change as attribute methods
For now, `increment` with aliased attribute does work, but `increment!`
with aliased attribute does not work, due to `clear_attribute_change` is
not aware of attribute aliases.

We sometimes partially updates specific attributes in dirties, at that
time it relies on `clear_attribute_change` to clear partially updated
attribute dirties. If `clear_attribute_change` is not attribute method
unlike others, we need to resolve attribute aliases manually only for
`clear_attribute_change`, it is a little inconvinient for me.

From another point of view, we have `restore_attributes`,
`restore_attribute!`, `clear_attribute_changes`, and
`clear_attribute_change`. Despite almost similar features
`restore_attribute!` is an attribute method but `clear_attribute_change`
is not.

Given the above, I'd like to promote `clear_attribute_change` as
attribute methods to fix issues caused by the inconsisteny.
2020-06-04 04:17:17 +09:00
Aaron Patterson
35fe9bc0aa
Merge pull request #39477 from p8/improve-inspect
Make custom inspect methods more consistent
2020-06-03 10:43:35 -07:00
Ryuta Kamizono
4dbbba4a97 Don't call ruby2_keywords for user supplied block 2020-06-04 02:19:30 +09:00
Petrik
74cb9a6f38 Make inspect look more like regular Object#inspect
Move the # outside the < > just like regular Object#inspect
2020-05-29 21:53:35 +02:00
Ryuta Kamizono
c65864cdca Prefer no allocation start/end_with? over String#[] == 2020-05-29 10:20:13 +09:00
Eugene Kenny
7e14c16cc0 Optimise serializable_hash when options are empty
This reverts 8538dfdc084555673d18cfc3479ebef09f325c9c, which broke the
activemodel-serializers-xml gem.

We can still get most of the benefit by applying the optimisation from
7b3919774252f99e55e6b6ec370aafc42adca2b2 to empty hashes as well as nil.
This has the additional benefit of retaining the optimisation when the
user passes an empty options hash.
2020-05-22 00:04:31 +01:00
Eugene Kenny
8538dfdc08 Reduce allocations in to_json's include option
Since 7b3919774252f99e55e6b6ec370aafc42adca2b2, `serializable_hash`
allocates fewer objects when options is nil rather than empty.
2020-05-19 22:00:00 +01:00
Ryuta Kamizono
fba016c7a3 Fix update with dirty locking column to not match latest object accidentally
Related #32163.

We should not identify an object by dirty value. If do so, accidentally
matches latest object even though it is a stale object.
2020-05-18 09:46:09 +09:00
fatkodima
7b39197742 Avoid allocating extra hash and arrays when as_json is called without options
Co-authored-by: Eugene Kenny <elkenny@gmail.com>
2020-05-17 22:54:55 +03:00
eileencodes
6833bf4d10
Remove implementation of unchecked_serialize
Since we're checking `serializable?` in the new `HomogeneousIn`
`serialize` will no longer raise an exception. We implemented
`unchecked_serialize` to avoid raising in these cases, but with some of
our refactoring we no longer need it.

I discovered this while trying to fix a query in our application that
was not properly serializing binary columns. I discovered that in at
least 2 of our active model types we were not calling the correct
serialization. Since `serialize` wasn't aliased to `unchecked_serialize`
in `ActiveModel::Type::Binary` and `ActiveModel::Type::Boolean` (I
didn't check others but pretty sure all the AM Types are broken) the SQL
was being treated as a `String` and not the correct type.

This caused Rails to incorrectly query by string values. This is
problematic for columns storing binary data like our emoji columns at
GitHub. The test added here is an example of how the Binary type was
broken previously. The SQL should be using the hex values, not the
string value of "🥦" or other emoji.

We still have the problem `unchecked_serialize` was supposed to fix -
that `serialize` shouldn't validate data, just convert it. We'll be
fixing that in a followup PR so for now we should use `serialize` so we
know all the values are going through the right serialization for their
SQL.
2020-05-12 13:37:22 -04:00
Akira Matsuda
1edf103b52 undef_method can take varargs 2020-05-08 23:58:01 +09:00
Ryuta Kamizono
12c2f44316 Remove redundant squish for single line message 2020-05-06 15:08:06 +09:00
eileencodes
70ddb8a704
Merge branch 'fix-array-builder-wheres' 2020-05-05 12:57:14 -04:00
Ryuta Kamizono
199e4e96d6 Attributes can be dup-ed 2020-05-06 00:40:48 +09:00
Ryuta Kamizono
776f2abc5a Type::Value#initialize doesn't take positional arguments
Follow up to 257d8f97921a234425817404eab662f590d2d2b3.
2020-05-05 20:40:37 +09:00
Ryuta Kamizono
f93b04afab Deprecate marshalling load from legacy attributes format
Since #31827, marshalling attributes hash format is changed to improve
performance because materializing lazy attribute hash is too expensive.

In that time, we had kept an ability to load from legacy attributes
format, since that performance improvement is backported to 5-1-stable
and 5-0-stable.

Now all supported versions will dump attributes as new format, the
backward compatibity should no longer be needed.
2020-05-02 15:49:09 +09:00
eileencodes
272f2f081a
Use range.member? over range.cover?
Rails has a monkey patch on `range.cover?` that is slower than Ruby's
`range.cover?`. We don't need Range support in this case because the SQL
creates a `BETWEEN` not an `IN` statement.
2020-05-01 15:12:05 -04:00
eileencodes
72fd0bae59
Perf: Improve performance of where when using an array of values
A coworker at GitHub found a few months back that if we used
`santitize_sql` over `where` when we knew the values going into `where`
it was a lot faster than `where`.

This PR adds a new Arel node type called `HomogenousIn` that will be
used when Rails knows the values are all homogenous and can therefore
pick a faster codepath. This new codepath skips some of the required
processing by `where` to make `wheres` with homogenous arrays faster
without requiring the application author to know when to use which query
type.

Using our benchmark code:

```ruby
ids = (1..1000).each.map do |n|
  Post.create!.id
end

Benchmark.ips do |x|
  x.report("where with ids") do
    Post.where(id: ids).to_a
  end

  x.report("where with sanitize") do
    Post.where(ActiveRecord::Base.sanitize_sql(["id IN (?)", ids])).to_a
  end

  x.compare!
end
```

Before this PR comparing where with a list of IDs to santitize sql:

```
Warming up --------------------------------------
      where with ids    11.000  i/100ms
 where with sanitize    17.000  i/100ms

Calculating -------------------------------------
      where with ids    115.733  (± 4.3%) i/s -    583.000  in   5.045828s
 where with sanitize    174.231  (± 4.0%) i/s -    884.000  in   5.081495s

Comparison:
 where with sanitize:      174.2 i/s
      where with ids:      115.7 i/s - 1.51x  slower
```

After this PR comparing where with a list of IDs to santitize sql:

```
Warming up --------------------------------------
      where with ids    16.000  i/100ms
 where with sanitize    19.000  i/100ms

Calculating -------------------------------------
      where with ids    158.293  (± 6.3%) i/s -    800.000  in   5.072208s
 where with sanitize    169.141  (± 3.5%) i/s -    855.000  in   5.060878s

Comparison:
 where with sanitize:      169.1 i/s
      where with ids:      158.3 i/s - same-ish: difference falls within error
```

Co-authored-by: Aaron Patterson <aaron.patterson@gmail.com>
2020-05-01 15:12:05 -04:00
Jean Boussier
d12418a776 Also batch attribute readers and writers 2020-05-01 12:21:16 +02:00
Jean Boussier
9e8bbf6fc9 Batch attribute methods definition in a single module_eval 2020-04-30 18:09:48 +02:00
Adam Hess
096f2d1f83 Reference updated errors attribute names method in deprecation warning 2020-04-22 09:08:42 -07:00
nimish
b3c308dd20 Reject signed hexadecimal numbers while validating numericality 2020-04-22 12:15:57 +00:00
Ryuta Kamizono
6f2126c760 Fixup CHANGELOGs [ci skip] 2020-04-15 21:23:24 +09:00
Rafael Mendonça França
a4deb63798
No need to deprecate Errors#first
This deprecation is useless since the result is still an Error object
and there is no way to fix the code to remove the deprecation.

Let's just accept as a breaking change.
2020-04-13 19:07:59 -04:00
Rafael França
6f6f4e40ab
Merge pull request #36125 from lulalala/doc-for-model-errors
Document update for ActiveModel#errors
2020-04-13 14:11:55 -04:00
Rafael França
46cb94f6ed
Merge pull request #38903 from HParker/add-access-to-attributes-on-errors
Add attribute_names method on errors
2020-04-08 19:18:11 -04:00
Adam Hess
89eb554025 Add attribute_names method on errors
This method replaces the `keys` method on `errors` as a way to get the error attribute names from the errors object without treating `errors` like a hash.
2020-04-08 16:02:24 -07:00
Adam Hess
19ec6233cc Update the Active Model deprecation warning
This message more clearly communicates how to access the attribute and message keys that you would expect to get when using the previous API.

before you might iterate over errors like,

errors.each do |attribute, message|
  # My error code here
end

This message helps the user find the methods on error that match the previous API.
2020-04-08 15:43:38 -07:00
Abhay Nikam
bdfffd1355 Update the Rails mailing list URLs to new discuss discourse URL [ci skip] 2020-04-02 22:00:28 +05:30
Ryuta Kamizono
de8a404751
Merge pull request #38784 from JuanitoFatas/doc/am-absence-validator
Fix a typo in AbsenceValidator

[ci skip]
2020-03-21 22:49:56 +09:00
Juanito Fatas
1c9a427ca9 Fix a typo in AbsenceValidator 2020-03-21 21:24:38 +09:00
Tim Dorr
55fdf173cc
Tiny doc fix in .validates
This should be a string array literal. Simple as that :)
2020-03-17 11:08:50 -04:00
Ryuta Kamizono
1ef8c60dfc Avoid extra string allocation in the methods generated by eval 2020-03-10 17:43:35 +09:00
Ryuta Kamizono
1d3eb7be13 Fixup CHANGELOGs [ci skip] 2020-02-25 14:14:54 +09:00
Rafael França
df186bd16f
Merge pull request #38401 from vinistock/stop_stringifying_during_attribute_assignment
Do not stringify attributes in assign_attributes
2020-02-13 16:54:35 -05:00
aminamos
7bb0706f2c update from PR #36222 2020-02-12 13:31:43 -05:00
Vinicius Stock
2e9e940e22
Change safe guard to check for each_pair instead of stringify_keys 2020-02-07 11:36:35 -05:00
Vinicius Stock
112c3ec0f5
Only dup attributes in activerecord attribute_assignment 2020-02-06 17:02:56 -05:00
Vinicius Stock
8b59960cd4
Do not stringify attributes in assign_attributes 2020-02-06 16:27:24 -05:00
Jean Boussier
1e209d71b0 Save a string allocation for each attribute method call 2020-01-30 20:40:31 +01:00
Ryuta Kamizono
dd77e787a0 Remove unnecessary include ActiveModel::Model in the doc [ci skip] 2020-01-29 11:40:41 +09:00
Ryuta Kamizono
1f08fec27e Generalize FrozenError on write attribute 2020-01-29 11:23:41 +09:00
George Claghorn
a6841c720a Allow checking whether an attribute previously changed from/to a particular value 2020-01-27 16:38:24 -05:00
Ryuta Kamizono
501cb3eb68 Fix warnings for attribute methods with kwargs 2020-01-21 00:34:06 +09:00
Ryuta Kamizono
289d3db332 Defined attribute should not expand positional hash argument 2020-01-21 00:16:02 +09:00
lulalala
bbf839d1a8 Add list of deprecated methods 2020-01-15 00:17:23 +08:00
lulalala
fcd1e41e82 Document on ActiveModel::Errors changes
Mark private constants

Display alternative for deprecation removal warning

Annotate Error's attributes

More emphasis on adding an error instead of message

Rewrite scaffold template using new errors API

Set first and last with behavior change deprecation

Update more doc and example

Add inspect for easier debugging
2020-01-14 23:55:09 +08:00
Gannon McGibbon
f72f743dc3 Add scale support to ActiveRecord::Validations::NumericalityValidator 2020-01-13 11:00:22 -05:00
Gannon McGibbon
b5c9974fa7 Add ActiveRecord::Validations::NumericalityValidator
Add Active Record numericality validator with support for casting
floats using a database columns' precision value.
2020-01-06 19:01:29 -05:00
Abhay Nikam
d8beb77252 Bump license years from 2019 to 2020 [ci skip] 2020-01-01 15:10:31 +05:30
Ryuta Kamizono
57ace94c42 Merge pull request #38038 from Shopify/activerecord-ruby-2.7-warnings-6-0-stable-batch-2
Activerecord ruby 2.7 warnings 6 0 stable batch 2
2019-12-20 19:43:49 +09:00
Richard
e58f41af2d Api-docs validation defaults missing absence [ci skip] 2019-12-18 13:10:04 +00:00
Rafael França
886f397e98
Merge pull request #37088 from enriikke/fix-activemodel-error-frozen
Fix FrozenError on ActiveModel::Error clear and delete
2019-12-17 19:39:28 -03:00
Eugene Kenny
ee525ff663 Load framework test files in deterministic order
`Dir.glob` doesn't guarantee the order of its results:

https://ruby-doc.org/core-2.6.5/Dir.html#method-c-glob

> Case sensitivity depends on your system (File::FNM_CASEFOLD is
> ignored), as does the order in which the results are returned.

Minitest stores a list of all test cases in the order that they were
defined; it shuffles them before they're run, but doesn't sort them:

https://github.com/seattlerb/minitest/blob/v5.13.0/lib/minitest.rb#L1048
https://github.com/seattlerb/minitest/blob/v5.13.0/lib/minitest.rb#L156

This means that the order in which framework tests run is platform
dependent, and running a test command that failed in CI locally won't
necessarily reproduce the error, even when the same seed is provided.

`Rake::FileList` resolves glob patterns to a sorted list of files:

https://github.com/ruby/rake/blob/v13.0.1/lib/rake/file_list.rb#L408

By using `Rake::FileList` instead of `Dir.glob`, framework tests will
always run in the same order when given the same seed, and reproducing
order dependent CI failures will be easier.
2019-12-16 16:55:06 +00:00
Rafael Mendonça França
e67fdc5aeb
Revert "Merge pull request #37504 from utilum/no_implicit_conversion_of_nil"
This reverts commit 4e105385d046e2aeab16955943df97c5eefa3a6f, reversing
changes made to 62b43839098bbbbfc4be789128d33dc0612f1ab3.

The change in Ruby that made those changes required was reverted in
8852fa8760
2019-12-09 11:50:39 -03:00
Ryuta Kamizono
56f63552f1 Add missing period 2019-11-24 10:28:48 +09:00
Ryuta Kamizono
214f439343 Fixup CHANGELOGs [ci skip] 2019-11-24 09:20:00 +09:00
Kasper Timm Hansen
a67a2f63e7
Merge pull request #37518 from shioyama/test_clear_changes_information_directly
Test clear_changes_information rather than reload
2019-11-17 22:05:17 +01:00
utilum
2ca6830831 TypeError Regexp#match?(nil) in Ruby Head
Aa of ruby/ruby@2a22a6b2d8 calling
`Regexp#match?(nil)` raises an exception.

[utilum, eregon, eugeneius]
2019-11-03 09:26:46 +02:00
Ryuta Kamizono
98754de141 Fix multi-threaded issue for AcceptanceValidator 2019-11-03 12:55:30 +09:00
Ryuta Kamizono
8d8011f0bb Simplify LazilyDefineAttributes 2019-10-21 22:30:34 +09:00
Chris Salzberg
4b67bd51c2
Rewrite LazilyDefineAttributes so that it removes itself
LazilyDefineAttributes only needs to stay in the model's ancestors long
enough to define accessors for acceptance attributes, after that it is
not needed anymore. To optimize this, we eagerly define attributes as
soon as either +method_missing+ or +respond_to_missing?+ is called, then
immediately remove those methods from the module so that future calls
will incur no performance penalty.

I've also removed the call to +define_attribute_methods+ here, which
is no longer be necessary to avoid an infinite loop.
2019-10-21 19:53:31 +09:00
Chris Salzberg
8937c72217
Test clear_changes_information rather than reload
reload is an ActiveRecord method, not an ActiveModel one.
clear_changes_information is a public method so it should be tested
directly, not through a method defined for on the DirtyModel test class.
2019-10-21 10:52:54 +09:00
Jonathan Hefner
cd619e9781 Fix i18n of attributes with multi-digit indexes
Follow-up to #33615 and #37447.
2019-10-17 10:23:00 -04:00
Rafael França
c2a002b98d
Merge pull request #37447 from jonathankwok/i18n-error-lookup-for-indexed-attribute
Support ActiveModel::Error translation lookup on indexed attributes.
2019-10-15 17:54:35 -04:00
jonathankwok
236e20e6fb Don't add new lookup; replace existing one instead 2019-10-15 15:18:07 -04:00
willnet
68b11a8dbb [ci skip]fix typo 2019-10-14 11:29:40 +09:00
Orien Madgwick
493edf044f Add bug tracker/documentation/mailing list URIs to the gemspecs 2019-10-11 20:47:19 -04:00
jonathankwok
5c9b008f36 Support ActiveModel::Error translation lookup on indexed attributes.
Instances of ActiveModel::Error where `attribute` is a nested attribute
can use translation keys that don't include the index in their lookup key.
2019-10-11 17:15:02 -04:00
Kasper Timm Hansen
4c5da6093d
Merge pull request #37217 from joshmn/frozen_attributes
Raise FrozenError for frozen objects when trying to write to a non-database-backed attribute
2019-10-07 03:00:26 +02:00
Takayuki Nakata
6497096b85 Remove unused require
`except` and `slice` were removed at d2b78b3594
2019-10-03 09:51:16 +09:00
Matthew Draper
ade48853d9
Merge pull request #36907 from wjessop/string_attribute_should_compare_with_typecast_symbol_after_update
Serialize symbols to strings in ImmutableString serialize method
2019-09-28 18:20:08 +09:30
Ryuta Kamizono
63299ce7a3 Revert register proc takes keyword arguments
Because Ruby 2.6 cannot ignore empty kwargs.

https://buildkite.com/rails/rails/builds/63958#9932c536-b1df-4d2c-bda0-c59ed0e254c1/987-995
2019-09-28 15:07:38 +09:00
Ryuta Kamizono
2cf74f6b87 Fix remaining keyword arguments warnings for Active Record
Except required `ruby2_keywords` things.
2019-09-28 14:42:25 +09:00