aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.codeclimate.yml27
-rw-r--r--.rubocop.yml27
-rw-r--r--Gemfile6
-rw-r--r--Gemfile.lock42
-rw-r--r--actioncable/README.md18
-rw-r--r--actioncable/lib/action_cable/engine.rb2
-rw-r--r--actioncable/test/client_test.rb3
-rw-r--r--actionmailer/lib/action_mailer/base.rb5
-rw-r--r--actionpack/lib/abstract_controller/base.rb7
-rw-r--r--actionpack/lib/abstract_controller/callbacks.rb2
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb2
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb39
-rw-r--r--actionpack/lib/action_controller/renderer.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb27
-rw-r--r--actionpack/test/controller/integration_test.rb30
-rw-r--r--actionpack/test/controller/parameters/parameters_permit_test.rb6
-rw-r--r--actionpack/test/controller/render_test.rb7
-rw-r--r--actionpack/test/controller/send_file_test.rb15
-rw-r--r--actionpack/test/dispatch/cookies_test.rb4
-rw-r--r--actionpack/test/dispatch/routing_test.rb30
-rw-r--r--actionview/CHANGELOG.md21
-rw-r--r--actionview/lib/action_view/digestor.rb10
-rw-r--r--actionview/lib/action_view/helpers/date_helper.rb3
-rw-r--r--actionview/lib/action_view/helpers/form_helper.rb65
-rw-r--r--actionview/lib/action_view/helpers/form_tag_helper.rb19
-rw-r--r--actionview/lib/action_view/helpers/number_helper.rb2
-rw-r--r--actionview/lib/action_view/helpers/tags/datetime_field.rb2
-rw-r--r--actionview/lib/action_view/helpers/tags/file_field.rb15
-rw-r--r--actionview/lib/action_view/template/handlers/raw.rb2
-rw-r--r--actionview/test/actionpack/controller/render_test.rb5
-rw-r--r--actionview/test/fixtures/digestor/api/comments/_comment.json.erb1
-rw-r--r--actionview/test/fixtures/digestor/api/comments/_comments.json.erb1
-rw-r--r--actionview/test/fixtures/digestor/messages/thread.json.erb1
-rw-r--r--actionview/test/template/date_helper_test.rb7
-rw-r--r--actionview/test/template/digestor_test.rb42
-rw-r--r--actionview/test/template/form_helper_test.rb123
-rw-r--r--actionview/test/template/form_tag_helper_test.rb6
-rw-r--r--actionview/test/template/render_test.rb7
-rw-r--r--activejob/lib/active_job/logging.rb2
-rw-r--r--activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb2
-rw-r--r--activejob/lib/active_job/test_helper.rb15
-rw-r--r--activejob/test/cases/logging_test.rb7
-rw-r--r--activejob/test/cases/test_helper_test.rb12
-rw-r--r--activejob/test/jobs/overridden_logging_job.rb9
-rw-r--r--activemodel/lib/active_model/errors.rb19
-rw-r--r--activemodel/lib/active_model/validations.rb2
-rw-r--r--activemodel/test/cases/errors_test.rb6
-rw-r--r--activerecord/CHANGELOG.md14
-rw-r--r--activerecord/lib/active_record/attribute_set/yaml_encoder.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb14
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql/column.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_handling.rb2
-rw-r--r--activerecord/lib/active_record/enum.rb2
-rw-r--r--activerecord/lib/active_record/fixtures.rb2
-rw-r--r--activerecord/lib/active_record/inheritance.rb3
-rw-r--r--activerecord/lib/active_record/query_cache.rb4
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb14
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb2
-rw-r--r--activerecord/lib/active_record/tasks/mysql_database_tasks.rb1
-rw-r--r--activerecord/lib/active_record/tasks/postgresql_database_tasks.rb3
-rw-r--r--activerecord/lib/active_record/validations/uniqueness.rb6
-rw-r--r--activerecord/lib/rails/generators/active_record/model/model_generator.rb14
-rw-r--r--activerecord/test/cases/adapters/sqlite3/quoting_test.rb178
-rw-r--r--activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb28
-rw-r--r--activerecord/test/cases/associations/eager_test.rb4
-rw-r--r--activerecord/test/cases/associations/left_outer_join_association_test.rb2
-rw-r--r--activerecord/test/cases/base_test.rb8
-rw-r--r--activerecord/test/cases/batches_test.rb4
-rw-r--r--activerecord/test/cases/column_definition_test.rb7
-rw-r--r--activerecord/test/cases/dirty_test.rb17
-rw-r--r--activerecord/test/cases/enum_test.rb4
-rw-r--r--activerecord/test/cases/finder_test.rb6
-rw-r--r--activerecord/test/cases/multiparameter_attributes_test.rb14
-rw-r--r--activerecord/test/cases/query_cache_test.rb17
-rw-r--r--activerecord/test/cases/tasks/mysql_rake_test.rb8
-rw-r--r--activerecord/test/cases/tasks/postgresql_rake_test.rb4
-rw-r--r--activerecord/test/cases/test_case.rb4
-rw-r--r--activesupport/CHANGELOG.md15
-rw-r--r--activesupport/lib/active_support/cache.rb4
-rw-r--r--activesupport/lib/active_support/callbacks.rb9
-rw-r--r--activesupport/lib/active_support/core_ext/hash/compact.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/json.rb14
-rw-r--r--activesupport/lib/active_support/evented_file_update_checker.rb49
-rw-r--r--activesupport/lib/active_support/json/decoding.rb11
-rw-r--r--activesupport/lib/active_support/logger.rb18
-rw-r--r--activesupport/lib/active_support/ordered_options.rb2
-rw-r--r--activesupport/lib/active_support/per_thread_registry.rb2
-rw-r--r--activesupport/lib/active_support/test_case.rb7
-rw-r--r--activesupport/lib/active_support/testing/assertions.rb2
-rw-r--r--activesupport/lib/active_support/testing/isolation.rb11
-rw-r--r--activesupport/lib/active_support/testing/time_helpers.rb6
-rw-r--r--activesupport/test/broadcast_logger_test.rb134
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb10
-rw-r--r--activesupport/test/deprecation_test.rb2
-rw-r--r--activesupport/test/evented_file_update_checker_test.rb44
-rw-r--r--activesupport/test/json/decoding_test.rb16
-rw-r--r--activesupport/test/json/encoding_test_cases.rb4
-rw-r--r--activesupport/test/logger_test.rb12
-rw-r--r--guides/source/4_2_release_notes.md2
-rw-r--r--guides/source/5_0_release_notes.md78
-rw-r--r--guides/source/action_controller_overview.md4
-rw-r--r--guides/source/action_mailer_basics.md2
-rw-r--r--guides/source/active_job_basics.md22
-rw-r--r--guides/source/active_record_callbacks.md4
-rw-r--r--guides/source/active_record_postgresql.md4
-rw-r--r--guides/source/active_record_validations.md12
-rw-r--r--guides/source/api_documentation_guidelines.md2
-rw-r--r--guides/source/configuring.md30
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md2
-rw-r--r--guides/source/credits.html.erb2
-rw-r--r--guides/source/documents.yaml5
-rw-r--r--guides/source/layout.html.erb2
-rw-r--r--guides/source/testing.md18
-rw-r--r--railties/CHANGELOG.md9
-rw-r--r--railties/lib/rails/application/configuration.rb3
-rw-r--r--railties/lib/rails/application/finisher.rb7
-rw-r--r--railties/lib/rails/generators/erb/mailer/mailer_generator.rb7
-rw-r--r--railties/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt13
-rw-r--r--railties/lib/rails/generators/erb/mailer/templates/layout.text.erb.tt1
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt55
-rw-r--r--railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb10
-rw-r--r--railties/lib/rails/tasks/framework.rake2
-rw-r--r--railties/test/application/routing_test.rb19
-rw-r--r--railties/test/generators/app_generator_test.rb21
-rw-r--r--railties/test/generators/mailer_generator_test.rb8
-rw-r--r--railties/test/generators/model_generator_test.rb14
-rw-r--r--railties/test/generators/namespaced_generators_test.rb12
-rw-r--r--railties/test/generators/plugin_generator_test.rb15
-rw-r--r--railties/test/generators/resource_generator_test.rb4
-rw-r--r--railties/test/generators/scaffold_controller_generator_test.rb4
-rw-r--r--railties/test/generators/scaffold_generator_test.rb6
-rw-r--r--railties/test/isolation/abstract_unit.rb1
-rw-r--r--railties/test/rails_info_controller_test.rb6
-rw-r--r--railties/test/railties/engine_test.rb6
141 files changed, 1187 insertions, 734 deletions
diff --git a/.codeclimate.yml b/.codeclimate.yml
new file mode 100644
index 0000000000..877c67873d
--- /dev/null
+++ b/.codeclimate.yml
@@ -0,0 +1,27 @@
+engines:
+ rubocop:
+ enabled: true
+
+ratings:
+ paths:
+ - "**.rb"
+
+exclude_paths:
+ - actioncable/lib/rails/generators/
+ - actioncable/test/
+ - actionmailer/lib/rails/generators/
+ - actionmailer/test/
+ - actionpack/test/
+ - actionview/test/
+ - activejob/lib/rails/generators/
+ - activejob/test/
+ - activemodel/test/
+ - activerecord/lib/rails/generators/
+ - activerecord/test/
+ - activesupport/test/
+ - railties/lib/rails/generators/
+ - railties/test/
+ - ci/
+ - guides/
+ - tasks/
+ - tools/
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000000..dd8db6af3a
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,27 @@
+AllCops:
+ TargetRubyVersion: 2.3
+ DisabledByDefault: true
+
+# Two spaces, no tabs (for indentation).
+Style/IndentationWidth:
+ enabled: true
+
+# No trailing whitespace.
+Style/TrailingWhitespace:
+ enabled: true
+
+# Blank lines should not have any spaces.
+Style/TrailingBlankLines:
+ enabled: true
+
+# Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
+Style/HashSyntax:
+ enabled: true
+
+# Prefer &&/|| over and/or.
+Style/AndOr:
+ enabled: true
+
+# Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
+Lint/RequireParentheses:
+ enabled: true
diff --git a/Gemfile b/Gemfile
index c851d32dea..5650147099 100644
--- a/Gemfile
+++ b/Gemfile
@@ -68,8 +68,8 @@ group :cable do
# Lock to 1.1.1 until the fix for https://github.com/faye/faye/issues/394 is released
gem 'faye', '1.1.1', require: false
- gem 'blade', '~> 0.5.5', require: false
- gem 'blade-sauce_labs_plugin', '~> 0.5.1', require: false
+ gem 'blade', require: false
+ gem 'blade-sauce_labs_plugin', require: false
end
# Add your own local bundler stuff.
@@ -89,7 +89,7 @@ group :test do
end
platforms :ruby, :mswin, :mswin64, :mingw, :x64_mingw do
- gem 'nokogiri', '>= 1.6.7.1'
+ gem 'nokogiri', '>= 1.6.8'
# Needed for compiling the ActionDispatch::Journey parser.
gem 'racc', '>=1.4.6', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index ed325aef55..71f4302a5b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -116,7 +116,7 @@ GEM
bcrypt (3.1.11-x86-mingw32)
beaneater (1.0.0)
benchmark-ips (2.6.1)
- blade (0.5.5)
+ blade (0.5.6)
activesupport (>= 3.0.0)
blade-qunit_adapter (~> 1.20.0)
coffee-script
@@ -126,11 +126,11 @@ GEM
faye
sprockets (>= 3.0)
sprockets-export (~> 0.9.1)
- thin (~> 1.6.0)
+ thin (>= 1.6.0)
thor (~> 0.19.1)
useragent (~> 0.16.7)
blade-qunit_adapter (1.20.0)
- blade-sauce_labs_plugin (0.5.1)
+ blade-sauce_labs_plugin (0.5.2)
childprocess
faraday
selenium-webdriver
@@ -166,7 +166,7 @@ GEM
eventmachine (1.2.0.1)
eventmachine (1.2.0.1-x64-mingw32)
eventmachine (1.2.0.1-x86-mingw32)
- execjs (2.6.0)
+ execjs (2.7.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
faye (1.1.1)
@@ -208,7 +208,7 @@ GEM
mime-types (3.0)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0221)
- mini_portile2 (2.0.0)
+ mini_portile2 (2.1.0)
minitest (5.3.3)
mocha (0.14.0)
metaclass (~> 0.0.1)
@@ -220,15 +220,19 @@ GEM
mysql2 (0.4.4-x64-mingw32)
mysql2 (0.4.4-x86-mingw32)
nio4r (1.2.1)
- nokogiri (1.6.7.2)
- mini_portile2 (~> 2.0.0.rc2)
- nokogiri (1.6.7.2-x64-mingw32)
- mini_portile2 (~> 2.0.0.rc2)
- nokogiri (1.6.7.2-x86-mingw32)
- mini_portile2 (~> 2.0.0.rc2)
+ nokogiri (1.6.8)
+ mini_portile2 (~> 2.1.0)
+ pkg-config (~> 1.1.7)
+ nokogiri (1.6.8-x64-mingw32)
+ mini_portile2 (~> 2.1.0)
+ pkg-config (~> 1.1.7)
+ nokogiri (1.6.8-x86-mingw32)
+ mini_portile2 (~> 2.1.0)
+ pkg-config (~> 1.1.7)
pg (0.18.4)
pg (0.18.4-x64-mingw32)
pg (0.18.4-x86-mingw32)
+ pkg-config (1.1.7)
psych (2.0.17)
puma (3.4.0)
qu (0.2.0)
@@ -296,7 +300,7 @@ GEM
serverengine (~> 1.5.11)
thor
thread (~> 0.1.7)
- sprockets (3.6.0)
+ sprockets (3.6.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-export (0.9.1)
@@ -310,10 +314,10 @@ GEM
stackprof (0.2.9)
sucker_punch (2.0.2)
concurrent-ruby (~> 1.0.0)
- thin (1.6.2)
- daemons (>= 1.0.9)
- eventmachine (>= 1.0.0)
- rack (>= 1.0.0)
+ thin (1.7.0)
+ daemons (~> 1.0, >= 1.0.9)
+ eventmachine (~> 1.0, >= 1.0.4)
+ rack (>= 1, < 3)
thor (0.19.1)
thread (0.1.7)
thread_safe (0.3.5)
@@ -348,8 +352,8 @@ DEPENDENCIES
backburner
bcrypt (~> 3.1.11)
benchmark-ips
- blade (~> 0.5.5)
- blade-sauce_labs_plugin (~> 0.5.1)
+ blade
+ blade-sauce_labs_plugin
byebug
coffee-rails!
dalli (>= 2.2.1)
@@ -365,7 +369,7 @@ DEPENDENCIES
minitest (< 5.3.4)
mocha (~> 0.14)
mysql2 (>= 0.4.4)
- nokogiri (>= 1.6.7.1)
+ nokogiri (>= 1.6.8)
pg (>= 0.18.0)
psych (~> 2.0)
puma
diff --git a/actioncable/README.md b/actioncable/README.md
index b5eababa90..b3bfd83120 100644
--- a/actioncable/README.md
+++ b/actioncable/README.md
@@ -7,7 +7,6 @@ and scalable. It's a full-stack offering that provides both a client-side
JavaScript framework and a server-side Ruby framework. You have access to your full
domain model written with Active Record or your ORM of choice.
-
## Terminology
A single Action Cable server can handle multiple connection instances. It has one
@@ -300,7 +299,6 @@ The rebroadcast will be received by all connected clients, _including_ the clien
See the [rails/actioncable-examples](https://github.com/rails/actioncable-examples) repository for a full example of how to setup Action Cable in a Rails app, and how to add channels.
-
## Configuration
Action Cable has three required configurations: a subscription adapter, allowed request origins, and the cable server URL (which can optionally be set on the client side).
@@ -444,21 +442,13 @@ The Ruby side of things is built on top of [websocket-driver](https://github.com
## Deployment
+>>>>>>> b94b04b1d11b1d095918b8bae2b6b5f76f092cf7
-Action Cable is powered by a combination of WebSockets and threads. All of the
-connection management is handled internally by utilizing Ruby’s native thread
-support, which means you can use all your regular Rails models with no problems
-as long as you haven’t committed any thread-safety sins.
+ $ gem install actioncable
-The Action Cable server does _not_ need to be a multi-threaded application server.
-This is because Action Cable uses the [Rack socket hijacking API](http://www.rubydoc.info/github/rack/rack/file/SPEC#Hijacking)
-to take over control of connections from the application server. Action Cable
-then manages connections internally, in a multithreaded manner, regardless of
-whether the application server is multi-threaded or not. So Action Cable works
-with all the popular application servers -- Unicorn, Puma and Passenger.
+Source code can be downloaded as part of the Rails project on GitHub
-Action Cable does not work with WEBrick, because WEBrick does not support the
-Rack socket hijacking API.
+* https://github.com/rails/rails/tree/master/actioncable
## License
diff --git a/actioncable/lib/action_cable/engine.rb b/actioncable/lib/action_cable/engine.rb
index 96176e0014..34f9952c71 100644
--- a/actioncable/lib/action_cable/engine.rb
+++ b/actioncable/lib/action_cable/engine.rb
@@ -22,7 +22,7 @@ module ActionCable
initializer "action_cable.set_configs" do |app|
options = app.config.action_cable
- options.allowed_request_origins ||= "http://localhost:3000" if ::Rails.env.development?
+ options.allowed_request_origins ||= /https?:\/\/localhost:\d+/ if ::Rails.env.development?
app.paths.add "config/cable", with: "config/cable.yml"
diff --git a/actioncable/test/client_test.rb b/actioncable/test/client_test.rb
index f4b4a53aea..283ba9daaf 100644
--- a/actioncable/test/client_test.rb
+++ b/actioncable/test/client_test.rb
@@ -1,9 +1,6 @@
require 'test_helper'
require 'concurrent'
-require 'active_support/core_ext/hash/indifferent_access'
-require 'pathname'
-
require 'faye/websocket'
require 'json'
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 6e0ae8a0a9..e766221008 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -390,9 +390,8 @@ module ActionMailer
# to use it. Defaults to <tt>true</tt>.
# * <tt>:openssl_verify_mode</tt> - When using TLS, you can set how OpenSSL checks the certificate. This is
# really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name
- # of an OpenSSL verify constant (<tt>'none'</tt>, <tt>'peer'</tt>, <tt>'client_once'</tt>,
- # <tt>'fail_if_no_peer_cert'</tt>) or directly the constant (<tt>OpenSSL::SSL::VERIFY_NONE</tt>,
- # <tt>OpenSSL::SSL::VERIFY_PEER</tt>, ...).
+ # of an OpenSSL verify constant (<tt>'none'</tt> or <tt>'peer'</tt>) or directly the constant
+ # (<tt>OpenSSL::SSL::VERIFY_NONE</tt> or <tt>OpenSSL::SSL::VERIFY_PEER</tt>).
# <tt>:ssl/:tls</tt> Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection)
#
# * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method.
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index d4317399ed..aa06f70433 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -150,6 +150,13 @@ module AbstractController
_find_action_name(action_name)
end
+ # Tests if a response body is set. Used to determine if the
+ # +process_action+ callback needs to be terminated in
+ # +AbstractController::Callbacks+.
+ def performed?
+ response_body
+ end
+
# Returns true if the given controller is capable of rendering
# a path. A subclass of +AbstractController::Base+
# may return false. An Email controller for example does not
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb
index d63ce9c1c3..3ef8da86fa 100644
--- a/actionpack/lib/abstract_controller/callbacks.rb
+++ b/actionpack/lib/abstract_controller/callbacks.rb
@@ -9,7 +9,7 @@ module AbstractController
included do
define_callbacks :process_action,
- terminator: ->(controller, result_lambda) { result_lambda.call if result_lambda.is_a?(Proc); controller.response_body },
+ terminator: ->(controller, result_lambda) { result_lambda.call if result_lambda.is_a?(Proc); controller.performed? },
skip_after_callbacks_if_terminated: true
end
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index a6fb0dbe1d..4ba2c26949 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -122,7 +122,7 @@ module AbstractController
def _normalize_render(*args, &block)
options = _normalize_args(*args, &block)
#TODO: remove defined? when we restore AP <=> AV dependency
- if defined?(request) && request.variant.present?
+ if defined?(request) && !request.nil? && request.variant.present?
options[:variant] = request.variant
end
_normalize_options(options)
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 46589901fd..b326695ce2 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -58,8 +58,7 @@ module ActionController
# })
#
# permitted = params.require(:person).permit(:name, :age)
- # permitted # => {"name"=>"Francesco", "age"=>22}
- # permitted.class # => ActionController::Parameters
+ # permitted # => <ActionController::Parameters {"name"=>"Francesco", "age"=>22} permitted: true>
# permitted.permitted? # => true
#
# Person.first.update!(permitted)
@@ -87,7 +86,7 @@ module ActionController
#
# params = ActionController::Parameters.new(a: "123", b: "456")
# params.permit(:c)
- # # => {}
+ # # => <ActionController::Parameters {} permitted: true>
#
# ActionController::Parameters.action_on_unpermitted_parameters = :raise
#
@@ -107,6 +106,8 @@ module ActionController
# params["key"] # => "value"
class Parameters
cattr_accessor :permit_all_parameters, instance_accessor: false
+ self.permit_all_parameters = false
+
cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?,
@@ -255,7 +256,7 @@ module ActionController
# either present or the singleton +false+, returns said value:
#
# ActionController::Parameters.new(person: { name: 'Francesco' }).require(:person)
- # # => {"name"=>"Francesco"}
+ # # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
#
# Otherwise raises <tt>ActionController::ParameterMissing</tt>:
#
@@ -276,12 +277,12 @@ module ActionController
# returned:
#
# params = ActionController::Parameters.new(user: { ... }, profile: { ... })
- # user_params, profile_params = params.require(:user, :profile)
+ # user_params, profile_params = params.require([:user, :profile])
#
# Otherwise, the method re-raises the first exception found:
#
# params = ActionController::Parameters.new(user: {}, profile: {})
- # user_params, profile_params = params.require(:user, :profile)
+ # user_params, profile_params = params.require([:user, :profile])
# # ActionController::ParameterMissing: param is missing or the value is empty: user
#
# Technically this method can be used to fetch terminal values:
@@ -374,13 +375,13 @@ module ActionController
# })
#
# params.require(:person).permit(:contact)
- # # => {}
+ # # => <ActionController::Parameters {} permitted: true>
#
# params.require(:person).permit(contact: :phone)
- # # => {"contact"=>{"phone"=>"555-1234"}}
+ # # => <ActionController::Parameters {"contact"=><ActionController::Parameters {"phone"=>"555-1234"} permitted: true>} permitted: true>
#
# params.require(:person).permit(contact: [ :email, :phone ])
- # # => {"contact"=>{"email"=>"none@test.com", "phone"=>"555-1234"}}
+ # # => <ActionController::Parameters {"contact"=><ActionController::Parameters {"email"=>"none@test.com", "phone"=>"555-1234"} permitted: true>} permitted: true>
def permit(*filters)
params = self.class.new
@@ -402,7 +403,7 @@ module ActionController
# returns +nil+.
#
# params = ActionController::Parameters.new(person: { name: 'Francesco' })
- # params[:person] # => {"name"=>"Francesco"}
+ # params[:person] # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
# params[:none] # => nil
def [](key)
convert_hashes_to_parameters(key, @parameters[key])
@@ -421,7 +422,7 @@ module ActionController
# is given, then that will be run and its result returned.
#
# params = ActionController::Parameters.new(person: { name: 'Francesco' })
- # params.fetch(:person) # => {"name"=>"Francesco"}
+ # params.fetch(:person) # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
# params.fetch(:none) # => ActionController::ParameterMissing: param is missing or the value is empty: none
# params.fetch(:none, 'Francesco') # => "Francesco"
# params.fetch(:none) { 'Francesco' } # => "Francesco"
@@ -457,8 +458,8 @@ module ActionController
# don't exist, returns an empty hash.
#
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
- # params.slice(:a, :b) # => {"a"=>1, "b"=>2}
- # params.slice(:d) # => {}
+ # params.slice(:a, :b) # => <ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
+ # params.slice(:d) # => <ActionController::Parameters {} permitted: false>
def slice(*keys)
new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
end
@@ -474,8 +475,8 @@ module ActionController
# filters out the given +keys+.
#
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
- # params.except(:a, :b) # => {"c"=>3}
- # params.except(:d) # => {"a"=>1,"b"=>2,"c"=>3}
+ # params.except(:a, :b) # => <ActionController::Parameters {"c"=>3} permitted: false>
+ # params.except(:d) # => <ActionController::Parameters {"a"=>1, "b"=>2, "c"=>3} permitted: false>
def except(*keys)
new_instance_with_inherited_permitted_status(@parameters.except(*keys))
end
@@ -483,8 +484,8 @@ module ActionController
# Removes and returns the key/value pairs matching the given keys.
#
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
- # params.extract!(:a, :b) # => {"a"=>1, "b"=>2}
- # params # => {"c"=>3}
+ # params.extract!(:a, :b) # => <ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
+ # params # => <ActionController::Parameters {"c"=>3} permitted: false>
def extract!(*keys)
new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
end
@@ -494,7 +495,7 @@ module ActionController
#
# params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
# params.transform_values { |x| x * 2 }
- # # => {"a"=>2, "b"=>4, "c"=>6}
+ # # => <ActionController::Parameters {"a"=>2, "b"=>4, "c"=>6} permitted: false>
def transform_values(&block)
if block
new_instance_with_inherited_permitted_status(
@@ -577,7 +578,7 @@ module ActionController
# params = ActionController::Parameters.new(a: 1)
# params.permit!
# params.permitted? # => true
- # copy_params = params.dup # => {"a"=>1}
+ # copy_params = params.dup # => <ActionController::Parameters {"a"=>1} permitted: true>
# copy_params.permitted? # => true
def dup
super.tap do |duplicate|
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index 5ff4a658ad..a8c8d66682 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -1,7 +1,7 @@
require 'active_support/core_ext/hash/keys'
module ActionController
- # ActionController::Renderer allows to render arbitrary templates
+ # ActionController::Renderer allows you to render arbitrary templates
# without requirement of being in controller actions.
#
# You get a concrete renderer class by invoking ActionController::Base#renderer.
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 8ff3b42a40..40b6500553 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -106,7 +106,7 @@ module ActionDispatch
@ast = ast
@anchor = anchor
@via = via
- @internal = options[:internal]
+ @internal = options.delete(:internal)
path_params = ast.find_all(&:symbol?).map(&:to_sym)
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 8777666f9f..5627e79bb7 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -327,17 +327,17 @@ module ActionDispatch
request_encoder = RequestEncoder.encoder(as)
if path =~ %r{://}
- location = URI.parse(path)
- https! URI::HTTPS === location if location.scheme
- if url_host = location.host
- default = Rack::Request::DEFAULT_PORTS[location.scheme]
- url_host += ":#{location.port}" if default != location.port
- host! url_host
+ path = build_expanded_path(path, request_encoder) do |location|
+ https! URI::HTTPS === location if location.scheme
+
+ if url_host = location.host
+ default = Rack::Request::DEFAULT_PORTS[location.scheme]
+ url_host += ":#{location.port}" if default != location.port
+ host! url_host
+ end
end
- path = request_encoder.append_format_to location.path
- path = location.query ? "#{path}?#{location.query}" : path
- else
- path = request_encoder.append_format_to path
+ elsif as
+ path = build_expanded_path(path, request_encoder)
end
hostname, port = host.split(':')
@@ -396,6 +396,13 @@ module ActionDispatch
"#{env['rack.url_scheme']}://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{path}"
end
+ def build_expanded_path(path, request_encoder)
+ location = URI.parse(path)
+ yield location if block_given?
+ path = request_encoder.append_format_to location.path
+ location.query ? "#{path}?#{location.query}" : path
+ end
+
class RequestEncoder # :nodoc:
@encoders = {}
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index 97571c1308..3b89531e90 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -1147,6 +1147,22 @@ class IntegrationRequestEncodersTest < ActionDispatch::IntegrationTest
end
end
+ def test_standard_json_encoding_works
+ with_routing do |routes|
+ routes.draw do
+ ActiveSupport::Deprecation.silence do
+ post ':action' => FooController
+ end
+ end
+
+ post '/foos_json.json', params: { foo: 'fighters' }.to_json,
+ headers: { 'Content-Type' => 'application/json' }
+
+ assert_response :success
+ assert_equal({ 'foo' => 'fighters' }, response.parsed_body)
+ end
+ end
+
def test_encoding_as_json
post_to_foos as: :json do
assert_response :success
@@ -1194,6 +1210,20 @@ class IntegrationRequestEncodersTest < ActionDispatch::IntegrationTest
end
end
+ def test_get_parameters_with_as_option
+ with_routing do |routes|
+ routes.draw do
+ ActiveSupport::Deprecation.silence do
+ get ':action' => FooController
+ end
+ end
+
+ get '/foos_json?foo=heyo', as: :json
+
+ assert_equal({ 'foo' => 'heyo' }, response.parsed_body)
+ end
+ end
+
private
def post_to_foos(as:)
with_routing do |routes|
diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb
index b75eb0e3bf..2eed2996f6 100644
--- a/actionpack/test/controller/parameters/parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/parameters_permit_test.rb
@@ -369,4 +369,10 @@ class ParametersPermitTest < ActiveSupport::TestCase
refute params.permit(foo: [:bar]).has_key?(:foo)
refute params.permit(foo: :bar).has_key?(:foo)
end
+
+ test '#permitted? is false by default' do
+ params = ActionController::Parameters.new
+
+ assert_equal false, params.permitted?
+ end
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index f42efd35af..8d3134630d 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -564,6 +564,13 @@ class MetalRenderTest < ActionController::TestCase
end
end
+class ActionControllerBaseRenderTest < ActionController::TestCase
+ def test_direct_render_to_string
+ ac = ActionController::Base.new()
+ assert_equal "Hello world!", ac.render_to_string(template: 'test/hello_world')
+ end
+end
+
class ImplicitRenderTest < ActionController::TestCase
tests ImplicitRenderTestController
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 2820425c31..9df70dacbf 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -11,6 +11,8 @@ class SendFileController < ActionController::Base
include ActionController::Testing
layout "layouts/standard" # to make sure layouts don't interfere
+ before_action :file, only: :file_from_before_action
+
attr_writer :options
def options
@options ||= {}
@@ -20,6 +22,10 @@ class SendFileController < ActionController::Base
send_file(file_path, options)
end
+ def file_from_before_action
+ raise 'No file sent from before action.'
+ end
+
def test_send_file_headers_bang
options = {
:type => Mime[:png],
@@ -192,6 +198,15 @@ class SendFileTest < ActionController::TestCase
assert_nil @controller.headers['Content-Disposition']
end
+ def test_send_file_from_before_action
+ response = nil
+ assert_nothing_raised { response = process('file_from_before_action') }
+ assert_not_nil response
+
+ assert_kind_of String, response.body
+ assert_equal file_data, response.body
+ end
+
%w(file data).each do |method|
define_method "test_send_#{method}_status" do
@controller.options = { :stream => false, :status => 500 }
diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb
index dfcef14344..c7194cde4a 100644
--- a/actionpack/test/dispatch/cookies_test.rb
+++ b/actionpack/test/dispatch/cookies_test.rb
@@ -520,7 +520,7 @@ class CookiesTest < ActionController::TestCase
def test_accessing_nonexistent_signed_cookie_should_not_raise_an_invalid_signature
get :set_signed_cookie
- assert_nil @controller.send(:cookies).signed[:non_existant_attribute]
+ assert_nil @controller.send(:cookies).signed[:non_existent_attribute]
end
def test_encrypted_cookie_using_default_serializer
@@ -638,7 +638,7 @@ class CookiesTest < ActionController::TestCase
def test_accessing_nonexistent_encrypted_cookie_should_not_raise_invalid_message
get :set_encrypted_cookie
- assert_nil @controller.send(:cookies).encrypted[:non_existant_attribute]
+ assert_nil @controller.send(:cookies).encrypted[:non_existent_attribute]
end
def test_setting_invalid_encrypted_cookie_should_return_nil_when_accessing_it
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index ade4b0c381..75fdc9469f 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -4795,3 +4795,33 @@ class TestPathParameters < ActionDispatch::IntegrationTest
assert_equal "/ar | /ar/about", @response.body
end
end
+
+class TestInternalRoutingParams < ActionDispatch::IntegrationTest
+ Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
+ app.draw do
+ get '/test_internal/:internal' => 'internal#internal'
+ end
+ end
+
+ class ::InternalController < ActionController::Base
+ def internal
+ head :ok
+ end
+ end
+
+ APP = build_app Routes
+
+ def app
+ APP
+ end
+
+ def test_paths_with_partial_dynamic_segments_are_recognised
+ get '/test_internal/123'
+ assert_equal 200, response.status
+
+ assert_equal(
+ { controller: 'internal', action: 'internal', internal: '123' },
+ request.path_parameters
+ )
+ end
+end
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 9d669c7cd8..099842025c 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,5 +1,24 @@
+* Change `datetime_field` and `datetime_field_tag` to generate `datetime-local` fields.
+
+ As a new specification of the HTML 5 the text field type `datetime` will no longer exist
+ and it is recomended to use `datetime-local`.
+ Ref: https://html.spec.whatwg.org/multipage/forms.html#local-date-and-time-state-(type=datetime-local)
+
+ *Herminio Torres*
+
+* Raw template handler (which is also the default template handler in Rails 5) now outputs
+ HTML-safe strings.
+
+ In Rails 5 the default template handler was changed to the raw template handler. Because
+ the ERB template handler escaped strings by default this broke some applications that
+ expected plain JS or HTML files to be rendered unescaped. This fixes the issue caused
+ by changing the default handler by changing the Raw template handler to output HTML-safe
+ strings.
+
+ *Eileen M. Uchitelle*
+
* `select_tag`'s `include_blank` option for generation for blank option tag, now adds an empty space label,
- when the value as well as content for option tag are empty, so that we confirm with html specification.
+ when the value as well as content for option tag are empty, so that we conform with html specification.
Ref: https://www.w3.org/TR/html5/forms.html#the-option-element.
Generation of option before:
diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb
index b91e61da18..f3c29d663c 100644
--- a/actionview/lib/action_view/digestor.rb
+++ b/actionview/lib/action_view/digestor.rb
@@ -15,7 +15,7 @@ module ActionView
# * <tt>partial</tt> - Specifies whether the template is a partial
def digest(name:, finder:, dependencies: [])
dependencies ||= []
- cache_key = ([ name ].compact + dependencies).join('.')
+ cache_key = [ name, finder.rendered_format, dependencies ].flatten.compact.join('.')
# this is a correctly done double-checked locking idiom
# (Concurrent::Map's lookups have volatile semantics)
@@ -39,8 +39,12 @@ module ActionView
def tree(name, finder, partial = false, seen = {})
logical_name = name.gsub(%r|/_|, "/")
- if finder.disable_cache { finder.exists?(logical_name, [], partial) }
- template = finder.disable_cache { finder.find(logical_name, [], partial) }
+ options = {}
+ options[:formats] = [finder.rendered_format] if finder.rendered_format
+
+ if finder.disable_cache { finder.exists?(logical_name, [], partial, [], options) }
+ template = finder.disable_cache { finder.find(logical_name, [], partial, [], options) }
+ finder.rendered_format ||= template.formats.first
if node = seen[template.identifier] # handle cycles in the tree
node
diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb
index 9042b9cffd..a02702bf7a 100644
--- a/actionview/lib/action_view/helpers/date_helper.rb
+++ b/actionview/lib/action_view/helpers/date_helper.rb
@@ -3,6 +3,7 @@ require 'action_view/helpers/tag_helper'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/date/conversions'
require 'active_support/core_ext/hash/slice'
+require 'active_support/core_ext/object/acts_like'
require 'active_support/core_ext/object/with_options'
module ActionView
@@ -1058,7 +1059,7 @@ module ActionView
prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
prefix += "[#{@options[:index]}]" if @options.has_key?(:index)
- field_name = @options[:field_name] || type
+ field_name = @options[:field_name] || type.to_s
if @options[:include_position]
field_name += "(#{ActionView::Helpers::DateTimeSelector::POSITION[type]}i)"
end
diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb
index 7ced37572e..3d2ae0cfe0 100644
--- a/actionview/lib/action_view/helpers/form_helper.rb
+++ b/actionview/lib/action_view/helpers/form_helper.rb
@@ -860,24 +860,6 @@ module ActionView
#
# file_field(:attachment, :file, class: 'file_input')
# # => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
- #
- # ==== Gotcha
- #
- # The HTML specification says that when a file field is empty, web browsers
- # do not send any value to the server. Unfortunately this introduces a
- # gotcha: if a +User+ model has an +avatar+ field, and no file is selected,
- # then the +avatar+ parameter is empty. Thus, any mass-assignment idiom like
- #
- # @user.update(params[:user])
- #
- # wouldn't update the +avatar+ field.
- #
- # To prevent this, the helper generates an auxiliary hidden field before
- # every file field. The hidden field has the same name as the file one and
- # a blank value.
- #
- # In case you don't want the helper to generate this hidden field you can
- # specify the <tt>include_hidden: false</tt> option.
def file_field(object_name, method, options = {})
Tags::FileField.new(object_name, method, self, options).render
end
@@ -1066,7 +1048,7 @@ module ActionView
# Returns a text_field of type "time".
#
# The default value is generated by trying to call +strftime+ with "%T.%L"
- # on the objects's value. It is still possible to override that
+ # on the object's value. It is still possible to override that
# by passing the "value" option.
#
# === Options
@@ -1092,42 +1074,9 @@ module ActionView
Tags::TimeField.new(object_name, method, self, options).render
end
- # Returns a text_field of type "datetime".
- #
- # datetime_field("user", "born_on")
- # # => <input id="user_born_on" name="user[born_on]" type="datetime" />
- #
- # The default value is generated by trying to call +strftime+ with "%Y-%m-%dT%T.%L%z"
- # on the object's value, which makes it behave as expected for instances
- # of DateTime and ActiveSupport::TimeWithZone.
- #
- # @user.born_on = Date.new(1984, 1, 12)
- # datetime_field("user", "born_on")
- # # => <input id="user_born_on" name="user[born_on]" type="datetime" value="1984-01-12T00:00:00.000+0000" />
- #
- # You can create values for the "min" and "max" attributes by passing
- # instances of Date or Time to the options hash.
- #
- # datetime_field("user", "born_on", min: Date.today)
- # # => <input id="user_born_on" name="user[born_on]" type="datetime" min="2014-05-20T00:00:00.000+0000" />
- #
- # Alternatively, you can pass a String formatted as an ISO8601 datetime
- # with UTC offset as the values for "min" and "max."
- #
- # datetime_field("user", "born_on", min: "2014-05-20T00:00:00+0000")
- # # => <input id="user_born_on" name="user[born_on]" type="datetime" min="2014-05-20T00:00:00.000+0000" />
- #
- def datetime_field(object_name, method, options = {})
- ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
- datetime_field is deprecated and will be removed in Rails 5.1.
- Use datetime_local_field instead.
- MESSAGE
- Tags::DatetimeField.new(object_name, method, self, options).render
- end
-
# Returns a text_field of type "datetime-local".
#
- # datetime_local_field("user", "born_on")
+ # datetime_field("user", "born_on")
# # => <input id="user_born_on" name="user[born_on]" type="datetime-local" />
#
# The default value is generated by trying to call +strftime+ with "%Y-%m-%dT%T"
@@ -1135,25 +1084,27 @@ module ActionView
# of DateTime and ActiveSupport::TimeWithZone.
#
# @user.born_on = Date.new(1984, 1, 12)
- # datetime_local_field("user", "born_on")
+ # datetime_field("user", "born_on")
# # => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="1984-01-12T00:00:00" />
#
# You can create values for the "min" and "max" attributes by passing
# instances of Date or Time to the options hash.
#
- # datetime_local_field("user", "born_on", min: Date.today)
+ # datetime_field("user", "born_on", min: Date.today)
# # => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
#
# Alternatively, you can pass a String formatted as an ISO8601 datetime as
# the values for "min" and "max."
#
- # datetime_local_field("user", "born_on", min: "2014-05-20T00:00:00")
+ # datetime_field("user", "born_on", min: "2014-05-20T00:00:00")
# # => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
#
- def datetime_local_field(object_name, method, options = {})
+ def datetime_field(object_name, method, options = {})
Tags::DatetimeLocalField.new(object_name, method, self, options).render
end
+ alias datetime_local_field datetime_field
+
# Returns a text_field of type "month".
#
# month_field("user", "born_on")
diff --git a/actionview/lib/action_view/helpers/form_tag_helper.rb b/actionview/lib/action_view/helpers/form_tag_helper.rb
index 82f2fd30c7..f1375570f2 100644
--- a/actionview/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionview/lib/action_view/helpers/form_tag_helper.rb
@@ -685,21 +685,6 @@ module ActionView
text_field_tag(name, value, options.merge(type: :time))
end
- # Creates a text field of type "datetime".
- #
- # === Options
- # * <tt>:min</tt> - The minimum acceptable value.
- # * <tt>:max</tt> - The maximum acceptable value.
- # * <tt>:step</tt> - The acceptable value granularity.
- # * Otherwise accepts the same options as text_field_tag.
- def datetime_field_tag(name, value = nil, options = {})
- ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
- datetime_field_tag is deprecated and will be removed in Rails 5.1.
- Use datetime_local_field_tag instead.
- MESSAGE
- text_field_tag(name, value, options.merge(type: :datetime))
- end
-
# Creates a text field of type "datetime-local".
#
# === Options
@@ -707,10 +692,12 @@ module ActionView
# * <tt>:max</tt> - The maximum acceptable value.
# * <tt>:step</tt> - The acceptable value granularity.
# * Otherwise accepts the same options as text_field_tag.
- def datetime_local_field_tag(name, value = nil, options = {})
+ def datetime_field_tag(name, value = nil, options = {})
text_field_tag(name, value, options.merge(type: 'datetime-local'))
end
+ alias datetime_local_field_tag datetime_field_tag
+
# Creates a text field of type "month".
#
# === Options
diff --git a/actionview/lib/action_view/helpers/number_helper.rb b/actionview/lib/action_view/helpers/number_helper.rb
index f0222582c7..23081c5f07 100644
--- a/actionview/lib/action_view/helpers/number_helper.rb
+++ b/actionview/lib/action_view/helpers/number_helper.rb
@@ -263,8 +263,6 @@ module ActionView
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
# insignificant zeros after the decimal separator (defaults to
# +true+)
- # * <tt>:prefix</tt> - If +:si+ formats the number using the SI
- # prefix (defaults to :binary)
# * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
# the argument is invalid.
#
diff --git a/actionview/lib/action_view/helpers/tags/datetime_field.rb b/actionview/lib/action_view/helpers/tags/datetime_field.rb
index b2cee9d198..b3940c7e44 100644
--- a/actionview/lib/action_view/helpers/tags/datetime_field.rb
+++ b/actionview/lib/action_view/helpers/tags/datetime_field.rb
@@ -14,7 +14,7 @@ module ActionView
private
def format_date(value)
- value.try(:strftime, "%Y-%m-%dT%T.%L%z")
+ raise NotImplementedError
end
def datetime_value(value)
diff --git a/actionview/lib/action_view/helpers/tags/file_field.rb b/actionview/lib/action_view/helpers/tags/file_field.rb
index e6a1d9c62d..476b820d84 100644
--- a/actionview/lib/action_view/helpers/tags/file_field.rb
+++ b/actionview/lib/action_view/helpers/tags/file_field.rb
@@ -2,21 +2,6 @@ module ActionView
module Helpers
module Tags # :nodoc:
class FileField < TextField # :nodoc:
-
- def render
- options = @options.stringify_keys
-
- if options.fetch("include_hidden", true)
- add_default_name_and_id(options)
- options[:type] = "file"
- tag("input", name: options["name"], type: "hidden", value: "") + tag("input", options)
- else
- options.delete("include_hidden")
- @options = options
-
- super
- end
- end
end
end
end
diff --git a/actionview/lib/action_view/template/handlers/raw.rb b/actionview/lib/action_view/template/handlers/raw.rb
index 760f517431..e7519e94f9 100644
--- a/actionview/lib/action_view/template/handlers/raw.rb
+++ b/actionview/lib/action_view/template/handlers/raw.rb
@@ -2,7 +2,7 @@ module ActionView
module Template::Handlers
class Raw
def call(template)
- "#{template.source.inspect};"
+ "#{template.source.inspect}.html_safe;"
end
end
end
diff --git a/actionview/test/actionpack/controller/render_test.rb b/actionview/test/actionpack/controller/render_test.rb
index bdb9e0397b..7b69ffc628 100644
--- a/actionview/test/actionpack/controller/render_test.rb
+++ b/actionview/test/actionpack/controller/render_test.rb
@@ -726,11 +726,6 @@ class RenderTest < ActionController::TestCase
assert_equal "Elastica", @response.body
end
- def test_render_process
- get :render_action_hello_world_as_string
- assert_equal "Hello world!", @controller.process(:render_action_hello_world_as_string)
- end
-
# :ported:
def test_render_from_variable
get :render_hello_world_from_variable
diff --git a/actionview/test/fixtures/digestor/api/comments/_comment.json.erb b/actionview/test/fixtures/digestor/api/comments/_comment.json.erb
new file mode 100644
index 0000000000..696eb13917
--- /dev/null
+++ b/actionview/test/fixtures/digestor/api/comments/_comment.json.erb
@@ -0,0 +1 @@
+{"content": "Great story!"}
diff --git a/actionview/test/fixtures/digestor/api/comments/_comments.json.erb b/actionview/test/fixtures/digestor/api/comments/_comments.json.erb
new file mode 100644
index 0000000000..c28646a283
--- /dev/null
+++ b/actionview/test/fixtures/digestor/api/comments/_comments.json.erb
@@ -0,0 +1 @@
+<%= render partial: "comments/comment", collection: commentable.comments %>
diff --git a/actionview/test/fixtures/digestor/messages/thread.json.erb b/actionview/test/fixtures/digestor/messages/thread.json.erb
new file mode 100644
index 0000000000..e4c1ba97cd
--- /dev/null
+++ b/actionview/test/fixtures/digestor/messages/thread.json.erb
@@ -0,0 +1 @@
+<%= render "comments/comments" %>
diff --git a/actionview/test/template/date_helper_test.rb b/actionview/test/template/date_helper_test.rb
index e67d5d0e8c..0f89f2ca09 100644
--- a/actionview/test/template/date_helper_test.rb
+++ b/actionview/test/template/date_helper_test.rb
@@ -534,6 +534,13 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, select_year(nil, start_year: 2003, end_year: 2005, with_css_classes: { year: 'my-year' })
end
+
+ def test_select_year_with_position
+ expected = %(<select id="date_year_1i" name="date[year(1i)]">\n)
+ expected << %(<option value="2003">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n)
+ expected << "</select>\n"
+ assert_dom_equal expected, select_year(Date.current, include_position: true, start_year: 2003, end_year: 2005)
+ end
def test_select_hour
expected = %(<select id="date_hour" name="date[hour]">\n)
diff --git a/actionview/test/template/digestor_test.rb b/actionview/test/template/digestor_test.rb
index 4750d2a5a3..410f562f07 100644
--- a/actionview/test/template/digestor_test.rb
+++ b/actionview/test/template/digestor_test.rb
@@ -17,7 +17,14 @@ class FixtureFinder < ActionView::LookupContext
FIXTURES_DIR = "#{File.dirname(__FILE__)}/../fixtures/digestor"
def initialize(details = {})
- super(ActionView::PathSet.new(['digestor']), details, [])
+ super(ActionView::PathSet.new(['digestor', 'digestor/api']), details, [])
+ @rendered_format = :html
+ end
+end
+
+class ActionView::Digestor::Node
+ def flatten
+ [self] + children.flat_map(&:flatten)
end
end
@@ -147,6 +154,21 @@ class TemplateDigestorTest < ActionView::TestCase
assert_equal nested_deps, nested_dependencies("messages/show")
end
+ def test_nested_template_deps_with_non_default_rendered_format
+ finder.rendered_format = nil
+ nested_deps = [{"comments/comments"=>["comments/comment"]}]
+ assert_equal nested_deps, nested_dependencies("messages/thread")
+ end
+
+ def test_template_formats_of_nested_deps_with_non_default_rendered_format
+ finder.rendered_format = nil
+ assert_equal [:json], tree_template_formats("messages/thread").uniq
+ end
+
+ def test_template_formats_of_dependencies_with_same_logical_name_and_different_rendered_format
+ assert_equal [:html], tree_template_formats("messages/show").uniq
+ end
+
def test_recursion_in_renders
assert digest("level/recursion") # assert recursion is possible
assert_not_nil digest("level/recursion") # assert digest is stored
@@ -258,6 +280,13 @@ class TemplateDigestorTest < ActionView::TestCase
assert_not_equal digest_phone, digest_fridge_phone
end
+ def test_different_formats_with_same_logical_template_names_results_in_different_digests
+ html_digest = digest("comments/_comment", format: :html)
+ json_digest = digest("comments/_comment", format: :json)
+
+ assert_not_equal html_digest, json_digest
+ end
+
def test_digest_cache_cleanup_with_recursion
first_digest = digest("level/_recursion")
second_digest = digest("level/_recursion")
@@ -280,7 +309,6 @@ class TemplateDigestorTest < ActionView::TestCase
end
end
-
private
def assert_logged(message)
old_logger = ActionView::Base.logger
@@ -309,8 +337,11 @@ class TemplateDigestorTest < ActionView::TestCase
def digest(template_name, options = {})
options = options.dup
+ finder_options = options.extract!(:variants, :format)
+
+ finder.variants = finder_options[:variants] || []
+ finder.rendered_format = finder_options[:format] if finder_options[:format]
- finder.variants = options.delete(:variants) || []
ActionView::Digestor.digest(name: template_name, finder: finder, dependencies: (options[:dependencies] || []))
end
@@ -324,6 +355,11 @@ class TemplateDigestorTest < ActionView::TestCase
tree.children.map(&:to_dep_map)
end
+ def tree_template_formats(template_name)
+ tree = ActionView::Digestor.tree(template_name, finder)
+ tree.flatten.map(&:template).compact.flat_map(&:formats)
+ end
+
def disable_resolver_caching
old_caching, ActionView::Resolver.caching = ActionView::Resolver.caching, false
yield
diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb
index 310d0ce514..54da2b0c9c 100644
--- a/actionview/test/template/form_helper_test.rb
+++ b/actionview/test/template/form_helper_test.rb
@@ -528,33 +528,18 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, text_field(object_name, "title")
end
- def test_file_field_does_generate_a_hidden_field
- expected = '<input name="user[avatar]" type="hidden" value="" /><input id="user_avatar" name="user[avatar]" type="file" />'
- assert_dom_equal expected, file_field("user", "avatar")
- end
-
- def test_file_field_does_not_generate_a_hidden_field_if_included_hidden_option_is_false
- expected = '<input id="user_avatar" name="user[avatar]" type="file" />'
- assert_dom_equal expected, file_field("user", "avatar", include_hidden: false)
- end
-
- def test_file_field_does_not_generate_a_hidden_field_if_included_hidden_option_is_false_with_key_as_string
- expected = '<input id="user_avatar" name="user[avatar]" type="file" />'
- assert_dom_equal expected, file_field("user", "avatar", "include_hidden" => false)
- end
-
def test_file_field_has_no_size
- expected = '<input name="user[avatar]" type="hidden" value="" /><input id="user_avatar" name="user[avatar]" type="file" />'
+ expected = '<input id="user_avatar" name="user[avatar]" type="file" />'
assert_dom_equal expected, file_field("user", "avatar")
end
def test_file_field_with_multiple_behavior
- expected = '<input name="import[file][]" type="hidden" value="" /><input id="import_file" multiple="multiple" name="import[file][]" type="file" />'
+ expected = '<input id="import_file" multiple="multiple" name="import[file][]" type="file" />'
assert_dom_equal expected, file_field("import", "file", :multiple => true)
end
def test_file_field_with_multiple_behavior_and_explicit_name
- expected = '<input name="custom" type="hidden" value="" /><input id="import_file" multiple="multiple" name="custom" type="file" />'
+ expected = '<input id="import_file" multiple="multiple" name="custom" type="file" />'
assert_dom_equal expected, file_field("import", "file", :multiple => true, :name => "custom")
end
@@ -1138,76 +1123,60 @@ class FormHelperTest < ActionView::TestCase
end
def test_datetime_field
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T00:00:00.000+0000" />}
- assert_deprecated do
- assert_dom_equal(expected, datetime_field("post", "written_on"))
- end
+ expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T00:00:00" />}
+ assert_dom_equal(expected, datetime_field("post", "written_on"))
end
def test_datetime_field_with_datetime_value
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T01:02:03.000+0000" />}
+ expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />}
@post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
- assert_deprecated do
- assert_dom_equal(expected, datetime_field("post", "written_on"))
- end
+ assert_dom_equal(expected, datetime_field("post", "written_on"))
end
def test_datetime_field_with_extra_attrs
- expected = %{<input id="post_written_on" step="60" max="2010-08-15T10:25:00.000+0000" min="2000-06-15T20:45:30.000+0000" name="post[written_on]" type="datetime" value="2004-06-15T01:02:03.000+0000" />}
+ expected = %{<input id="post_written_on" step="60" max="2010-08-15T10:25:00" min="2000-06-15T20:45:30" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />}
@post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
min_value = DateTime.new(2000, 6, 15, 20, 45, 30)
max_value = DateTime.new(2010, 8, 15, 10, 25, 00)
step = 60
- assert_deprecated do
- assert_dom_equal(expected, datetime_field("post", "written_on", min: min_value, max: max_value, step: step))
- end
+ assert_dom_equal(expected, datetime_field("post", "written_on", min: min_value, max: max_value, step: step))
end
def test_datetime_field_with_value_attr
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2013-06-29T13:37:00+00:00" />}
+ expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2013-06-29T13:37:00+00:00" />}
value = DateTime.new(2013,6,29,13,37)
- assert_deprecated do
- assert_dom_equal(expected, datetime_field("post", "written_on", value: value))
- end
+ assert_dom_equal(expected, datetime_field("post", "written_on", value: value))
end
def test_datetime_field_with_timewithzone_value
previous_time_zone, Time.zone = Time.zone, 'UTC'
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T15:30:45.000+0000" />}
+ expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T15:30:45" />}
@post.written_on = Time.zone.parse('2004-06-15 15:30:45')
- assert_deprecated do
- assert_dom_equal(expected, datetime_field("post", "written_on"))
- end
+ assert_dom_equal(expected, datetime_field("post", "written_on"))
ensure
Time.zone = previous_time_zone
end
def test_datetime_field_with_nil_value
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" />}
+ expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" />}
@post.written_on = nil
- assert_deprecated do
- assert_dom_equal(expected, datetime_field("post", "written_on"))
- end
+ assert_dom_equal(expected, datetime_field("post", "written_on"))
end
def test_datetime_field_with_string_values_for_min_and_max
- expected = %{<input id="post_written_on" max="2010-08-15T10:25:00.000+0000" min="2000-06-15T20:45:30.000+0000" name="post[written_on]" type="datetime" value="2004-06-15T01:02:03.000+0000" />}
+ expected = %{<input id="post_written_on" max="2010-08-15T10:25:00" min="2000-06-15T20:45:30" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />}
@post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
- min_value = "2000-06-15T20:45:30.000+0000"
- max_value = "2010-08-15T10:25:00.000+0000"
- assert_deprecated do
- assert_dom_equal(expected, datetime_field("post", "written_on", min: min_value, max: max_value))
- end
+ min_value = "2000-06-15T20:45:30"
+ max_value = "2010-08-15T10:25:00"
+ assert_dom_equal(expected, datetime_field("post", "written_on", min: min_value, max: max_value))
end
def test_datetime_field_with_invalid_string_values_for_min_and_max
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T01:02:03.000+0000" />}
+ expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />}
@post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
min_value = "foo"
max_value = "bar"
- assert_deprecated do
- assert_dom_equal(expected, datetime_field("post", "written_on", min: min_value, max: max_value))
- end
+ assert_dom_equal(expected, datetime_field("post", "written_on", min: min_value, max: max_value))
end
def test_datetime_local_field
@@ -1215,52 +1184,6 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal(expected, datetime_local_field("post", "written_on"))
end
- def test_datetime_local_field_with_datetime_value
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />}
- @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
- assert_dom_equal(expected, datetime_local_field("post", "written_on"))
- end
-
- def test_datetime_local_field_with_extra_attrs
- expected = %{<input id="post_written_on" step="60" max="2010-08-15T10:25:00" min="2000-06-15T20:45:30" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />}
- @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
- min_value = DateTime.new(2000, 6, 15, 20, 45, 30)
- max_value = DateTime.new(2010, 8, 15, 10, 25, 00)
- step = 60
- assert_dom_equal(expected, datetime_local_field("post", "written_on", min: min_value, max: max_value, step: step))
- end
-
- def test_datetime_local_field_with_timewithzone_value
- previous_time_zone, Time.zone = Time.zone, 'UTC'
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T15:30:45" />}
- @post.written_on = Time.zone.parse('2004-06-15 15:30:45')
- assert_dom_equal(expected, datetime_local_field("post", "written_on"))
- ensure
- Time.zone = previous_time_zone
- end
-
- def test_datetime_local_field_with_nil_value
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" />}
- @post.written_on = nil
- assert_dom_equal(expected, datetime_local_field("post", "written_on"))
- end
-
- def test_datetime_local_field_with_string_values_for_min_and_max
- expected = %{<input id="post_written_on" max="2010-08-15T10:25:00" min="2000-06-15T20:45:30" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />}
- @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
- min_value = "2000-06-15T20:45:30"
- max_value = "2010-08-15T10:25:00"
- assert_dom_equal(expected, datetime_local_field("post", "written_on", min: min_value, max: max_value))
- end
-
- def test_datetime_local_field_with_invalid_string_values_for_min_and_max
- expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />}
- @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3)
- min_value = "foo"
- max_value = "bar"
- assert_dom_equal(expected, datetime_local_field("post", "written_on", min: min_value, max: max_value))
- end
-
def test_month_field
expected = %{<input id="post_written_on" name="post[written_on]" type="month" value="2004-06" />}
assert_dom_equal(expected, month_field("post", "written_on"))
@@ -1838,7 +1761,7 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts/123", "create-post", "edit_post", method: "patch", multipart: true) do
- "<input name='post[file]' type='hidden' value='' /><input name='post[file]' type='file' id='post_file' />"
+ "<input name='post[file]' type='file' id='post_file' />"
end
assert_dom_equal expected, output_buffer
@@ -1854,7 +1777,7 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts/123", "edit_post_123", "edit_post", method: "patch", multipart: true) do
- "<input name='post[comment][file]' type='hidden' value='' /><input name='post[comment][file]' type='file' id='post_comment_file' />"
+ "<input name='post[comment][file]' type='file' id='post_comment_file' />"
end
assert_dom_equal expected, output_buffer
diff --git a/actionview/test/template/form_tag_helper_test.rb b/actionview/test/template/form_tag_helper_test.rb
index 5b0b708618..4fdca4976f 100644
--- a/actionview/test/template/form_tag_helper_test.rb
+++ b/actionview/test/template/form_tag_helper_test.rb
@@ -621,10 +621,8 @@ class FormTagHelperTest < ActionView::TestCase
end
def test_datetime_field_tag
- expected = %{<input id="appointment" name="appointment" type="datetime" />}
- assert_deprecated do
- assert_dom_equal(expected, datetime_field_tag("appointment"))
- end
+ expected = %{<input id="appointment" name="appointment" type="datetime-local" />}
+ assert_dom_equal(expected, datetime_field_tag("appointment"))
end
def test_datetime_local_field_tag
diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb
index ad93236d32..25b21850b1 100644
--- a/actionview/test/template/render_test.rb
+++ b/actionview/test/template/render_test.rb
@@ -100,6 +100,13 @@ module RenderTestCases
assert_equal %q;Here are some characters: !@#$%^&*()-="'}{`; + "\n", @view.render(:template => "plain_text_with_characters")
end
+ def test_render_raw_is_html_safe_and_does_not_escape_output
+ buffer = ActiveSupport::SafeBuffer.new
+ buffer << @view.render(file: "plain_text")
+ assert_equal true, buffer.html_safe?
+ assert_equal buffer, "<%= hello_world %>\n"
+ end
+
def test_render_ruby_template_with_handlers
assert_equal "Hello from Ruby code", @view.render(:template => "ruby_template")
end
diff --git a/activejob/lib/active_job/logging.rb b/activejob/lib/active_job/logging.rb
index 605057d1e8..d5c7920131 100644
--- a/activejob/lib/active_job/logging.rb
+++ b/activejob/lib/active_job/logging.rb
@@ -41,7 +41,7 @@ module ActiveJob
def tag_logger(*tags)
if logger.respond_to?(:tagged)
tags.unshift "ActiveJob" unless logger_tagged_by_active_job?
- ActiveJob::Base.logger.tagged(*tags){ yield }
+ logger.tagged(*tags){ yield }
else
yield
end
diff --git a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
index 311109e958..163c8eb212 100644
--- a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb
@@ -5,7 +5,7 @@ module ActiveJob
# == Sucker Punch adapter for Active Job
#
# Sucker Punch is a single-process Ruby asynchronous processing library.
- # This reduces the cost of of hosting on a service like Heroku along
+ # This reduces the cost of hosting on a service like Heroku along
# with the memory footprint of having to maintain additional jobs if
# hosting on a dedicated server. All queues can run within a
# single application (eg. Rails, Sinatra, etc.) process.
diff --git a/activejob/lib/active_job/test_helper.rb b/activejob/lib/active_job/test_helper.rb
index 3feb82d432..e16af1947f 100644
--- a/activejob/lib/active_job/test_helper.rb
+++ b/activejob/lib/active_job/test_helper.rb
@@ -9,7 +9,7 @@ module ActiveJob
to: :queue_adapter
def before_setup # :nodoc:
- test_adapter = ActiveJob::QueueAdapters::TestAdapter.new
+ test_adapter = queue_adapter_for_test
@old_queue_adapters = (ActiveJob::Base.subclasses << ActiveJob::Base).select do |klass|
# only override explicitly set adapters, a quirk of `class_attribute`
@@ -32,6 +32,19 @@ module ActiveJob
end
end
+ # Specifies the queue adapter to use with all active job test helpers.
+ #
+ # Returns an instance of the queue adapter and defaults to
+ # <tt>ActiveJob::QueueAdapters::TestAdapter</tt>.
+ #
+ # Note: The adapter provided by this method must provide some additional
+ # methods from those expected of a standard <tt>ActiveJob::QueueAdapter</tt>
+ # in order to be used with the active job test helpers. Refer to
+ # <tt>ActiveJob::QueueAdapters::TestAdapter</tt>.
+ def queue_adapter_for_test
+ ActiveJob::QueueAdapters::TestAdapter.new
+ end
+
# Asserts that the number of enqueued jobs matches the given number.
#
# def test_jobs
diff --git a/activejob/test/cases/logging_test.rb b/activejob/test/cases/logging_test.rb
index 820e9112de..bf8a66432a 100644
--- a/activejob/test/cases/logging_test.rb
+++ b/activejob/test/cases/logging_test.rb
@@ -3,6 +3,7 @@ require "active_support/log_subscriber/test_helper"
require 'active_support/core_ext/numeric/time'
require 'jobs/hello_job'
require 'jobs/logging_job'
+require 'jobs/overridden_logging_job'
require 'jobs/nested_job'
require 'models/person'
@@ -41,7 +42,6 @@ class LoggingTest < ActiveSupport::TestCase
ActiveJob::Base.logger = logger
end
-
def test_uses_active_job_as_tag
HelloJob.perform_later "Cristian"
assert_match(/\[ActiveJob\]/, @logger.messages)
@@ -119,4 +119,9 @@ class LoggingTest < ActiveSupport::TestCase
rescue NotImplementedError
skip
end
+
+ def test_for_tagged_logger_support_is_consistent
+ set_logger ::Logger.new(nil)
+ OverriddenLoggingJob.perform_later "Dummy"
+ end
end
diff --git a/activejob/test/cases/test_helper_test.rb b/activejob/test/cases/test_helper_test.rb
index f7ee763e8a..3d863f5e65 100644
--- a/activejob/test/cases/test_helper_test.rb
+++ b/activejob/test/cases/test_helper_test.rb
@@ -509,3 +509,15 @@ class PerformedJobsTest < ActiveJob::TestCase
assert_equal 2, ActiveJob::Base.queue_adapter.performed_jobs.count
end
end
+
+class OverrideQueueAdapterTest < ActiveJob::TestCase
+ class CustomQueueAdapter < ActiveJob::QueueAdapters::TestAdapter; end
+
+ def queue_adapter_for_test
+ CustomQueueAdapter.new
+ end
+
+ def test_assert_job_has_custom_queue_adapter_set
+ assert_instance_of CustomQueueAdapter, HelloJob.queue_adapter
+ end
+end
diff --git a/activejob/test/jobs/overridden_logging_job.rb b/activejob/test/jobs/overridden_logging_job.rb
new file mode 100644
index 0000000000..2b17a65142
--- /dev/null
+++ b/activejob/test/jobs/overridden_logging_job.rb
@@ -0,0 +1,9 @@
+class OverriddenLoggingJob < ActiveJob::Base
+ def perform(dummy)
+ logger.info "Dummy, here is it: #{dummy}"
+ end
+
+ def logger
+ @logger ||= ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(nil))
+ end
+end
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 6f2c8c1c53..2f883917b0 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -147,9 +147,9 @@ module ActiveModel
# Delete messages for +key+. Returns the deleted messages.
#
- # person.errors[:name] # => ["cannot be nil"]
+ # person.errors[:name] # => ["cannot be nil"]
# person.errors.delete(:name) # => ["cannot be nil"]
- # person.errors[:name] # => []
+ # person.errors[:name] # => []
def delete(key)
details.delete(key)
messages.delete(key)
@@ -382,10 +382,21 @@ module ActiveModel
end
# Returns +true+ if an error on the attribute with the given message is
- # present, +false+ otherwise. +message+ is treated the same as for +add+.
+ # present, or +false+ otherwise. +message+ is treated the same as for +add+.
#
# person.errors.add :name, :blank
- # person.errors.added? :name, :blank # => true
+ # person.errors.added? :name, :blank # => true
+ # person.errors.added? :name, "can't be blank" # => true
+ #
+ # If the error message requires an option, then it returns +true+ with
+ # the correct option, or +false+ with an incorrect or missing option.
+ #
+ # person.errors.add :name, :too_long, { count: 25 }
+ # person.errors.added? :name, :too_long, count: 25 # => true
+ # person.errors.added? :name, "is too long (maximum is 25 characters)" # => true
+ # person.errors.added? :name, :too_long, count: 24 # => false
+ # person.errors.added? :name, :too_long # => false
+ # person.errors.added? :name, "is too long" # => false
def added?(attribute, message = :invalid, options = {})
message = message.call if message.respond_to?(:call)
message = normalize_message(attribute, message, options)
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 8159b9b1d3..a10d2285a2 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -304,8 +304,6 @@ module ActiveModel
# Runs all the specified validations and returns +true+ if no errors were
# added otherwise +false+.
#
- # Aliased as validate.
- #
# class Person
# include ActiveModel::Validations
#
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index c90ee7021c..13fa5c76bc 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -219,6 +219,12 @@ class ErrorsTest < ActiveModel::TestCase
assert !person.errors.added?(:name, "cannot be blank")
end
+ test "added? returns false when checking for an error, but not providing message arguments" do
+ person = Person.new
+ person.errors.add(:name, "cannot be blank")
+ assert !person.errors.added?(:name)
+ end
+
test "size calculates the number of error messages" do
person = Person.new
person.errors.add(:name, "cannot be blank")
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index a1a4d2646f..0bd3c2e78c 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -18,4 +18,18 @@
*Erol Fornoles*
+* PostgreSQL: Fix db:structure:load silent failure on SQL error
+
+ The command line flag "-v ON_ERROR_STOP=1" should be used
+ when invoking psql to make sure errors are not suppressed.
+
+ Example:
+
+ psql -v ON_ERROR_STOP=1 -q -f awesome-file.sql my-app-db
+
+ Fixes #23818.
+
+ *Ralin Chimev*
+
+
Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/activerecord/CHANGELOG.md) for previous changes.
diff --git a/activerecord/lib/active_record/attribute_set/yaml_encoder.rb b/activerecord/lib/active_record/attribute_set/yaml_encoder.rb
index 6208048231..f9d527a5a3 100644
--- a/activerecord/lib/active_record/attribute_set/yaml_encoder.rb
+++ b/activerecord/lib/active_record/attribute_set/yaml_encoder.rb
@@ -2,7 +2,7 @@ module ActiveRecord
class AttributeSet
# Attempts to do more intelligent YAML dumping of an
# ActiveRecord::AttributeSet to reduce the size of the resulting string
- class YAMLEncoder
+ class YAMLEncoder # :nodoc:
def initialize(default_types)
@default_types = default_types
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index 5939ee9956..eec0bc8518 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -790,7 +790,7 @@ module ActiveRecord
# [<tt>:type</tt>]
# The reference column type. Defaults to +:integer+.
# [<tt>:index</tt>]
- # Add an appropriate index. Defaults to false.
+ # Add an appropriate index. Defaults to false.
# See #add_index for usage of this option.
# [<tt>:foreign_key</tt>]
# Add an appropriate foreign key constraint. Defaults to false.
@@ -1128,7 +1128,6 @@ module ActiveRecord
index_type ||= options[:unique] ? "UNIQUE" : ""
index_name = options[:name].to_s if options.key?(:name)
index_name ||= index_name(table_name, index_name_options(column_names))
- max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
if options.key?(:algorithm)
algorithm = index_algorithms.fetch(options[:algorithm]) {
@@ -1142,9 +1141,8 @@ module ActiveRecord
index_options = options[:where] ? " WHERE #{options[:where]}" : ""
end
- if index_name.length > max_index_length
- raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{max_index_length} characters"
- end
+ validate_index_length!(table_name, index_name, options.fetch(:internal, false))
+
if data_source_exists?(table_name) && index_name_exists?(table_name, index_name, false)
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
end
@@ -1276,8 +1274,10 @@ module ActiveRecord
end
end
- def validate_index_length!(table_name, new_name) # :nodoc:
- if new_name.length > allowed_index_name_length
+ def validate_index_length!(table_name, new_name, internal = false) # :nodoc:
+ max_index_length = internal ? index_name_length : allowed_index_name_length
+
+ if new_name.length > max_index_length
raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters"
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql/column.rb b/activerecord/lib/active_record/connection_adapters/mysql/column.rb
index 9c45fdd44a..ea554b188c 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql/column.rb
@@ -6,7 +6,6 @@ module ActiveRecord
def initialize(*)
super
- assert_valid_default
extract_default
end
@@ -38,12 +37,6 @@ module ActiveRecord
@default = null || strict ? nil : ''
end
end
-
- def assert_valid_default
- if blob_or_text_column? && default.present?
- raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}"
- end
- end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 6318b1c65a..f6860b9aba 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -641,7 +641,7 @@ module ActiveRecord
when 1, 2; 'smallint'
when nil, 3, 4; 'integer'
when 5..8; 'bigint'
- else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
+ else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead.")
end
else
super(type, limit, precision, scale)
diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb
index 086c678af5..99fdef67d0 100644
--- a/activerecord/lib/active_record/connection_handling.rb
+++ b/activerecord/lib/active_record/connection_handling.rb
@@ -131,7 +131,7 @@ module ActiveRecord
def remove_connection(name = nil)
name ||= @connection_specification_name if defined?(@connection_specification_name)
- # if removing a connection that have a pool, we reset the
+ # if removing a connection that has a pool, we reset the
# connection_specification_name so it will use the parent
# pool.
if connection_handler.retrieve_connection_pool(name)
diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb
index 7be332fb97..b884edf920 100644
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ -105,6 +105,8 @@ module ActiveRecord
end
class EnumType < Type::Value # :nodoc:
+ delegate :type, to: :subtype
+
def initialize(name, mapping, subtype)
@name = name
@mapping = mapping
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index ed1bbf5dcd..51bf12d0bf 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -66,7 +66,7 @@ module ActiveRecord
# By default, +test_helper.rb+ will load all of your fixtures into your test
# database, so this test will succeed.
#
- # The testing environment will automatically load the all fixtures into the database before each
+ # The testing environment will automatically load all the fixtures into the database before each
# test. To ensure consistent data, the environment deletes the fixtures before running the load.
#
# In addition to being available in the database, the fixture's data may also be accessed by
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index 899683ee4f..b5fec57c8c 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -19,7 +19,7 @@ module ActiveRecord
# Be aware that because the type column is an attribute on the record every new
# subclass will instantly be marked as dirty and the type column will be included
# in the list of changed attributes on the record. This is different from non
- # STI classes:
+ # Single Table Inheritance(STI) classes:
#
# Company.new.changed? # => false
# Firm.new.changed? # => true
@@ -37,6 +37,7 @@ module ActiveRecord
included do
# Determines whether to store the full constant name including namespace when using STI.
+ # This is true, by default.
class_attribute :store_full_sti_class, instance_writer: false
self.store_full_sti_class = true
end
diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb
index ca12a603da..07d863d15e 100644
--- a/activerecord/lib/active_record/query_cache.rb
+++ b/activerecord/lib/active_record/query_cache.rb
@@ -5,7 +5,7 @@ module ActiveRecord
# Enable the query cache within the block if Active Record is configured.
# If it's not, it will execute the given block.
def cache(&block)
- if ActiveRecord::Base.connected?
+ if connected?
connection.cache(&block)
else
yield
@@ -15,7 +15,7 @@ module ActiveRecord
# Disable the query cache within the block if Active Record is configured.
# If it's not, it will execute the given block.
def uncached(&block)
- if ActiveRecord::Base.connected?
+ if connected?
connection.uncached(&block)
else
yield
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 87eea8277a..d255cad91b 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -333,6 +333,8 @@ module ActiveRecord
end
connection.select_value(relation, "#{name} Exists", relation.bound_attributes) ? true : false
+ rescue RangeError
+ false
end
# This method is called whenever no records are found with either a single
@@ -398,15 +400,7 @@ module ActiveRecord
end
def construct_relation_for_association_calculations
- from = arel.froms.first
- if Arel::Table === from
- apply_join_dependency(self, construct_join_dependency(joins_values))
- else
- # FIXME: as far as I can tell, `from` will always be an Arel::Table.
- # There are no tests that test this branch, but presumably it's
- # possible for `from` to be a list?
- apply_join_dependency(self, construct_join_dependency(from))
- end
+ apply_join_dependency(self, construct_join_dependency(joins_values))
end
def apply_join_dependency(relation, join_dependency)
@@ -579,7 +573,7 @@ module ActiveRecord
# e.g., reverse_order.offset(index-1).first
end
end
-
+
private
def find_nth_with_limit_and_offset(index, limit, offset:) # :nodoc:
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 2a831c2017..8a87015e44 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -658,7 +658,7 @@ module ActiveRecord
# present). Neither relation may have a #limit, #offset, or #distinct set.
#
# Post.where("id = 1").or(Post.where("author_id = 3"))
- # # SELECT `posts`.* FROM `posts` WHERE (('id = 1' OR 'author_id = 3'))
+ # # SELECT `posts`.* FROM `posts` WHERE ((id = 1) OR (author_id = 3))
#
def or(other)
unless other.is_a? Relation
diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
index af0c935342..b1a0ad0115 100644
--- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
@@ -58,6 +58,7 @@ module ActiveRecord
args.concat(["--result-file", "#{filename}"])
args.concat(["--no-data"])
args.concat(["--routines"])
+ args.concat(["--skip-comments"])
args.concat(["#{configuration['database']}"])
run_cmd('mysqldump', args, 'dumping')
diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb
index 8b4874044c..b19ab57ee4 100644
--- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb
@@ -2,6 +2,7 @@ module ActiveRecord
module Tasks # :nodoc:
class PostgreSQLDatabaseTasks # :nodoc:
DEFAULT_ENCODING = ENV['CHARSET'] || 'utf8'
+ ON_ERROR_STOP_1 = 'ON_ERROR_STOP=1'.freeze
delegate :connection, :establish_connection, :clear_active_connections!,
to: ActiveRecord::Base
@@ -67,7 +68,7 @@ module ActiveRecord
def structure_load(filename)
set_psql_env
- args = [ '-q', '-f', filename, configuration['database'] ]
+ args = [ '-v', ON_ERROR_STOP_1, '-q', '-f', filename, configuration['database'] ]
run_cmd('psql', args, 'loading' )
end
diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb
index 1f59276137..ec9f498c40 100644
--- a/activerecord/lib/active_record/validations/uniqueness.rb
+++ b/activerecord/lib/active_record/validations/uniqueness.rb
@@ -65,8 +65,6 @@ module ActiveRecord
column = klass.columns_hash[attribute_name]
cast_type = klass.type_for_attribute(attribute_name)
- value = cast_type.serialize(value)
- value = klass.connection.type_cast(value)
comparison = if !options[:case_sensitive] && !value.nil?
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
@@ -77,11 +75,9 @@ module ActiveRecord
if value.nil?
klass.unscoped.where(comparison)
else
- bind = Relation::QueryAttribute.new(attribute_name, value, Type::Value.new)
+ bind = Relation::QueryAttribute.new(attribute_name, value, cast_type)
klass.unscoped.where(comparison, bind)
end
- rescue RangeError
- klass.none
end
def scope_relation(record, table, relation)
diff --git a/activerecord/lib/rails/generators/active_record/model/model_generator.rb b/activerecord/lib/rails/generators/active_record/model/model_generator.rb
index f191eff5bf..0d72913258 100644
--- a/activerecord/lib/rails/generators/active_record/model/model_generator.rb
+++ b/activerecord/lib/rails/generators/active_record/model/model_generator.rb
@@ -21,14 +21,14 @@ module ActiveRecord
end
def create_model_file
- template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
generate_application_record
+ template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
end
def create_module_file
return if regular_class_path.empty?
- template 'module.rb', File.join('app/models', "#{class_path.join('/')}.rb") if behavior == :invoke
generate_application_record
+ template 'module.rb', File.join('app/models', "#{class_path.join('/')}.rb") if behavior == :invoke
end
hook_for :test_framework
@@ -48,7 +48,7 @@ module ActiveRecord
# Used by the migration template to determine the parent name of the model
def parent_class_name
- options[:parent] || determine_default_parent_class
+ options[:parent] || 'ApplicationRecord'
end
def application_record_exist?
@@ -64,14 +64,6 @@ module ActiveRecord
'app/models/application_record.rb'
end
end
-
- def determine_default_parent_class
- if application_record_exist?
- "ApplicationRecord"
- else
- "ActiveRecord::Base"
- end
- end
end
end
end
diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
index f3ec2b98d3..fe2425b845 100644
--- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
@@ -3,98 +3,92 @@ require 'bigdecimal'
require 'yaml'
require 'securerandom'
-module ActiveRecord
- module ConnectionAdapters
- class SQLite3Adapter
- class QuotingTest < ActiveRecord::SQLite3TestCase
- def setup
- @conn = ActiveRecord::Base.connection
- end
-
- def test_type_cast_binary_encoding_without_logger
- @conn.extend(Module.new { def logger; end })
- binary = SecureRandom.hex
- expected = binary.dup.encode!(Encoding::UTF_8)
- assert_equal expected, @conn.type_cast(binary)
- end
-
- def test_type_cast_symbol
- assert_equal 'foo', @conn.type_cast(:foo)
- end
-
- def test_type_cast_date
- date = Date.today
- expected = @conn.quoted_date(date)
- assert_equal expected, @conn.type_cast(date)
- end
-
- def test_type_cast_time
- time = Time.now
- expected = @conn.quoted_date(time)
- assert_equal expected, @conn.type_cast(time)
- end
-
- def test_type_cast_numeric
- assert_equal 10, @conn.type_cast(10)
- assert_equal 2.2, @conn.type_cast(2.2)
- end
-
- def test_type_cast_nil
- assert_equal nil, @conn.type_cast(nil)
- end
-
- def test_type_cast_true
- assert_equal 't', @conn.type_cast(true)
- end
-
- def test_type_cast_false
- assert_equal 'f', @conn.type_cast(false)
- end
-
- def test_type_cast_bigdecimal
- bd = BigDecimal.new '10.0'
- assert_equal bd.to_f, @conn.type_cast(bd)
- end
-
- def test_type_cast_unknown_should_raise_error
- obj = Class.new.new
- assert_raise(TypeError) { @conn.type_cast(obj) }
- end
-
- def test_type_cast_object_which_responds_to_quoted_id
- quoted_id_obj = Class.new {
- def quoted_id
- "'zomg'"
- end
-
- def id
- 10
- end
- }.new
- assert_equal 10, @conn.type_cast(quoted_id_obj)
-
- quoted_id_obj = Class.new {
- def quoted_id
- "'zomg'"
- end
- }.new
- assert_raise(TypeError) { @conn.type_cast(quoted_id_obj) }
- end
-
- def test_quoting_binary_strings
- value = "hello".encode('ascii-8bit')
- type = Type::String.new
-
- assert_equal "'hello'", @conn.quote(type.serialize(value))
- end
-
- def test_quoted_time_returns_date_qualified_time
- value = ::Time.utc(2000, 1, 1, 12, 30, 0, 999999)
- type = Type::Time.new
-
- assert_equal "'2000-01-01 12:30:00.999999'", @conn.quote(type.serialize(value))
- end
+class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase
+ def setup
+ @conn = ActiveRecord::Base.connection
+ end
+
+ def test_type_cast_binary_encoding_without_logger
+ @conn.extend(Module.new { def logger; end })
+ binary = SecureRandom.hex
+ expected = binary.dup.encode!(Encoding::UTF_8)
+ assert_equal expected, @conn.type_cast(binary)
+ end
+
+ def test_type_cast_symbol
+ assert_equal 'foo', @conn.type_cast(:foo)
+ end
+
+ def test_type_cast_date
+ date = Date.today
+ expected = @conn.quoted_date(date)
+ assert_equal expected, @conn.type_cast(date)
+ end
+
+ def test_type_cast_time
+ time = Time.now
+ expected = @conn.quoted_date(time)
+ assert_equal expected, @conn.type_cast(time)
+ end
+
+ def test_type_cast_numeric
+ assert_equal 10, @conn.type_cast(10)
+ assert_equal 2.2, @conn.type_cast(2.2)
+ end
+
+ def test_type_cast_nil
+ assert_equal nil, @conn.type_cast(nil)
+ end
+
+ def test_type_cast_true
+ assert_equal 't', @conn.type_cast(true)
+ end
+
+ def test_type_cast_false
+ assert_equal 'f', @conn.type_cast(false)
+ end
+
+ def test_type_cast_bigdecimal
+ bd = BigDecimal.new '10.0'
+ assert_equal bd.to_f, @conn.type_cast(bd)
+ end
+
+ def test_type_cast_unknown_should_raise_error
+ obj = Class.new.new
+ assert_raise(TypeError) { @conn.type_cast(obj) }
+ end
+
+ def test_type_cast_object_which_responds_to_quoted_id
+ quoted_id_obj = Class.new {
+ def quoted_id
+ "'zomg'"
+ end
+
+ def id
+ 10
end
- end
+ }.new
+ assert_equal 10, @conn.type_cast(quoted_id_obj)
+
+ quoted_id_obj = Class.new {
+ def quoted_id
+ "'zomg'"
+ end
+ }.new
+ assert_raise(TypeError) { @conn.type_cast(quoted_id_obj) }
+ end
+
+ def test_quoting_binary_strings
+ value = "hello".encode('ascii-8bit')
+ type = ActiveRecord::Type::String.new
+
+ assert_equal "'hello'", @conn.quote(type.serialize(value))
+ end
+
+ def test_quoted_time_returns_date_qualified_time
+ value = ::Time.utc(2000, 1, 1, 12, 30, 0, 999999)
+ type = ActiveRecord::Type::Time.new
+
+ assert_equal "'2000-01-01 12:30:00.999999'", @conn.quote(type.serialize(value))
end
end
diff --git a/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb b/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb
index 559b951109..24cc6875ab 100644
--- a/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb
@@ -1,24 +1,20 @@
require 'cases/helper'
-module ActiveRecord::ConnectionAdapters
- class SQLite3Adapter
- class StatementPoolTest < ActiveRecord::SQLite3TestCase
- if Process.respond_to?(:fork)
- def test_cache_is_per_pid
+class SQLite3StatementPoolTest < ActiveRecord::SQLite3TestCase
+ if Process.respond_to?(:fork)
+ def test_cache_is_per_pid
- cache = StatementPool.new(10)
- cache['foo'] = 'bar'
- assert_equal 'bar', cache['foo']
+ cache = ActiveRecord::ConnectionAdapters::SQLite3Adapter::StatementPool.new(10)
+ cache['foo'] = 'bar'
+ assert_equal 'bar', cache['foo']
- pid = fork {
- lookup = cache['foo'];
- exit!(!lookup)
- }
+ pid = fork {
+ lookup = cache['foo'];
+ exit!(!lookup)
+ }
- Process.waitpid pid
- assert $?.success?, 'process should exit successfully'
- end
- end
+ Process.waitpid pid
+ assert $?.success?, 'process should exit successfully'
end
end
end
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index f7bb3e54d5..80d9a6083b 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -90,6 +90,10 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_no_queries { authors.map(&:post) }
end
+ def test_calculate_with_string_in_from_and_eager_loading
+ assert_equal 10, Post.from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").count
+ end
+
def test_with_two_tables_in_from_without_getting_double_quoted
posts = Post.select("posts.*").from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").order("posts.id").to_a
assert_equal 2, posts.first.comments.size
diff --git a/activerecord/test/cases/associations/left_outer_join_association_test.rb b/activerecord/test/cases/associations/left_outer_join_association_test.rb
index 4af791b758..eee135cfb8 100644
--- a/activerecord/test/cases/associations/left_outer_join_association_test.rb
+++ b/activerecord/test/cases/associations/left_outer_join_association_test.rb
@@ -50,7 +50,7 @@ class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
def test_join_conditions_added_to_join_clause
queries = capture_sql { Author.left_outer_joins(:essays).to_a }
- assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1)/i =~ sql }
+ assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1|\:a1)/i =~ sql }
assert queries.none? { |sql| /WHERE/i =~ sql }
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 80dcba1cf4..7b1ce40c0d 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -14,7 +14,6 @@ require 'models/auto_id'
require 'models/boolean'
require 'models/column_name'
require 'models/subscriber'
-require 'models/keyboard'
require 'models/comment'
require 'models/minimalistic'
require 'models/warehouse_thing'
@@ -25,7 +24,6 @@ require 'models/joke'
require 'models/bird'
require 'models/car'
require 'models/bulb'
-require 'rexml/document'
require 'concurrent/atomic/count_down_latch'
class FirstAbstractClass < ActiveRecord::Base
@@ -1034,12 +1032,6 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal t1.title, t2.title
end
- def test_reload_with_exclusive_scope
- dev = DeveloperCalledDavid.first
- dev.update!(name: "NotDavid" )
- assert_equal dev, dev.reload
- end
-
def test_switching_between_table_name
k = Class.new(Joke)
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index 91ff5146fd..db71840658 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -170,8 +170,8 @@ class EachTest < ActiveRecord::TestCase
end
end
- def test_find_in_batches_should_not_error_if_config_overriden
- # Set the config option which will be overriden
+ def test_find_in_batches_should_not_error_if_config_overridden
+ # Set the config option which will be overridden
prev = ActiveRecord::Base.error_on_ignored_order_or_limit
ActiveRecord::Base.error_on_ignored_order_or_limit = true
assert_nothing_raised do
diff --git a/activerecord/test/cases/column_definition_test.rb b/activerecord/test/cases/column_definition_test.rb
index 81162b7e98..78c0853992 100644
--- a/activerecord/test/cases/column_definition_test.rb
+++ b/activerecord/test/cases/column_definition_test.rb
@@ -60,15 +60,8 @@ module ActiveRecord
end
def test_should_not_set_default_for_blob_and_text_data_types
- assert_raise ArgumentError do
- MySQL::Column.new("title", "a", SqlTypeMetadata.new(sql_type: "blob"))
- end
-
text_type = MySQL::TypeMetadata.new(
SqlTypeMetadata.new(type: :text))
- assert_raise ArgumentError do
- MySQL::Column.new("title", "Hello", text_type)
- end
text_column = MySQL::Column.new("title", nil, text_type)
assert_equal nil, text_column.default
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index 7ad9ff1f57..f9794518c7 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -5,23 +5,6 @@ require 'models/parrot'
require 'models/person' # For optimistic locking
require 'models/aircraft'
-class Pirate # Just reopening it, not defining it
- attr_accessor :detected_changes_in_after_update # Boolean for if changes are detected
- attr_accessor :changes_detected_in_after_update # Actual changes
-
- after_update :check_changes
-
-private
- # after_save/update and the model itself
- # can end up checking dirty status and acting on the results
- def check_changes
- if self.changed?
- self.detected_changes_in_after_update = true
- self.changes_detected_in_after_update = self.changes
- end
- end
-end
-
class NumericData < ActiveRecord::Base
self.table_name = 'numeric_data'
end
diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb
index babacd1ee9..e781b60464 100644
--- a/activerecord/test/cases/enum_test.rb
+++ b/activerecord/test/cases/enum_test.rb
@@ -421,4 +421,8 @@ class EnumTest < ActiveRecord::TestCase
book = Book.new
assert book.hard?
end
+
+ test "data type of Enum type" do
+ assert_equal :integer, Book.type_for_attribute('status').type
+ end
end
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 374a8ba199..6eaaa30cd0 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -173,11 +173,9 @@ class FinderTest < ActiveRecord::TestCase
end
end
- def test_exists_fails_when_parameter_has_invalid_type
- assert_raises(ActiveModel::RangeError) do
- assert_equal false, Topic.exists?(("9"*53).to_i) # number that's bigger than int
- end
+ def test_exists_returns_false_when_parameter_has_invalid_type
assert_equal false, Topic.exists?("foo")
+ assert_equal false, Topic.exists?(("9"*53).to_i) # number that's bigger than int
end
def test_exists_does_not_select_columns_without_alias
diff --git a/activerecord/test/cases/multiparameter_attributes_test.rb b/activerecord/test/cases/multiparameter_attributes_test.rb
index ae18573126..d05cb22740 100644
--- a/activerecord/test/cases/multiparameter_attributes_test.rb
+++ b/activerecord/test/cases/multiparameter_attributes_test.rb
@@ -11,15 +11,13 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase
topic.attributes = attributes
# note that extra #to_date call allows test to pass for Oracle, which
# treats dates/times the same
- assert_date_from_db Date.new(2004, 6, 24), topic.last_read.to_date
+ assert_equal Date.new(2004, 6, 24), topic.last_read.to_date
end
def test_multiparameter_attributes_on_date_with_empty_year
attributes = { "last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "24" }
topic = Topic.find(1)
topic.attributes = attributes
- # note that extra #to_date call allows test to pass for Oracle, which
- # treats dates/times the same
assert_nil topic.last_read
end
@@ -27,8 +25,6 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase
attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "24" }
topic = Topic.find(1)
topic.attributes = attributes
- # note that extra #to_date call allows test to pass for Oracle, which
- # treats dates/times the same
assert_nil topic.last_read
end
@@ -36,8 +32,6 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase
attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "" }
topic = Topic.find(1)
topic.attributes = attributes
- # note that extra #to_date call allows test to pass for Oracle, which
- # treats dates/times the same
assert_nil topic.last_read
end
@@ -45,8 +39,6 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase
attributes = { "last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "" }
topic = Topic.find(1)
topic.attributes = attributes
- # note that extra #to_date call allows test to pass for Oracle, which
- # treats dates/times the same
assert_nil topic.last_read
end
@@ -54,8 +46,6 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase
attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "" }
topic = Topic.find(1)
topic.attributes = attributes
- # note that extra #to_date call allows test to pass for Oracle, which
- # treats dates/times the same
assert_nil topic.last_read
end
@@ -63,8 +53,6 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase
attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "24" }
topic = Topic.find(1)
topic.attributes = attributes
- # note that extra #to_date call allows test to pass for Oracle, which
- # treats dates/times the same
assert_nil topic.last_read
end
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index 406643d6fb..d5c01315c1 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -133,7 +133,6 @@ class QueryCacheTest < ActiveRecord::TestCase
def test_cache_is_flat
Task.cache do
- Topic.columns # don't count this query
assert_queries(1) { Topic.find(1); Topic.find(1); }
end
@@ -175,6 +174,22 @@ class QueryCacheTest < ActiveRecord::TestCase
ActiveRecord::Base.configurations = conf
end
+ def test_cache_is_not_available_when_using_a_not_connected_connection
+ spec_name = Task.connection_specification_name
+ conf = ActiveRecord::Base.configurations['arunit'].merge('name' => 'test2')
+ ActiveRecord::Base.connection_handler.establish_connection(conf)
+ Task.connection_specification_name = "test2"
+ refute Task.connected?
+
+ Task.cache do
+ Task.connection # warmup postgresql connection setup queries
+ assert_queries(2) { Task.find(1); Task.find(1) }
+ end
+ ensure
+ ActiveRecord::Base.connection_handler.remove_connection(Task.connection_specification_name)
+ Task.connection_specification_name = spec_name
+ end
+
def test_query_cache_doesnt_leak_cached_results_of_rolled_back_queries
ActiveRecord::Base.connection.enable_query_cache!
post = Post.first
diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb
index 8e480bbaee..70e406038f 100644
--- a/activerecord/test/cases/tasks/mysql_rake_test.rb
+++ b/activerecord/test/cases/tasks/mysql_rake_test.rb
@@ -289,7 +289,7 @@ module ActiveRecord
def test_structure_dump
filename = "awesome-file.sql"
- Kernel.expects(:system).with("mysqldump", "--result-file", filename, "--no-data", "--routines", "test-db").returns(true)
+ Kernel.expects(:system).with("mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db").returns(true)
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
end
@@ -297,7 +297,7 @@ module ActiveRecord
def test_warn_when_external_structure_dump_command_execution_fails
filename = "awesome-file.sql"
Kernel.expects(:system)
- .with("mysqldump", "--result-file", filename, "--no-data", "--routines", "test-db")
+ .with("mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db")
.returns(false)
e = assert_raise(RuntimeError) {
@@ -308,7 +308,7 @@ module ActiveRecord
def test_structure_dump_with_port_number
filename = "awesome-file.sql"
- Kernel.expects(:system).with("mysqldump", "--port=10000", "--result-file", filename, "--no-data", "--routines", "test-db").returns(true)
+ Kernel.expects(:system).with("mysqldump", "--port=10000", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db").returns(true)
ActiveRecord::Tasks::DatabaseTasks.structure_dump(
@configuration.merge('port' => 10000),
@@ -317,7 +317,7 @@ module ActiveRecord
def test_structure_dump_with_ssl
filename = "awesome-file.sql"
- Kernel.expects(:system).with("mysqldump", "--ssl-ca=ca.crt", "--result-file", filename, "--no-data", "--routines", "test-db").returns(true)
+ Kernel.expects(:system).with("mysqldump", "--ssl-ca=ca.crt", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db").returns(true)
ActiveRecord::Tasks::DatabaseTasks.structure_dump(
@configuration.merge("sslca" => "ca.crt"),
diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb
index 6a0c7fbcb5..99d73e91a4 100644
--- a/activerecord/test/cases/tasks/postgresql_rake_test.rb
+++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb
@@ -288,14 +288,14 @@ module ActiveRecord
def test_structure_load
filename = "awesome-file.sql"
- Kernel.expects(:system).with('psql', '-q', '-f', filename, @configuration['database']).returns(true)
+ Kernel.expects(:system).with('psql', '-v', 'ON_ERROR_STOP=1', '-q', '-f', filename, @configuration['database']).returns(true)
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
def test_structure_load_accepts_path_with_spaces
filename = "awesome file.sql"
- Kernel.expects(:system).with('psql', '-q', '-f', filename, @configuration['database']).returns(true)
+ Kernel.expects(:system).with('psql', '-v', 'ON_ERROR_STOP=1', '-q', '-f', filename, @configuration['database']).returns(true)
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb
index 87299c0dab..c8adc21bbc 100644
--- a/activerecord/test/cases/test_case.rb
+++ b/activerecord/test/cases/test_case.rb
@@ -12,10 +12,6 @@ module ActiveRecord
SQLCounter.clear_log
end
- def assert_date_from_db(expected, actual, message = nil)
- assert_equal expected.to_s, actual.to_s, message
- end
-
def capture_sql
SQLCounter.clear_log
yield
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 2842b692e2..01ff1a858d 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,18 @@
+* Fix parsing JSON time in `YYYY-MM-DD hh:mm:ss` (without `Z`).
+ Before such time was considered in UTC timezone, now, to comply with standard, it uses local timezone.
+
+ *Grzegorz Witek*
+
+* Fixed `ActiveSupport::Logger.broadcast` so that calls to `#silence` now
+ properly delegate to all loggers. Silencing now properly suppresses logging
+ to both the log and the console.
+
+ *Kevin McPhillips*
+
+* Remove deprecated arguments in `assert_nothing_raised`.
+
+ *Rafel Mendonça França*
+
* `Date.to_s` doesn't produce too many spaces. For example, `to_s(:short)`
will now produce `01 Feb` instead of ` 1 Feb`.
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index bc114e0785..179ca13b49 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -250,14 +250,14 @@ module ActiveSupport
# sleep 60
#
# Thread.new do
- # val_1 = cache.fetch('foo', race_condition_ttl: 10) do
+ # val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
# sleep 1
# 'new value 1'
# end
# end
#
# Thread.new do
- # val_2 = cache.fetch('foo', race_condition_ttl: 10) do
+ # val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
# 'new value 2'
# end
# end
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 904d3f0eb0..557a4695a6 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -103,7 +103,7 @@ module ActiveSupport
end
# A hook invoked every time a before callback is halted.
- # This can be overridden in AS::Callback implementors in order
+ # This can be overridden in ActiveSupport::Callbacks implementors in order
# to provide better debugging/logging.
def halted_callback_hook(filter)
end
@@ -736,8 +736,13 @@ module ActiveSupport
#
# would call <tt>Audit#save</tt>.
#
- # NOTE: +method_name+ passed to `define_model_callbacks` must not end with
+ # ===== Notes
+ #
+ # +names+ passed to `define_callbacks` must not end with
# `!`, `?` or `=`.
+ #
+ # Calling `define_callbacks` multiple times with the same +names+ will
+ # overwrite previous callbacks registered with `set_callback`.
def define_callbacks(*names)
options = names.extract_options!
diff --git a/activesupport/lib/active_support/core_ext/hash/compact.rb b/activesupport/lib/active_support/core_ext/hash/compact.rb
index 62ea579c65..f072530e04 100644
--- a/activesupport/lib/active_support/core_ext/hash/compact.rb
+++ b/activesupport/lib/active_support/core_ext/hash/compact.rb
@@ -2,18 +2,21 @@ class Hash
# Returns a hash with non +nil+ values.
#
# hash = { a: true, b: false, c: nil }
- # hash.compact # => { a: true, b: false }
- # hash # => { a: true, b: false, c: nil }
- # { c: nil }.compact # => {}
+ # hash.compact # => { a: true, b: false }
+ # hash # => { a: true, b: false, c: nil }
+ # { c: nil }.compact # => {}
+ # { c: true }.compact # => { c: true }
def compact
self.select { |_, value| !value.nil? }
end
# Replaces current hash with non +nil+ values.
+ # Returns nil if no changes were made, otherwise returns the hash.
#
# hash = { a: true, b: false, c: nil }
- # hash.compact! # => { a: true, b: false }
- # hash # => { a: true, b: false }
+ # hash.compact! # => { a: true, b: false }
+ # hash # => { a: true, b: false }
+ # { c: true }.compact! # => nil
def compact!
self.reject! { |_, value| value.nil? }
end
diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb
index 0b3d18301e..045668c207 100644
--- a/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb
+++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb
@@ -25,7 +25,7 @@ class Module
# end
# # => NameError: invalid attribute name: 1_Badname
#
- # If you want to opt out the creation on the instance reader method, pass
+ # If you want to opt out of the creation of the instance reader method, pass
# <tt>instance_reader: false</tt> or <tt>instance_accessor: false</tt>.
#
# class Current
@@ -65,7 +65,7 @@ class Module
# Current.user = "DHH"
# Thread.current[:attr_Current_user] # => "DHH"
#
- # If you want to opt out the instance writer method, pass
+ # If you want to opt out of the creation of the instance writer method, pass
# <tt>instance_writer: false</tt> or <tt>instance_accessor: false</tt>.
#
# class Current
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index 7f968d10b5..3f6e8bd26c 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -164,8 +164,8 @@ class Module
''
end
- file, line = caller(1, 1).first.split(':'.freeze, 2)
- line = line.to_i
+ location = caller_locations(1, 1).first
+ file, line = location.path, location.lineno
to = to.to_s
to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
diff --git a/activesupport/lib/active_support/core_ext/object/json.rb b/activesupport/lib/active_support/core_ext/object/json.rb
index d49b2fbe54..363bde5a68 100644
--- a/activesupport/lib/active_support/core_ext/object/json.rb
+++ b/activesupport/lib/active_support/core_ext/object/json.rb
@@ -1,6 +1,8 @@
# Hack to load json gem first so we can overwrite its to_json.
require 'json'
require 'bigdecimal'
+require 'uri/generic'
+require 'pathname'
require 'active_support/core_ext/big_decimal/conversions' # for #to_s
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/slice'
@@ -192,6 +194,18 @@ class DateTime
end
end
+class URI::Generic #:nodoc:
+ def as_json(options = nil)
+ to_s
+ end
+end
+
+class Pathname #:nodoc:
+ def as_json(options = nil)
+ to_s
+ end
+end
+
class Process::Status #:nodoc:
def as_json(options = nil)
{ :exitstatus => exitstatus, :pid => pid }
diff --git a/activesupport/lib/active_support/evented_file_update_checker.rb b/activesupport/lib/active_support/evented_file_update_checker.rb
index 21fdf7bb80..a2dcf31132 100644
--- a/activesupport/lib/active_support/evented_file_update_checker.rb
+++ b/activesupport/lib/active_support/evented_file_update_checker.rb
@@ -3,6 +3,33 @@ require 'pathname'
require 'concurrent/atomic/atomic_boolean'
module ActiveSupport
+ # Allows you to "listen" to changes in a file system.
+ # The evented file updater does not hit disk when checking for updates
+ # instead it uses platform specific file system events to trigger a change
+ # in state.
+ #
+ # The file checker takes an array of files to watch or a hash specifying directories
+ # and file extensions to watch. It also takes a block that is called when
+ # EventedFileUpdateChecker#execute is run or when EventedFileUpdateChecker#execute_if_updated
+ # is run and there have been changes to the file system.
+ #
+ # Note: Forking will cause the first call to `updated?` to return `true`.
+ #
+ # Example:
+ #
+ # checker = EventedFileUpdateChecker.new(["/tmp/foo"], -> { puts "changed" })
+ # checker.updated?
+ # # => false
+ # checker.execute_if_updated
+ # # => nil
+ #
+ # FileUtils.touch("/tmp/foo")
+ #
+ # checker.updated?
+ # # => true
+ # checker.execute_if_updated
+ # # => "changed"
+ #
class EventedFileUpdateChecker #:nodoc: all
def initialize(files, dirs = {}, &block)
@ph = PathHelper.new
@@ -13,11 +40,13 @@ module ActiveSupport
@dirs[@ph.xpath(dir)] = Array(exts).map { |ext| @ph.normalize_extension(ext) }
end
- @block = block
- @updated = Concurrent::AtomicBoolean.new(false)
- @lcsp = @ph.longest_common_subpath(@dirs.keys)
+ @block = block
+ @updated = Concurrent::AtomicBoolean.new(false)
+ @lcsp = @ph.longest_common_subpath(@dirs.keys)
+ @pid = Process.pid
+ @boot_mutex = Mutex.new
- if (dtw = directories_to_watch).any?
+ if (@dtw = directories_to_watch).any?
# Loading listen triggers warnings. These are originated by a legit
# usage of attr_* macros for private attributes, but adds a lot of noise
# to our test suite. Thus, we lazy load it and disable warnings locally.
@@ -28,11 +57,18 @@ module ActiveSupport
raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
end
end
- Listen.to(*dtw, &method(:changed)).start
end
+ boot!
end
def updated?
+ @boot_mutex.synchronize do
+ if @pid != Process.pid
+ boot!
+ @pid = Process.pid
+ @updated.make_true
+ end
+ end
@updated.true?
end
@@ -50,6 +86,9 @@ module ActiveSupport
end
private
+ def boot!
+ Listen.to(*@dtw, &method(:changed)).start
+ end
def changed(modified, added, removed)
unless updated?
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
index 2932954f03..64e4b0e7a9 100644
--- a/activesupport/lib/active_support/json/decoding.rb
+++ b/activesupport/lib/active_support/json/decoding.rb
@@ -8,7 +8,8 @@ module ActiveSupport
module JSON
# matches YAML-formatted dates
- DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?))$/
+ DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/
+ DATETIME_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)$/
class << self
# Parses a JSON string (JavaScript Object Notation) into a hash.
@@ -48,7 +49,13 @@ module ActiveSupport
nil
when DATE_REGEX
begin
- DateTime.parse(data)
+ Date.parse(data)
+ rescue ArgumentError
+ data
+ end
+ when DATETIME_REGEX
+ begin
+ Time.zone.parse(data)
rescue ArgumentError
data
end
diff --git a/activesupport/lib/active_support/logger.rb b/activesupport/lib/active_support/logger.rb
index de48e717b6..92b890dbb0 100644
--- a/activesupport/lib/active_support/logger.rb
+++ b/activesupport/lib/active_support/logger.rb
@@ -55,6 +55,24 @@ module ActiveSupport
logger.local_level = level if logger.respond_to?(:local_level=)
super(level) if respond_to?(:local_level=)
end
+
+ define_method(:silence) do |level = Logger::ERROR, &block|
+ if logger.respond_to?(:silence)
+ logger.silence(level) do
+ if respond_to?(:silence)
+ super(level, &block)
+ else
+ block.call(self)
+ end
+ end
+ else
+ if respond_to?(:silence)
+ super(level, &block)
+ else
+ block.call(self)
+ end
+ end
+ end
end
end
diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb
index 53a55bd986..501ba7fc76 100644
--- a/activesupport/lib/active_support/ordered_options.rb
+++ b/activesupport/lib/active_support/ordered_options.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/blank'
+
module ActiveSupport
# Usually key value pairs are handled something like this:
#
diff --git a/activesupport/lib/active_support/per_thread_registry.rb b/activesupport/lib/active_support/per_thread_registry.rb
index 88e2b12cc7..18ca951372 100644
--- a/activesupport/lib/active_support/per_thread_registry.rb
+++ b/activesupport/lib/active_support/per_thread_registry.rb
@@ -1,7 +1,7 @@
require 'active_support/core_ext/module/delegation'
module ActiveSupport
- # NOTE: This approach has been deprecated for end-user code in favor of thread_mattr_accessor and friends.
+ # NOTE: This approach has been deprecated for end-user code in favor of {thread_mattr_accessor}[rdoc-ref:Module#thread_mattr_accessor] and friends.
# Please use that approach instead.
#
# This module is used to encapsulate access to thread local variables.
diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb
index 1fc12d0bc1..221e1171e7 100644
--- a/activesupport/lib/active_support/test_case.rb
+++ b/activesupport/lib/active_support/test_case.rb
@@ -74,12 +74,7 @@ module ActiveSupport
# assert_nothing_raised do
# perform_service(param: 'no_exception')
# end
- def assert_nothing_raised(*args)
- if args.present?
- ActiveSupport::Deprecation.warn(
- "Passing arguments to assert_nothing_raised " \
- "is deprecated and will be removed in Rails 5.1.")
- end
+ def assert_nothing_raised
yield
end
end
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index 29305e0082..ad83638572 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/object/blank'
-
module ActiveSupport
module Testing
module Assertions
diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb
index edf8b30a0a..7dd03ce65d 100644
--- a/activesupport/lib/active_support/testing/isolation.rb
+++ b/activesupport/lib/active_support/testing/isolation.rb
@@ -13,17 +13,6 @@ module ActiveSupport
!ENV["NO_FORK"] && Process.respond_to?(:fork)
end
- @@class_setup_mutex = Mutex.new
-
- def _run_class_setup # class setup method should only happen in parent
- @@class_setup_mutex.synchronize do
- unless defined?(@@ran_class_setup) || ENV['ISOLATION_TEST']
- self.class.setup if self.class.respond_to?(:setup)
- @@ran_class_setup = true
- end
- end
- end
-
def run
serialized = run_in_isolation do
super
diff --git a/activesupport/lib/active_support/testing/time_helpers.rb b/activesupport/lib/active_support/testing/time_helpers.rb
index fca0947c5b..ef27ce8eb5 100644
--- a/activesupport/lib/active_support/testing/time_helpers.rb
+++ b/activesupport/lib/active_support/testing/time_helpers.rb
@@ -66,7 +66,7 @@ module ActiveSupport
# +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
#
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
- # travel_to Time.new(2004, 11, 24, 01, 04, 44)
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
# Date.current # => Wed, 24 Nov 2004
# DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
@@ -88,7 +88,7 @@ module ActiveSupport
# state at the end of the block:
#
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
- # travel_to Time.new(2004, 11, 24, 01, 04, 44) do
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44) do
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
# end
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
@@ -116,7 +116,7 @@ module ActiveSupport
# `travel` and `travel_to`.
#
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
- # travel_to Time.new(2004, 11, 24, 01, 04, 44)
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
# travel_back
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
diff --git a/activesupport/test/broadcast_logger_test.rb b/activesupport/test/broadcast_logger_test.rb
index 6d4e3b74f7..f95b3e5ad3 100644
--- a/activesupport/test/broadcast_logger_test.rb
+++ b/activesupport/test/broadcast_logger_test.rb
@@ -3,75 +3,147 @@ require 'abstract_unit'
module ActiveSupport
class BroadcastLoggerTest < TestCase
attr_reader :logger, :log1, :log2
- def setup
+
+ setup do
@log1 = FakeLogger.new
@log2 = FakeLogger.new
@log1.extend Logger.broadcast @log2
@logger = @log1
end
- def test_debug
- logger.debug "foo"
- assert_equal 'foo', log1.adds.first[2]
- assert_equal 'foo', log2.adds.first[2]
+ Logger::Severity.constants.each do |level_name|
+ method = level_name.downcase
+ level = Logger::Severity.const_get(level_name)
+
+ test "##{method} adds the message to all loggers" do
+ logger.send(method, "msg")
+
+ assert_equal [level, "msg", nil], log1.adds.first
+ assert_equal [level, "msg", nil], log2.adds.first
+ end
end
- def test_close
+ test "#close broadcasts to all loggers" do
logger.close
+
assert log1.closed, 'should be closed'
assert log2.closed, 'should be closed'
end
- def test_chevrons
+ test "#<< shovels the value into all loggers" do
logger << "foo"
+
assert_equal %w{ foo }, log1.chevrons
assert_equal %w{ foo }, log2.chevrons
end
- def test_level
- assert_nil logger.level
- logger.level = 10
- assert_equal 10, log1.level
- assert_equal 10, log2.level
+ test "#level= assigns the level to all loggers" do
+ assert_equal ::Logger::DEBUG, logger.level
+ logger.level = ::Logger::FATAL
+
+ assert_equal ::Logger::FATAL, log1.level
+ assert_equal ::Logger::FATAL, log2.level
end
- def test_progname
+ test "#progname= assigns to all the loggers" do
assert_nil logger.progname
- logger.progname = 10
- assert_equal 10, log1.progname
- assert_equal 10, log2.progname
+ logger.progname = ::Logger::FATAL
+
+ assert_equal ::Logger::FATAL, log1.progname
+ assert_equal ::Logger::FATAL, log2.progname
end
- def test_formatter
+ test "#formatter= assigns to all the loggers" do
assert_nil logger.formatter
- logger.formatter = 10
- assert_equal 10, log1.formatter
- assert_equal 10, log2.formatter
+ logger.formatter = ::Logger::FATAL
+
+ assert_equal ::Logger::FATAL, log1.formatter
+ assert_equal ::Logger::FATAL, log2.formatter
+ end
+
+ test "#local_level= assigns the local_level to all loggers" do
+ assert_equal ::Logger::DEBUG, logger.local_level
+ logger.local_level = ::Logger::FATAL
+
+ assert_equal ::Logger::FATAL, log1.local_level
+ assert_equal ::Logger::FATAL, log2.local_level
+ end
+
+ test "#silence silences all loggers below the default level of ERROR" do
+ logger.silence do
+ logger.debug "test"
+ end
+
+ assert_equal [], log1.adds
+ assert_equal [], log2.adds
+ end
+
+ test "#silence does not silence at or above ERROR" do
+ logger.silence do
+ logger.error "from error"
+ logger.unknown "from unknown"
+ end
+
+ assert_equal [[::Logger::ERROR, "from error", nil], [::Logger::UNKNOWN, "from unknown", nil]], log1.adds
+ assert_equal [[::Logger::ERROR, "from error", nil], [::Logger::UNKNOWN, "from unknown", nil]], log2.adds
+ end
+
+ test "#silence allows you to override the silence level" do
+ logger.silence(::Logger::FATAL) do
+ logger.error "unseen"
+ logger.fatal "seen"
+ end
+
+ assert_equal [[::Logger::FATAL, "seen", nil]], log1.adds
+ assert_equal [[::Logger::FATAL, "seen", nil]], log2.adds
end
class FakeLogger
+ include LoggerSilence
+
attr_reader :adds, :closed, :chevrons
- attr_accessor :level, :progname, :formatter
+ attr_accessor :level, :progname, :formatter, :local_level
def initialize
- @adds = []
- @closed = false
- @chevrons = []
- @level = nil
- @progname = nil
- @formatter = nil
+ @adds = []
+ @closed = false
+ @chevrons = []
+ @level = ::Logger::DEBUG
+ @local_level = ::Logger::DEBUG
+ @progname = nil
+ @formatter = nil
+ end
+
+ def debug(message, &block)
+ add(::Logger::DEBUG, message, &block)
+ end
+
+ def info(message, &block)
+ add(::Logger::INFO, message, &block)
+ end
+
+ def warn(message, &block)
+ add(::Logger::WARN, message, &block)
+ end
+
+ def error(message, &block)
+ add(::Logger::ERROR, message, &block)
+ end
+
+ def fatal(message, &block)
+ add(::Logger::FATAL, message, &block)
end
- def debug msg, &block
- add(:omg, nil, msg, &block)
+ def unknown(message, &block)
+ add(::Logger::UNKNOWN, message, &block)
end
def << x
@chevrons << x
end
- def add(*args)
- @adds << args
+ def add(message_level, message=nil, progname=nil, &block)
+ @adds << [message_level, message, progname] if message_level >= local_level
end
def close
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index f0a4c4dddc..e8099baa35 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -999,6 +999,10 @@ class HashExtTest < ActiveSupport::TestCase
h = hash_with_only_nil_values.dup
assert_equal({}, h.compact)
assert_equal(hash_with_only_nil_values, h)
+
+ h = @symbols.dup
+ assert_equal(@symbols, h.compact)
+ assert_equal(@symbols, h)
end
def test_compact!
@@ -1012,6 +1016,10 @@ class HashExtTest < ActiveSupport::TestCase
h = hash_with_only_nil_values.dup
assert_equal({}, h.compact!)
assert_equal({}, h)
+
+ h = @symbols.dup
+ assert_equal(nil, h.compact!)
+ assert_equal(@symbols, h)
end
def test_new_with_to_hash_conversion
@@ -1034,7 +1042,7 @@ class HashExtTest < ActiveSupport::TestCase
assert_equal 3, new_hash[2]
new_hash.default = 2
- assert_equal 2, new_hash[:non_existant]
+ assert_equal 2, new_hash[:non_existent]
end
def test_to_hash_with_raising_default_proc
diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb
index ec34bd823d..dbde3d2e15 100644
--- a/activesupport/test/deprecation_test.rb
+++ b/activesupport/test/deprecation_test.rb
@@ -143,7 +143,7 @@ class DeprecationTest < ActiveSupport::TestCase
stderr_output = capture(:stderr) {
assert_nil behavior.call('Some error!', ['call stack!'])
}
- assert stderr_output.blank?
+ assert stderr_output.empty?
end
def test_deprecated_instance_variable_proxy
diff --git a/activesupport/test/evented_file_update_checker_test.rb b/activesupport/test/evented_file_update_checker_test.rb
index bc3f77bd54..2cb2d8167f 100644
--- a/activesupport/test/evented_file_update_checker_test.rb
+++ b/activesupport/test/evented_file_update_checker_test.rb
@@ -11,7 +11,7 @@ class EventedFileUpdateCheckerTest < ActiveSupport::TestCase
end
def new_checker(files = [], dirs = {}, &block)
- ActiveSupport::EventedFileUpdateChecker.new(files, dirs, &block).tap do
+ ActiveSupport::EventedFileUpdateChecker.new(files, dirs, &block).tap do |c|
wait
end
end
@@ -34,6 +34,48 @@ class EventedFileUpdateCheckerTest < ActiveSupport::TestCase
super
wait
end
+
+ test 'notifies forked processes' do
+ FileUtils.touch(tmpfiles)
+
+ checker = new_checker(tmpfiles) { }
+ assert !checker.updated?
+
+ # Pipes used for flow controll across fork.
+ boot_reader, boot_writer = IO.pipe
+ touch_reader, touch_writer = IO.pipe
+
+ pid = fork do
+ assert checker.updated?
+
+ # Clear previous check value.
+ checker.execute
+ assert !checker.updated?
+
+ # Fork is booted, ready for file to be touched
+ # notify parent process.
+ boot_writer.write("booted")
+
+ # Wait for parent process to signal that file
+ # has been touched.
+ IO.select([touch_reader])
+
+ assert checker.updated?
+ end
+
+ assert pid
+
+ # Wait for fork to be booted before touching files.
+ IO.select([boot_reader])
+ touch(tmpfiles)
+
+ # Notify fork that files have been touched.
+ touch_writer.write("touched")
+
+ assert checker.updated?
+
+ Process.wait(pid)
+ end
end
class EventedFileUpdateCheckerPathHelperTest < ActiveSupport::TestCase
diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index f2fc456f4b..887ef1681d 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -1,8 +1,11 @@
require 'abstract_unit'
require 'active_support/json'
require 'active_support/time'
+require 'time_zone_test_helpers'
class TestJSONDecoding < ActiveSupport::TestCase
+ include TimeZoneTestHelpers
+
class Foo
def self.json_create(object)
"Foo"
@@ -24,10 +27,11 @@ class TestJSONDecoding < ActiveSupport::TestCase
%(["2007-01-01 01:12:34 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34)],
%(["2007-01-01 01:12:34 Z", "2007-01-01 01:12:35 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34), Time.utc(2007, 1, 1, 1, 12, 35)],
# no time zone
- %({"a": "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
+ %({"a": "2007-01-01 01:12:34"}) => {'a' => Time.new(2007, 1, 1, 1, 12, 34, "-05:00")},
# invalid date
%({"a": "1089-10-40"}) => {'a' => "1089-10-40"},
# xmlschema date notation
+ %({"a": "2009-08-10T19:01:02"}) => {'a' => Time.new(2009, 8, 10, 19, 1, 2, "-04:00")},
%({"a": "2009-08-10T19:01:02Z"}) => {'a' => Time.utc(2009, 8, 10, 19, 1, 2)},
%({"a": "2009-08-10T19:01:02+02:00"}) => {'a' => Time.utc(2009, 8, 10, 17, 1, 2)},
%({"a": "2009-08-10T19:01:02-05:00"}) => {'a' => Time.utc(2009, 8, 11, 00, 1, 2)},
@@ -72,10 +76,12 @@ class TestJSONDecoding < ActiveSupport::TestCase
TESTS.each_with_index do |(json, expected), index|
test "json decodes #{index}" do
- with_parse_json_times(true) do
- silence_warnings do
- assert_equal expected, ActiveSupport::JSON.decode(json), "JSON decoding \
- failed for #{json}"
+ with_tz_default 'Eastern Time (US & Canada)' do
+ with_parse_json_times(true) do
+ silence_warnings do
+ assert_equal expected, ActiveSupport::JSON.decode(json), "JSON decoding \
+ failed for #{json}"
+ end
end
end
end
diff --git a/activesupport/test/json/encoding_test_cases.rb b/activesupport/test/json/encoding_test_cases.rb
index 0159ba8606..e043fadf56 100644
--- a/activesupport/test/json/encoding_test_cases.rb
+++ b/activesupport/test/json/encoding_test_cases.rb
@@ -76,6 +76,10 @@ module JSONTest
RegexpTests = [[ /^a/, '"(?-mix:^a)"' ], [/^\w{1,2}[a-z]+/ix, '"(?ix-m:^\\\\w{1,2}[a-z]+)"']]
+ URITests = [[ URI.parse('http://example.com'), %("http://example.com") ]]
+
+ PathnameTests = [[ Pathname.new('lib/index.rb'), %("lib/index.rb") ]]
+
DateTests = [[ Date.new(2005,2,1), %("2005/02/01") ]]
TimeTests = [[ Time.utc(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]]
DateTimeTests = [[ DateTime.civil(2005,2,1,15,15,10), %("2005/02/01 15:15:10 +0000") ]]
diff --git a/activesupport/test/logger_test.rb b/activesupport/test/logger_test.rb
index 5a91420f1e..dfc5f3fdf4 100644
--- a/activesupport/test/logger_test.rb
+++ b/activesupport/test/logger_test.rb
@@ -143,12 +143,13 @@ class LoggerTest < ActiveSupport::TestCase
def test_logger_silencing_works_for_broadcast
another_output = StringIO.new
- another_logger = Logger.new(another_output)
+ another_logger = ActiveSupport::Logger.new(another_output)
- @logger.extend Logger.broadcast(another_logger)
+ @logger.extend ActiveSupport::Logger.broadcast(another_logger)
@logger.debug "CORRECT DEBUG"
- @logger.silence do
+ @logger.silence do |logger|
+ assert_kind_of ActiveSupport::Logger, logger
@logger.debug "FAILURE"
@logger.error "CORRECT ERROR"
end
@@ -166,10 +167,11 @@ class LoggerTest < ActiveSupport::TestCase
another_output = StringIO.new
another_logger = ::Logger.new(another_output)
- @logger.extend Logger.broadcast(another_logger)
+ @logger.extend ActiveSupport::Logger.broadcast(another_logger)
@logger.debug "CORRECT DEBUG"
- @logger.silence do
+ @logger.silence do |logger|
+ assert_kind_of ActiveSupport::Logger, logger
@logger.debug "FAILURE"
@logger.error "CORRECT ERROR"
end
diff --git a/guides/source/4_2_release_notes.md b/guides/source/4_2_release_notes.md
index 73e6c2c05b..a30bfc458a 100644
--- a/guides/source/4_2_release_notes.md
+++ b/guides/source/4_2_release_notes.md
@@ -871,7 +871,7 @@ Please refer to the [Changelog][active-support] for detailed changes.
`module Foo; extend ActiveSupport::Concern; end` boilerplate.
([Commit](https://github.com/rails/rails/commit/b16c36e688970df2f96f793a759365b248b582ad))
-* New [guide](constant_autoloading_and_reloading.html) about constant autoloading and reloading.
+* New [guide](autoloading_and_reloading_constants.html) about constant autoloading and reloading.
Credits
-------
diff --git a/guides/source/5_0_release_notes.md b/guides/source/5_0_release_notes.md
index 638547565c..5639438b93 100644
--- a/guides/source/5_0_release_notes.md
+++ b/guides/source/5_0_release_notes.md
@@ -37,9 +37,20 @@ Major Features
--------------
### Action Cable
-[Pull Request](https://github.com/rails/rails/pull/22586)
-ToDo...
+Action Cable is a new framework in Rails 5. It seamlessly integrates
+[WebSockets](https://en.wikipedia.org/wiki/WebSocket) with the rest of your
+Rails application.
+
+Action Cable allows for real-time features to be written in Ruby in the
+same style and form as the rest of your Rails application, while still being
+performant and scalable. It's a full-stack offering that provides both a
+client-side JavaScript framework and a server-side Ruby framework. You have
+access to your full domain model written with Active Record or your ORM of
+choice.
+
+See the [Action Cable Overview](action_cable_overview.html) guide for more
+information.
### Rails API
[Pull Request](https://github.com/rails/rails/pull/19832)
@@ -48,9 +59,9 @@ ToDo...
### Active Record attributes API
-Defines an attribute with a type on a model. It will override the type of existing attributes if needed.
+Defines an attribute with a type on a model. It will override the type of existing attributes if needed.
This allows control over how values are converted to and from SQL when assigned to a model.
-It also changes the behavior of values passed to ActiveRecord::Base.where, which lets use our domain objects across much of Active Record,
+It also changes the behavior of values passed to `ActiveRecord::Base.where`, which lets use our domain objects across much of Active Record,
without having to rely on implementation details or monkey patching.
Some things that you can achieve with this:
@@ -80,7 +91,7 @@ class StoreListing < ActiveRecord::Base
attribute :price_in_cents, :integer # custom type
attribute :my_string, :string, default: "new default" # default value
attribute :my_default_proc, :datetime, default: -> { Time.now } # default value
- attribute :field_without_db_column, :integer, array: true
+ attribute :field_without_db_column, :integer, array: true
end
# after
@@ -96,22 +107,22 @@ model.attributes #=> {field_without_db_column: [1, 2, 3]}
You can define your own custom types, as long as they respond
to the methods defined on the value type. The method +deserialize+ or
+cast+ will be called on your type object, with raw input from the
-database or from your controllers. This is useful, for example, when doing custom conversion,
+database or from your controllers. This is useful, for example, when doing custom conversion,
like Money data.
**Querying:**
When `ActiveRecord::Base.where` is called, it will
use the type defined by the model class to convert the value to SQL,
-calling +serialize+ on your type object.
+calling +serialize+ on your type object.
-This gives the objects ability to specify, how to convert values when performing SQL queries.
+This gives the objects ability to specify, how to convert values when performing SQL queries.
**Dirty Tracking:**
The type of an attribute is given the opportunity to change how dirty
-tracking is performed.
-
+tracking is performed.
+
See its
[documentation](http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html)
for a detailed write up.
@@ -209,6 +220,15 @@ Please refer to the [Changelog][railties] for detailed changes.
([commit](https://github.com/rails/rails/commit/b04d07337fd7bc17e88500e9d6bcd361885a45f8))
+* Added `--skip-action-mailer` to skip Action Mailer while generating new app.
+ ([Pull Request](https://github.com/rails/rails/pull/18288))
+
+* Removed `tmp/sessions` directory and the clear rake task associated with it.
+ ([Pull Request](https://github.com/rails/rails/pull/18314))
+
+* Changed `_form.html.erb` generated by scaffold generator to use local variables.
+ ([Pull Request](https://github.com/rails/rails/pull/13434))
+
Action Pack
-----------
@@ -371,6 +391,9 @@ Please refer to the [Changelog][action-pack] for detailed changes.
at the controller level.
([Pull Request](https://github.com/rails/rails/pull/24866))
+* Discarded flash messages get removed before storing into session.
+ ([Pull Request](https://github.com/rails/rails/pull/18721))
+
Action View
-------------
@@ -413,6 +436,9 @@ Please refer to the [Changelog][action-view] for detailed changes.
button on submit to prevent double submits.
([Pull Request](https://github.com/rails/rails/pull/21135))
+* Partial template name no longer has to be a valid Ruby identifier.
+ ([commit](https://github.com/rails/rails/commit/da9038e))
+
Action Mailer
-------------
@@ -507,6 +533,9 @@ Please refer to the [Changelog][active-record] for detailed changes.
* Removed support for PostgreSQL versions below 9.1.
([Pull Request](https://github.com/rails/rails/pull/23434))
+* Removed support for `activerecord-deprecated_finders` gem.
+ ([commit](https://github.com/rails/rails/commit/78dab2a8569408658542e462a957ea5a35aa4679))
+
### Deprecations
* Deprecated passing a class as a value in a query. Users should pass strings
@@ -671,10 +700,24 @@ Please refer to the [Changelog][active-record] for detailed changes.
with comments stored in database metadata for PostgreSQL & MySQL.
([Pull Request](https://github.com/rails/rails/pull/22911))
-* Added prepared statements support to `mysql2` adapter, for mysql2 0.4.4+,
- Previously this was only supported on the deprecated `mysql` legacy adapter.
+* Added prepared statements support to `mysql2` adapter, for mysql2 0.4.4+,
+ Previously this was only supported on the deprecated `mysql` legacy adapter.
To enable, set `prepared_statements: true` in config/database.yml.
- ([Pull Request](https://github.com/rails/rails/pull/23461))
+ ([Pull Request](https://github.com/rails/rails/pull/23461))
+
+* Added ability to call `ActionRecord::Relation#update` on relation objects
+ which will run validations on callbacks on all objects in the relation.
+ ([Pull Request](https://github.com/rails/rails/pull/11898))
+
+* Added `:touch` option to the `save` method so that records can be saved without
+ updating timestamps.
+ ([Pull Request](https://github.com/rails/rails/pull/18225))
+
+* Added expression indexes and operator classes support for PostgreSQL.
+ ([commit](https://github.com/rails/rails/commit/edc2b7718725016e988089b5fb6d6fb9d6e16882))
+
+* Added `:index_errors` option to add indexes to errors of nested attributes.
+ ([Pull Request](https://github.com/rails/rails/pull/19686))
Active Model
------------
@@ -691,6 +734,9 @@ Please refer to the [Changelog][active-model] for detailed changes.
[activemodel-serializers-xml](https://github.com/rails/activemodel-serializers-xml) gem.
([Pull Request](https://github.com/rails/rails/pull/21161))
+* Removed `ActionController::ModelNaming` module.
+ ([Pull Request](https://github.com/rails/rails/pull/18194))
+
### Deprecations
* Deprecated returning `false` as a way to halt Active Model and
@@ -797,6 +843,9 @@ Please refer to the [Changelog][active-support] for detailed changes.
* Removed deprecated `ThreadSafe::Cache`. Use `Concurrent::Map` instead.
([Pull Request](https://github.com/rails/rails/pull/21679))
+* Removed `Object#itself` as it is implemented in Ruby 2.2.
+ ([Pull Request](https://github.com/rails/rails/pull/18244))
+
### Deprecations
* Deprecated `MissingSourceFile` in favor of `LoadError`.
@@ -918,6 +967,9 @@ Please refer to the [Changelog][active-support] for detailed changes.
* `ActiveSupport::Duration` now supports ISO8601 formatting and parsing.
([Pull Request](https://github.com/rails/rails/pull/16917))
+* Added ability to `TaggedLogging` to allow loggers to be instantiated multiple
+ times so that they don't share tags with each other.
+ ([Pull Request](https://github.com/rails/rails/pull/9065))
Credits
-------
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index e6cd00728d..58362fea58 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -815,7 +815,7 @@ In every controller there are two accessor methods pointing to the request and t
### The `request` Object
-The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the [API documentation](http://api.rubyonrails.org/classes/ActionDispatch/Request.html). Among the properties that you can access on this object are:
+The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the [Rails API documentation](http://api.rubyonrails.org/classes/ActionDispatch/Request.html) and [Rack Documentation](http://www.rubydoc.info/github/rack/rack/Rack/Request). Among the properties that you can access on this object are:
| Property of `request` | Purpose |
| ----------------------------------------- | -------------------------------------------------------------------------------- |
@@ -837,7 +837,7 @@ Rails collects all of the parameters sent along with the request in the `params`
### The `response` Object
-The response object is not usually used directly, but is built up during the execution of the action and rendering of the data that is being sent back to the user, but sometimes - like in an after filter - it can be useful to access the response directly. Some of these accessor methods also have setters, allowing you to change their values.
+The response object is not usually used directly, but is built up during the execution of the action and rendering of the data that is being sent back to the user, but sometimes - like in an after filter - it can be useful to access the response directly. Some of these accessor methods also have setters, allowing you to change their values. To get a full list of the available methods, refer to the [Rails API documentation](http://api.rubyonrails.org/classes/ActionDispatch/Response.html) and [Rack Documentation](http://www.rubydoc.info/github/rack/rack/Rack/Response).
| Property of `response` | Purpose |
| ---------------------- | --------------------------------------------------------------------------------------------------- |
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 5346b7c32b..7359438025 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -734,7 +734,7 @@ files (environment.rb, production.rb, etc...)
| Configuration | Description |
|---------------|-------------|
|`logger`|Generates information on the mailing run if available. Can be set to `nil` for no logging. Compatible with both Ruby's own `Logger` and `Log4r` loggers.|
-|`smtp_settings`|Allows detailed configuration for `:smtp` delivery method:<ul><li>`:address` - Allows you to use a remote mail server. Just change it from its default `"localhost"` setting.</li><li>`:port` - On the off chance that your mail server doesn't run on port 25, you can change it.</li><li>`:domain` - If you need to specify a HELO domain, you can do it here.</li><li>`:user_name` - If your mail server requires authentication, set the username in this setting.</li><li>`:password` - If your mail server requires authentication, set the password in this setting.</li><li>`:authentication` - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of `:plain` (will send the password in the clear), `:login` (will send password Base64 encoded) or `:cram_md5` (combines a Challenge/Response mechanism to exchange information and a cryptographic Message Digest 5 algorithm to hash important information)</li><li>`:enable_starttls_auto` - Detects if STARTTLS is enabled in your SMTP server and starts to use it. Defaults to `true`.</li><li>`:openssl_verify_mode` - When using TLS, you can set how OpenSSL checks the certificate. This is really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name of an OpenSSL verify constant ('none', 'peer', 'client_once', 'fail_if_no_peer_cert') or directly the constant (`OpenSSL::SSL::VERIFY_NONE`, `OpenSSL::SSL::VERIFY_PEER`, ...).</li></ul>|
+|`smtp_settings`|Allows detailed configuration for `:smtp` delivery method:<ul><li>`:address` - Allows you to use a remote mail server. Just change it from its default `"localhost"` setting.</li><li>`:port` - On the off chance that your mail server doesn't run on port 25, you can change it.</li><li>`:domain` - If you need to specify a HELO domain, you can do it here.</li><li>`:user_name` - If your mail server requires authentication, set the username in this setting.</li><li>`:password` - If your mail server requires authentication, set the password in this setting.</li><li>`:authentication` - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of `:plain` (will send the password in the clear), `:login` (will send password Base64 encoded) or `:cram_md5` (combines a Challenge/Response mechanism to exchange information and a cryptographic Message Digest 5 algorithm to hash important information)</li><li>`:enable_starttls_auto` - Detects if STARTTLS is enabled in your SMTP server and starts to use it. Defaults to `true`.</li><li>`:openssl_verify_mode` - When using TLS, you can set how OpenSSL checks the certificate. This is really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name of an OpenSSL verify constant ('none' or 'peer') or directly the constant (`OpenSSL::SSL::VERIFY_NONE` or `OpenSSL::SSL::VERIFY_PEER`).</li></ul>|
|`sendmail_settings`|Allows you to override options for the `:sendmail` delivery method.<ul><li>`:location` - The location of the sendmail executable. Defaults to `/usr/sbin/sendmail`.</li><li>`:arguments` - The command line arguments to be passed to sendmail. Defaults to `-i -t`.</li></ul>|
|`raise_delivery_errors`|Whether or not errors should be raised if the email fails to be delivered. This only works if the external email server is configured for immediate delivery.|
|`delivery_method`|Defines a delivery method. Possible values are:<ul><li>`:smtp` (default), can be configured by using `config.action_mailer.smtp_settings`.</li><li>`:sendmail`, can be configured by using `config.action_mailer.sendmail_settings`.</li><li>`:file`: save emails to files; can be configured by using `config.action_mailer.file_settings`.</li><li>`:test`: save emails to `ActionMailer::Base.deliveries` array.</li></ul>See [API docs](http://api.rubyonrails.org/classes/ActionMailer/Base.html) for more info.|
diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md
index d6de92ace6..c9f70dc87b 100644
--- a/guides/source/active_job_basics.md
+++ b/guides/source/active_job_basics.md
@@ -62,12 +62,12 @@ $ bin/rails generate job guests_cleanup --queue urgent
```
If you don't want to use a generator, you could create your own file inside of
-`app/jobs`, just make sure that it inherits from `ActiveJob::Base`.
+`app/jobs`, just make sure that it inherits from `ApplicationJob`.
Here's what a job looks like:
```ruby
-class GuestsCleanupJob < ActiveJob::Base
+class GuestsCleanupJob < ApplicationJob
queue_as :default
def perform(*guests)
@@ -141,7 +141,7 @@ end
You can also configure your backend on a per job basis.
```ruby
-class GuestsCleanupJob < ActiveJob::Base
+class GuestsCleanupJob < ApplicationJob
self.queue_adapter = :resque
#....
end
@@ -171,7 +171,7 @@ Most of the adapters support multiple queues. With Active Job you can schedule
the job to run on a specific queue:
```ruby
-class GuestsCleanupJob < ActiveJob::Base
+class GuestsCleanupJob < ApplicationJob
queue_as :low_priority
#....
end
@@ -189,7 +189,7 @@ module YourApp
end
# app/jobs/guests_cleanup_job.rb
-class GuestsCleanupJob < ActiveJob::Base
+class GuestsCleanupJob < ApplicationJob
queue_as :low_priority
#....
end
@@ -212,7 +212,7 @@ module YourApp
end
# app/jobs/guests_cleanup_job.rb
-class GuestsCleanupJob < ActiveJob::Base
+class GuestsCleanupJob < ApplicationJob
queue_as :low_priority
#....
end
@@ -234,7 +234,7 @@ block will be executed in the job context (so you can access `self.arguments`)
and you must return the queue name:
```ruby
-class ProcessVideoJob < ActiveJob::Base
+class ProcessVideoJob < ApplicationJob
queue_as do
video = self.arguments.first
if video.owner.premium?
@@ -274,7 +274,7 @@ trigger logic during the life cycle of a job.
### Usage
```ruby
-class GuestsCleanupJob < ActiveJob::Base
+class GuestsCleanupJob < ApplicationJob
queue_as :default
before_enqueue do |job|
@@ -331,7 +331,7 @@ Active Record objects to your job instead of class/id pairs, which you then have
to manually deserialize. Before, jobs would look like this:
```ruby
-class TrashableCleanupJob < ActiveJob::Base
+class TrashableCleanupJob < ApplicationJob
def perform(trashable_class, trashable_id, depth)
trashable = trashable_class.constantize.find(trashable_id)
trashable.cleanup(depth)
@@ -342,7 +342,7 @@ end
Now you can simply do:
```ruby
-class TrashableCleanupJob < ActiveJob::Base
+class TrashableCleanupJob < ApplicationJob
def perform(trashable, depth)
trashable.cleanup(depth)
end
@@ -360,7 +360,7 @@ Active Job provides a way to catch exceptions raised during the execution of the
job:
```ruby
-class GuestsCleanupJob < ActiveJob::Base
+class GuestsCleanupJob < ApplicationJob
queue_as :default
rescue_from(ActiveRecord::RecordNotFound) do |exception|
diff --git a/guides/source/active_record_callbacks.md b/guides/source/active_record_callbacks.md
index fb5d2065d3..a7975c7772 100644
--- a/guides/source/active_record_callbacks.md
+++ b/guides/source/active_record_callbacks.md
@@ -399,7 +399,7 @@ By using the `after_commit` callback we can account for this case.
```ruby
class PictureFile < ApplicationRecord
- after_commit :delete_picture_file_from_disk, on: [:destroy]
+ after_commit :delete_picture_file_from_disk, on: :destroy
def delete_picture_file_from_disk
if File.exist?(filepath)
@@ -409,7 +409,7 @@ class PictureFile < ApplicationRecord
end
```
-NOTE: the `:on` option specifies when a callback will be fired. If you
+NOTE: The `:on` option specifies when a callback will be fired. If you
don't supply the `:on` option the callback will fire for every action.
Since using `after_commit` callback only on create, update or delete is
diff --git a/guides/source/active_record_postgresql.md b/guides/source/active_record_postgresql.md
index dee64e6439..d7e35490ef 100644
--- a/guides/source/active_record_postgresql.md
+++ b/guides/source/active_record_postgresql.md
@@ -503,9 +503,9 @@ second = Article.create! title: "Brace yourself",
status: "draft",
published_at: 1.month.ago
-Article.count # => 1
-first.archive!
Article.count # => 2
+first.archive!
+Article.count # => 1
```
NOTE: This application only cares about non-archived `Articles`. A view also
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index 936d6a30b8..2737237c1a 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -392,7 +392,8 @@ The `exclusion` helper has an option `:in` that receives the set of values that
will not be accepted for the validated attributes. The `:in` option has an
alias called `:within` that you can use for the same purpose, if you'd like to.
This example uses the `:message` option to show how you can include the
-attribute's value.
+attribute's value. For full options to the message argument please see the
+[message documentation](#message).
The default error message is _"is reserved"_.
@@ -427,7 +428,8 @@ end
The `inclusion` helper has an option `:in` that receives the set of values that
will be accepted. The `:in` option has an alias called `:within` that you can
use for the same purpose, if you'd like to. The previous example uses the
-`:message` option to show how you can include the attribute's value.
+`:message` option to show how you can include the attribute's value. For full
+options please see the [message documentation](#message).
The default error message for this helper is _"is not included in the list"_.
@@ -768,6 +770,9 @@ class Coffee < ApplicationRecord
end
```
+For full options to the message argument please see the
+[message documentation](#message).
+
### `:allow_blank`
The `:allow_blank` option is similar to the `:allow_nil` option. This option
@@ -792,7 +797,8 @@ for each validation helper. The `:message` option accepts a `String` or `Proc`.
A `String` `:message` value can optionally contain any/all of `%{value}`,
`%{attribute}`, and `%{model}` which will be dynamically replaced when
-validation fails.
+validation fails. This replacement is done using the I18n gem, and the
+placeholders must match exactly, no spaces are allowed.
A `Proc` `:message` value is given two arguments: the object being validated, and
a hash with `:model`, `:attribute`, and `:value` key-value pairs.
diff --git a/guides/source/api_documentation_guidelines.md b/guides/source/api_documentation_guidelines.md
index 5b34330936..34b9c0d2ca 100644
--- a/guides/source/api_documentation_guidelines.md
+++ b/guides/source/api_documentation_guidelines.md
@@ -20,7 +20,7 @@ The [Rails API documentation](http://api.rubyonrails.org) is generated with
in the rails root directory, run `bundle install` and execute:
```bash
- ./bin/rails rdoc
+ bundle exec rake rdoc
```
Resulting HTML files can be found in the ./doc/rdoc directory.
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 51a2649ec0..f34b6473b2 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -94,6 +94,8 @@ application. Accepts a valid week day symbol (e.g. `:monday`).
* `config.eager_load_paths` accepts an array of paths from which Rails will eager load on boot if cache classes is enabled. Defaults to every folder in the `app` directory of the application.
+* `config.enable_dependency_loading`: when true, enables autoload loading, even if the application is eager loaded and `config.cache_classes` is set as true. Defaults to false.
+
* `config.encoding` sets up the application-wide encoding. Defaults to UTF-8.
* `config.exceptions_app` sets the exceptions application invoked by the ShowException middleware when an exception happens. Defaults to `ActionDispatch::PublicExceptions.new(Rails.public_path)`.
@@ -242,6 +244,12 @@ This will put the `Magical::Unicorns` middleware on the end of the stack. You ca
config.middleware.insert_before Rack::Head, Magical::Unicorns
```
+Or you can insert a middleware to exact position by using indexes. For example, if you want to insert `Magical::Unicorns` middleware on top of the stack, you can do it, like so:
+
+```ruby
+config.middleware.insert_before 0, Magical::Unicorns
+```
+
There's also `insert_after` which will insert a middleware after another:
```ruby
@@ -272,6 +280,26 @@ All these configuration options are delegated to the `I18n` library.
* `config.i18n.load_path` sets the path Rails uses to look for locale files. Defaults to `config/locales/*.{yml,rb}`.
+* `config.i18n.fallbacks` sets fallback behavior for missing translations. Here are 3 usage examples for this option:
+
+ * You can set the option to `true` for using default locale as fallback, like so:
+
+ ```ruby
+ config.i18n.fallbacks = true
+ ```
+
+ * Or you can set an array of locales as fallback, like so:
+
+ ```ruby
+ config.i18n.fallbacks = [:tr, :en]
+ ```
+
+ * Or you can set different fallbacks for locales individually. For example, if you want to use `:tr` for `:az` and `:de`, `:en` for `:da` as fallbacks, you can do it, like so:
+
+ ```ruby
+ config.i18n.fallbacks = { az: :tr, da: [:de, :en] }
+ ```
+
### Configuring Active Record
`config.active_record` includes a variety of configuration options:
@@ -498,7 +526,7 @@ There are a number of settings available on `config.action_mailer`:
* `:password` - If your mail server requires authentication, set the password in this setting.
* `:authentication` - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of `:plain`, `:login`, `:cram_md5`.
* `:enable_starttls_auto` - Detects if STARTTLS is enabled in your SMTP server and starts to use it. It defaults to `true`.
- * `:openssl_verify_mode` - When using TLS, you can set how OpenSSL checks the certificate. This is useful if you need to validate a self-signed and/or a wildcard certificate. This can be one of the OpenSSL verify constants, `:none`, `:peer`, `:client_once`, `:fail_if_no_peer_cert`, or the constant directly `OpenSSL::SSL::VERIFY_NONE`.
+ * `:openssl_verify_mode` - When using TLS, you can set how OpenSSL checks the certificate. This is useful if you need to validate a self-signed and/or a wildcard certificate. This can be one of the OpenSSL verify constants, `:none` or `:peer` -- or the constant directly `OpenSSL::SSL::VERIFY_NONE` or `OpenSSL::SSL::VERIFY_PEER`, respectively.
* `:ssl/:tls` - Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection).
* `config.action_mailer.sendmail_settings` allows detailed configuration for the `sendmail` delivery method. It accepts a hash of options, which can include any of these options:
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index 49d5f5a555..ba8d085f79 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -131,7 +131,7 @@ learn about Ruby on Rails, and the API, which serves as a reference.
You can help improve the Rails guides by making them more coherent, consistent or readable, adding missing information, correcting factual errors, fixing typos, or bringing them up to date with the latest edge Rails.
You can either open a pull request to [Rails](https://github.com/rails/rails) or
-ask the [Rails core team](http://rubyonrails.org/core) for commit access on
+ask the [Rails core team](http://rubyonrails.org/community/#core) for commit access on
docrails if you contribute regularly.
Please do not open pull requests in docrails, if you'd like to get feedback on your
change, ask for it in [Rails](https://github.com/rails/rails) instead.
diff --git a/guides/source/credits.html.erb b/guides/source/credits.html.erb
index 1d995581fa..511d76041b 100644
--- a/guides/source/credits.html.erb
+++ b/guides/source/credits.html.erb
@@ -64,7 +64,7 @@ Oscar Del Ben is a software engineer at <a href="http://www.wildfireapp.com/">Wi
<% end %>
<%= author('Pratik Naik', 'lifo') do %>
- Pratik Naik is a Ruby on Rails developer at <a href="https://basecamp.com/">Basecamp</a> and also a member of the <a href="http://rubyonrails.org/core">Rails core team</a>. He maintains a blog at <a href="http://m.onkey.org">has_many :bugs, :through =&gt; :rails</a> and has a semi-active <a href="http://twitter.com/lifo">twitter account</a>.
+ Pratik Naik is a Ruby on Rails developer at <a href="https://basecamp.com/">Basecamp</a> and maintains a blog at <a href="http://m.onkey.org">has_many :bugs, :through =&gt; :rails</a>. He also has a semi-active <a href="http://twitter.com/lifo">twitter account</a>.
<% end %>
<%= author('Emilio Tagua', 'miloops') do %>
diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml
index a5b8a75509..a06a53b250 100644
--- a/guides/source/documents.yaml
+++ b/guides/source/documents.yaml
@@ -195,6 +195,11 @@
url: upgrading_ruby_on_rails.html
description: This guide helps in upgrading applications to latest Ruby on Rails versions.
-
+ name: Ruby on Rails 5.0 Release Notes
+ url: 5_0_release_notes.html
+ description: Release notes for Rails 5.0.
+ work_in_progress: true
+ -
name: Ruby on Rails 4.2 Release Notes
url: 4_2_release_notes.html
description: Release notes for Rails 4.2.
diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb
index 6db76b528e..9abb863da6 100644
--- a/guides/source/layout.html.erb
+++ b/guides/source/layout.html.erb
@@ -111,7 +111,7 @@
<%= link_to 'open an issue', 'https://github.com/rails/rails/issues' %>.
</p>
<p>And last but not least, any kind of discussion regarding Ruby on Rails
- documentation is very welcome in the <%= link_to 'rubyonrails-docs mailing list', 'http://groups.google.com/group/rubyonrails-docs' %>.
+ documentation is very welcome in the <%= link_to 'rubyonrails-docs mailing list', 'https://groups.google.com/forum/#!forum/rubyonrails-docs' %>.
</p>
</div>
</div>
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 050bdda9e3..d4a826cee5 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -695,7 +695,7 @@ end
In the `test_should_get_index` test, Rails simulates a request on the action called `index`, making sure the request was successful
and also ensuring that the right response body has been generated.
-The `get` method kicks off the web request and populates the results into the `@response`. It accepts 4 arguments:
+The `get` method kicks off the web request and populates the results into the `@response`. It can accept up to 6 arguments:
* The action of the controller you are requesting.
This can be in the form of a string or a route (i.e. `articles_url`).
@@ -703,22 +703,26 @@ The `get` method kicks off the web request and populates the results into the `@
* `params`: option with a hash of request parameters to pass into the action
(e.g. query string parameters or article variables).
-* `session`: option with a hash of session variables to pass along with the request.
+* `headers`: for setting the headers that will be passed with the request.
-* `flash`: option with a hash of flash values.
+* `env`: for customizing the request environment as needed.
+
+* `xhr`: whether the request is Ajax request or not. Can be set to true for marking the request as Ajax.
+
+* `as`: for encoding the request with different content type. Supports `:json` by default.
All of these keyword arguments are optional.
-Example: Calling the `:show` action, passing an `id` of 12 as the `params` and setting a `user_id` of 5 in the session:
+Example: Calling the `:show` action, passing an `id` of 12 as the `params` and setting `HTTP_REFERER` header:
```ruby
-get(:show, params: { id: 12 }, session: { user_id: 5 })
+get :show, params: { id: 12 }, headers: { "HTTP_REFERER" => "http://example.com/home" }
```
-Another example: Calling the `:view` action, passing an `id` of 12 as the `params`, this time with no session, but with a flash message.
+Another example: Calling the `:update` action, passing an `id` of 12 as the `params` as an Ajax request.
```ruby
-get(view_url, params: { id: 12 }, flash: { message: 'booya!' })
+patch update_url, params: { id: 12 }, xhr: true
```
NOTE: If you try running `test_should_create_article` test from `articles_controller_test.rb` it will fail on account of the newly added model level validation and rightly so.
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index b8f1cda329..83fe6f56a4 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,12 @@
+* Default `config.assets.quiet = true` in the development environment. Suppress
+ logging of `sprockets-rails` requests by default.
+
+ *Kevin McPhillips*
+
+* Ensure `/rails/info` routes match in development for apps with a catch-all globbing route.
+
+ *Nicholas Firth-McCoy*
+
* Added a shared section to `config/secrets.yml` that will be loaded for all environments.
*DHH*
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index f415a20833..5ee08d96e1 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -16,7 +16,7 @@ module Rails
:railties_order, :relative_url_root, :secret_key_base, :secret_token,
:ssl_options, :public_file_server,
:session_options, :time_zone, :reload_classes_only_on_change,
- :beginning_of_week, :filter_redirect, :x
+ :beginning_of_week, :filter_redirect, :x, :enable_dependency_loading
attr_writer :log_level
attr_reader :encoding, :api_only, :static_cache_control
@@ -54,6 +54,7 @@ module Rails
@api_only = false
@debug_exception_response_format = nil
@x = Custom.new
+ @enable_dependency_loading = false
end
def static_cache_control=(value)
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index 4e24640510..daf3a24b16 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -21,10 +21,13 @@ module Rails
initializer :add_builtin_route do |app|
if Rails.env.development?
- app.routes.append do
+ app.routes.prepend do
get '/rails/info/properties' => "rails/info#properties", internal: true
get '/rails/info/routes' => "rails/info#routes", internal: true
get '/rails/info' => "rails/info#index", internal: true
+ end
+
+ app.routes.append do
get '/' => "rails/welcome#index", internal: true
end
end
@@ -173,7 +176,7 @@ module Rails
# Disable dependency loading during request cycle
initializer :disable_dependency_loading do
- if config.eager_load && config.cache_classes
+ if config.eager_load && config.cache_classes && !config.enable_dependency_loading
ActiveSupport::Dependencies.unhook!
end
end
diff --git a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
index 7f00943d80..97f3657070 100644
--- a/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
+++ b/railties/lib/rails/generators/erb/mailer/mailer_generator.rb
@@ -9,6 +9,13 @@ module Erb # :nodoc:
view_base_path = File.join("app/views", class_path, file_name + '_mailer')
empty_directory view_base_path
+ if self.behavior == :invoke
+ formats.each do |format|
+ layout_path = File.join('app/views/layouts', class_path, filename_with_extensions('mailer', format))
+ template filename_with_extensions(:layout, format), layout_path
+ end
+ end
+
actions.each do |action|
@action = action
diff --git a/railties/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt b/railties/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt
new file mode 100644
index 0000000000..55f3675d49
--- /dev/null
+++ b/railties/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <style>
+ /* Email styles need to be inline */
+ </style>
+ </head>
+
+ <body>
+ <%%= yield %>
+ </body>
+</html>
diff --git a/railties/lib/rails/generators/erb/mailer/templates/layout.text.erb.tt b/railties/lib/rails/generators/erb/mailer/templates/layout.text.erb.tt
new file mode 100644
index 0000000000..6363733e6e
--- /dev/null
+++ b/railties/lib/rails/generators/erb/mailer/templates/layout.text.erb.tt
@@ -0,0 +1 @@
+<%%= yield %>
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index c288b3dfce..448dce06af 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -90,7 +90,6 @@ module Rails
def config_when_updating
cookie_serializer_config_exist = File.exist?('config/initializers/cookies_serializer.rb')
- new_framework_defaults_config_exist = File.exist?('config/initializers/new_framework_defaults.rb')
action_cable_config_exist = File.exist?('config/cable.yml')
rack_cors_config_exist = File.exist?('config/initializers/cors.rb')
@@ -102,10 +101,6 @@ module Rails
gsub_file 'config/initializers/cookies_serializer.rb', /json(?!,)/, 'marshal'
end
- unless new_framework_defaults_config_exist
- remove_file 'config/initializers/new_framework_defaults.rb'
- end
-
unless action_cable_config_exist
template 'config/cable.yml'
end
diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt
index f4ee1409af..70b579d10e 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt
@@ -1,6 +1,4 @@
-<% unless options.api? -%>
//= link_tree ../images
-<% end -%>
<% unless options.skip_javascript -%>
//= link_directory ../javascripts .js
<% end -%>
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
index 7a537610e9..f3ccf95045 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
@@ -46,6 +46,9 @@ Rails.application.configure do
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
+
+ # Suppress logger output for asset requests.
+ config.assets.quiet = true
<%- end -%>
# Raises error for missing translations
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt
index 730938a1ba..991963b65e 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt
@@ -1,37 +1,34 @@
# Be sure to restart your server when you modify this file.
-# This file contains all the new default configuration options from
-# Rails 5.0.
-<%- unless options[:skip_active_record] -%>
-
-# Require `belongs_to` associations by default. This is a new Rails 5.0
-# default, so it is introduced as a configuration option to ensure that apps
-# made on earlier versions of Rails are not affected when upgrading.
-Rails.application.config.active_record.belongs_to_required_by_default = true
+#
+# This file contains migration options to ease your Rails 5.0 upgrade.
+#
+<%- if options[:update] -%>
+# Once upgraded flip defaults one by one to migrate to the new default.
+#
<%- end -%>
-
-# Do not halt callback chains when a callback returns false. This is a new
-# Rails 5.0 default, so it is introduced as a configuration option to ensure
-# that apps made with earlier versions of Rails are not affected when upgrading.
-ActiveSupport.halt_callback_chains_on_return_false = false
+# Read the Rails 5.0 release notes for more info on each option.
<%- unless options[:api] -%>
-# Enable per-form CSRF tokens.
-Rails.application.config.action_controller.per_form_csrf_tokens = true
+# Enable per-form CSRF tokens. Previous versions had false.
+Rails.application.config.action_controller.per_form_csrf_tokens = <%= options[:update] ? false : true %>
-# Enable origin-checking CSRF mitigation.
-Rails.application.config.action_controller.forgery_protection_origin_check = true
+# Enable origin-checking CSRF mitigation. Previous versions had false.
+Rails.application.config.action_controller.forgery_protection_origin_check = <%= options[:update] ? false : true %>
<%- end -%>
-# Configure SSL options to enable HSTS with subdomains. This is a new
-# Rails 5.0 default, so it is introduced as a configuration option to ensure
-# that apps made on earlier versions of Rails are not affected when upgrading.
-Rails.application.config.ssl_options = { hsts: { subdomains: true } }
+# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`.
+# Previous versions had false.
+ActiveSupport.to_time_preserves_timezone = <%= options[:update] ? false : true %>
+<%- unless options[:skip_active_record] -%>
-# Preserve the timezone of the receiver when calling to `to_time`.
-# Ruby 2.4 will change the behavior of `to_time` to preserve the timezone
-# when converting to an instance of `Time` instead of the previous behavior
-# of converting to the local system timezone.
-#
-# Rails 5.0 introduced this config option so that apps made with earlier
-# versions of Rails are not affected when upgrading.
-ActiveSupport.to_time_preserves_timezone = true
+# Require `belongs_to` associations by default. Previous versions had false.
+Rails.application.config.active_record.belongs_to_required_by_default = <%= options[:update] ? false : true %>
+<%- end -%>
+
+# Do not halt callback chains when a callback returns false. Previous versions had true.
+ActiveSupport.halt_callback_chains_on_return_false = <%= options[:update] ? true : false %>
+<%- unless options[:update] -%>
+
+# Configure SSL options to enable HSTS with subdomains. Previous versions had false.
+Rails.application.config.ssl_options = { hsts: { subdomains: true } }
+<%- end -%>
diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb
index 0d18478043..c469c188e6 100644
--- a/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb
+++ b/railties/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb
@@ -11,31 +11,31 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
end
test "should get index" do
- get <%= index_helper %>_url
+ get <%= index_helper %>_url, as: :json
assert_response :success
end
test "should create <%= singular_table_name %>" do
assert_difference('<%= class_name %>.count') do
- post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: { #{attributes_hash} }" %> }
+ post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: { #{attributes_hash} }" %> }, as: :json
end
assert_response 201
end
test "should show <%= singular_table_name %>" do
- get <%= show_helper %>
+ get <%= show_helper %>, as: :json
assert_response :success
end
test "should update <%= singular_table_name %>" do
- patch <%= show_helper %>, params: { <%= "#{singular_table_name}: { #{attributes_hash} }" %> }
+ patch <%= show_helper %>, params: { <%= "#{singular_table_name}: { #{attributes_hash} }" %> }, as: :json
assert_response 200
end
test "should destroy <%= singular_table_name %>" do
assert_difference('<%= class_name %>.count', -1) do
- delete <%= show_helper %>
+ delete <%= show_helper %>, as: :json
end
assert_response 204
diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake
index 3e771167ee..51d9daaaa9 100644
--- a/railties/lib/rails/tasks/framework.rake
+++ b/railties/lib/rails/tasks/framework.rake
@@ -48,7 +48,7 @@ namespace :app do
require 'rails/generators'
require 'rails/generators/rails/app/app_generator'
gen = Rails::Generators::AppGenerator.new ["rails"],
- { api: !!Rails.application.config.api_only },
+ { api: !!Rails.application.config.api_only, update: true },
destination_root: Rails.root
File.exist?(Rails.root.join("config", "application.rb")) ?
gen.send(:app_const) : gen.send(:valid_const?)
diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb
index e51f32aaed..93847c7aa9 100644
--- a/railties/test/application/routing_test.rb
+++ b/railties/test/application/routing_test.rb
@@ -39,6 +39,25 @@ module ApplicationTests
assert_equal 200, last_response.status
end
+ test "/rails/info routes are accessible with globbing route present" do
+ app("development")
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ get '*foo', to: 'foo#index'
+ end
+ RUBY
+
+ get "/rails/info"
+ assert_equal 302, last_response.status
+
+ get "rails/info/routes"
+ assert_equal 200, last_response.status
+
+ get "rails/info/properties"
+ assert_equal 200, last_response.status
+ end
+
test "root takes precedence over internal welcome controller" do
app("development")
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index bea8db087f..058308aa13 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -208,24 +208,15 @@ class AppGeneratorTest < Rails::Generators::TestCase
FileUtils.rm("#{app_root}/config/initializers/new_framework_defaults.rb")
stub_rails_application(app_root) do
- generator = Rails::Generators::AppGenerator.new ["rails"], [], destination_root: app_root, shell: @shell
+ generator = Rails::Generators::AppGenerator.new ["rails"], { update: true }, destination_root: app_root, shell: @shell
generator.send(:app_const)
quietly { generator.send(:update_config_files) }
- assert_no_file "#{app_root}/config/initializers/new_framework_defaults.rb"
- end
- end
-
- def test_rails_update_does_not_new_framework_defaults_if_already_present
- app_root = File.join(destination_root, 'myapp')
- run_generator [app_root]
- FileUtils.touch("#{app_root}/config/initializers/new_framework_defaults.rb")
-
- stub_rails_application(app_root) do
- generator = Rails::Generators::AppGenerator.new ["rails"], [], destination_root: app_root, shell: @shell
- generator.send(:app_const)
- quietly { generator.send(:update_config_files) }
- assert_file "#{app_root}/config/initializers/new_framework_defaults.rb"
+ assert_file "#{app_root}/config/initializers/new_framework_defaults.rb" do |content|
+ assert_match(/ActiveSupport\.halt_callback_chains_on_return_false = true/, content)
+ assert_match(/Rails\.application\.config.active_record\.belongs_to_required_by_default = false/, content)
+ assert_no_match(/Rails\.application\.config\.ssl_options/, content)
+ end
end
end
diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb
index 8728b39dae..6a4951840d 100644
--- a/railties/test/generators/mailer_generator_test.rb
+++ b/railties/test/generators/mailer_generator_test.rb
@@ -84,6 +84,10 @@ class MailerGeneratorTest < Rails::Generators::TestCase
assert_match(%r(\sapp/views/notifier_mailer/bar\.text\.erb), view)
assert_match(/<%= @greeting %>/, view)
end
+
+ assert_file "app/views/layouts/mailer.text.erb" do |view|
+ assert_match(/<%= yield %>/, view)
+ end
end
def test_invokes_default_html_template_engine
@@ -97,6 +101,10 @@ class MailerGeneratorTest < Rails::Generators::TestCase
assert_match(%r(\sapp/views/notifier_mailer/bar\.html\.erb), view)
assert_match(/<%= @greeting %>/, view)
end
+
+ assert_file "app/views/layouts/mailer.html.erb" do |view|
+ assert_match(%r{<body>\n <%= yield %>\n </body>}, view)
+ end
end
def test_invokes_default_template_engine_even_with_no_action
diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb
index ed6846abc3..6b30c40476 100644
--- a/railties/test/generators/model_generator_test.rb
+++ b/railties/test/generators/model_generator_test.rb
@@ -34,7 +34,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase
def test_invokes_default_orm
run_generator
- assert_file "app/models/account.rb", /class Account < ActiveRecord::Base/
+ assert_file "app/models/account.rb", /class Account < ApplicationRecord/
end
def test_model_with_parent_option
@@ -56,7 +56,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase
def test_plural_names_are_singularized
content = run_generator ["accounts".freeze]
- assert_file "app/models/account.rb", /class Account < ActiveRecord::Base/
+ assert_file "app/models/account.rb", /class Account < ApplicationRecord/
assert_file "test/models/account_test.rb", /class AccountTest/
assert_match(/\[WARNING\] The model name 'accounts' was recognized as a plural, using the singular 'account' instead\. Override with --force-plural or setup custom inflection rules for this noun before running the generator\./, content)
end
@@ -71,7 +71,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase
assert_file "app/models/admin.rb", /module Admin/
assert_file "app/models/admin.rb", /def self\.table_name_prefix/
assert_file "app/models/admin.rb", /'admin_'/
- assert_file "app/models/admin/account.rb", /class Admin::Account < ActiveRecord::Base/
+ assert_file "app/models/admin/account.rb", /class Admin::Account < ApplicationRecord/
end
def test_migration
@@ -386,7 +386,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase
run_generator ["account", "supplier:references{required}"]
expected_file = <<-FILE.strip_heredoc
- class Account < ActiveRecord::Base
+ class Account < ApplicationRecord
belongs_to :supplier, required: true
end
FILE
@@ -397,7 +397,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase
run_generator ["account", "supplier:references{required,polymorphic}"]
expected_file = <<-FILE.strip_heredoc
- class Account < ActiveRecord::Base
+ class Account < ApplicationRecord
belongs_to :supplier, polymorphic: true, required: true
end
FILE
@@ -408,7 +408,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase
run_generator ["account", "supplier:references{polymorphic.required}"]
expected_file = <<-FILE.strip_heredoc
- class Account < ActiveRecord::Base
+ class Account < ApplicationRecord
belongs_to :supplier, polymorphic: true, required: true
end
FILE
@@ -459,7 +459,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase
def test_token_option_adds_has_secure_token
run_generator ["user", "token:token", "auth_token:token"]
expected_file = <<-FILE.strip_heredoc
- class User < ActiveRecord::Base
+ class User < ApplicationRecord
has_secure_token
has_secure_token :auth_token
end
diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb
index d76759a7d1..902c340321 100644
--- a/railties/test/generators/namespaced_generators_test.rb
+++ b/railties/test/generators/namespaced_generators_test.rb
@@ -91,7 +91,7 @@ class NamespacedModelGeneratorTest < NamespacedGeneratorTestCase
def test_adds_namespace_to_model
run_generator
- assert_file "app/models/test_app/account.rb", /module TestApp/, / class Account < ActiveRecord::Base/
+ assert_file "app/models/test_app/account.rb", /module TestApp/, / class Account < ApplicationRecord/
end
def test_model_with_namespace
@@ -99,7 +99,7 @@ class NamespacedModelGeneratorTest < NamespacedGeneratorTestCase
assert_file "app/models/test_app/admin.rb", /module TestApp/, /module Admin/
assert_file "app/models/test_app/admin.rb", /def self\.table_name_prefix/
assert_file "app/models/test_app/admin.rb", /'test_app_admin_'/
- assert_file "app/models/test_app/admin/account.rb", /module TestApp/, /class Admin::Account < ActiveRecord::Base/
+ assert_file "app/models/test_app/admin/account.rb", /module TestApp/, /class Admin::Account < ApplicationRecord/
end
def test_migration
@@ -201,7 +201,7 @@ class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase
run_generator
# Model
- assert_file "app/models/test_app/product_line.rb", /module TestApp\n class ProductLine < ActiveRecord::Base/
+ assert_file "app/models/test_app/product_line.rb", /module TestApp\n class ProductLine < ApplicationRecord/
assert_file "test/models/test_app/product_line_test.rb", /module TestApp\n class ProductLineTest < ActiveSupport::TestCase/
assert_file "test/fixtures/test_app/product_lines.yml"
assert_migration "db/migrate/create_test_app_product_lines.rb"
@@ -268,7 +268,7 @@ class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase
# Model
assert_file "app/models/test_app/admin.rb", /module TestApp\n module Admin/
- assert_file "app/models/test_app/admin/role.rb", /module TestApp\n class Admin::Role < ActiveRecord::Base/
+ assert_file "app/models/test_app/admin/role.rb", /module TestApp\n class Admin::Role < ApplicationRecord/
assert_file "test/models/test_app/admin/role_test.rb", /module TestApp\n class Admin::RoleTest < ActiveSupport::TestCase/
assert_file "test/fixtures/test_app/admin/roles.yml"
assert_migration "db/migrate/create_test_app_admin_roles.rb"
@@ -336,7 +336,7 @@ class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase
# Model
assert_file "app/models/test_app/admin/user/special.rb", /module TestApp\n module Admin/
- assert_file "app/models/test_app/admin/user/special/role.rb", /module TestApp\n class Admin::User::Special::Role < ActiveRecord::Base/
+ assert_file "app/models/test_app/admin/user/special/role.rb", /module TestApp\n class Admin::User::Special::Role < ApplicationRecord/
assert_file "test/models/test_app/admin/user/special/role_test.rb", /module TestApp\n class Admin::User::Special::RoleTest < ActiveSupport::TestCase/
assert_file "test/fixtures/test_app/admin/user/special/roles.yml"
assert_migration "db/migrate/create_test_app_admin_user_special_roles.rb"
@@ -402,7 +402,7 @@ class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase
# Model
assert_file "app/models/test_app/admin.rb", /module TestApp\n module Admin/
- assert_file "app/models/test_app/admin/role.rb", /module TestApp\n class Admin::Role < ActiveRecord::Base/
+ assert_file "app/models/test_app/admin/role.rb", /module TestApp\n class Admin::Role < ApplicationRecord/
assert_file "test/models/test_app/admin/role_test.rb", /module TestApp\n class Admin::RoleTest < ActiveSupport::TestCase/
assert_file "test/fixtures/test_app/admin/roles.yml"
assert_migration "db/migrate/create_test_app_admin_roles.rb"
diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb
index 3cc8e1de55..5dd4cce28a 100644
--- a/railties/test/generators/plugin_generator_test.rb
+++ b/railties/test/generators/plugin_generator_test.rb
@@ -669,6 +669,21 @@ class PluginGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_generate_mailer_layouts_when_does_not_exist_in_mountable_engine
+ run_generator [destination_root, '--mountable']
+ capture(:stdout) do
+ `#{destination_root}/bin/rails g mailer User`
+ end
+
+ assert_file "#{destination_root}/app/views/layouts/bukkits/mailer.text.erb" do |view|
+ assert_match(/<%= yield %>/, view)
+ end
+
+ assert_file "#{destination_root}/app/views/layouts/bukkits/mailer.html.erb" do |view|
+ assert_match(%r{<body>\n <%= yield %>\n </body>}, view)
+ end
+ end
+
def test_generate_application_job_when_does_not_exist_in_mountable_engine
run_generator [destination_root, '--mountable']
FileUtils.rm "#{destination_root}/app/jobs/bukkits/application_job.rb"
diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb
index addaf83bc8..53dcfc4024 100644
--- a/railties/test/generators/resource_generator_test.rb
+++ b/railties/test/generators/resource_generator_test.rb
@@ -60,14 +60,14 @@ class ResourceGeneratorTest < Rails::Generators::TestCase
def test_plural_names_are_singularized
content = run_generator ["accounts".freeze]
- assert_file "app/models/account.rb", /class Account < ActiveRecord::Base/
+ assert_file "app/models/account.rb", /class Account < ApplicationRecord/
assert_file "test/models/account_test.rb", /class AccountTest/
assert_match(/\[WARNING\] The model name 'accounts' was recognized as a plural, using the singular 'account' instead\. Override with --force-plural or setup custom inflection rules for this noun before running the generator\./, content)
end
def test_plural_names_can_be_forced
content = run_generator ["accounts", "--force-plural"]
- assert_file "app/models/accounts.rb", /class Accounts < ActiveRecord::Base/
+ assert_file "app/models/accounts.rb", /class Accounts < ApplicationRecord/
assert_file "test/models/accounts_test.rb", /class AccountsTest/
assert_no_match(/\[WARNING\]/, content)
end
diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb
index c37e289f4b..736ff0b41f 100644
--- a/railties/test/generators/scaffold_controller_generator_test.rb
+++ b/railties/test/generators/scaffold_controller_generator_test.rb
@@ -238,8 +238,8 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
assert_file "test/controllers/users_controller_test.rb" do |content|
assert_match(/class UsersControllerTest < ActionDispatch::IntegrationTest/, content)
assert_match(/test "should get index"/, content)
- assert_match(/post users_url, params: \{ user: \{ age: @user\.age, name: @user\.name, organization_id: @user\.organization_id, organization_type: @user\.organization_type \} \}/, content)
- assert_match(/patch user_url\(@user\), params: \{ user: \{ age: @user\.age, name: @user\.name, organization_id: @user\.organization_id, organization_type: @user\.organization_type \} \}/, content)
+ assert_match(/post users_url, params: \{ user: \{ age: @user\.age, name: @user\.name, organization_id: @user\.organization_id, organization_type: @user\.organization_type \} \}, as: :json/, content)
+ assert_match(/patch user_url\(@user\), params: \{ user: \{ age: @user\.age, name: @user\.name, organization_id: @user\.organization_id, organization_type: @user\.organization_type \} \}, as: :json/, content)
assert_no_match(/assert_redirected_to/, content)
end
end
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index 146be5a85a..bd69906b9d 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -11,7 +11,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
run_generator
# Model
- assert_file "app/models/product_line.rb", /class ProductLine < ActiveRecord::Base/
+ assert_file "app/models/product_line.rb", /class ProductLine < ApplicationRecord/
assert_file "test/models/product_line_test.rb", /class ProductLineTest < ActiveSupport::TestCase/
assert_file "test/fixtures/product_lines.yml"
assert_migration "db/migrate/create_product_lines.rb", /belongs_to :product/
@@ -91,7 +91,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
run_generator %w(product_line title:string product:belongs_to user:references --api --no-template-engine --no-helper --no-assets)
# Model
- assert_file "app/models/product_line.rb", /class ProductLine < ActiveRecord::Base/
+ assert_file "app/models/product_line.rb", /class ProductLine < ApplicationRecord/
assert_file "test/models/product_line_test.rb", /class ProductLineTest < ActiveSupport::TestCase/
assert_file "test/fixtures/product_lines.yml"
assert_migration "db/migrate/create_product_lines.rb", /belongs_to :product/
@@ -205,7 +205,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
# Model
assert_file "app/models/admin.rb", /module Admin/
- assert_file "app/models/admin/role.rb", /class Admin::Role < ActiveRecord::Base/
+ assert_file "app/models/admin/role.rb", /class Admin::Role < ApplicationRecord/
assert_file "test/models/admin/role_test.rb", /class Admin::RoleTest < ActiveSupport::TestCase/
assert_file "test/fixtures/admin/roles.yml"
assert_migration "db/migrate/create_admin_roles.rb"
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 9dac1008fa..e427614dfa 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -18,6 +18,7 @@ RAILS_FRAMEWORK_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../..")
# These files do not require any others and are needed
# to run the tests
+require "active_support/core_ext/object/blank"
require "active_support/testing/isolation"
require "active_support/core_ext/kernel/reporting"
require 'tmpdir'
diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb
index c51503c2b7..2e10d63599 100644
--- a/railties/test/rails_info_controller_test.rb
+++ b/railties/test/rails_info_controller_test.rb
@@ -78,4 +78,10 @@ class InfoControllerTest < ActionController::TestCase
get :routes, params: { path: 'rails/info/routes.html' }
assert fuzzy_count.call == 0, 'should match optional parts of route literally'
end
+
+ test "internal routes do not have a default params[:internal] value" do
+ get :properties
+ assert_response :success
+ assert_nil @controller.params[:internal]
+ end
end
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 4a47ab32b4..fb8a7656d0 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -481,7 +481,7 @@ YAML
end
RUBY
- add_to_config "config.middleware.use \"Bukkits\""
+ add_to_config "config.middleware.use Bukkits"
boot_rails
end
@@ -1155,10 +1155,10 @@ YAML
assert_equal "App's bar partial", last_response.body.strip
get("/assets/foo.js")
- assert_equal "// Bukkit's foo js", last_response.body.strip
+ assert_match "// Bukkit's foo js", last_response.body.strip
get("/assets/bar.js")
- assert_equal "// App's bar js", last_response.body.strip
+ assert_match "// App's bar js", last_response.body.strip
# ensure that railties are not added twice
railties = Rails.application.send(:ordered_railties).map(&:class)