diff options
-rw-r--r-- | actionview/lib/action_view/test_case.rb | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/errors.rb | 2 | ||||
-rw-r--r-- | activemodel/test/cases/errors_test.rb | 11 | ||||
-rw-r--r-- | activerecord/lib/active_record/transactions.rb | 17 | ||||
-rw-r--r-- | activerecord/test/cases/adapters/postgresql/connection_test.rb | 6 | ||||
-rw-r--r-- | activerecord/test/cases/migration_test.rb | 4 | ||||
-rw-r--r-- | activerecord/test/cases/test_case.rb | 16 | ||||
-rw-r--r-- | activerecord/test/cases/transaction_callbacks_test.rb | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/hash_with_indifferent_access.rb | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/notifications/fanout.rb | 4 | ||||
-rw-r--r-- | activesupport/test/hash_with_indifferent_access_test.rb | 28 | ||||
-rw-r--r-- | activesupport/test/notifications_test.rb | 7 | ||||
-rw-r--r-- | guides/source/getting_started.md | 8 | ||||
-rw-r--r-- | guides/source/i18n.md | 21 |
14 files changed, 68 insertions, 62 deletions
diff --git a/actionview/lib/action_view/test_case.rb b/actionview/lib/action_view/test_case.rb index e14f7aaec7..3a75633743 100644 --- a/actionview/lib/action_view/test_case.rb +++ b/actionview/lib/action_view/test_case.rb @@ -284,7 +284,7 @@ module ActionView def respond_to_missing?(name, include_private = false) begin - routes = @controller.respond_to?(:_routes) && @controller._routes + routes = defined?(@controller) && @controller.respond_to?(:_routes) && @controller._routes rescue # Don't call routes, if there is an error on _routes call end diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index fd87d3c9bc..d7bcfacce3 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -64,7 +64,7 @@ module ActiveModel include Enumerable extend Forwardable - def_delegators :@errors, :size, :clear, :blank?, :empty?, :uniq! + def_delegators :@errors, :size, :clear, :blank?, :empty?, :uniq!, :any? # TODO: forward all enumerable methods after `each` deprecation is removed. def_delegators :@errors, :count diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb index 0837e9db96..baaf404f2e 100644 --- a/activemodel/test/cases/errors_test.rb +++ b/activemodel/test/cases/errors_test.rb @@ -44,6 +44,17 @@ class ErrorsTest < ActiveModel::TestCase assert_includes errors, "foo", "errors should include 'foo' as :foo" end + def test_any? + errors = ActiveModel::Errors.new(Person.new) + errors.add(:name) + assert_not_deprecated { + assert errors.any?, "any? should return true" + } + assert_not_deprecated { + assert errors.any? { |_| true }, "any? should return true" + } + end + def test_dup errors = ActiveModel::Errors.new(Person.new) errors.add(:name) diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index bf781b23eb..9e03deede7 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -333,7 +333,7 @@ module ActiveRecord # Ensure that it is not called if the object was never persisted (failed create), # but call it after the commit of a destroyed object. def committed!(should_run_callbacks: true) #:nodoc: - if should_run_callbacks && (destroyed? || persisted?) + if should_run_callbacks && trigger_transactional_callbacks? @_committed_already_called = true _run_commit_without_transaction_enrollment_callbacks _run_commit_callbacks @@ -346,7 +346,7 @@ module ActiveRecord # Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record # state should be rolled back to the beginning or just to the last savepoint. def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc: - if should_run_callbacks + if should_run_callbacks && trigger_transactional_callbacks? _run_rollback_callbacks _run_rollback_without_transaction_enrollment_callbacks end @@ -364,7 +364,9 @@ module ActiveRecord def with_transaction_returning_status status = nil self.class.transaction do - unless has_transactional_callbacks? + if has_transactional_callbacks? + add_to_transaction + else sync_with_transaction_state if @transaction_state&.finalized? @transaction_state = self.class.connection.transaction_state end @@ -372,11 +374,6 @@ module ActiveRecord status = yield raise ActiveRecord::Rollback unless status - ensure - if has_transactional_callbacks? && - (@_new_record_before_last_commit && !new_record? || _trigger_update_callback || _trigger_destroy_callback) - add_to_transaction - end end status end @@ -460,6 +457,10 @@ module ActiveRecord self.class.connection.add_transaction_record(self) end + def trigger_transactional_callbacks? + @_new_record_before_last_commit && !new_record? || _trigger_update_callback || _trigger_destroy_callback + end + def has_transactional_callbacks? !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty? end diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index 210758f462..9494863a75 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -26,19 +26,19 @@ module ActiveRecord end def test_encoding - assert_queries(1) do + assert_queries(1, ignore_none: true) do assert_not_nil @connection.encoding end end def test_collation - assert_queries(1) do + assert_queries(1, ignore_none: true) do assert_not_nil @connection.collation end end def test_ctype - assert_queries(1) do + assert_queries(1, ignore_none: true) do assert_not_nil @connection.ctype end end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 8e8ed494d9..255885b599 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -854,7 +854,7 @@ if ActiveRecord::Base.connection.supports_bulk_alter? classname = ActiveRecord::Base.connection.class.name[/[^:]*$/] expected_query_count = { - "Mysql2Adapter" => 3, # Adding an index fires a query every time to check if an index already exists or not + "Mysql2Adapter" => 1, # mysql2 supports creating two indexes using one statement "PostgreSQLAdapter" => 2, }.fetch(classname) { raise "need an expected query count for #{classname}" @@ -886,7 +886,7 @@ if ActiveRecord::Base.connection.supports_bulk_alter? classname = ActiveRecord::Base.connection.class.name[/[^:]*$/] expected_query_count = { - "Mysql2Adapter" => 3, # Adding an index fires a query every time to check if an index already exists or not + "Mysql2Adapter" => 1, # mysql2 supports dropping and creating two indexes using one statement "PostgreSQLAdapter" => 2, }.fetch(classname) { raise "need an expected query count for #{classname}" diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb index 5b25432dc0..78dc0a6d9f 100644 --- a/activerecord/test/cases/test_case.rb +++ b/activerecord/test/cases/test_case.rb @@ -107,19 +107,7 @@ module ActiveRecord clear_log - self.ignored_sql = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/] - - # FIXME: this needs to be refactored so specific database can add their own - # ignored SQL, or better yet, use a different notification for the queries - # instead examining the SQL content. - oracle_ignored = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im, /^\s*select .* from all_constraints/im, /^\s*select .* from all_tab_cols/im, /^\s*select .* from all_sequences/im] - mysql_ignored = [/^SHOW FULL TABLES/i, /^SHOW FULL FIELDS/, /^SHOW CREATE TABLE /i, /^SHOW VARIABLES /, /^\s*SELECT (?:column_name|table_name)\b.*\bFROM information_schema\.(?:key_column_usage|tables)\b/im] - postgresql_ignored = [/^\s*select\b.*\bfrom\b.*pg_namespace\b/im, /^\s*select tablename\b.*from pg_tables\b/im, /^\s*select\b.*\battname\b.*\bfrom\b.*\bpg_attribute\b/im, /^SHOW search_path/i, /^\s*SELECT\b.*::regtype::oid\b/im] - sqlite3_ignored = [/^\s*SELECT name\b.*\bFROM sqlite_master/im, /^\s*SELECT sql\b.*\bFROM sqlite_master/im] - - [oracle_ignored, mysql_ignored, postgresql_ignored, sqlite3_ignored].each do |db_ignored_sql| - ignored_sql.concat db_ignored_sql - end + self.ignored_sql = [/^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/] attr_reader :ignore @@ -132,7 +120,7 @@ module ActiveRecord sql = values[:sql] self.class.log_all << sql - self.class.log << sql unless ignore.match?(sql) + self.class.log << sql unless values[:name] == "SCHEMA" || ignore.match?(sql) end end diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index 53fe31e087..135e2cb382 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -36,6 +36,8 @@ class TransactionCallbacksTest < ActiveRecord::TestCase has_many :replies, class_name: "ReplyWithCallbacks", foreign_key: "parent_id" + before_destroy { self.class.find(id).touch if persisted? } + before_commit { |record| record.do_before_commit(nil) } after_commit { |record| record.do_after_commit(nil) } after_save_commit { |record| record.do_after_commit(:save) } diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 42ae7e9b7b..5981763f0e 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -69,7 +69,7 @@ module ActiveSupport super() update(constructor) - hash = constructor.to_hash + hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash self.default = hash.default if hash.default self.default_proc = hash.default_proc if hash.default_proc else diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb index 8812b67f63..c506b35b1e 100644 --- a/activesupport/lib/active_support/notifications/fanout.rb +++ b/activesupport/lib/active_support/notifications/fanout.rb @@ -180,13 +180,13 @@ module ActiveSupport def start(name, id, payload) timestack = Thread.current[:_timestack] ||= [] - timestack.push Concurrent.monotonic_time + timestack.push Time.now end def finish(name, id, payload) timestack = Thread.current[:_timestack] started = timestack.pop - @delegate.call(name, started, Concurrent.monotonic_time, id, payload) + @delegate.call(name, started, Time.now, id, payload) end end diff --git a/activesupport/test/hash_with_indifferent_access_test.rb b/activesupport/test/hash_with_indifferent_access_test.rb index 1d6a07ec5f..af96231801 100644 --- a/activesupport/test/hash_with_indifferent_access_test.rb +++ b/activesupport/test/hash_with_indifferent_access_test.rb @@ -836,4 +836,32 @@ class HashWithIndifferentAccessTest < ActiveSupport::TestCase assert_equal 3, hash_wia[:foo] assert_equal 3, hash_wia[:bar] end + + def test_should_copy_the_default_when_converting_non_hash_to_hash_with_indifferent_access + non_hash = Object.new + + def non_hash.to_hash + h = { foo: :bar } + h.default = :baz + h + end + + hash_wia = HashWithIndifferentAccess.new(non_hash) + assert_equal :bar, hash_wia[:foo] + assert_equal :baz, hash_wia[:missing] + end + + def test_should_copy_the_default_proc_when_converting_non_hash_to_hash_with_indifferent_access + non_hash = Object.new + + def non_hash.to_hash + h = { foo: :bar } + h.default_proc = ->(hash, key) { hash[key] = :baz } + h + end + + hash_wia = HashWithIndifferentAccess.new(non_hash) + assert_equal :bar, hash_wia[:foo] + assert_equal :baz, hash_wia[:missing] + end end diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb index 0af59764b5..d3c660a014 100644 --- a/activesupport/test/notifications_test.rb +++ b/activesupport/test/notifications_test.rb @@ -302,7 +302,7 @@ module Notifications class EventTest < TestCase def test_events_are_initialized_with_details - time = Concurrent.monotonic_time + time = Time.now event = event(:foo, time, time + 0.01, random_id, {}) assert_equal :foo, event.name @@ -310,12 +310,11 @@ module Notifications assert_in_delta 10.0, event.duration, 0.00001 end - def test_event_cpu_time_and_idle_time_when_start_and_finish_is_not_called - time = Concurrent.monotonic_time + def test_event_cpu_time_does_not_raise_error_when_start_or_finished_not_called + time = Time.now event = event(:foo, time, time + 0.01, random_id, {}) assert_equal 0, event.cpu_time - assert_in_delta 10.0, event.idle_time, 0.00001 end diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md index e486c53fe3..1f6744caba 100644 --- a/guides/source/getting_started.md +++ b/guides/source/getting_started.md @@ -126,7 +126,7 @@ run the following: $ rails --version ``` -If it says something like "Rails 5.2.1", you are ready to continue. +If it says something like "Rails 6.0.0", you are ready to continue. ### Creating the Blog Application @@ -205,12 +205,10 @@ $ rails server TIP: If you are using Windows, you have to pass the scripts under the `bin` folder directly to the Ruby interpreter e.g. `ruby bin\rails server`. -TIP: Compiling CoffeeScript and JavaScript asset compression requires you +TIP: Compiling JavaScript asset compression requires you have a JavaScript runtime available on your system, in the absence of a runtime you will see an `execjs` error during asset compilation. Usually macOS and Windows come with a JavaScript runtime installed. -Rails adds the `mini_racer` gem to the generated `Gemfile` in a -commented line for new apps and you can uncomment if you need it. `therubyrhino` is the recommended runtime for JRuby users and is added by default to the `Gemfile` in apps generated under JRuby. You can investigate all the supported runtimes at [ExecJS](https://github.com/rails/execjs#readme). @@ -1560,7 +1558,7 @@ class CreateComments < ActiveRecord::Migration[6.0] create_table :comments do |t| t.string :commenter t.text :body - t.references :article, foreign_key: true + t.references :article, null: false, foreign_key: true t.timestamps end diff --git a/guides/source/i18n.md b/guides/source/i18n.md index d6fccadb28..5d91a6df33 100644 --- a/guides/source/i18n.md +++ b/guides/source/i18n.md @@ -992,27 +992,6 @@ So, for example, instead of the default error message `"cannot be blank"` you co | numericality | :odd | :odd | - | | numericality | :even | :even | - | -#### Translations for the Active Record `error_messages_for` Helper - -If you are using the Active Record `error_messages_for` helper, you will want to add -translations for it. - -Rails ships with the following translations: - -```yaml -en: - activerecord: - errors: - template: - header: - one: "1 error prohibited this %{model} from being saved" - other: "%{count} errors prohibited this %{model} from being saved" - body: "There were problems with the following fields:" -``` - -NOTE: In order to use this helper, you need to install [DynamicForm](https://github.com/joelmoss/dynamic_form) -gem by adding this line to your `Gemfile`: `gem 'dynamic_form'`. - ### Translations for Action Mailer E-Mail Subjects If you don't pass a subject to the `mail` method, Action Mailer will try to find |