aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock4
-rw-r--r--actioncable/lib/action_cable/channel/periodic_timers.rb3
-rw-r--r--actioncable/lib/action_cable/connection/identification.rb3
-rw-r--r--actionmailer/lib/action_mailer/base.rb3
-rw-r--r--actionmailer/lib/action_mailer/delivery_methods.rb6
-rw-r--r--actionpack/CHANGELOG.md10
-rw-r--r--actionpack/lib/abstract_controller/caching.rb3
-rw-r--r--actionpack/lib/abstract_controller/helpers.rb7
-rw-r--r--actionpack/lib/action_controller/metal.rb3
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb3
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_template_digest.rb3
-rw-r--r--actionpack/lib/action_controller/metal/flash.rb3
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb5
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb3
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb3
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb10
-rw-r--r--actionpack/lib/action_dispatch/system_test_case.rb8
-rw-r--r--actionpack/lib/action_dispatch/system_testing/driver.rb29
-rw-r--r--actionpack/test/dispatch/system_testing/driver_test.rb18
-rw-r--r--actionview/app/assets/javascripts/README.md5
-rw-r--r--actionview/app/assets/javascripts/rails-ujs/start.coffee2
-rw-r--r--actionview/lib/action_view/helpers/form_helper.rb17
-rw-r--r--actionview/lib/action_view/layouts.rb6
-rw-r--r--actionview/lib/action_view/template/handlers/builder.rb5
-rw-r--r--actionview/lib/action_view/template/handlers/erb.rb9
-rw-r--r--actionview/lib/action_view/test_case.rb2
-rw-r--r--actionview/lib/action_view/view_paths.rb4
-rw-r--r--actionview/test/template/date_helper_test.rb14
-rw-r--r--activejob/lib/active_job/queue_name.rb7
-rw-r--r--activejob/lib/active_job/queue_priority.rb4
-rw-r--r--activemodel/lib/active_model/attribute_assignment.rb4
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb5
-rw-r--r--activemodel/lib/active_model/serializers/json.rb3
-rw-r--r--activemodel/lib/active_model/validations.rb3
-rw-r--r--activerecord/CHANGELOG.md4
-rw-r--r--activerecord/lib/active_record/associations/alias_tracker.rb7
-rw-r--r--activerecord/lib/active_record/associations/association.rb10
-rw-r--r--activerecord/lib/active_record/associations/association_scope.rb2
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb3
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb33
-rw-r--r--activerecord/lib/active_record/associations/preloader/association.rb7
-rw-r--r--activerecord/lib/active_record/associations/preloader/belongs_to.rb2
-rw-r--r--activerecord/lib/active_record/associations/preloader/through_association.rb2
-rw-r--r--activerecord/lib/active_record/attribute_decorators.rb3
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb3
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb7
-rw-r--r--activerecord/lib/active_record/attributes.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb19
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb13
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb12
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb19
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb3
-rw-r--r--activerecord/lib/active_record/enum.rb3
-rw-r--r--activerecord/lib/active_record/fixtures.rb20
-rw-r--r--activerecord/lib/active_record/inheritance.rb3
-rw-r--r--activerecord/lib/active_record/integration.rb6
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb3
-rw-r--r--activerecord/lib/active_record/model_schema.rb27
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb3
-rw-r--r--activerecord/lib/active_record/querying.rb2
-rw-r--r--activerecord/lib/active_record/readonly_attributes.rb3
-rw-r--r--activerecord/lib/active_record/reflection.rb44
-rw-r--r--activerecord/lib/active_record/relation/delegation.rb2
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb19
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb7
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb7
-rw-r--r--activerecord/lib/active_record/relation/where_clause_factory.rb2
-rw-r--r--activerecord/lib/active_record/scoping/default.rb13
-rw-r--r--activerecord/lib/active_record/scoping/named.rb11
-rw-r--r--activerecord/lib/active_record/tasks/sqlite_database_tasks.rb2
-rw-r--r--activerecord/lib/active_record/timestamp.rb3
-rw-r--r--activerecord/lib/active_record/type.rb3
-rw-r--r--activerecord/lib/active_record/type/internal/abstract_json.rb33
-rw-r--r--activerecord/lib/active_record/type/json.rb28
-rw-r--r--activerecord/test/cases/adapters/mysql2/json_test.rb15
-rw-r--r--activerecord/test/cases/adapters/postgresql/json_test.rb27
-rw-r--r--activerecord/test/cases/adapters/postgresql/uuid_test.rb10
-rw-r--r--activerecord/test/cases/associations/extension_test.rb6
-rw-r--r--activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb13
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb12
-rw-r--r--activerecord/test/cases/associations_test.rb12
-rw-r--r--activerecord/test/cases/base_test.rb74
-rw-r--r--activerecord/test/cases/calculations_test.rb9
-rw-r--r--activerecord/test/cases/dirty_test.rb5
-rw-r--r--activerecord/test/cases/enum_test.rb2
-rw-r--r--activerecord/test/cases/finder_test.rb10
-rw-r--r--activerecord/test/cases/inheritance_test.rb7
-rw-r--r--activerecord/test/cases/json_attribute_test.rb33
-rw-r--r--activerecord/test/cases/json_shared_test_cases.rb77
-rw-r--r--activerecord/test/cases/migration/rename_table_test.rb23
-rw-r--r--activerecord/test/cases/numeric_data_test.rb71
-rw-r--r--activerecord/test/cases/relation/where_test.rb6
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb18
-rw-r--r--activerecord/test/cases/scoping/named_scoping_test.rb6
-rw-r--r--activerecord/test/models/comment.rb12
-rw-r--r--activerecord/test/models/company.rb1
-rw-r--r--activerecord/test/models/numeric_data.rb8
-rw-r--r--activerecord/test/models/post.rb2
-rw-r--r--activesupport/CHANGELOG.md19
-rw-r--r--activesupport/lib/active_support/callbacks.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/date_and_time/calculations.rb16
-rw-r--r--activesupport/lib/active_support/reloader.rb7
-rw-r--r--activesupport/lib/active_support/rescuable.rb3
-rw-r--r--activesupport/lib/active_support/testing/assertions.rb2
-rw-r--r--activesupport/test/core_ext/class/attribute_test.rb10
-rw-r--r--activesupport/test/core_ext/date_time_ext_test.rb22
-rw-r--r--guides/source/active_record_querying.md4
-rw-r--r--guides/source/asset_pipeline.md2
-rw-r--r--guides/source/getting_started.md7
-rw-r--r--guides/source/testing.md25
-rw-r--r--railties/lib/rails/generators/app_base.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/setup.tt3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/update.tt3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt7
-rw-r--r--railties/lib/rails/generators/testing/behaviour.rb8
-rw-r--r--railties/lib/rails/secrets.rb2
-rw-r--r--railties/lib/rails/test_unit/reporter.rb3
-rw-r--r--railties/test/commands/secrets_test.rb2
-rw-r--r--railties/test/generators/app_generator_test.rb2
123 files changed, 705 insertions, 540 deletions
diff --git a/Gemfile b/Gemfile
index 8260533cb5..2a1b9fa7ef 100644
--- a/Gemfile
+++ b/Gemfile
@@ -154,7 +154,3 @@ end
gem "ibm_db" if ENV["IBM_DB"]
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem "wdm", ">= 0.1.0", platforms: [:mingw, :mswin, :x64_mingw, :mswin64]
-
-platforms :ruby_25 do
- gem "mathn"
-end
diff --git a/Gemfile.lock b/Gemfile.lock
index 15b7aeb639..d08ddaf1b4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -209,7 +209,6 @@ GEM
nokogiri (>= 1.5.9)
mail (2.6.5)
mime-types (>= 1.16, < 4)
- mathn (0.1.0)
metaclass (0.0.4)
method_source (0.8.2)
mime-types (3.1)
@@ -283,7 +282,7 @@ GEM
redis (~> 3.3)
resque (~> 1.26)
rufus-scheduler (~> 3.2)
- rubocop (0.49.0)
+ rubocop (0.49.1)
parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
@@ -400,7 +399,6 @@ DEPENDENCIES
kindlerb (~> 1.2.0)
libxml-ruby
listen (>= 3.0.5, < 3.2)
- mathn
minitest (< 5.3.4)
mocha (~> 0.14)
mysql2 (>= 0.4.4)
diff --git a/actioncable/lib/action_cable/channel/periodic_timers.rb b/actioncable/lib/action_cable/channel/periodic_timers.rb
index c9daa0bcd3..90c68cfe84 100644
--- a/actioncable/lib/action_cable/channel/periodic_timers.rb
+++ b/actioncable/lib/action_cable/channel/periodic_timers.rb
@@ -4,8 +4,7 @@ module ActionCable
extend ActiveSupport::Concern
included do
- class_attribute :periodic_timers, instance_reader: false
- self.periodic_timers = []
+ class_attribute :periodic_timers, instance_reader: false, default: []
after_subscribe :start_periodic_timers
after_unsubscribe :stop_periodic_timers
diff --git a/actioncable/lib/action_cable/connection/identification.rb b/actioncable/lib/action_cable/connection/identification.rb
index c91a1d1fd7..ffab359429 100644
--- a/actioncable/lib/action_cable/connection/identification.rb
+++ b/actioncable/lib/action_cable/connection/identification.rb
@@ -6,8 +6,7 @@ module ActionCable
extend ActiveSupport::Concern
included do
- class_attribute :identifiers
- self.identifiers = Set.new
+ class_attribute :identifiers, default: Set.new
end
class_methods do
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 6849f5c0f9..7133670b65 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -459,8 +459,7 @@ module ActionMailer
helper ActionMailer::MailHelper
- class_attribute :default_params
- self.default_params = {
+ class_attribute :default_params, default: {
mime_version: "1.0",
charset: "UTF-8",
content_type: "text/plain",
diff --git a/actionmailer/lib/action_mailer/delivery_methods.rb b/actionmailer/lib/action_mailer/delivery_methods.rb
index bcc4ef03cf..afdc28aa2a 100644
--- a/actionmailer/lib/action_mailer/delivery_methods.rb
+++ b/actionmailer/lib/action_mailer/delivery_methods.rb
@@ -7,8 +7,6 @@ module ActionMailer
extend ActiveSupport::Concern
included do
- class_attribute :delivery_methods, :delivery_method
-
# Do not make this inheritable, because we always want it to propagate
cattr_accessor :raise_delivery_errors
self.raise_delivery_errors = true
@@ -19,8 +17,8 @@ module ActionMailer
cattr_accessor :deliver_later_queue_name
self.deliver_later_queue_name = :mailers
- self.delivery_methods = {}.freeze
- self.delivery_method = :smtp
+ class_attribute :delivery_methods, default: {}.freeze
+ class_attribute :delivery_method, default: :smtp
add_delivery_method :smtp, Mail::SMTP,
address: "localhost",
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 54937617df..d3d3188d95 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,13 @@
+* `driven_by` now registers poltergeist and capybara-webkit
+
+ If driver poltergeist or capybara-webkit is set for System Tests,
+ `driven_by` will register the driver and set additional options passed via
+ `:options` param.
+
+ Refer to drivers documentation to learn what options can be passed.
+
+ *Mario Chavez*
+
* AEAD encrypted cookies and sessions with GCM
Encrypted cookies now use AES-GCM which couples authentication and
diff --git a/actionpack/lib/abstract_controller/caching.rb b/actionpack/lib/abstract_controller/caching.rb
index 26e3f08bc1..30e3d4426c 100644
--- a/actionpack/lib/abstract_controller/caching.rb
+++ b/actionpack/lib/abstract_controller/caching.rb
@@ -37,8 +37,7 @@ module AbstractController
config_accessor :enable_fragment_cache_logging
self.enable_fragment_cache_logging = false
- class_attribute :_view_cache_dependencies
- self._view_cache_dependencies = []
+ class_attribute :_view_cache_dependencies, default: []
helper_method :view_cache_dependencies if respond_to?(:helper_method)
end
diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb
index ef3be7af83..2e50637c39 100644
--- a/actionpack/lib/abstract_controller/helpers.rb
+++ b/actionpack/lib/abstract_controller/helpers.rb
@@ -5,11 +5,8 @@ module AbstractController
extend ActiveSupport::Concern
included do
- class_attribute :_helpers
- self._helpers = Module.new
-
- class_attribute :_helper_methods
- self._helper_methods = Array.new
+ class_attribute :_helpers, default: Module.new
+ class_attribute :_helper_methods, default: Array.new
end
class MissingHelperError < LoadError
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 246644dcbd..96c708f45a 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -208,8 +208,7 @@ module ActionController
@_request.reset_session
end
- class_attribute :middleware_stack
- self.middleware_stack = ActionController::MiddlewareStack.new
+ class_attribute :middleware_stack, default: ActionController::MiddlewareStack.new
def self.inherited(base) # :nodoc:
base.middleware_stack = middleware_stack.dup
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index eb636fa3f6..0525252c7c 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -7,8 +7,7 @@ module ActionController
include Head
included do
- class_attribute :etaggers
- self.etaggers = []
+ class_attribute :etaggers, default: []
end
module ClassMethods
diff --git a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
index 798564db96..69c3979a0e 100644
--- a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
@@ -22,8 +22,7 @@ module ActionController
include ActionController::ConditionalGet
included do
- class_attribute :etag_with_template_digest
- self.etag_with_template_digest = true
+ class_attribute :etag_with_template_digest, default: true
ActiveSupport.on_load :action_view, yield: true do
etag do |options|
diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb
index 347fbf0e74..24d1097ebe 100644
--- a/actionpack/lib/action_controller/metal/flash.rb
+++ b/actionpack/lib/action_controller/metal/flash.rb
@@ -3,8 +3,7 @@ module ActionController #:nodoc:
extend ActiveSupport::Concern
included do
- class_attribute :_flash_types, instance_accessor: false
- self._flash_types = []
+ class_attribute :_flash_types, instance_accessor: false, default: []
delegate :flash, to: :request
add_flash_types(:alert, :notice)
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 476d081239..913a4b9a04 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -53,9 +53,8 @@ module ActionController
include AbstractController::Helpers
included do
- class_attribute :helpers_path, :include_all_helpers
- self.helpers_path ||= []
- self.include_all_helpers = true
+ class_attribute :helpers_path, default: []
+ class_attribute :include_all_helpers, default: true
end
module ClassMethods
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index a89fc1678b..68881b8402 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -159,8 +159,7 @@ module ActionController
end
included do
- class_attribute :_wrapper_options
- self._wrapper_options = Options.from_hash(format: [])
+ class_attribute :_wrapper_options, default: Options.from_hash(format: [])
end
module ClassMethods
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 733aca195d..23c21b0501 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -26,8 +26,7 @@ module ActionController
RENDERERS = Set.new
included do
- class_attribute :_renderers
- self._renderers = Set.new.freeze
+ class_attribute :_renderers, default: Set.new.freeze
end
# Used in <tt>ActionController::Base</tt>
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
index 7bc15aa6b3..0acbac1d9d 100644
--- a/actionpack/lib/action_dispatch/journey/route.rb
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -10,11 +10,11 @@ module ActionDispatch
module VerbMatchers
VERBS = %w{ DELETE GET HEAD OPTIONS LINK PATCH POST PUT TRACE UNLINK }
VERBS.each do |v|
- class_eval <<-eoc
- class #{v}
- def self.verb; name.split("::").last; end
- def self.call(req); req.#{v.downcase}?; end
- end
+ class_eval <<-eoc, __FILE__, __LINE__ + 1
+ class #{v}
+ def self.verb; name.split("::").last; end
+ def self.call(req); req.#{v.downcase}?; end
+ end
eoc
end
diff --git a/actionpack/lib/action_dispatch/system_test_case.rb b/actionpack/lib/action_dispatch/system_test_case.rb
index 98fdb36c91..723d912bcd 100644
--- a/actionpack/lib/action_dispatch/system_test_case.rb
+++ b/actionpack/lib/action_dispatch/system_test_case.rb
@@ -67,13 +67,17 @@ module ActionDispatch
# To use a headless driver, like Poltergeist, update your Gemfile to use
# Poltergeist instead of Selenium and then declare the driver name in the
# +application_system_test_case.rb+ file. In this case you would leave out the +:using+
- # option because the driver is headless.
+ # option because the driver is headless, but you can still use
+ # +:screen_size+ to change the size of the browser screen, also you can use
+ # +:options+ to pass options supported by the driver. Please refeer to your
+ # driver documentation to learn about supported options.
#
# require "test_helper"
# require "capybara/poltergeist"
#
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
- # driven_by :poltergeist
+ # driven_by :poltergeist, screen_size: [1400, 1400], options:
+ # { js_errors: true }
# end
#
# Because <tt>ActionDispatch::SystemTestCase</tt> is a shim between Capybara
diff --git a/actionpack/lib/action_dispatch/system_testing/driver.rb b/actionpack/lib/action_dispatch/system_testing/driver.rb
index 5cf17883f7..1a027f2e23 100644
--- a/actionpack/lib/action_dispatch/system_testing/driver.rb
+++ b/actionpack/lib/action_dispatch/system_testing/driver.rb
@@ -9,23 +9,42 @@ module ActionDispatch
end
def use
- register if selenium?
+ register unless rack_test?
+
setup
end
private
- def selenium?
- @name == :selenium
+ def rack_test?
+ @name == :rack_test
end
def register
Capybara.register_driver @name do |app|
- Capybara::Selenium::Driver.new(app, { browser: @browser }.merge(@options)).tap do |driver|
- driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size)
+ case @name
+ when :selenium then register_selenium(app)
+ when :poltergeist then register_poltergeist(app)
+ when :webkit then register_webkit(app)
end
end
end
+ def register_selenium(app)
+ Capybara::Selenium::Driver.new(app, { browser: @browser }.merge(@options)).tap do |driver|
+ driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size)
+ end
+ end
+
+ def register_poltergeist(app)
+ Capybara::Poltergeist::Driver.new(app, @options.merge(window_size: @screen_size))
+ end
+
+ def register_webkit(app)
+ Capybara::Webkit::Driver.new(app, Capybara::Webkit::Configuration.to_hash.merge(@options)).tap do |driver|
+ driver.resize_window(*@screen_size)
+ end
+ end
+
def setup
Capybara.current_driver = @name
end
diff --git a/actionpack/test/dispatch/system_testing/driver_test.rb b/actionpack/test/dispatch/system_testing/driver_test.rb
index 814e1d707b..4a1b971da5 100644
--- a/actionpack/test/dispatch/system_testing/driver_test.rb
+++ b/actionpack/test/dispatch/system_testing/driver_test.rb
@@ -15,7 +15,21 @@ class DriverTest < ActiveSupport::TestCase
assert_equal ({ url: "http://example.com/wd/hub" }), driver.instance_variable_get(:@options)
end
- test "selenium? returns false if driver is poltergeist" do
- assert_not ActionDispatch::SystemTesting::Driver.new(:poltergeist).send(:selenium?)
+ test "initializing the driver with a poltergeist" do
+ driver = ActionDispatch::SystemTesting::Driver.new(:poltergeist, screen_size: [1400, 1400], options: { js_errors: false })
+ assert_equal :poltergeist, driver.instance_variable_get(:@name)
+ assert_equal [1400, 1400], driver.instance_variable_get(:@screen_size)
+ assert_equal ({ js_errors: false }), driver.instance_variable_get(:@options)
+ end
+
+ test "initializing the driver with a webkit" do
+ driver = ActionDispatch::SystemTesting::Driver.new(:webkit, screen_size: [1400, 1400], options: { skip_image_loading: true })
+ assert_equal :webkit, driver.instance_variable_get(:@name)
+ assert_equal [1400, 1400], driver.instance_variable_get(:@screen_size)
+ assert_equal ({ skip_image_loading: true }), driver.instance_variable_get(:@options)
+ end
+
+ test "rack_test? returns false if driver is poltergeist" do
+ assert_not ActionDispatch::SystemTesting::Driver.new(:poltergeist).send(:rack_test?)
end
end
diff --git a/actionview/app/assets/javascripts/README.md b/actionview/app/assets/javascripts/README.md
index 0819d5da5f..f321b9f720 100644
--- a/actionview/app/assets/javascripts/README.md
+++ b/actionview/app/assets/javascripts/README.md
@@ -30,7 +30,7 @@ Run `yarn add rails-ujs` to install the rails-ujs package.
Usage
------------
-Require `rails-ujs` into your application.js manifest.
+Require `rails-ujs` in your application.js manifest.
```javascript
//= require rails-ujs
@@ -39,7 +39,8 @@ Require `rails-ujs` into your application.js manifest.
Usage with yarn
------------
-When using with Webpacker gem or your preferred JavaScript bundler. Just add the following to your main JS file and compile.
+When using with the Webpacker gem or your preferred JavaScript bundler, just
+add the following to your main JS file and compile.
```javascript
import Rails from 'rails-ujs';
diff --git a/actionview/app/assets/javascripts/rails-ujs/start.coffee b/actionview/app/assets/javascripts/rails-ujs/start.coffee
index 5746a22287..55595ac96f 100644
--- a/actionview/app/assets/javascripts/rails-ujs/start.coffee
+++ b/actionview/app/assets/javascripts/rails-ujs/start.coffee
@@ -9,7 +9,7 @@
} = Rails
# For backward compatibility
-if jQuery? and not jQuery.rails
+if jQuery? and jQuery.ajax? and not jQuery.rails
jQuery.rails = Rails
jQuery.ajaxPrefilter (options, originalOptions, xhr) ->
CSRFProtection(xhr) unless options.crossDomain
diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb
index 3eafe0028e..672269b811 100644
--- a/actionview/lib/action_view/helpers/form_helper.rb
+++ b/actionview/lib/action_view/helpers/form_helper.rb
@@ -1606,14 +1606,15 @@ module ActionView
include ModelNaming
# The methods which wrap a form helper call.
- class_attribute :field_helpers
- self.field_helpers = [:fields_for, :fields, :label, :text_field, :password_field,
- :hidden_field, :file_field, :text_area, :check_box,
- :radio_button, :color_field, :search_field,
- :telephone_field, :phone_field, :date_field,
- :time_field, :datetime_field, :datetime_local_field,
- :month_field, :week_field, :url_field, :email_field,
- :number_field, :range_field]
+ class_attribute :field_helpers, default: [
+ :fields_for, :fields, :label, :text_field, :password_field,
+ :hidden_field, :file_field, :text_area, :check_box,
+ :radio_button, :color_field, :search_field,
+ :telephone_field, :phone_field, :date_field,
+ :time_field, :datetime_field, :datetime_local_field,
+ :month_field, :week_field, :url_field, :email_field,
+ :number_field, :range_field
+ ]
attr_accessor :object_name, :object, :options
diff --git a/actionview/lib/action_view/layouts.rb b/actionview/lib/action_view/layouts.rb
index 81feb90486..ab8409e8d0 100644
--- a/actionview/lib/action_view/layouts.rb
+++ b/actionview/lib/action_view/layouts.rb
@@ -204,9 +204,9 @@ module ActionView
include ActionView::Rendering
included do
- class_attribute :_layout, :_layout_conditions, instance_accessor: false
- self._layout = nil
- self._layout_conditions = {}
+ class_attribute :_layout, instance_accessor: false
+ class_attribute :_layout_conditions, instance_accessor: false, default: {}
+
_write_layout_method
end
diff --git a/actionview/lib/action_view/template/handlers/builder.rb b/actionview/lib/action_view/template/handlers/builder.rb
index e99b921cb7..67ad78133d 100644
--- a/actionview/lib/action_view/template/handlers/builder.rb
+++ b/actionview/lib/action_view/template/handlers/builder.rb
@@ -1,9 +1,7 @@
module ActionView
module Template::Handlers
class Builder
- # Default format used by Builder.
- class_attribute :default_format
- self.default_format = :xml
+ class_attribute :default_format, default: :xml
def call(template)
require_engine
@@ -14,7 +12,6 @@ module ActionView
end
private
-
def require_engine # :doc:
@required ||= begin
require "builder"
diff --git a/actionview/lib/action_view/template/handlers/erb.rb b/actionview/lib/action_view/template/handlers/erb.rb
index 58c7fd1a88..48c2e22a89 100644
--- a/actionview/lib/action_view/template/handlers/erb.rb
+++ b/actionview/lib/action_view/template/handlers/erb.rb
@@ -9,16 +9,13 @@ module ActionView
# Specify trim mode for the ERB compiler. Defaults to '-'.
# See ERB documentation for suitable values.
- class_attribute :erb_trim_mode
- self.erb_trim_mode = "-"
+ class_attribute :erb_trim_mode, default: "-"
# Default implementation used.
- class_attribute :erb_implementation
- self.erb_implementation = Erubi
+ class_attribute :erb_implementation, default: Erubi
# Do not escape templates of these mime types.
- class_attribute :escape_whitelist
- self.escape_whitelist = ["text/plain"]
+ class_attribute :escape_whitelist, default: ["text/plain"]
ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
diff --git a/actionview/lib/action_view/test_case.rb b/actionview/lib/action_view/test_case.rb
index ae4fec4337..80403799ab 100644
--- a/actionview/lib/action_view/test_case.rb
+++ b/actionview/lib/action_view/test_case.rb
@@ -71,7 +71,7 @@ module ActionView
def helper_method(*methods)
# Almost a duplicate from ActionController::Helpers
methods.flatten.each do |method|
- _helpers.module_eval <<-end_eval
+ _helpers.module_eval <<-end_eval, __FILE__, __LINE__ + 1
def #{method}(*args, &block) # def current_user(*args, &block)
_test_case.send(%(#{method}), *args, &block) # _test_case.send(%(current_user), *args, &block)
end # end
diff --git a/actionview/lib/action_view/view_paths.rb b/actionview/lib/action_view/view_paths.rb
index f0fe6831fa..938f0fc17f 100644
--- a/actionview/lib/action_view/view_paths.rb
+++ b/actionview/lib/action_view/view_paths.rb
@@ -3,9 +3,7 @@ module ActionView
extend ActiveSupport::Concern
included do
- class_attribute :_view_paths
- self._view_paths = ActionView::PathSet.new
- _view_paths.freeze
+ class_attribute :_view_paths, default: ActionView::PathSet.new.freeze
end
delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,
diff --git a/actionview/test/template/date_helper_test.rb b/actionview/test/template/date_helper_test.rb
index a259752d6a..b667303318 100644
--- a/actionview/test/template/date_helper_test.rb
+++ b/actionview/test/template/date_helper_test.rb
@@ -138,11 +138,19 @@ class DateHelperTest < ActionView::TestCase
assert_equal "10 minutes", distance_of_time_in_words(Time.at(600), 0)
end
- def test_distance_in_words_with_mathn_required
- # test we avoid Integer#/ (redefined by mathn)
- silence_warnings { require "mathn" }
+ def test_distance_in_words_doesnt_use_the_quotient_operator
+ rubinius_skip "Date is written in Ruby and relies on Fixnum#/"
+ jruby_skip "Date is written in Ruby and relies on Fixnum#/"
+
+ klass = RUBY_VERSION > "2.4" ? Integer : Fixnum
+
+ # Make sure that we avoid {Integer,Fixnum}#/ (redefined by mathn)
+ klass.send :private, :/
+
from = Time.utc(2004, 6, 6, 21, 45, 0)
assert_distance_of_time_in_words(from)
+ ensure
+ klass.send :public, :/
end
def test_time_ago_in_words_passes_include_seconds
diff --git a/activejob/lib/active_job/queue_name.rb b/activejob/lib/active_job/queue_name.rb
index 352cf62424..d83113af60 100644
--- a/activejob/lib/active_job/queue_name.rb
+++ b/activejob/lib/active_job/queue_name.rb
@@ -32,11 +32,8 @@ module ActiveJob
end
included do
- class_attribute :queue_name, instance_accessor: false
- class_attribute :queue_name_delimiter, instance_accessor: false
-
- self.queue_name = default_queue_name
- self.queue_name_delimiter = "_" # set default delimiter to '_'
+ class_attribute :queue_name, instance_accessor: false, default: default_queue_name
+ class_attribute :queue_name_delimiter, instance_accessor: false, default: "_"
end
# Returns the name of the queue the job will be run on.
diff --git a/activejob/lib/active_job/queue_priority.rb b/activejob/lib/active_job/queue_priority.rb
index b02202fcc8..db8d9178a4 100644
--- a/activejob/lib/active_job/queue_priority.rb
+++ b/activejob/lib/active_job/queue_priority.rb
@@ -27,9 +27,7 @@ module ActiveJob
end
included do
- class_attribute :priority, instance_accessor: false
-
- self.priority = default_priority
+ class_attribute :priority, instance_accessor: false, default: default_priority
end
# Returns the priority that the job will be created with
diff --git a/activemodel/lib/active_model/attribute_assignment.rb b/activemodel/lib/active_model/attribute_assignment.rb
index ee130df989..930e89d611 100644
--- a/activemodel/lib/active_model/attribute_assignment.rb
+++ b/activemodel/lib/active_model/attribute_assignment.rb
@@ -19,10 +19,10 @@ module ActiveModel
# cat = Cat.new
# cat.assign_attributes(name: "Gorby", status: "yawning")
# cat.name # => 'Gorby'
- # cat.status => 'yawning'
+ # cat.status # => 'yawning'
# cat.assign_attributes(status: "sleeping")
# cat.name # => 'Gorby'
- # cat.status => 'sleeping'
+ # cat.status # => 'sleeping'
def assign_attributes(new_attributes)
if !new_attributes.respond_to?(:stringify_keys)
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index b5c0b43b61..b3b39bf7ae 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -68,9 +68,8 @@ module ActiveModel
CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/
included do
- class_attribute :attribute_aliases, :attribute_method_matchers, instance_writer: false
- self.attribute_aliases = {}
- self.attribute_method_matchers = [ClassMethods::AttributeMethodMatcher.new]
+ class_attribute :attribute_aliases, instance_writer: false, default: {}
+ class_attribute :attribute_method_matchers, instance_writer: false, default: [ ClassMethods::AttributeMethodMatcher.new ]
end
module ClassMethods
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index a9d92eb92a..205b84ddb4 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -10,8 +10,7 @@ module ActiveModel
included do
extend ActiveModel::Naming
- class_attribute :include_root_in_json, instance_writer: false
- self.include_root_in_json = false
+ class_attribute :include_root_in_json, instance_writer: false, default: false
end
# Returns a hash representing the model. Some configuration can be
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 1f14a068d1..ae1d69f685 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -49,8 +49,7 @@ module ActiveModel
private :validation_context=
define_callbacks :validate, scope: :name
- class_attribute :_validators, instance_writer: false
- self._validators = Hash.new { |h, k| h[k] = [] }
+ class_attribute :_validators, instance_writer: false, default: Hash.new { |h, k| h[k] = [] }
end
module ClassMethods
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 1f8163db12..f75f1a9108 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Prevent making bind param if casted value is nil.
+
+ *Ryuta Kamizono*
+
* Deprecate passing arguments and block at the same time to `count` and `sum` in `ActiveRecord::Calculations`.
*Ryuta Kamizono*
diff --git a/activerecord/lib/active_record/associations/alias_tracker.rb b/activerecord/lib/active_record/associations/alias_tracker.rb
index 3963008a76..4a5c821607 100644
--- a/activerecord/lib/active_record/associations/alias_tracker.rb
+++ b/activerecord/lib/active_record/associations/alias_tracker.rb
@@ -4,8 +4,6 @@ module ActiveRecord
module Associations
# Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
class AliasTracker # :nodoc:
- attr_reader :aliases
-
def self.create(connection, initial_table, type_caster)
aliases = Hash.new(0)
aliases[initial_table] = 1
@@ -80,6 +78,11 @@ module ActiveRecord
end
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
+ protected
+ attr_reader :aliases
+
private
def truncate(name)
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index 6b13e6936f..ee2e79889f 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -133,6 +133,16 @@ module ActiveRecord
AssociationRelation.create(klass, klass.arel_table, klass.predicate_builder, self).merge!(klass.all)
end
+ def extensions
+ extensions = klass.default_extensions | reflection.extensions
+
+ if scope = reflection.scope
+ extensions |= klass.unscoped.instance_exec(owner, &scope).extensions
+ end
+
+ extensions
+ end
+
# Loads the \target if needed and returns it.
#
# This method is abstract in the sense that it relies on +find_target+,
diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb
index 120d75416c..1593b94f0c 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -24,7 +24,7 @@ module ActiveRecord
alias_tracker = AliasTracker.create connection, association.klass.table_name, klass.type_caster
chain_head, chain_tail = get_chain(reflection, association, alias_tracker)
- scope.extending! Array(reflection.options[:extend])
+ scope.extending! reflection.extensions
add_constraints(scope, owner, reflection, chain_head, chain_tail)
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 62c944fce3..edc53e2517 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -30,7 +30,8 @@ module ActiveRecord
reload
end
- CollectionProxy.create(klass, self)
+ @proxy ||= CollectionProxy.create(klass, self)
+ @proxy.reset_scope
end
# Implements the writer method, e.g. foo.items= for Foo.has_many :items
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 74a4d515c2..8cdb508c43 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -31,6 +31,9 @@ module ActiveRecord
def initialize(klass, association) #:nodoc:
@association = association
super klass, klass.arel_table, klass.predicate_builder
+
+ extensions = association.extensions
+ extend(*extensions) if extensions.any?
end
def target
@@ -1084,9 +1087,8 @@ module ActiveRecord
# person.pets(true) # fetches pets from the database
# # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
def reload
- @scope = nil
proxy_association.reload
- self
+ reset_scope
end
# Unloads the association. Returns +self+.
@@ -1106,9 +1108,13 @@ module ActiveRecord
# person.pets # fetches pets from the database
# # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
def reset
- @scope = nil
proxy_association.reset
proxy_association.reset_scope
+ reset_scope
+ end
+
+ def reset_scope # :nodoc:
+ @scope = nil
self
end
@@ -1121,19 +1127,6 @@ module ActiveRecord
delegate(*delegate_methods, to: :scope)
- module DelegateExtending # :nodoc:
- private
- def method_missing(method, *args, &block)
- extending_values = association_scope.extending_values
- if extending_values.any? && (extending_values - self.class.included_modules).any?
- self.class.include(*extending_values)
- public_send(method, *args, &block)
- else
- super
- end
- end
- end
-
private
def find_nth_with_limit(index, limit)
@@ -1154,17 +1147,9 @@ module ActiveRecord
@association.find_from_target?
end
- def association_scope
- @association.association_scope
- end
-
def exec_queries
load_target
end
-
- def respond_to_missing?(method, _)
- association_scope.respond_to?(method) || super
- end
end
end
end
diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb
index 4072d19380..63ef3f2d8c 100644
--- a/activerecord/lib/active_record/associations/preloader/association.rb
+++ b/activerecord/lib/active_record/associations/preloader/association.rb
@@ -51,11 +51,10 @@ module ActiveRecord
raise NotImplementedError
end
- def options
- reflection.options
- end
-
private
+ def options
+ reflection.options
+ end
def associated_records_by_owner(preloader)
records = load_records do |record|
diff --git a/activerecord/lib/active_record/associations/preloader/belongs_to.rb b/activerecord/lib/active_record/associations/preloader/belongs_to.rb
index 38e231826c..c20145770f 100644
--- a/activerecord/lib/active_record/associations/preloader/belongs_to.rb
+++ b/activerecord/lib/active_record/associations/preloader/belongs_to.rb
@@ -3,7 +3,7 @@ module ActiveRecord
class Preloader
class BelongsTo < SingularAssociation #:nodoc:
def association_key_name
- reflection.options[:primary_key] || klass && klass.primary_key
+ options[:primary_key] || klass && klass.primary_key
end
def owner_key_name
diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb
index d53d3f777b..8b954138cd 100644
--- a/activerecord/lib/active_record/associations/preloader/through_association.rb
+++ b/activerecord/lib/active_record/associations/preloader/through_association.rb
@@ -65,7 +65,7 @@ module ActiveRecord
def reset_association(owners, association_name)
should_reset = (through_scope != through_reflection.klass.unscoped) ||
- (reflection.options[:source_type] && through_reflection.collection?)
+ (options[:source_type] && through_reflection.collection?)
# Don't cache the association - we would only be caching a subset
if should_reset
diff --git a/activerecord/lib/active_record/attribute_decorators.rb b/activerecord/lib/active_record/attribute_decorators.rb
index c39e9ce4c5..5bc8527745 100644
--- a/activerecord/lib/active_record/attribute_decorators.rb
+++ b/activerecord/lib/active_record/attribute_decorators.rb
@@ -3,8 +3,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :attribute_type_decorations, instance_accessor: false # :internal:
- self.attribute_type_decorations = TypeDecorator.new
+ class_attribute :attribute_type_decorations, instance_accessor: false, default: TypeDecorator.new # :internal:
end
module ClassMethods # :nodoc:
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index bd5003d63a..76987fb8f4 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -14,8 +14,7 @@ module ActiveRecord
raise "You cannot include Dirty after Timestamp"
end
- class_attribute :partial_writes, instance_writer: false
- self.partial_writes = true
+ class_attribute :partial_writes, instance_writer: false, default: true
after_create { changes_internally_applied }
after_update { changes_internally_applied }
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index 321d039ed4..4a8d231503 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -57,11 +57,8 @@ module ActiveRecord
mattr_accessor :time_zone_aware_attributes, instance_writer: false
self.time_zone_aware_attributes = false
- class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false
- self.skip_time_zone_conversion_for_attributes = []
-
- class_attribute :time_zone_aware_types, instance_writer: false
- self.time_zone_aware_types = [:datetime, :time]
+ class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false, default: []
+ class_attribute :time_zone_aware_types, instance_writer: false, default: [ :datetime, :time ]
end
module ClassMethods
diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb
index 75f5ba3a96..475b9beec4 100644
--- a/activerecord/lib/active_record/attributes.rb
+++ b/activerecord/lib/active_record/attributes.rb
@@ -6,8 +6,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false # :internal:
- self.attributes_to_define_after_schema_loads = {}
+ class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false, default: {} # :internal:
end
module ClassMethods
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 16a398f631..6cf8645cab 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -188,6 +188,8 @@ module ActiveRecord
# The name of the primary key, if one is to be added automatically.
# Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
#
+ # If an array is passed, a composite primary key will created.
+ #
# Note that Active Record models will automatically detect their
# primary key. This can be avoided by using
# {self.primary_key=}[rdoc-ref:AttributeMethods::PrimaryKey::ClassMethods#primary_key=] on the model
@@ -241,6 +243,23 @@ module ActiveRecord
# label varchar
# )
#
+ # ====== Create a composite primary key
+ #
+ # create_table(:orders, primary_key: [:product_id, :client_id]) do |t|
+ # t.belongs_to :product
+ # t.belongs_to :client
+ # end
+ #
+ # generates:
+ #
+ # CREATE TABLE order (
+ # product_id integer NOT NULL,
+ # client_id integer NOT NULL
+ # );
+ #
+ # ALTER TABLE ONLY "orders"
+ # ADD CONSTRAINT orders_pkey PRIMARY KEY (product_id, client_id);
+ #
# ====== Do not add a primary key column
#
# create_table(:categories_suppliers, id: false) do |t|
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index abc15f595f..648c869915 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -29,8 +29,7 @@ module ActiveRecord
# to your application.rb file:
#
# ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans = false
- class_attribute :emulate_booleans
- self.emulate_booleans = true
+ class_attribute :emulate_booleans, default: true
NATIVE_DATABASE_TYPES = {
primary_key: "bigint auto_increment PRIMARY KEY",
@@ -544,7 +543,7 @@ module ActiveRecord
m.register_type %r(longblob)i, Type::Binary.new(limit: 2**32 - 1)
m.register_type %r(^float)i, Type::Float.new(limit: 24)
m.register_type %r(^double)i, Type::Float.new(limit: 53)
- m.register_type %r(^json)i, MysqlJson.new
+ m.register_type %r(^json)i, Type::Json.new
register_integer_type m, %r(^bigint)i, limit: 8
register_integer_type m, %r(^int)i, limit: 4
@@ -838,12 +837,7 @@ module ActiveRecord
end
end
- class MysqlJson < Type::Internal::AbstractJson # :nodoc:
- def changed_in_place?(raw_old_value, new_value)
- # Normalization is required because MySQL JSON data format includes
- # the space between the elements.
- super(serialize(deserialize(raw_old_value)), new_value)
- end
+ class MysqlJson < Type::Json # :nodoc:
end
class MysqlString < Type::String # :nodoc:
@@ -866,7 +860,6 @@ module ActiveRecord
end
end
- ActiveRecord::Type.register(:json, MysqlJson, adapter: :mysql2)
ActiveRecord::Type.register(:string, MysqlString, adapter: :mysql2)
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :mysql2)
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb
index dbc879ffd4..3c706c27c4 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/json.rb
@@ -2,7 +2,7 @@ module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
- class Json < Type::Internal::AbstractJson
+ class Json < Type::Json # :nodoc:
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb
index 87391b5dc7..a1fec289d4 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb
@@ -2,20 +2,10 @@ module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
- class Jsonb < Json # :nodoc:
+ class Jsonb < Type::Json # :nodoc:
def type
:jsonb
end
-
- def changed_in_place?(raw_old_value, new_value)
- # Postgres does not preserve insignificant whitespaces when
- # round-tripping jsonb columns. This causes some false positives for
- # the comparison here. Therefore, we need to parse and re-dump the
- # raw value here to ensure the insignificant whitespaces are
- # consistent with our encoder's output.
- raw_old_value = serialize(deserialize(raw_old_value))
- super(raw_old_value, new_value)
- end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index da8d0c6992..44eb666965 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -62,7 +62,7 @@ module ActiveRecord
def quote_default_expression(value, column) # :nodoc:
if value.is_a?(Proc)
value.call
- elsif column.type == :uuid && value.include?("()")
+ elsif column.type == :uuid && /\(\)/.match?(value)
value # Does not quote function default values for UUID columns
elsif column.respond_to?(:array?)
value = type_cast_from_column(column, value)
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 3eff9e2f83..cb45d7ba6b 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -290,9 +290,17 @@ module ActiveRecord
if pk && sequence
quoted_sequence = quote_table_name(sequence)
+ max_pk = select_value("select MAX(#{quote_column_name pk}) from #{quote_table_name(table)}")
+ if max_pk.nil?
+ if postgresql_version >= 100000
+ minvalue = select_value("SELECT seqmin from pg_sequence where seqrelid = '#{quoted_sequence}'::regclass")
+ else
+ minvalue = select_value("SELECT min_value FROM #{quoted_sequence}")
+ end
+ end
select_value(<<-end_sql, "SCHEMA")
- SELECT setval('#{quoted_sequence}', (SELECT COALESCE(MAX(#{quote_column_name pk})+(SELECT increment_by FROM #{quoted_sequence}), (SELECT min_value FROM #{quoted_sequence})) FROM #{quote_table_name(table)}), false)
+ SELECT setval('#{quoted_sequence}', #{max_pk ? max_pk : minvalue}, #{max_pk ? true : false})
end_sql
end
end
@@ -377,14 +385,15 @@ module ActiveRecord
clear_cache!
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
pk, seq = pk_and_sequence_for(new_name)
- if seq && seq.identifier == "#{table_name}_#{pk}_seq"
- new_seq = "#{new_name}_#{pk}_seq"
+ if pk
idx = "#{table_name}_pkey"
new_idx = "#{new_name}_pkey"
- execute "ALTER TABLE #{seq.quoted} RENAME TO #{quote_table_name(new_seq)}"
execute "ALTER INDEX #{quote_table_name(idx)} RENAME TO #{quote_table_name(new_idx)}"
+ if seq && seq.identifier == "#{table_name}_#{pk}_seq"
+ new_seq = "#{new_name}_#{pk}_seq"
+ execute "ALTER TABLE #{seq.quoted} RENAME TO #{quote_table_name(new_seq)}"
+ end
end
-
rename_table_indexes(table_name, new_name)
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index f74f966fd9..5287dd6a51 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -458,7 +458,7 @@ module ActiveRecord
m.register_type "bytea", OID::Bytea.new
m.register_type "point", OID::Point.new
m.register_type "hstore", OID::Hstore.new
- m.register_type "json", OID::Json.new
+ m.register_type "json", Type::Json.new
m.register_type "jsonb", OID::Jsonb.new
m.register_type "cidr", OID::Cidr.new
m.register_type "inet", OID::Inet.new
@@ -843,7 +843,6 @@ module ActiveRecord
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
- ActiveRecord::Type.register(:json, OID::Json, adapter: :postgresql)
ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql)
diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb
index 496abfc5d9..12ef58a941 100644
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ -95,8 +95,7 @@ module ActiveRecord
module Enum
def self.extended(base) # :nodoc:
- base.class_attribute(:defined_enums, instance_writer: false)
- base.defined_enums = {}
+ base.class_attribute(:defined_enums, instance_writer: false, default: {})
end
def inherited(base) # :nodoc:
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index c19216702c..bad6542be2 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -878,20 +878,12 @@ module ActiveRecord
included do
class_attribute :fixture_path, instance_writer: false
- class_attribute :fixture_table_names
- class_attribute :fixture_class_names
- class_attribute :use_transactional_tests
- class_attribute :use_instantiated_fixtures # true, false, or :no_instances
- class_attribute :pre_loaded_fixtures
- class_attribute :config
-
- self.fixture_table_names = []
- self.use_instantiated_fixtures = false
- self.pre_loaded_fixtures = false
- self.config = ActiveRecord::Base
-
- self.fixture_class_names = {}
- self.use_transactional_tests = true
+ class_attribute :fixture_table_names, default: []
+ class_attribute :fixture_class_names, default: {}
+ class_attribute :use_transactional_tests, default: true
+ class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
+ class_attribute :pre_loaded_fixtures, default: false
+ class_attribute :config, default: ActiveRecord::Base
end
module ClassMethods
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index 236a65eba7..5776807507 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -38,8 +38,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
+ class_attribute :store_full_sti_class, instance_writer: false, default: true
end
module ClassMethods
diff --git a/activerecord/lib/active_record/integration.rb b/activerecord/lib/active_record/integration.rb
index 32362fa86f..cf954852bc 100644
--- a/activerecord/lib/active_record/integration.rb
+++ b/activerecord/lib/active_record/integration.rb
@@ -11,8 +11,7 @@ module ActiveRecord
# versioning is off. Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
#
# This is +:usec+, by default.
- class_attribute :cache_timestamp_format, instance_writer: false
- self.cache_timestamp_format = :usec
+ class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
##
# :singleton-method:
@@ -20,8 +19,7 @@ module ActiveRecord
# by a changing version in the #cache_version method.
#
# This is +false+, by default until Rails 6.0.
- class_attribute :cache_versioning, instance_writer: false
- self.cache_versioning = false
+ class_attribute :cache_versioning, instance_writer: false, default: false
end
# Returns a +String+, which Action Pack uses for constructing a URL to this
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 78ce9f8291..3c7110369b 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -51,8 +51,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :lock_optimistically, instance_writer: false
- self.lock_optimistically = true
+ class_attribute :lock_optimistically, instance_writer: false, default: true
end
def locking_enabled? #:nodoc:
diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb
index 013562708c..1179a60e9b 100644
--- a/activerecord/lib/active_record/model_schema.rb
+++ b/activerecord/lib/active_record/model_schema.rb
@@ -130,26 +130,13 @@ module ActiveRecord
included do
mattr_accessor :primary_key_prefix_type, instance_writer: false
- class_attribute :table_name_prefix, instance_writer: false
- self.table_name_prefix = ""
-
- class_attribute :table_name_suffix, instance_writer: false
- self.table_name_suffix = ""
-
- class_attribute :schema_migrations_table_name, instance_accessor: false
- self.schema_migrations_table_name = "schema_migrations"
-
- class_attribute :internal_metadata_table_name, instance_accessor: false
- self.internal_metadata_table_name = "ar_internal_metadata"
-
- class_attribute :protected_environments, instance_accessor: false
- self.protected_environments = ["production"]
-
- class_attribute :pluralize_table_names, instance_writer: false
- self.pluralize_table_names = true
-
- class_attribute :ignored_columns, instance_accessor: false
- self.ignored_columns = [].freeze
+ class_attribute :table_name_prefix, instance_writer: false, default: ""
+ class_attribute :table_name_suffix, instance_writer: false, default: ""
+ class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
+ class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
+ class_attribute :protected_environments, instance_accessor: false, default: [ "production" ]
+ class_attribute :pluralize_table_names, instance_writer: false, default: true
+ class_attribute :ignored_columns, instance_accessor: false, default: [].freeze
self.inheritance_column = "type"
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index 3f39fb84e8..917bc76993 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -10,8 +10,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :nested_attributes_options, instance_writer: false
- self.nested_attributes_options = {}
+ class_attribute :nested_attributes_options, instance_writer: false, default: {}
end
# = Active Record Nested Attributes
diff --git a/activerecord/lib/active_record/querying.rb b/activerecord/lib/active_record/querying.rb
index c4a22398f0..b16e178358 100644
--- a/activerecord/lib/active_record/querying.rb
+++ b/activerecord/lib/active_record/querying.rb
@@ -8,7 +8,7 @@ module ActiveRecord
delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, to: :all
delegate :find_each, :find_in_batches, :in_batches, to: :all
delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
- :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly,
+ :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
:having, :create_with, :distinct, :references, :none, :unscope, :merge, to: :all
delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
delegate :pluck, :ids, to: :all
diff --git a/activerecord/lib/active_record/readonly_attributes.rb b/activerecord/lib/active_record/readonly_attributes.rb
index 6274996ab8..af6473d250 100644
--- a/activerecord/lib/active_record/readonly_attributes.rb
+++ b/activerecord/lib/active_record/readonly_attributes.rb
@@ -3,8 +3,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :_attr_readonly, instance_accessor: false
- self._attr_readonly = []
+ class_attribute :_attr_readonly, instance_accessor: false, default: []
end
module ClassMethods
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 65fdbc2fe4..e8ee8279fd 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -8,10 +8,8 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :_reflections, instance_writer: false
- class_attribute :aggregate_reflections, instance_writer: false
- self._reflections = {}
- self.aggregate_reflections = {}
+ class_attribute :_reflections, instance_writer: false, default: {}
+ class_attribute :aggregate_reflections, instance_writer: false, default: {}
end
def self.create(macro, name, scope, options, ar)
@@ -289,6 +287,11 @@ module ActiveRecord
JoinKeys.new(join_pk(association_klass), join_fk)
end
+ protected
+ def actual_source_reflection # FIXME: this is a horrible name
+ self
+ end
+
private
def join_pk(_)
@@ -581,11 +584,9 @@ module ActiveRecord
seed + [self]
end
- protected
-
- def actual_source_reflection # FIXME: this is a horrible name
- self
- end
+ def extensions
+ Array(options[:extend])
+ end
private
@@ -759,7 +760,6 @@ module ActiveRecord
# Holds all the metadata about a :through association as it was specified
# in the Active Record class.
class ThroughReflection < AbstractReflection #:nodoc:
- attr_reader :delegate_reflection
delegate :foreign_key, :foreign_type, :association_foreign_key,
:active_record_primary_key, :type, :get_join_keys, to: :source_reflection
@@ -985,19 +985,23 @@ module ActiveRecord
collect_join_reflections(seed + [self])
end
- def collect_join_reflections(seed)
- a = source_reflection.add_as_source seed
- if options[:source_type]
- through_reflection.add_as_polymorphic_through self, a
- else
- through_reflection.add_as_through a
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
+ protected
+ attr_reader :delegate_reflection
+
+ def actual_source_reflection # FIXME: this is a horrible name
+ source_reflection.actual_source_reflection
end
- end
private
-
- def actual_source_reflection # FIXME: this is a horrible name
- source_reflection.send(:actual_source_reflection)
+ def collect_join_reflections(seed)
+ a = source_reflection.add_as_source seed
+ if options[:source_type]
+ through_reflection.add_as_polymorphic_through self, a
+ else
+ through_reflection.add_as_through a
+ end
end
def primary_key(klass)
diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb
index 4f739a0415..dada0fddf8 100644
--- a/activerecord/lib/active_record/relation/delegation.rb
+++ b/activerecord/lib/active_record/relation/delegation.rb
@@ -25,8 +25,6 @@ module ActiveRecord
def inherited(child_class)
child_class.initialize_relation_delegate_cache
- delegate = child_class.relation_delegate_class(ActiveRecord::Associations::CollectionProxy)
- delegate.include ActiveRecord::Associations::CollectionProxy::DelegateExtending
super
end
end
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index a6309e0b5c..7dea5deec5 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -107,21 +107,26 @@ module ActiveRecord
first = value.begin
last = value.end
unless first.respond_to?(:infinite?) && first.infinite?
- binds << build_bind_param(column_name, first)
+ binds << build_bind_attribute(column_name, first)
first = Arel::Nodes::BindParam.new
end
unless last.respond_to?(:infinite?) && last.infinite?
- binds << build_bind_param(column_name, last)
+ binds << build_bind_attribute(column_name, last)
last = Arel::Nodes::BindParam.new
end
result[column_name] = RangeHandler::RangeWithBinds.new(first, last, value.exclude_end?)
+ when value.is_a?(Relation)
+ binds.concat(value.bound_attributes)
else
if can_be_bound?(column_name, value)
- result[column_name] = Arel::Nodes::BindParam.new
- binds << build_bind_param(column_name, value)
- elsif value.is_a?(Relation)
- binds.concat(value.bound_attributes)
+ bind_attribute = build_bind_attribute(column_name, value)
+ if value.is_a?(StatementCache::Substitute) || !bind_attribute.value_for_database.nil?
+ result[column_name] = Arel::Nodes::BindParam.new
+ binds << bind_attribute
+ else
+ result[column_name] = nil
+ end
end
end
end
@@ -164,7 +169,7 @@ module ActiveRecord
end
end
- def build_bind_param(column_name, value)
+ def build_bind_attribute(column_name, value)
Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
end
end
diff --git a/activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb b/activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb
index 2fe0f81cab..3e19646ae5 100644
--- a/activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb
@@ -1,8 +1,6 @@
module ActiveRecord
class PredicateBuilder
class AssociationQueryValue # :nodoc:
- attr_reader :associated_table, :value
-
def initialize(associated_table, value)
@associated_table = associated_table
@value = value
@@ -12,6 +10,11 @@ module ActiveRecord
[associated_table.association_foreign_key.to_s => ids]
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
+ protected
+ attr_reader :associated_table, :value
+
private
def ids
case value
diff --git a/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb b/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb
index 9bb2f8c8dc..7029ae5f47 100644
--- a/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb
@@ -1,8 +1,6 @@
module ActiveRecord
class PredicateBuilder
class PolymorphicArrayValue # :nodoc:
- attr_reader :associated_table, :values
-
def initialize(associated_table, values)
@associated_table = associated_table
@values = values
@@ -17,6 +15,11 @@ module ActiveRecord
end
end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
+ protected
+ attr_reader :associated_table, :values
+
private
def type_to_ids_mapping
default_hash = Hash.new { |hsh, key| hsh[key] = [] }
diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb
index 04bee73e8f..b862dd56a5 100644
--- a/activerecord/lib/active_record/relation/where_clause_factory.rb
+++ b/activerecord/lib/active_record/relation/where_clause_factory.rb
@@ -57,7 +57,7 @@ module ActiveRecord
else
column = klass.column_for_attribute(attribute)
- binds << predicate_builder.send(:build_bind_param, attribute, value)
+ binds << predicate_builder.send(:build_bind_attribute, attribute, value)
value = Arel::Nodes::BindParam.new
predicate = if options[:case_sensitive]
diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb
index 2daa48859a..70b2693b28 100644
--- a/activerecord/lib/active_record/scoping/default.rb
+++ b/activerecord/lib/active_record/scoping/default.rb
@@ -5,11 +5,8 @@ module ActiveRecord
included do
# Stores the default scope for the class.
- class_attribute :default_scopes, instance_writer: false, instance_predicate: false
- class_attribute :default_scope_override, instance_writer: false, instance_predicate: false
-
- self.default_scopes = []
- self.default_scope_override = nil
+ class_attribute :default_scopes, instance_writer: false, instance_predicate: false, default: []
+ class_attribute :default_scope_override, instance_writer: false, instance_predicate: false, default: nil
end
module ClassMethods
@@ -110,7 +107,11 @@ module ActiveRecord
if default_scope_override
# The user has defined their own default scope method, so call that
- evaluate_default_scope { default_scope }
+ evaluate_default_scope do
+ if scope = default_scope
+ (base_rel ||= relation).merge(scope)
+ end
+ end
elsif default_scopes.any?
base_rel ||= relation
evaluate_default_scope do
diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb
index 029156189d..a61fdd6454 100644
--- a/activerecord/lib/active_record/scoping/named.rb
+++ b/activerecord/lib/active_record/scoping/named.rb
@@ -30,12 +30,15 @@ module ActiveRecord
end
def default_scoped # :nodoc:
- scope = build_default_scope
+ scope = relation
+ build_default_scope(scope) || scope
+ end
- if scope
- relation.spawn.merge!(scope)
+ def default_extensions # :nodoc:
+ if scope = current_scope || build_default_scope
+ scope.extensions
else
- relation
+ []
end
end
diff --git a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb
index 7043d2f0c8..01562b21e9 100644
--- a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb
@@ -42,7 +42,7 @@ module ActiveRecord
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
if ignore_tables.any?
- condition = ignore_tables.map { |table| connection.quote_table_name(table) }.join(", ")
+ condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
else
args << ".schema"
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index 09d8d1cdd4..55f3a194a9 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -43,8 +43,7 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- class_attribute :record_timestamps
- self.record_timestamps = true
+ class_attribute :record_timestamps, default: true
end
def initialize_dup(other) # :nodoc:
diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb
index 4f632660a8..9ed6c95bf9 100644
--- a/activerecord/lib/active_record/type.rb
+++ b/activerecord/lib/active_record/type.rb
@@ -1,11 +1,11 @@
require "active_model/type"
-require "active_record/type/internal/abstract_json"
require "active_record/type/internal/timezone"
require "active_record/type/date"
require "active_record/type/date_time"
require "active_record/type/decimal_without_scale"
+require "active_record/type/json"
require "active_record/type/time"
require "active_record/type/text"
require "active_record/type/unsigned_integer"
@@ -69,6 +69,7 @@ module ActiveRecord
register(:decimal, Type::Decimal, override: false)
register(:float, Type::Float, override: false)
register(:integer, Type::Integer, override: false)
+ register(:json, Type::Json, override: false)
register(:string, Type::String, override: false)
register(:text, Type::Text, override: false)
register(:time, Type::Time, override: false)
diff --git a/activerecord/lib/active_record/type/internal/abstract_json.rb b/activerecord/lib/active_record/type/internal/abstract_json.rb
deleted file mode 100644
index e19c5a14da..0000000000
--- a/activerecord/lib/active_record/type/internal/abstract_json.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-module ActiveRecord
- module Type
- module Internal # :nodoc:
- class AbstractJson < ActiveModel::Type::Value # :nodoc:
- include ActiveModel::Type::Helpers::Mutable
-
- def type
- :json
- end
-
- def deserialize(value)
- if value.is_a?(::String)
- ::ActiveSupport::JSON.decode(value) rescue nil
- else
- value
- end
- end
-
- def serialize(value)
- if value.nil?
- nil
- else
- ::ActiveSupport::JSON.encode(value)
- end
- end
-
- def accessor
- ActiveRecord::Store::StringKeyedHashAccessor
- end
- end
- end
- end
-end
diff --git a/activerecord/lib/active_record/type/json.rb b/activerecord/lib/active_record/type/json.rb
new file mode 100644
index 0000000000..c4732fe388
--- /dev/null
+++ b/activerecord/lib/active_record/type/json.rb
@@ -0,0 +1,28 @@
+module ActiveRecord
+ module Type
+ class Json < ActiveModel::Type::Value
+ include ActiveModel::Type::Helpers::Mutable
+
+ def type
+ :json
+ end
+
+ def deserialize(value)
+ return value unless value.is_a?(::String)
+ ActiveSupport::JSON.decode(value) rescue nil
+ end
+
+ def serialize(value)
+ ActiveSupport::JSON.encode(value) unless value.nil?
+ end
+
+ def changed_in_place?(raw_old_value, new_value)
+ deserialize(raw_old_value) != new_value
+ end
+
+ def accessor
+ ActiveRecord::Store::StringKeyedHashAccessor
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/mysql2/json_test.rb b/activerecord/test/cases/adapters/mysql2/json_test.rb
index d311ffb703..26c69edc7b 100644
--- a/activerecord/test/cases/adapters/mysql2/json_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/json_test.rb
@@ -7,20 +7,13 @@ if ActiveRecord::Base.connection.supports_json?
self.use_transactional_tests = false
def setup
- @connection = ActiveRecord::Base.connection
- begin
- @connection.create_table("json_data_type") do |t|
- t.json "payload"
- t.json "settings"
- end
+ super
+ @connection.create_table("json_data_type") do |t|
+ t.json "payload"
+ t.json "settings"
end
end
- def teardown
- @connection.drop_table :json_data_type, if_exists: true
- JsonDataType.reset_column_information
- end
-
private
def column_type
:json
diff --git a/activerecord/test/cases/adapters/postgresql/json_test.rb b/activerecord/test/cases/adapters/postgresql/json_test.rb
index 4eeb563781..6aa60630c2 100644
--- a/activerecord/test/cases/adapters/postgresql/json_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/json_test.rb
@@ -5,35 +5,26 @@ module PostgresqlJSONSharedTestCases
include JSONSharedTestCases
def setup
- @connection = ActiveRecord::Base.connection
- begin
- @connection.create_table("json_data_type") do |t|
- t.public_send column_type, "payload", default: {} # t.json 'payload', default: {}
- t.public_send column_type, "settings" # t.json 'settings'
- t.public_send column_type, "objects", array: true # t.json 'objects', array: true
- end
- rescue ActiveRecord::StatementInvalid
- skip "do not test on PostgreSQL without #{column_type} type."
+ super
+ @connection.create_table("json_data_type") do |t|
+ t.public_send column_type, "payload", default: {} # t.json 'payload', default: {}
+ t.public_send column_type, "settings" # t.json 'settings'
+ t.public_send column_type, "objects", array: true # t.json 'objects', array: true
end
- end
-
- def teardown
- @connection.drop_table :json_data_type, if_exists: true
- JsonDataType.reset_column_information
+ rescue ActiveRecord::StatementInvalid
+ skip "do not test on PostgreSQL without #{column_type} type."
end
def test_default
@connection.add_column "json_data_type", "permissions", column_type, default: { "users": "read", "posts": ["read", "write"] }
- JsonDataType.reset_column_information
+ klass.reset_column_information
assert_equal({ "users" => "read", "posts" => ["read", "write"] }, JsonDataType.column_defaults["permissions"])
assert_equal({ "users" => "read", "posts" => ["read", "write"] }, JsonDataType.new.permissions)
- ensure
- JsonDataType.reset_column_information
end
def test_deserialize_with_array
- x = JsonDataType.new(objects: ["foo" => "bar"])
+ x = klass.new(objects: ["foo" => "bar"])
assert_equal ["foo" => "bar"], x.objects
x.save!
assert_equal ["foo" => "bar"], x.objects
diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
index 52e4a38cae..6ebe9d82a7 100644
--- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
@@ -63,6 +63,16 @@ class PostgresqlUUIDTest < ActiveRecord::PostgreSQLTestCase
UUIDType.reset_column_information
end
+ def test_add_column_with_null_true_and_default_nil
+ assert_nothing_raised do
+ connection.add_column :uuid_data_type, :thingy, :uuid, null: true, default: nil
+ end
+ UUIDType.reset_column_information
+ column = UUIDType.columns_hash["thingy"]
+ assert column.null
+ assert_nil column.default
+ end
+
def test_data_type_of_uuid_types
column = UUIDType.columns_hash["guid"]
assert_equal :uuid, column.type
diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb
index 87d842f21d..f707a170f5 100644
--- a/activerecord/test/cases/associations/extension_test.rb
+++ b/activerecord/test/cases/associations/extension_test.rb
@@ -78,6 +78,12 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase
assert_equal post.association(:comments), post.comments.where("1=1").the_association
end
+ def test_association_with_default_scope
+ assert_raises OopsError do
+ posts(:welcome).comments.destroy_all
+ end
+ end
+
private
def extend!(model)
diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
index 4bf1b5bcd5..f73005b3cb 100644
--- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
@@ -367,19 +367,6 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
end
- def test_create_by_new_record
- devel = Developer.new(name: "Marcel", salary: 75000)
- devel.projects.build(name: "Make bed")
- proj2 = devel.projects.build(name: "Lie in it")
- assert_equal devel.projects.last, proj2
- assert !proj2.persisted?
- devel.save
- assert devel.persisted?
- assert proj2.persisted?
- assert_equal devel.projects.last, proj2
- assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
- end
-
def test_creation_respects_hash_condition
# in Oracle '' is saved as null therefore need to save ' ' in not null column
post = categories(:general).post_with_conditions.build(body: " ")
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 6a479a344c..590d3642bd 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1355,7 +1355,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
Client.create(client_of: firm.id, name: "SmallTime Inc.")
# only one of two clients is included in the association due to the :conditions key
assert_equal 2, Client.where(client_of: firm.id).size
- assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
+ assert_equal 1, firm.dependent_hash_conditional_clients_of_firm.size
firm.destroy
# only the correctly associated client should have been deleted
assert_equal 1, Client.where(client_of: firm.id).size
@@ -2251,7 +2251,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
test "association with extend option with multiple extensions" do
post = posts(:welcome)
assert_equal "lifo", post.comments_with_extend_2.author
- assert_equal "hello", post.comments_with_extend_2.greeting
+ assert_equal "hullo", post.comments_with_extend_2.greeting
+ end
+
+ test "extend option affects per association" do
+ post = posts(:welcome)
+ assert_equal "lifo", post.comments_with_extend.author
+ assert_equal "lifo", post.comments_with_extend_2.author
+ assert_equal "hello", post.comments_with_extend.greeting
+ assert_equal "hullo", post.comments_with_extend_2.greeting
end
test "delete record with complex joins" do
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index 4ab690bfc6..2eb31326a5 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -220,6 +220,18 @@ class AssociationProxyTest < ActiveRecord::TestCase
assert_equal david.projects, david.projects.scope
end
+ test "proxy object is cached" do
+ david = developers(:david)
+ assert_same david.projects, david.projects
+ end
+
+ test "proxy object can be stubbed" do
+ david = developers(:david)
+ david.projects.define_singleton_method(:extra_method) { 42 }
+
+ assert_equal 42, david.projects.extra_method
+ end
+
test "inverses get set of subsets of the association" do
man = Man.create
man.interests.create
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 15c253890b..dc32e995a4 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -907,80 +907,6 @@ class BasicsTest < ActiveRecord::TestCase
end
end
- class NumericData < ActiveRecord::Base
- self.table_name = "numeric_data"
-
- attribute :my_house_population, :integer
- attribute :atoms_in_universe, :integer
- end
-
- def test_big_decimal_conditions
- m = NumericData.new(
- bank_balance: 1586.43,
- big_bank_balance: BigDecimal("1000234000567.95"),
- world_population: 6000000000,
- my_house_population: 3
- )
- assert m.save
- assert_equal 0, NumericData.where("bank_balance > ?", 2000.0).count
- end
-
- def test_numeric_fields
- m = NumericData.new(
- bank_balance: 1586.43,
- big_bank_balance: BigDecimal("1000234000567.95"),
- world_population: 6000000000,
- my_house_population: 3
- )
- assert m.save
-
- m1 = NumericData.find(m.id)
- assert_not_nil m1
-
- # As with migration_test.rb, we should make world_population >= 2**62
- # to cover 64-bit platforms and test it is a Bignum, but the main thing
- # is that it's an Integer.
- assert_kind_of Integer, m1.world_population
- assert_equal 6000000000, m1.world_population
-
- assert_kind_of Integer, m1.my_house_population
- assert_equal 3, m1.my_house_population
-
- assert_kind_of BigDecimal, m1.bank_balance
- assert_equal BigDecimal("1586.43"), m1.bank_balance
-
- assert_kind_of BigDecimal, m1.big_bank_balance
- assert_equal BigDecimal("1000234000567.95"), m1.big_bank_balance
- end
-
- def test_numeric_fields_with_scale
- m = NumericData.new(
- bank_balance: 1586.43122334,
- big_bank_balance: BigDecimal("234000567.952344"),
- world_population: 6000000000,
- my_house_population: 3
- )
- assert m.save
-
- m1 = NumericData.find(m.id)
- assert_not_nil m1
-
- # As with migration_test.rb, we should make world_population >= 2**62
- # to cover 64-bit platforms and test it is a Bignum, but the main thing
- # is that it's an Integer.
- assert_kind_of Integer, m1.world_population
- assert_equal 6000000000, m1.world_population
-
- assert_kind_of Integer, m1.my_house_population
- assert_equal 3, m1.my_house_population
-
- assert_kind_of BigDecimal, m1.bank_balance
- assert_equal BigDecimal("1586.43"), m1.bank_balance
-
- assert_kind_of BigDecimal, m1.big_bank_balance
- assert_equal BigDecimal("234000567.95"), m1.big_bank_balance
- end
-
def test_auto_id
auto = AutoId.new
auto.save
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 93f8ab18c2..21c5c0efee 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -8,6 +8,7 @@ require "models/organization"
require "models/possession"
require "models/topic"
require "models/reply"
+require "models/numeric_data"
require "models/minivan"
require "models/speedometer"
require "models/ship_part"
@@ -17,14 +18,6 @@ require "models/post"
require "models/comment"
require "models/rating"
-class NumericData < ActiveRecord::Base
- self.table_name = "numeric_data"
-
- attribute :world_population, :integer
- attribute :my_house_population, :integer
- attribute :atoms_in_universe, :integer
-end
-
class CalculationsTest < ActiveRecord::TestCase
fixtures :companies, :accounts, :topics, :speedometers, :minivans, :books
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index 721861975a..f72e0d2ead 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -4,10 +4,7 @@ require "models/pirate" # For timestamps
require "models/parrot"
require "models/person" # For optimistic locking
require "models/aircraft"
-
-class NumericData < ActiveRecord::Base
- self.table_name = "numeric_data"
-end
+require "models/numeric_data"
class DirtyTest < ActiveRecord::TestCase
include InTimeZone
diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb
index db3da53487..4ef9a125e6 100644
--- a/activerecord/test/cases/enum_test.rb
+++ b/activerecord/test/cases/enum_test.rb
@@ -60,6 +60,7 @@ class EnumTest < ActiveRecord::TestCase
assert_not_equal @book, Book.where(status: [:written]).first
assert_not_equal @book, Book.where.not(status: :published).first
assert_equal @book, Book.where.not(status: :written).first
+ assert_equal books(:ddd), Book.where(read_status: :forgotten).first
end
test "find via where with strings" do
@@ -69,6 +70,7 @@ class EnumTest < ActiveRecord::TestCase
assert_not_equal @book, Book.where(status: ["written"]).first
assert_not_equal @book, Book.where.not(status: "published").first
assert_equal @book, Book.where.not(status: "written").first
+ assert_equal books(:ddd), Book.where(read_status: "forgotten").first
end
test "build from scope" do
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 4837a169fa..420f552ef6 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -1023,16 +1023,6 @@ class FinderTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::StatementInvalid) { Topic.find_by_sql "select 1 from badtable" }
end
- def test_find_all_with_join
- developers_on_project_one = Developer.
- joins("LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id").
- where("project_id=1").to_a
- assert_equal 3, developers_on_project_one.length
- developer_names = developers_on_project_one.map(&:name)
- assert_includes developer_names, "David"
- assert_includes developer_names, "Jamis"
- end
-
def test_joins_dont_clobber_id
first = Firm.
joins("INNER JOIN companies clients ON clients.firm_id = companies.id").
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index b4bbdc6dad..fb5a7bcc31 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -1,6 +1,7 @@
require "cases/helper"
require "models/author"
require "models/company"
+require "models/membership"
require "models/person"
require "models/post"
require "models/project"
@@ -29,7 +30,7 @@ end
class InheritanceTest < ActiveRecord::TestCase
include InheritanceTestHelper
- fixtures :companies, :projects, :subscribers, :accounts, :vegetables
+ fixtures :companies, :projects, :subscribers, :accounts, :vegetables, :memberships
def test_class_with_store_full_sti_class_returns_full_name
with_store_full_sti_class do
@@ -435,6 +436,10 @@ class InheritanceTest < ActiveRecord::TestCase
assert_nothing_raised { Company.of_first_firm }
assert_nothing_raised { Client.of_first_firm }
end
+
+ def test_inheritance_with_default_scope
+ assert_equal 1, SelectedMembership.count(:all)
+ end
end
class InheritanceComputeTypeTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/json_attribute_test.rb b/activerecord/test/cases/json_attribute_test.rb
new file mode 100644
index 0000000000..e5848b45f8
--- /dev/null
+++ b/activerecord/test/cases/json_attribute_test.rb
@@ -0,0 +1,33 @@
+require "cases/helper"
+require "cases/json_shared_test_cases"
+
+class JsonAttributeTest < ActiveRecord::TestCase
+ include JSONSharedTestCases
+ self.use_transactional_tests = false
+
+ class JsonDataTypeOnText < ActiveRecord::Base
+ self.table_name = "json_data_type"
+
+ attribute :payload, :json
+ attribute :settings, :json
+
+ store_accessor :settings, :resolution
+ end
+
+ def setup
+ super
+ @connection.create_table("json_data_type") do |t|
+ t.text "payload"
+ t.text "settings"
+ end
+ end
+
+ private
+ def column_type
+ :text
+ end
+
+ def klass
+ JsonDataTypeOnText
+ end
+end
diff --git a/activerecord/test/cases/json_shared_test_cases.rb b/activerecord/test/cases/json_shared_test_cases.rb
index d190b027bf..5aa41b9d6d 100644
--- a/activerecord/test/cases/json_shared_test_cases.rb
+++ b/activerecord/test/cases/json_shared_test_cases.rb
@@ -9,12 +9,21 @@ module JSONSharedTestCases
store_accessor :settings, :resolution
end
+ def setup
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def teardown
+ @connection.drop_table :json_data_type, if_exists: true
+ klass.reset_column_information
+ end
+
def test_column
- column = JsonDataType.columns_hash["payload"]
+ column = klass.columns_hash["payload"]
assert_equal column_type, column.type
assert_equal column_type.to_s, column.sql_type
- type = JsonDataType.type_for_attribute("payload")
+ type = klass.type_for_attribute("payload")
assert_not type.binary?
end
@@ -22,8 +31,8 @@ module JSONSharedTestCases
@connection.change_table("json_data_type") do |t|
t.public_send column_type, "users"
end
- JsonDataType.reset_column_information
- column = JsonDataType.columns_hash["users"]
+ klass.reset_column_information
+ column = klass.columns_hash["users"]
assert_equal column_type, column.type
assert_equal column_type.to_s, column.sql_type
end
@@ -34,7 +43,7 @@ module JSONSharedTestCases
end
def test_cast_value_on_write
- x = JsonDataType.new(payload: { "string" => "foo", :symbol => :bar })
+ x = klass.new(payload: { "string" => "foo", :symbol => :bar })
assert_equal({ "string" => "foo", :symbol => :bar }, x.payload_before_type_cast)
assert_equal({ "string" => "foo", "symbol" => "bar" }, x.payload)
x.save!
@@ -42,7 +51,7 @@ module JSONSharedTestCases
end
def test_type_cast_json
- type = JsonDataType.type_for_attribute("payload")
+ type = klass.type_for_attribute("payload")
data = '{"a_key":"a_value"}'
hash = type.deserialize(data)
@@ -56,75 +65,75 @@ module JSONSharedTestCases
def test_rewrite
@connection.execute(%q|insert into json_data_type (payload) VALUES ('{"k":"v"}')|)
- x = JsonDataType.first
+ x = klass.first
x.payload = { '"a\'' => "b" }
assert x.save!
end
def test_select
@connection.execute(%q|insert into json_data_type (payload) VALUES ('{"k":"v"}')|)
- x = JsonDataType.first
+ x = klass.first
assert_equal({ "k" => "v" }, x.payload)
end
def test_select_multikey
@connection.execute(%q|insert into json_data_type (payload) VALUES ('{"k1":"v1", "k2":"v2", "k3":[1,2,3]}')|)
- x = JsonDataType.first
+ x = klass.first
assert_equal({ "k1" => "v1", "k2" => "v2", "k3" => [1, 2, 3] }, x.payload)
end
def test_null_json
@connection.execute("insert into json_data_type (payload) VALUES(null)")
- x = JsonDataType.first
+ x = klass.first
assert_nil(x.payload)
end
def test_select_nil_json_after_create
- json = JsonDataType.create!(payload: nil)
- x = JsonDataType.where(payload: nil).first
+ json = klass.create!(payload: nil)
+ x = klass.where(payload: nil).first
assert_equal(json, x)
end
def test_select_nil_json_after_update
- json = JsonDataType.create!(payload: "foo")
- x = JsonDataType.where(payload: nil).first
+ json = klass.create!(payload: "foo")
+ x = klass.where(payload: nil).first
assert_nil(x)
json.update_attributes(payload: nil)
- x = JsonDataType.where(payload: nil).first
+ x = klass.where(payload: nil).first
assert_equal(json.reload, x)
end
def test_select_array_json_value
@connection.execute(%q|insert into json_data_type (payload) VALUES ('["v0",{"k1":"v1"}]')|)
- x = JsonDataType.first
+ x = klass.first
assert_equal(["v0", { "k1" => "v1" }], x.payload)
end
def test_rewrite_array_json_value
@connection.execute(%q|insert into json_data_type (payload) VALUES ('["v0",{"k1":"v1"}]')|)
- x = JsonDataType.first
+ x = klass.first
x.payload = ["v1", { "k2" => "v2" }, "v3"]
assert x.save!
end
def test_with_store_accessors
- x = JsonDataType.new(resolution: "320×480")
+ x = klass.new(resolution: "320×480")
assert_equal "320×480", x.resolution
x.save!
- x = JsonDataType.first
+ x = klass.first
assert_equal "320×480", x.resolution
x.resolution = "640×1136"
x.save!
- x = JsonDataType.first
+ x = klass.first
assert_equal "640×1136", x.resolution
end
def test_duplication_with_store_accessors
- x = JsonDataType.new(resolution: "320×480")
+ x = klass.new(resolution: "320×480")
assert_equal "320×480", x.resolution
y = x.dup
@@ -132,7 +141,7 @@ module JSONSharedTestCases
end
def test_yaml_round_trip_with_store_accessors
- x = JsonDataType.new(resolution: "320×480")
+ x = klass.new(resolution: "320×480")
assert_equal "320×480", x.resolution
y = YAML.load(YAML.dump(x))
@@ -140,7 +149,7 @@ module JSONSharedTestCases
end
def test_changes_in_place
- json = JsonDataType.new
+ json = klass.new
assert_not json.changed?
json.payload = { "one" => "two" }
@@ -160,18 +169,34 @@ module JSONSharedTestCases
assert_not json.changed?
end
+ def test_changes_in_place_with_ruby_object
+ time = Time.now.utc
+ json = klass.create!(payload: time)
+
+ json.reload
+ assert_not json.changed?
+
+ json.payload = time
+ assert_not json.changed?
+ end
+
def test_assigning_string_literal
- json = JsonDataType.create!(payload: "foo")
+ json = klass.create!(payload: "foo")
assert_equal "foo", json.payload
end
def test_assigning_number
- json = JsonDataType.create!(payload: 1.234)
+ json = klass.create!(payload: 1.234)
assert_equal 1.234, json.payload
end
def test_assigning_boolean
- json = JsonDataType.create!(payload: true)
+ json = klass.create!(payload: true)
assert_equal true, json.payload
end
+
+ private
+ def klass
+ JsonDataType
+ end
end
diff --git a/activerecord/test/cases/migration/rename_table_test.rb b/activerecord/test/cases/migration/rename_table_test.rb
index 7bcabd0cc6..5da3ad33a3 100644
--- a/activerecord/test/cases/migration/rename_table_test.rb
+++ b/activerecord/test/cases/migration/rename_table_test.rb
@@ -79,10 +79,33 @@ module ActiveRecord
assert_equal ConnectionAdapters::PostgreSQL::Name.new("public", "octopi_#{pk}_seq"), seq
end
+ def test_renaming_table_renames_primary_key
+ connection.create_table :cats, id: :uuid, default: "uuid_generate_v4()"
+ rename_table :cats, :felines
+
+ assert connection.table_exists? :felines
+ refute connection.table_exists? :cats
+
+ primary_key_name = connection.select_values(<<-SQL.strip_heredoc, "SCHEMA")[0]
+ SELECT c.relname
+ FROM pg_class c
+ JOIN pg_index i
+ ON c.oid = i.indexrelid
+ WHERE i.indisprimary
+ AND i.indrelid = 'felines'::regclass
+ SQL
+
+ assert_equal "felines_pkey", primary_key_name
+ ensure
+ connection.drop_table :cats, if_exists: true
+ connection.drop_table :felines, if_exists: true
+ end
+
def test_renaming_table_doesnt_attempt_to_rename_non_existent_sequences
connection.create_table :cats, id: :uuid, default: "uuid_generate_v4()"
assert_nothing_raised { rename_table :cats, :felines }
assert connection.table_exists? :felines
+ refute connection.table_exists? :cats
ensure
connection.drop_table :cats, if_exists: true
connection.drop_table :felines, if_exists: true
diff --git a/activerecord/test/cases/numeric_data_test.rb b/activerecord/test/cases/numeric_data_test.rb
new file mode 100644
index 0000000000..76b97033af
--- /dev/null
+++ b/activerecord/test/cases/numeric_data_test.rb
@@ -0,0 +1,71 @@
+require "cases/helper"
+require "models/numeric_data"
+
+class NumericDataTest < ActiveRecord::TestCase
+ def test_big_decimal_conditions
+ m = NumericData.new(
+ bank_balance: 1586.43,
+ big_bank_balance: BigDecimal("1000234000567.95"),
+ world_population: 6000000000,
+ my_house_population: 3
+ )
+ assert m.save
+ assert_equal 0, NumericData.where("bank_balance > ?", 2000.0).count
+ end
+
+ def test_numeric_fields
+ m = NumericData.new(
+ bank_balance: 1586.43,
+ big_bank_balance: BigDecimal("1000234000567.95"),
+ world_population: 6000000000,
+ my_house_population: 3
+ )
+ assert m.save
+
+ m1 = NumericData.find(m.id)
+ assert_not_nil m1
+
+ # As with migration_test.rb, we should make world_population >= 2**62
+ # to cover 64-bit platforms and test it is a Bignum, but the main thing
+ # is that it's an Integer.
+ assert_kind_of Integer, m1.world_population
+ assert_equal 6000000000, m1.world_population
+
+ assert_kind_of Integer, m1.my_house_population
+ assert_equal 3, m1.my_house_population
+
+ assert_kind_of BigDecimal, m1.bank_balance
+ assert_equal BigDecimal("1586.43"), m1.bank_balance
+
+ assert_kind_of BigDecimal, m1.big_bank_balance
+ assert_equal BigDecimal("1000234000567.95"), m1.big_bank_balance
+ end
+
+ def test_numeric_fields_with_scale
+ m = NumericData.new(
+ bank_balance: 1586.43122334,
+ big_bank_balance: BigDecimal("234000567.952344"),
+ world_population: 6000000000,
+ my_house_population: 3
+ )
+ assert m.save
+
+ m1 = NumericData.find(m.id)
+ assert_not_nil m1
+
+ # As with migration_test.rb, we should make world_population >= 2**62
+ # to cover 64-bit platforms and test it is a Bignum, but the main thing
+ # is that it's an Integer.
+ assert_kind_of Integer, m1.world_population
+ assert_equal 6000000000, m1.world_population
+
+ assert_kind_of Integer, m1.my_house_population
+ assert_equal 3, m1.my_house_population
+
+ assert_kind_of BigDecimal, m1.bank_balance
+ assert_equal BigDecimal("1586.43"), m1.bank_balance
+
+ assert_kind_of BigDecimal, m1.big_bank_balance
+ assert_equal BigDecimal("234000567.95"), m1.big_bank_balance
+ end
+end
diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb
index cbc466d6b8..42dae4d569 100644
--- a/activerecord/test/cases/relation/where_test.rb
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -15,7 +15,7 @@ require "models/vertex"
module ActiveRecord
class WhereTest < ActiveRecord::TestCase
- fixtures :posts, :edges, :authors, :author_addresses, :binaries, :essays, :cars, :treasures, :price_estimates
+ fixtures :posts, :edges, :authors, :author_addresses, :binaries, :essays, :cars, :treasures, :price_estimates, :topics
def test_where_copies_bind_params
author = authors(:david)
@@ -48,6 +48,10 @@ module ActiveRecord
assert_equal [chef], chefs.to_a
end
+ def test_where_with_casted_value_is_nil
+ assert_equal 4, Topic.where(last_read: "").count
+ end
+
def test_rewhere_on_root
assert_equal posts(:welcome), Post.rewhere(title: "Welcome to the weblog").first
end
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index cb8d449ba9..417c6f4832 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -116,32 +116,22 @@ class SchemaDumperTest < ActiveRecord::TestCase
def test_schema_dump_includes_limit_constraint_for_integer_columns
output = dump_all_table_schema([/^(?!integer_limits)/])
- assert_match %r{c_int_without_limit}, output
+ assert_match %r{"c_int_without_limit"(?!.*limit)}, output
if current_adapter?(:PostgreSQLAdapter)
- assert_no_match %r{c_int_without_limit.*limit:}, output
-
assert_match %r{c_int_1.*limit: 2}, output
assert_match %r{c_int_2.*limit: 2}, output
# int 3 is 4 bytes in postgresql
- assert_match %r{c_int_3.*}, output
- assert_no_match %r{c_int_3.*limit:}, output
-
- assert_match %r{c_int_4.*}, output
- assert_no_match %r{c_int_4.*limit:}, output
+ assert_match %r{"c_int_3"(?!.*limit)}, output
+ assert_match %r{"c_int_4"(?!.*limit)}, output
elsif current_adapter?(:Mysql2Adapter)
- assert_match %r{c_int_without_limit"$}, output
-
assert_match %r{c_int_1.*limit: 1}, output
assert_match %r{c_int_2.*limit: 2}, output
assert_match %r{c_int_3.*limit: 3}, output
- assert_match %r{c_int_4.*}, output
- assert_no_match %r{c_int_4.*:limit}, output
+ assert_match %r{"c_int_4"(?!.*limit)}, output
elsif current_adapter?(:SQLite3Adapter)
- assert_no_match %r{c_int_without_limit.*limit:}, output
-
assert_match %r{c_int_1.*limit: 1}, output
assert_match %r{c_int_2.*limit: 2}, output
assert_match %r{c_int_3.*limit: 3}, output
diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb
index 0c2cffe0d3..483ea7128d 100644
--- a/activerecord/test/cases/scoping/named_scoping_test.rb
+++ b/activerecord/test/cases/scoping/named_scoping_test.rb
@@ -551,6 +551,12 @@ class NamedScopingTest < ActiveRecord::TestCase
assert_equal 1, SpecialComment.where(body: "go crazy").created.count
end
+ def test_model_class_should_respond_to_extending
+ assert_raises OopsError do
+ Comment.unscoped.oops_comments.destroy_all
+ end
+ end
+
def test_model_class_should_respond_to_none
assert !Topic.none?
Topic.delete_all
diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb
index 76b484e616..d227f6fe86 100644
--- a/activerecord/test/models/comment.rb
+++ b/activerecord/test/models/comment.rb
@@ -19,6 +19,18 @@ class Comment < ActiveRecord::Base
has_many :children, class_name: "Comment", foreign_key: :parent_id
belongs_to :parent, class_name: "Comment", counter_cache: :children_count
+ class ::OopsError < RuntimeError; end
+
+ module OopsExtension
+ def destroy_all(*)
+ raise OopsError
+ end
+ end
+
+ default_scope { extending OopsExtension }
+
+ scope :oops_comments, -> { extending OopsExtension }
+
# Should not be called if extending modules that having the method exists on an association.
def self.greeting
raise
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index d269a95e8c..c6a5bf1c92 100644
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -175,6 +175,7 @@ end
class ExclusivelyDependentFirm < Company
has_one :account, foreign_key: "firm_id", dependent: :delete
has_many :dependent_sanitized_conditional_clients_of_firm, -> { order("id").where("name = 'BigShot Inc.'") }, foreign_key: "client_of", class_name: "Client", dependent: :delete_all
+ has_many :dependent_hash_conditional_clients_of_firm, -> { order("id").where(name: "BigShot Inc.") }, foreign_key: "client_of", class_name: "Client", dependent: :delete_all
has_many :dependent_conditional_clients_of_firm, -> { order("id").where("name = ?", "BigShot Inc.") }, foreign_key: "client_of", class_name: "Client", dependent: :delete_all
end
diff --git a/activerecord/test/models/numeric_data.rb b/activerecord/test/models/numeric_data.rb
new file mode 100644
index 0000000000..c6e025a9ce
--- /dev/null
+++ b/activerecord/test/models/numeric_data.rb
@@ -0,0 +1,8 @@
+class NumericData < ActiveRecord::Base
+ self.table_name = "numeric_data"
+ # Decimal columns with 0 scale being automatically treated as integers
+ # is deprecated, and will be removed in a future version of Rails.
+ attribute :world_population, :big_integer
+ attribute :my_house_population, :big_integer
+ attribute :atoms_in_universe, :big_integer
+end
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index a2028b3eb9..4c913b3b72 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -13,7 +13,7 @@ class Post < ActiveRecord::Base
module NamedExtension2
def greeting
- "hello"
+ "hullo"
end
end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index af70a81414..4c3eded38a 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,10 +1,25 @@
+* Add `Date#prev_occurring` and `Date#next_occurring` to return specified next/previous occurring day of week.
+
+ *Shota Iguchi*
+
+* Add default option to class_attribute. Before:
+
+ class_attribute :settings
+ self.settings = {}
+
+ Now:
+
+ class_attribute :settings, default: {}
+
+ *DHH*
+
* `#singularize` and `#pluralize` now respect uncountables for the specified locale.
*Eilis Hamilton*
-* Add ActiveSupport::CurrentAttributes to provide a thread-isolated attributes singleton.
+* Add `ActiveSupport::CurrentAttributes` to provide a thread-isolated attributes singleton.
Primary use case is keeping all the per-request attributes easily available to the whole system.
-
+
*DHH*
* Fix implicit coercion calculations with scalars and durations
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index d771cab68b..ddfa91a342 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -62,8 +62,7 @@ module ActiveSupport
included do
extend ActiveSupport::DescendantsTracker
- class_attribute :__callbacks, instance_writer: false
- self.__callbacks ||= {}
+ class_attribute :__callbacks, instance_writer: false, default: {}
end
CALLBACK_FILTER_TYPES = [:before, :after, :around]
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index ba422f9071..8caddcd5c3 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -68,11 +68,16 @@ class Class
# object.setting = false # => NoMethodError
#
# To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
+ #
+ # To set a default value for the attribute, pass <tt>default:</tt>, like so:
+ #
+ # class_attribute :settings, default: {}
def class_attribute(*attrs)
options = attrs.extract_options!
- instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
- instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
+ instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
+ instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
instance_predicate = options.fetch(:instance_predicate, true)
+ default_value = options.fetch(:default, nil)
attrs.each do |name|
remove_possible_singleton_method(name)
@@ -123,6 +128,10 @@ class Class
remove_possible_method "#{name}="
attr_writer name
end
+
+ unless default_value.nil?
+ self.send("#{name}=", default_value)
+ end
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
index f2ba7fdda5..e2e1d3e359 100644
--- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
@@ -320,6 +320,22 @@ module DateAndTime
beginning_of_year..end_of_year
end
+ # Returns specific next occurring day of week
+ def next_occurring(day_of_week)
+ current_day_number = wday != 0 ? wday - 1 : 6
+ from_now = DAYS_INTO_WEEK.fetch(day_of_week) - current_day_number
+ from_now += 7 unless from_now > 0
+ since(from_now.days)
+ end
+
+ # Returns specific previous occurring day of week
+ def prev_occurring(day_of_week)
+ current_day_number = wday != 0 ? wday - 1 : 6
+ ago = current_day_number - DAYS_INTO_WEEK.fetch(day_of_week)
+ ago += 7 unless ago > 0
+ ago(ago.days)
+ end
+
private
def first_hour(date_or_time)
date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
diff --git a/activesupport/lib/active_support/reloader.rb b/activesupport/lib/active_support/reloader.rb
index 121c621751..9558146201 100644
--- a/activesupport/lib/active_support/reloader.rb
+++ b/activesupport/lib/active_support/reloader.rb
@@ -69,11 +69,8 @@ module ActiveSupport
end
end
- class_attribute :executor
- class_attribute :check
-
- self.executor = Executor
- self.check = lambda { false }
+ class_attribute :executor, default: Executor
+ class_attribute :check, default: lambda { false }
def self.check! # :nodoc:
@should_reload ||= check.call
diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb
index 12ec8bf1b8..826832ba7d 100644
--- a/activesupport/lib/active_support/rescuable.rb
+++ b/activesupport/lib/active_support/rescuable.rb
@@ -8,8 +8,7 @@ module ActiveSupport
extend Concern
included do
- class_attribute :rescue_handlers
- self.rescue_handlers = []
+ class_attribute :rescue_handlers, default: []
end
module ClassMethods
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index 28cf2953bf..28e1df8870 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -167,7 +167,7 @@ module ActiveSupport
retval
end
- # Assertion that the result of evaluating an expression is changed before
+ # Assertion that the result of evaluating an expression is not changed before
# and after invoking the passed in block.
#
# assert_no_changes 'Status.all_good?' do
diff --git a/activesupport/test/core_ext/class/attribute_test.rb b/activesupport/test/core_ext/class/attribute_test.rb
index 5a9ec78cc1..f16043c612 100644
--- a/activesupport/test/core_ext/class/attribute_test.rb
+++ b/activesupport/test/core_ext/class/attribute_test.rb
@@ -3,7 +3,11 @@ require "active_support/core_ext/class/attribute"
class ClassAttributeTest < ActiveSupport::TestCase
def setup
- @klass = Class.new { class_attribute :setting }
+ @klass = Class.new do
+ class_attribute :setting
+ class_attribute :timeout, default: 5
+ end
+
@sub = Class.new(@klass)
end
@@ -12,6 +16,10 @@ class ClassAttributeTest < ActiveSupport::TestCase
assert_nil @sub.setting
end
+ test "custom default" do
+ assert_equal 5, @klass.timeout
+ end
+
test "inheritable" do
@klass.setting = 1
assert_equal 1, @sub.setting
diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb
index be7c14e9b4..276fa2bfd3 100644
--- a/activesupport/test/core_ext/date_time_ext_test.rb
+++ b/activesupport/test/core_ext/date_time_ext_test.rb
@@ -28,6 +28,28 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase
end
end
+ def test_next_occur
+ datetime = DateTime.new(2016, 9, 24, 0, 0) # saturday
+ assert_equal datetime.next_occurring(:monday), datetime.since(2.days)
+ assert_equal datetime.next_occurring(:tuesday), datetime.since(3.days)
+ assert_equal datetime.next_occurring(:wednesday), datetime.since(4.days)
+ assert_equal datetime.next_occurring(:thursday), datetime.since(5.days)
+ assert_equal datetime.next_occurring(:friday), datetime.since(6.days)
+ assert_equal datetime.next_occurring(:saturday), datetime.since(1.week)
+ assert_equal datetime.next_occurring(:sunday), datetime.since(1.day)
+ end
+
+ def test_prev_occur
+ datetime = DateTime.new(2016, 9, 24, 0, 0) # saturday
+ assert_equal datetime.prev_occurring(:monday), datetime.ago(5.days)
+ assert_equal datetime.prev_occurring(:tuesday), datetime.ago(4.days)
+ assert_equal datetime.prev_occurring(:wednesday), datetime.ago(3.days)
+ assert_equal datetime.prev_occurring(:thursday), datetime.ago(2.days)
+ assert_equal datetime.prev_occurring(:friday), datetime.ago(1.day)
+ assert_equal datetime.prev_occurring(:saturday), datetime.ago(1.week)
+ assert_equal datetime.prev_occurring(:sunday), datetime.ago(6.days)
+ end
+
def test_readable_inspect
datetime = DateTime.new(2005, 2, 21, 14, 30, 0)
assert_equal "Mon, 21 Feb 2005 14:30:00 +0000", datetime.readable_inspect
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index aea7515974..3676462788 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -559,8 +559,8 @@ SELECT * FROM clients WHERE (clients.locked != 1)
### OR Conditions
-`OR` condition between two relations can be build by calling `or` on the first relation
-and passing the second one as an argument.
+`OR` conditions between two relations can be built by calling `or` on the first
+relation, and passing the second one as an argument.
```ruby
Client.where(locked: true).or(Client.where(orders_count: [1,3,5]))
diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md
index 61b7112247..22b6b278d7 100644
--- a/guides/source/asset_pipeline.md
+++ b/guides/source/asset_pipeline.md
@@ -868,7 +868,7 @@ pre-existing JavaScript runtimes, you may want to add one to your Gemfile:
```ruby
group :production do
- gem 'therubyracer'
+ gem 'mini_racer'
end
```
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 5553f08456..49c691c841 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -208,7 +208,7 @@ TIP: Compiling CoffeeScript and JavaScript asset compression requires you
have a JavaScript runtime available on your system, in the absence
of a runtime you will see an `execjs` error during asset compilation.
Usually macOS and Windows come with a JavaScript runtime installed.
-Rails adds the `therubyracer` gem to the generated `Gemfile` in a
+Rails adds the `mini_racer` gem to the generated `Gemfile` in a
commented line for new apps and you can uncomment if you need it.
`therubyrhino` is the recommended runtime for JRuby users and is added by
default to the `Gemfile` in apps generated under JRuby. You can investigate
@@ -910,6 +910,7 @@ And then finally, add the view for this action, located at
<tr>
<th>Title</th>
<th>Text</th>
+ <th></th>
</tr>
<% @articles.each do |article| %>
@@ -1489,14 +1490,14 @@ second argument, and then the options as another argument. The `method: :delete`
and `data: { confirm: 'Are you sure?' }` options are used as HTML5 attributes so
that when the link is clicked, Rails will first show a confirm dialog to the
user, and then submit the link with method `delete`. This is done via the
-JavaScript file `jquery_ujs` which is automatically included in your
+JavaScript file `rails-ujs` which is automatically included in your
application's layout (`app/views/layouts/application.html.erb`) when you
generated the application. Without this file, the confirmation dialog box won't
appear.
![Confirm Dialog](images/getting_started/confirm_dialog.png)
-TIP: Learn more about jQuery Unobtrusive Adapter (jQuery UJS) on
+TIP: Learn more about Unobtrusive JavaScript on
[Working With JavaScript in Rails](working_with_javascript_in_rails.html) guide.
Congratulations, you can now create, show, list, update and destroy
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 1db48ed56c..565f40ed37 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -350,7 +350,7 @@ Rails adds some custom assertions of its own to the `minitest` framework:
| --------------------------------------------------------------------------------- | ------- |
| [`assert_difference(expressions, difference = 1, message = nil) {...}`](http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_difference) | Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.|
| [`assert_no_difference(expressions, message = nil, &block)`](http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_no_difference) | Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
-| [`assert_changes(expressions, message = nil, from:, to:, &block) {...}`](http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_changes) | Test that the result of evaluating an expression is changed after invoking the passed in block.|
+| [`assert_changes(expressions, message = nil, from:, to:, &block)`](http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_changes) | Test that the result of evaluating an expression is changed after invoking the passed in block.|
| [`assert_no_changes(expressions, message = nil, &block)`](http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_no_changes) | Test the result of evaluating an expression is not changed after invoking the passed in block.|
| [`assert_nothing_raised { block }`](http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_nothing_raised) | Ensures that the given block doesn't raise any exceptions.|
| [`assert_recognizes(expected_options, path, extras={}, message=nil)`](http://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_recognizes) | Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.|
@@ -602,11 +602,8 @@ Model tests don't have their own superclass like `ActionMailer::TestCase` instea
System Testing
--------------
-System tests are full-browser tests that can be used to test your application's
-JavaScript and user experience. System tests use Capybara as a base.
-
-System tests allow for running tests in either a real browser or a headless
-driver for testing full user interactions with your application.
+System tests allows test user interactions with your application, running tests
+in either a real or a headless browser. System tests uses Capybara as base.
For creating Rails system tests, you use the `test/system` directory in your
application. Rails provides a generator to create a system test skeleton for you.
@@ -660,8 +657,9 @@ end
The driver name is a required argument for `driven_by`. The optional arguments
that can be passed to `driven_by` are `:using` for the browser (this will only
-be used by Selenium), and `:screen_size` to change the size of the screen for
-screenshots.
+be used by Selenium), `:screen_size` to change the size of the screen for
+screenshots, and `:options` which can be used to set options supported by the
+driver.
```ruby
require "test_helper"
@@ -671,8 +669,9 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
end
```
-If your Capybara configuration requires more setup than provided by Rails, all
-of that configuration can be put into the `application_system_test_case.rb` file.
+If your Capybara configuration requires more setup than provided by Rails, this
+additional configuration could be added into `application_system_test_case.rb`
+file.
Please see [Capybara's documentation](https://github.com/teamcapybara/capybara#setup)
for additional settings.
@@ -695,9 +694,9 @@ take a screenshot of the browser.
Now we're going to add a system test to our blog application. We'll demonstrate
writing a system test by visiting the index page and creating a new blog article.
-If you used the scaffold generator, a system test skeleton is automatically
-created for you. If you did not use the generator start by creating a system
-test skeleton.
+If you used the scaffold generator, a system test skeleton was automatically
+created for you. If you didn't use the scaffold generator, start by creating a
+system test skeleton.
```bash
$ bin/rails generate system_test articles
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index e8b104a0b2..8429b6c7b8 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -349,7 +349,7 @@ module Rails
if defined?(JRUBY_VERSION)
GemfileEntry.version "therubyrhino", nil, comment
else
- GemfileEntry.new "therubyracer", nil, comment, { platforms: :ruby }, true
+ GemfileEntry.new "mini_racer", nil, comment, { platforms: :ruby }, true
end
end
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/setup.tt b/railties/lib/rails/generators/rails/app/templates/bin/setup.tt
index 560cc64a3f..ee9d077c30 100644
--- a/railties/lib/rails/generators/rails/app/templates/bin/setup.tt
+++ b/railties/lib/rails/generators/rails/app/templates/bin/setup.tt
@@ -1,9 +1,8 @@
-require 'pathname'
require 'fileutils'
include FileUtils
# path to your application root.
-APP_ROOT = Pathname.new File.expand_path('..', __dir__)
+APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/update.tt b/railties/lib/rails/generators/rails/app/templates/bin/update.tt
index 0aedf0d6e2..5b6e50883e 100644
--- a/railties/lib/rails/generators/rails/app/templates/bin/update.tt
+++ b/railties/lib/rails/generators/rails/app/templates/bin/update.tt
@@ -1,9 +1,8 @@
-require 'pathname'
require 'fileutils'
include FileUtils
# path to your application root.
-APP_ROOT = Pathname.new File.expand_path('..', __dir__)
+APP_ROOT = File.expand_path('..', __dir__)
def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
index 9c4a77fd1d..d44331a888 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -36,8 +36,8 @@ Rails.application.configure do
config.assets.compile = false
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
- <%- end -%>
+ <%- end -%>
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
@@ -50,8 +50,8 @@ Rails.application.configure do
# config.action_cable.mount_path = nil
# config.action_cable.url = 'wss://example.com/cable'
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
- <%- end -%>
+ <%- end -%>
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
@@ -68,14 +68,15 @@ Rails.application.configure do
# Use a real queuing backend for Active Job (and separate queues per environment)
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "<%= app_name %>_#{Rails.env}"
+
<%- unless options.skip_action_mailer? -%>
config.action_mailer.perform_caching = false
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
- <%- end -%>
+ <%- end -%>
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
diff --git a/railties/lib/rails/generators/testing/behaviour.rb b/railties/lib/rails/generators/testing/behaviour.rb
index 7a954a791d..ce0e42e60d 100644
--- a/railties/lib/rails/generators/testing/behaviour.rb
+++ b/railties/lib/rails/generators/testing/behaviour.rb
@@ -14,12 +14,12 @@ module Rails
include ActiveSupport::Testing::Stream
included do
- class_attribute :destination_root, :current_path, :generator_class, :default_arguments
-
# Generators frequently change the current path using +FileUtils.cd+.
# So we need to store the path at file load and revert back to it after each test.
- self.current_path = File.expand_path(Dir.pwd)
- self.default_arguments = []
+ class_attribute :current_path, default: File.expand_path(Dir.pwd)
+ class_attribute :default_arguments, default: []
+ class_attribute :destination_root
+ class_attribute :generator_class
end
module ClassMethods
diff --git a/railties/lib/rails/secrets.rb b/railties/lib/rails/secrets.rb
index 20c20cb9f1..c7a8676d7b 100644
--- a/railties/lib/rails/secrets.rb
+++ b/railties/lib/rails/secrets.rb
@@ -42,7 +42,7 @@ module Rails
<<-end_of_template.strip_heredoc
# See `secrets.yml` for tips on generating suitable keys.
# production:
- # external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289…
+ # external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289
end_of_template
end
diff --git a/railties/lib/rails/test_unit/reporter.rb b/railties/lib/rails/test_unit/reporter.rb
index fe11664d5e..1cc27f7b6c 100644
--- a/railties/lib/rails/test_unit/reporter.rb
+++ b/railties/lib/rails/test_unit/reporter.rb
@@ -3,8 +3,7 @@ require "minitest"
module Rails
class TestUnitReporter < Minitest::StatisticsReporter
- class_attribute :executable
- self.executable = "bin/rails test"
+ class_attribute :executable, default: "bin/rails test"
def record(result)
super
diff --git a/railties/test/commands/secrets_test.rb b/railties/test/commands/secrets_test.rb
index fb8fd2325e..be610f3b47 100644
--- a/railties/test/commands/secrets_test.rb
+++ b/railties/test/commands/secrets_test.rb
@@ -23,7 +23,7 @@ class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase
# Run twice to ensure encrypted secrets can be reread after first edit pass.
2.times do
- assert_match(/external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289…/, run_edit_command)
+ assert_match(/external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289/, run_edit_command)
end
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 31a5efb1b7..8a8c9a35ce 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -468,7 +468,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
if defined?(JRUBY_VERSION)
assert_gem "therubyrhino"
else
- assert_file "Gemfile", /# gem 'therubyracer', platforms: :ruby/
+ assert_file "Gemfile", /# gem 'mini_racer', platforms: :ruby/
end
end