aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.codeclimate.yml2
-rw-r--r--.rubocop.yml3
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock126
-rw-r--r--actioncable/actioncable.gemspec3
-rw-r--r--actionmailer/actionmailer.gemspec3
-rw-r--r--actionpack/CHANGELOG.md6
-rw-r--r--actionpack/actionpack.gemspec3
-rw-r--r--actionview/CHANGELOG.md2
-rw-r--r--actionview/actionview.gemspec3
-rw-r--r--activejob/activejob.gemspec3
-rw-r--r--activejob/lib/active_job/arguments.rb2
-rw-r--r--activemodel/activemodel.gemspec3
-rw-r--r--activerecord/CHANGELOG.md27
-rw-r--r--activerecord/activerecord.gemspec3
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb18
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/transaction.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb8
-rw-r--r--activerecord/lib/active_record/core.rb4
-rw-r--r--activerecord/lib/active_record/enum.rb4
-rw-r--r--activerecord/lib/active_record/fixture_set/model_metadata.rb11
-rw-r--r--activerecord/lib/active_record/fixture_set/table_row.rb76
-rw-r--r--activerecord/lib/active_record/fixture_set/table_rows.rb93
-rw-r--r--activerecord/lib/active_record/fixtures.rb11
-rw-r--r--activerecord/lib/active_record/railties/databases.rake17
-rw-r--r--activerecord/lib/active_record/tasks/database_tasks.rb10
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb7
-rw-r--r--activerecord/test/cases/core_test.rb12
-rw-r--r--activerecord/test/cases/enum_test.rb18
-rw-r--r--activerecord/test/cases/fixtures_test.rb18
-rw-r--r--activerecord/test/cases/hot_compatibility_test.rb2
-rw-r--r--activerecord/test/cases/migration_test.rb30
-rw-r--r--activerecord/test/cases/numeric_data_test.rb24
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb11
-rw-r--r--activerecord/test/models/topic.rb4
-rw-r--r--activestorage/activestorage.gemspec3
-rw-r--r--activesupport/activesupport.gemspec3
-rw-r--r--activesupport/lib/active_support/testing/parallelization.rb9
-rw-r--r--guides/source/active_record_validations.md3
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md23
-rw-r--r--guides/source/debugging_rails_applications.md2
-rw-r--r--guides/source/development_dependencies_install.md364
-rw-r--r--guides/source/ruby_on_rails_guides_guidelines.md4
-rw-r--r--guides/source/security.md5
-rw-r--r--railties/CHANGELOG.md6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/package.json.tt2
-rw-r--r--railties/lib/rails/info.rb4
-rw-r--r--railties/lib/rails/info_controller.rb12
-rw-r--r--railties/railties.gemspec3
-rw-r--r--railties/test/application/rake/multi_dbs_test.rb41
-rw-r--r--railties/test/application/rake_test.rb6
-rw-r--r--railties/test/application/test_runner_test.rb24
-rw-r--r--railties/test/generators/app_generator_test.rb11
-rw-r--r--railties/test/rails_info_controller_test.rb5
-rw-r--r--railties/test/rails_info_test.rb12
59 files changed, 635 insertions, 499 deletions
diff --git a/.codeclimate.yml b/.codeclimate.yml
index 7fd35d8241..139ee8013b 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -23,7 +23,7 @@ checks:
engines:
rubocop:
enabled: true
- channel: rubocop-0-58
+ channel: rubocop-0-60
ratings:
paths:
diff --git a/.rubocop.yml b/.rubocop.yml
index 615a229432..033f7adf49 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -133,9 +133,6 @@ Style/FrozenStringLiteralComment:
Style/RedundantFreeze:
Enabled: true
- Exclude:
- - 'actionpack/lib/action_dispatch/journey/router/utils.rb'
- - 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb'
# Use `foo {}` not `foo{}`.
Layout/SpaceBeforeBlockBraces:
diff --git a/Gemfile b/Gemfile
index fb15bf127e..9df706f9c2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -104,8 +104,6 @@ group :test do
platforms :mri do
gem "stackprof"
gem "byebug"
- # FIXME: Remove this when thor 0.21 is release
- gem "thor", git: "https://github.com/erikhuda/thor.git", ref: "006832ea32480618791f89bb7d9e67b22fc814b9"
end
gem "benchmark-ips"
diff --git a/Gemfile.lock b/Gemfile.lock
index 1321436814..f4f3e430ba 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,11 +1,4 @@
GIT
- remote: https://github.com/erikhuda/thor.git
- revision: 006832ea32480618791f89bb7d9e67b22fc814b9
- ref: 006832ea32480618791f89bb7d9e67b22fc814b9
- specs:
- thor (0.20.0)
-
-GIT
remote: https://github.com/matthewd/rb-inotify.git
revision: 856730aad4b285969e8dd621e44808a7c5af4242
branch: close-handling
@@ -32,9 +25,9 @@ GIT
GIT
remote: https://github.com/rails/webpacker.git
- revision: 48d9fd52c3e9637dbb21e551b48c84c0f2dbb2ed
+ revision: bb132d591da35095e3246082cba3d693f847e0b5
specs:
- webpacker (4.0.0.pre.pre.2)
+ webpacker (4.0.0.pre.3)
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
@@ -105,16 +98,16 @@ PATH
GEM
remote: https://rubygems.org/
specs:
- activerecord-jdbc-adapter (52.0-java)
+ activerecord-jdbc-adapter (52.1-java)
activerecord (~> 5.2.0)
- activerecord-jdbcmysql-adapter (52.0-java)
- activerecord-jdbc-adapter (= 52.0)
+ activerecord-jdbcmysql-adapter (52.1-java)
+ activerecord-jdbc-adapter (= 52.1)
jdbc-mysql (~> 5.1.36)
- activerecord-jdbcpostgresql-adapter (52.0-java)
- activerecord-jdbc-adapter (= 52.0)
+ activerecord-jdbcpostgresql-adapter (52.1-java)
+ activerecord-jdbc-adapter (= 52.1)
jdbc-postgres (>= 9.4, < 43)
- activerecord-jdbcsqlite3-adapter (52.0-java)
- activerecord-jdbc-adapter (= 52.0)
+ activerecord-jdbcsqlite3-adapter (52.1-java)
+ activerecord-jdbc-adapter (= 52.1)
jdbc-sqlite3 (~> 3.8, < 3.30)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
@@ -123,17 +116,17 @@ GEM
io-like (~> 0.3.0)
ast (2.4.0)
aws-eventstream (1.0.1)
- aws-partitions (1.102.0)
- aws-sdk-core (3.25.0)
+ aws-partitions (1.111.0)
+ aws-sdk-core (3.37.0)
aws-eventstream (~> 1.0)
aws-partitions (~> 1.0)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-kms (1.7.0)
- aws-sdk-core (~> 3)
+ aws-sdk-kms (1.11.0)
+ aws-sdk-core (~> 3, >= 3.26.0)
aws-sigv4 (~> 1.0)
- aws-sdk-s3 (1.17.1)
- aws-sdk-core (~> 3, >= 3.21.2)
+ aws-sdk-s3 (1.23.1)
+ aws-sdk-core (~> 3, >= 3.26.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.0)
aws-sigv4 (1.0.3)
@@ -173,38 +166,38 @@ GEM
childprocess
faraday
selenium-webdriver
- bootsnap (1.3.1)
+ bootsnap (1.3.2)
msgpack (~> 1.0)
- bootsnap (1.3.1-java)
+ bootsnap (1.3.2-java)
msgpack (~> 1.0)
builder (3.2.3)
bunny (2.9.2)
amq-protocol (~> 2.3.0)
byebug (10.0.2)
- capybara (3.7.1)
+ capybara (3.10.1)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
- xpath (~> 3.1)
+ regexp_parser (~> 1.2)
+ xpath (~> 3.2)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
- chromedriver-helper (2.0.0)
+ chromedriver-helper (2.1.0)
archive-zip (~> 0.10)
nokogiri (~> 1.8)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
- concurrent-ruby (1.0.5)
- concurrent-ruby (1.0.5-java)
+ concurrent-ruby (1.1.3)
connection_pool (2.2.2)
cookiejar (0.3.3)
crass (1.0.4)
curses (1.0.2)
daemons (1.2.6)
- dalli (2.7.8)
+ dalli (2.7.9)
dante (0.2.0)
declarative (0.0.10)
declarative-option (0.1.0)
@@ -228,7 +221,7 @@ GEM
event_emitter (0.2.6)
eventmachine (1.2.7)
execjs (2.7.0)
- faraday (0.15.2)
+ faraday (0.15.3)
multipart-post (>= 1.2, < 3)
faraday_middleware (0.12.2)
faraday (>= 0.7.4, < 1.0)
@@ -252,39 +245,39 @@ GEM
raabro (~> 1.1)
globalid (0.4.1)
activesupport (>= 4.2.0)
- google-api-client (0.23.8)
+ google-api-client (0.25.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.5, < 0.7.0)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
- signet (~> 0.9)
- google-cloud-core (1.2.3)
+ signet (~> 0.10)
+ google-cloud-core (1.2.7)
google-cloud-env (~> 1.0)
- google-cloud-env (1.0.2)
+ google-cloud-env (1.0.5)
faraday (~> 0.11)
- google-cloud-storage (1.13.1)
+ google-cloud-storage (1.15.0)
digest-crc (~> 0.4)
google-api-client (~> 0.23)
google-cloud-core (~> 1.2)
googleauth (~> 0.6.2)
- googleauth (0.6.6)
+ googleauth (0.6.7)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
- memoist (~> 0.12)
+ memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.7)
- hiredis (0.6.1)
- hiredis (0.6.1-java)
+ hiredis (0.6.3)
+ hiredis (0.6.3-java)
http_parser.rb (0.6.0)
httpclient (2.8.3)
- i18n (1.1.0)
+ i18n (1.1.1)
concurrent-ruby (~> 1.0)
- image_processing (1.6.0)
+ image_processing (1.7.1)
mini_magick (~> 4.0)
- ruby-vips (>= 2.0.11, < 3)
+ ruby-vips (>= 2.0.13, < 3)
io-like (0.3.0)
jaro_winkler (1.5.1)
jaro_winkler (1.5.1-java)
@@ -303,7 +296,7 @@ GEM
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
- loofah (2.2.2)
+ loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
@@ -311,7 +304,7 @@ GEM
marcel (0.3.3)
mimemagic (~> 0.3.2)
memoist (0.16.0)
- method_source (0.9.0)
+ method_source (0.9.1)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
@@ -334,7 +327,7 @@ GEM
msgpack (1.2.4-x86-mingw32)
multi_json (1.13.1)
multipart-post (2.0.0)
- mustache (1.0.5)
+ mustache (1.1.0)
mustermann (1.0.3)
mysql2 (0.5.2)
mysql2 (0.5.2-x64-mingw32)
@@ -350,14 +343,14 @@ GEM
mini_portile2 (~> 2.3.0)
os (1.0.0)
parallel (1.12.1)
- parser (2.5.1.2)
+ parser (2.5.3.0)
ast (~> 2.4.0)
path_expander (1.0.3)
pg (1.1.3)
pg (1.1.3-x64-mingw32)
pg (1.1.3-x86-mingw32)
powerpack (0.1.2)
- psych (3.0.2)
+ psych (3.0.3)
public_suffix (3.0.3)
puma (3.12.0)
puma (3.12.0-java)
@@ -367,10 +360,10 @@ GEM
thor
raabro (1.1.6)
racc (1.4.14)
- rack (2.0.5)
+ rack (2.0.6)
rack-cache (1.8.0)
rack (>= 0.4)
- rack-protection (2.0.3)
+ rack-protection (2.0.4)
rack
rack-proxy (0.6.5)
rack
@@ -386,9 +379,10 @@ GEM
rb-fsevent (0.10.3)
rdoc (6.0.4)
redcarpet (3.2.3)
- redis (4.0.2)
+ redis (4.0.3)
redis-namespace (1.6.0)
redis (>= 3.0.4)
+ regexp_parser (1.2.0)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
@@ -405,14 +399,14 @@ GEM
resque (~> 1.26)
rufus-scheduler (~> 3.2)
retriable (3.1.2)
- rubocop (0.58.2)
+ rubocop (0.60.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1)
powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
- unicode-display_width (~> 1.0, >= 1.0.1)
+ unicode-display_width (~> 1.4.0)
ruby-progressbar (1.10.0)
ruby-vips (2.0.13)
ffi (~> 1.9)
@@ -420,7 +414,7 @@ GEM
rubyzip (1.2.2)
rufus-scheduler (3.5.2)
fugit (~> 1.1, >= 1.1.5)
- sass (3.5.7)
+ sass (3.7.2)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
@@ -433,26 +427,26 @@ GEM
tilt (>= 1.1, < 3)
sdoc (1.0.0)
rdoc (>= 5.0)
- selenium-webdriver (3.14.0)
+ selenium-webdriver (3.141.0)
childprocess (~> 0.5)
- rubyzip (~> 1.2)
- sequel (5.12.0)
+ rubyzip (~> 1.2, >= 1.2.2)
+ sequel (5.14.0)
serverengine (2.0.7)
sigdump (~> 0.2.2)
- sidekiq (5.2.1)
+ sidekiq (5.2.3)
connection_pool (~> 2.2, >= 2.2.2)
rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5)
sigdump (0.2.4)
- signet (0.9.1)
+ signet (0.11.0)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
- sinatra (2.0.3)
+ sinatra (2.0.4)
mustermann (~> 1.0)
rack (~> 2.0)
- rack-protection (= 2.0.3)
+ rack-protection (= 2.0.4)
tilt (~> 2.0)
sneakers (2.7.0)
bunny (~> 2.9.2)
@@ -477,6 +471,7 @@ GEM
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
+ thor (0.20.3)
thread_safe (0.3.6)
thread_safe (0.3.6-java)
tilt (2.0.8)
@@ -485,10 +480,10 @@ GEM
turbolinks-source (5.2.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
- tzinfo-data (1.2018.5)
+ tzinfo-data (1.2018.7)
tzinfo (>= 1.0.0)
uber (0.1.0)
- uglifier (4.1.18)
+ uglifier (4.1.19)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.4.0)
useragent (0.16.10)
@@ -504,7 +499,7 @@ GEM
websocket-driver (0.7.0-java)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
- xpath (3.1.0)
+ xpath (3.2.0)
nokogiri (~> 1.8)
PLATFORMS
@@ -569,7 +564,6 @@ DEPENDENCIES
sqlite3 (~> 1.3.6)
stackprof
sucker_punch
- thor!
turbolinks (~> 5)
tzinfo-data
uglifier (>= 1.3.0)
@@ -579,4 +573,4 @@ DEPENDENCIES
websocket-client-simple!
BUNDLED WITH
- 1.16.6
+ 1.17.1
diff --git a/actioncable/actioncable.gemspec b/actioncable/actioncable.gemspec
index 137fa64431..31c6fb41f2 100644
--- a/actioncable/actioncable.gemspec
+++ b/actioncable/actioncable.gemspec
@@ -25,6 +25,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/actioncable/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "actionpack", version
s.add_dependency "nio4r", "~> 2.0"
diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec
index f2fb160bdd..6f8d6d0699 100644
--- a/actionmailer/actionmailer.gemspec
+++ b/actionmailer/actionmailer.gemspec
@@ -26,6 +26,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/actionmailer/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "actionpack", version
s.add_dependency "actionview", version
s.add_dependency "activejob", version
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 5554d4e6b8..81201795d4 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -3,9 +3,9 @@
There is no controller instance when using a redirect route or a
mounted rack application so pass the request object as the context
when resolving dynamic CSP sources in this scenario.
-
+
Fixes #34200.
-
+
*Andrew White*
* Apply mapping to symbols returned from dynamic CSP sources
@@ -14,7 +14,7 @@
would be converted to a string implicity, e.g:
policy.default_src -> { :self }
-
+
would generate the header:
Content-Security-Policy: default-src self
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index 1dc8abf746..ec56de18f1 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -26,6 +26,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/actionpack/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "activesupport", version
s.add_dependency "rack", "~> 2.0"
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index fd8bae0cdf..1f537e725a 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -11,7 +11,7 @@
*Eileen M. Uchitelle*, *Aaron Patterson*
* Respect the `only_path` option passed to `url_for` when the options are passed in as an array
-
+
Fixes #33237.
*Joel Ambass*
diff --git a/actionview/actionview.gemspec b/actionview/actionview.gemspec
index 49ee1a292b..5f1e746421 100644
--- a/actionview/actionview.gemspec
+++ b/actionview/actionview.gemspec
@@ -26,6 +26,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/actionview/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "activesupport", version
s.add_dependency "builder", "~> 3.1"
diff --git a/activejob/activejob.gemspec b/activejob/activejob.gemspec
index be6292f737..cd7ac210ec 100644
--- a/activejob/activejob.gemspec
+++ b/activejob/activejob.gemspec
@@ -25,6 +25,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/activejob/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "activesupport", version
s.add_dependency "globalid", ">= 0.3.6"
end
diff --git a/activejob/lib/active_job/arguments.rb b/activejob/lib/active_job/arguments.rb
index 31347194d2..a86a82c6e3 100644
--- a/activejob/lib/active_job/arguments.rb
+++ b/activejob/lib/active_job/arguments.rb
@@ -62,7 +62,7 @@ module ActiveJob
OBJECT_SERIALIZER_KEY, OBJECT_SERIALIZER_KEY.to_sym,
WITH_INDIFFERENT_ACCESS_KEY, WITH_INDIFFERENT_ACCESS_KEY.to_sym,
]
- private_constant :RESERVED_KEYS
+ private_constant :RESERVED_KEYS, :GLOBALID_KEY, :SYMBOL_KEYS_KEY, :WITH_INDIFFERENT_ACCESS_KEY
def serialize_argument(argument)
case argument
diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec
index 7be466dc4c..493fca698a 100644
--- a/activemodel/activemodel.gemspec
+++ b/activemodel/activemodel.gemspec
@@ -25,5 +25,8 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/activemodel/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "activesupport", version
end
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 9d80bbe51f..2a237f86cf 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,30 @@
+* Add an `:if_not_exists` option to `create_table`.
+
+ Example:
+
+ create_table :posts, if_not_exists: true do |t|
+ t.string :title
+ end
+
+ That would execute:
+
+ CREATE TABLE IF NOT EXISTS posts (
+ ...
+ )
+
+ If the table already exists, `if_not_exists: false` (the default) raises an
+ exception whereas `if_not_exists: true` does nothing.
+
+ *fatkodima*, *Stefan Kanev*
+
+* Defining an Enum as a Hash with blank key, or as an Array with a blank value, now raises an `ArgumentError`.
+
+ *Christophe Maximin*
+
+* Adds support for multiple databases to `rails db:schema:cache:dump` and `rails db:schema:cache:clear`.
+
+ *Gannon McGibbon*
+
* `update_columns` now correctly raises `ActiveModel::MissingAttributeError`
if the attribute does not exist.
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index a857d00c05..bcdd82052c 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -28,6 +28,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/activerecord/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "activesupport", version
s.add_dependency "activemodel", version
end
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 1e92ee3b96..fd8c1da842 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -328,7 +328,7 @@ module ActiveRecord
# person.attribute_for_inspect(:tag_ids)
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
def attribute_for_inspect(attr_name)
- value = read_attribute(attr_name)
+ value = _read_attribute(attr_name)
format_for_inspect(value)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb
index 9d9e8a4110..19ff780192 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb
@@ -39,7 +39,9 @@ module ActiveRecord
end
def visit_TableDefinition(o)
- create_sql = +"CREATE#{' TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} "
+ create_sql = +"CREATE#{' TEMPORARY' if o.temporary} TABLE "
+ create_sql << "IF NOT EXISTS " if o.if_not_exists
+ create_sql << "#{quote_table_name(o.name)} "
statements = o.columns.map { |c| accept c }
statements << accept(o.primary_keys) if o.primary_keys
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 70607fda5a..db489143af 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require "active_support/deprecation"
+
module ActiveRecord
module ConnectionAdapters #:nodoc:
# Abstract representation of an index definition on a table. Instances of
@@ -256,15 +258,25 @@ module ActiveRecord
class TableDefinition
include ColumnMethods
- attr_accessor :indexes
- attr_reader :name, :temporary, :options, :as, :foreign_keys, :comment
+ attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
+ attr_writer :indexes
+ deprecate :indexes=
- def initialize(name, temporary = false, options = nil, as = nil, comment: nil)
+ def initialize(
+ name,
+ temporary: false,
+ if_not_exists: false,
+ options: nil,
+ as: nil,
+ comment: nil,
+ **
+ )
@columns_hash = {}
@indexes = []
@foreign_keys = []
@primary_keys = nil
@temporary = temporary
+ @if_not_exists = if_not_exists
@options = options
@as = as
@name = name
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 8a7020a799..38cfc3a241 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -205,6 +205,9 @@ module ActiveRecord
# Set to true to drop the table before creating it.
# Set to +:cascade+ to drop dependent objects as well.
# Defaults to false.
+ # [<tt>:if_not_exists</tt>]
+ # Set to true to avoid raising an error when the table already exists.
+ # Defaults to false.
# [<tt>:as</tt>]
# SQL to use to generate the table. When this option is used, the block is
# ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
@@ -287,8 +290,8 @@ module ActiveRecord
# SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
#
# See also TableDefinition#column for details on how to create columns.
- def create_table(table_name, comment: nil, **options)
- td = create_table_definition table_name, options[:temporary], options[:options], options[:as], comment: comment
+ def create_table(table_name, **options)
+ td = create_table_definition(table_name, options)
if options[:id] != false && !options[:as]
pk = options.fetch(:primary_key) do
@@ -317,7 +320,9 @@ module ActiveRecord
end
if supports_comments? && !supports_comments_in_create?
- change_table_comment(table_name, comment) if comment.present?
+ if table_comment = options[:comment].presence
+ change_table_comment(table_name, table_comment)
+ end
td.columns.each do |column|
change_column_comment(table_name, column.name, column.comment) if column.comment.present?
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
index 564b226b39..0f2b1e85ff 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
@@ -137,7 +137,7 @@ module ActiveRecord
record.committed!
else
# if not running callbacks, only adds the record to the parent transaction
- record.add_to_transaction
+ connection.add_transaction_record(record)
end
end
ensure
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index e75202b0be..0895d06356 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -93,11 +93,11 @@ module ActiveRecord
elsif value.hex?
"X'#{value}'"
end
- when Float
- if value.infinite? || value.nan?
- "'#{value}'"
- else
+ when Numeric
+ if value.finite?
super
+ else
+ "'#{value}'"
end
when OID::Array::Data
_quote(encode_array(value))
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index da3e2549a2..50f3087c51 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -498,7 +498,7 @@ module ActiveRecord
inspection = if defined?(@attributes) && @attributes
self.class.attribute_names.collect do |name|
if has_attribute?(name)
- attr = read_attribute(name)
+ attr = _read_attribute(name)
value = if attr.nil?
attr.inspect
else
@@ -528,7 +528,7 @@ module ActiveRecord
pp.text attr_name
pp.text ":"
pp.breakable
- value = read_attribute(attr_name)
+ value = _read_attribute(attr_name)
value = inspection_filter.filter_param(attr_name, value) unless value.nil?
pp.pp value
end
diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb
index 3d97e4e513..3a600835e1 100644
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ -218,6 +218,10 @@ module ActiveRecord
MSG
raise ArgumentError, error_message
end
+
+ if values.is_a?(Hash) && values.keys.any?(&:blank?) || values.is_a?(Array) && values.any?(&:blank?)
+ raise ArgumentError, "Enum label name must not be blank."
+ end
end
ENUM_CONFLICT_MESSAGE = \
diff --git a/activerecord/lib/active_record/fixture_set/model_metadata.rb b/activerecord/lib/active_record/fixture_set/model_metadata.rb
index edc03939c8..fb23df6f45 100644
--- a/activerecord/lib/active_record/fixture_set/model_metadata.rb
+++ b/activerecord/lib/active_record/fixture_set/model_metadata.rb
@@ -3,9 +3,8 @@
module ActiveRecord
class FixtureSet
class ModelMetadata # :nodoc:
- def initialize(model_class, table_name)
+ def initialize(model_class)
@model_class = model_class
- @table_name = table_name
end
def primary_key_name
@@ -23,18 +22,12 @@ module ActiveRecord
def timestamp_column_names
@timestamp_column_names ||=
- %w(created_at created_on updated_at updated_on) & column_names
+ %w(created_at created_on updated_at updated_on) & @model_class.column_names
end
def inheritance_column_name
@inheritance_column_name ||= @model_class && @model_class.inheritance_column
end
-
- private
-
- def column_names
- @column_names ||= @model_class.connection.columns(@table_name).collect(&:name)
- end
end
end
end
diff --git a/activerecord/lib/active_record/fixture_set/table_row.rb b/activerecord/lib/active_record/fixture_set/table_row.rb
index 5f72c1df38..cb4726f1ee 100644
--- a/activerecord/lib/active_record/fixture_set/table_row.rb
+++ b/activerecord/lib/active_record/fixture_set/table_row.rb
@@ -3,6 +3,38 @@
module ActiveRecord
class FixtureSet
class TableRow # :nodoc:
+ class ReflectionProxy # :nodoc:
+ def initialize(association)
+ @association = association
+ end
+
+ def join_table
+ @association.join_table
+ end
+
+ def name
+ @association.name
+ end
+
+ def primary_key_type
+ @association.klass.type_for_attribute(@association.klass.primary_key).type
+ end
+ end
+
+ class HasManyThroughProxy < ReflectionProxy # :nodoc:
+ def rhs_key
+ @association.foreign_key
+ end
+
+ def lhs_key
+ @association.through_reflection.foreign_key
+ end
+
+ def join_table
+ @association.through_reflection.table_name
+ end
+ end
+
def initialize(fixture, table_rows:, label:, now:)
@table_rows = table_rows
@label = label
@@ -31,7 +63,7 @@ module ActiveRecord
interpolate_label
generate_primary_key
resolve_enums
- @table_rows.resolve_sti_reflections(@row)
+ resolve_sti_reflections
end
def reflection_class
@@ -74,6 +106,48 @@ module ActiveRecord
end
end
end
+
+ def resolve_sti_reflections
+ # If STI is used, find the correct subclass for association reflection
+ reflection_class._reflections.each_value do |association|
+ case association.macro
+ when :belongs_to
+ # Do not replace association name with association foreign key if they are named the same
+ fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
+
+ if association.name.to_s != fk_name && value = @row.delete(association.name.to_s)
+ if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
+ # support polymorphic belongs_to as "label (Type)"
+ @row[association.foreign_type] = $1
+ end
+
+ fk_type = reflection_class.type_for_attribute(fk_name).type
+ @row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
+ end
+ when :has_many
+ if association.options[:through]
+ add_join_records(HasManyThroughProxy.new(association))
+ end
+ end
+ end
+ end
+
+ def add_join_records(association)
+ # This is the case when the join table has no fixtures file
+ if (targets = @row.delete(association.name.to_s))
+ table_name = association.join_table
+ column_type = association.primary_key_type
+ lhs_key = association.lhs_key
+ rhs_key = association.rhs_key
+
+ targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
+ joins = targets.map do |target|
+ { lhs_key => @row[model_metadata.primary_key_name],
+ rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
+ end
+ @table_rows.tables[table_name].concat(joins)
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/fixture_set/table_rows.rb b/activerecord/lib/active_record/fixture_set/table_rows.rb
index 3e3c0bc7ab..23814b6cb5 100644
--- a/activerecord/lib/active_record/fixture_set/table_rows.rb
+++ b/activerecord/lib/active_record/fixture_set/table_rows.rb
@@ -6,40 +6,7 @@ require "active_record/fixture_set/model_metadata"
module ActiveRecord
class FixtureSet
class TableRows # :nodoc:
- class ReflectionProxy # :nodoc:
- def initialize(association)
- @association = association
- end
-
- def join_table
- @association.join_table
- end
-
- def name
- @association.name
- end
-
- def primary_key_type
- @association.klass.type_for_attribute(@association.klass.primary_key).type
- end
- end
-
- class HasManyThroughProxy < ReflectionProxy # :nodoc:
- def rhs_key
- @association.foreign_key
- end
-
- def lhs_key
- @association.through_reflection.foreign_key
- end
-
- def join_table
- @association.through_reflection.table_name
- end
- end
-
def initialize(table_name, model_class:, fixtures:, config:)
- @table_name = table_name
@model_class = model_class
# track any join tables we need to insert later
@@ -48,49 +15,22 @@ module ActiveRecord
# ensure this table is loaded before any HABTM associations
@tables[table_name] = nil
- build_table_rows_from(fixtures, config)
+ build_table_rows_from(table_name, fixtures, config)
end
- attr_reader :table_name, :model_class
+ attr_reader :tables, :model_class
def to_hash
@tables.transform_values { |rows| rows.map(&:to_hash) }
end
def model_metadata
- @model_metadata ||= ModelMetadata.new(model_class, table_name)
- end
-
- def resolve_sti_reflections(row)
- # If STI is used, find the correct subclass for association reflection
- reflection_class = reflection_class_for(row)
-
- reflection_class._reflections.each_value do |association|
- case association.macro
- when :belongs_to
- # Do not replace association name with association foreign key if they are named the same
- fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
-
- if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
- if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
- # support polymorphic belongs_to as "label (Type)"
- row[association.foreign_type] = $1
- end
-
- fk_type = reflection_class.type_for_attribute(fk_name).type
- row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
- end
- when :has_many
- if association.options[:through]
- add_join_records(row, HasManyThroughProxy.new(association))
- end
- end
- end
+ @model_metadata ||= ModelMetadata.new(model_class)
end
private
- def build_table_rows_from(fixtures, config)
+ def build_table_rows_from(table_name, fixtures, config)
now = config.default_timezone == :utc ? Time.now.utc : Time.now
@tables[table_name] = fixtures.map do |label, fixture|
@@ -102,31 +42,6 @@ module ActiveRecord
)
end
end
-
- def reflection_class_for(row)
- if row.include?(model_metadata.inheritance_column_name)
- row[model_metadata.inheritance_column_name].constantize rescue model_class
- else
- model_class
- end
- end
-
- def add_join_records(row, association)
- # This is the case when the join table has no fixtures file
- if (targets = row.delete(association.name.to_s))
- table_name = association.join_table
- column_type = association.primary_key_type
- lhs_key = association.lhs_key
- rhs_key = association.rhs_key
-
- targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
- joins = targets.map do |target|
- { lhs_key => row[model_metadata.primary_key_name],
- rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
- end
- @tables[table_name].concat(joins)
- end
- end
end
end
end
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index b090c76a38..1248ed00c5 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -577,9 +577,8 @@ module ActiveRecord
fixtures_map = {}
fixture_sets = fixture_files.map do |fixture_set_name|
klass = class_names[fixture_set_name]
- conn = klass&.connection || connection
fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
- conn,
+ nil,
fixture_set_name,
klass,
::File.join(fixtures_directory, fixture_set_name)
@@ -621,7 +620,7 @@ module ActiveRecord
attr_reader :table_name, :name, :fixtures, :model_class, :config
- def initialize(connection, name, class_name, path, config = ActiveRecord::Base)
+ def initialize(_, name, class_name, path, config = ActiveRecord::Base)
@name = name
@path = path
@config = config
@@ -630,11 +629,7 @@ module ActiveRecord
@fixtures = read_fixture_files(path)
- @connection = connection
-
- @table_name = (model_class.respond_to?(:table_name) ?
- model_class.table_name :
- self.class.default_fixture_table_name(name, config))
+ @table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
end
def [](x)
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 1c7ceb4981..475baa7559 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -300,15 +300,22 @@ db_namespace = namespace :db do
namespace :cache do
desc "Creates a db/schema_cache.yml file."
task dump: :load_config do
- conn = ActiveRecord::Base.connection
- filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
- ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(conn, filename)
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
+ ActiveRecord::Base.establish_connection(db_config.config)
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(
+ ActiveRecord::Base.connection,
+ filename,
+ )
+ end
end
desc "Clears a db/schema_cache.yml file."
task clear: :load_config do
- filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
- rm_f filename, verbose: false
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
+ rm_f filename, verbose: false
+ end
end
end
end
diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb
index 974d7a1c0a..27e401a756 100644
--- a/activerecord/lib/active_record/tasks/database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/database_tasks.rb
@@ -313,6 +313,16 @@ module ActiveRecord
ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
end
+ def cache_dump_filename(namespace)
+ filename = if namespace == "primary"
+ "schema_cache.yml"
+ else
+ "#{namespace}_schema_cache.yml"
+ end
+
+ ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
+ end
+
def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
each_current_configuration(environment) { |configuration, spec_name, env|
load_schema(configuration, format, file, env, spec_name)
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index 6c2e256447..0dbdd56ae6 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -56,6 +56,13 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", t.attribute_for_inspect(:content)
end
+ test "attribute_for_inspect with a non-primary key id attribute" do
+ t = topics(:first).becomes(TitlePrimaryKeyTopic)
+ t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
+
+ assert_equal "1", t.attribute_for_inspect(:id)
+ end
+
test "attribute_present" do
t = Topic.new
t.title = "hello there!"
diff --git a/activerecord/test/cases/core_test.rb b/activerecord/test/cases/core_test.rb
index f7fbf3ee8a..36e3d543cd 100644
--- a/activerecord/test/cases/core_test.rb
+++ b/activerecord/test/cases/core_test.rb
@@ -30,6 +30,11 @@ class CoreTest < ActiveRecord::TestCase
assert_equal %(#<Topic id: 1, title: "The First Topic">), Topic.all.merge!(select: "id, title", where: "id = 1").first.inspect
end
+ def test_inspect_instance_with_non_primary_key_id_attribute
+ topic = topics(:first).becomes(TitlePrimaryKeyTopic)
+ assert_match(/id: 1/, topic.inspect)
+ end
+
def test_inspect_class_without_table
assert_equal "NonExistentTable(Table doesn't exist)", NonExistentTable.inspect
end
@@ -110,4 +115,11 @@ class CoreTest < ActiveRecord::TestCase
PP.pp(subtopic.new, StringIO.new(actual))
assert_equal "inspecting topic\n", actual
end
+
+ def test_pretty_print_with_non_primary_key_id_attribute
+ topic = topics(:first).becomes(TitlePrimaryKeyTopic)
+ actual = +""
+ PP.pp(topic, StringIO.new(actual))
+ assert_match(/id: 1/, actual)
+ end
end
diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb
index b4593ccdf2..867ce7082b 100644
--- a/activerecord/test/cases/enum_test.rb
+++ b/activerecord/test/cases/enum_test.rb
@@ -274,6 +274,24 @@ class EnumTest < ActiveRecord::TestCase
end
assert_match(/must be either a hash, an array of symbols, or an array of strings./, e.message)
+
+ e = assert_raises(ArgumentError) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+ enum status: { "" => 1, "active" => 2 }
+ end
+ end
+
+ assert_match(/Enum label name must not be blank/, e.message)
+
+ e = assert_raises(ArgumentError) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+ enum status: ["active", ""]
+ end
+ end
+
+ assert_match(/Enum label name must not be blank/, e.message)
end
test "reserved enum names" do
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 1092b9553f..a5592fc86a 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -473,11 +473,11 @@ class FixturesTest < ActiveRecord::TestCase
end
def test_empty_yaml_fixture
- assert_not_nil ActiveRecord::FixtureSet.new(Account.connection, "accounts", Account, FIXTURES_ROOT + "/naked/yml/accounts")
+ assert_not_nil ActiveRecord::FixtureSet.new(nil, "accounts", Account, FIXTURES_ROOT + "/naked/yml/accounts")
end
def test_empty_yaml_fixture_with_a_comment_in_it
- assert_not_nil ActiveRecord::FixtureSet.new(Account.connection, "companies", Company, FIXTURES_ROOT + "/naked/yml/companies")
+ assert_not_nil ActiveRecord::FixtureSet.new(nil, "companies", Company, FIXTURES_ROOT + "/naked/yml/companies")
end
def test_nonexistent_fixture_file
@@ -487,14 +487,14 @@ class FixturesTest < ActiveRecord::TestCase
assert_empty Dir[nonexistent_fixture_path + "*"]
assert_raise(Errno::ENOENT) do
- ActiveRecord::FixtureSet.new(Account.connection, "companies", Company, nonexistent_fixture_path)
+ ActiveRecord::FixtureSet.new(nil, "companies", Company, nonexistent_fixture_path)
end
end
def test_dirty_dirty_yaml_file
fixture_path = FIXTURES_ROOT + "/naked/yml/courses"
error = assert_raise(ActiveRecord::Fixture::FormatError) do
- ActiveRecord::FixtureSet.new(Account.connection, "courses", Course, fixture_path)
+ ActiveRecord::FixtureSet.new(nil, "courses", Course, fixture_path)
end
assert_equal "fixture is not a hash: #{fixture_path}.yml", error.to_s
end
@@ -502,7 +502,7 @@ class FixturesTest < ActiveRecord::TestCase
def test_yaml_file_with_one_invalid_fixture
fixture_path = FIXTURES_ROOT + "/naked/yml/courses_with_invalid_key"
error = assert_raise(ActiveRecord::Fixture::FormatError) do
- ActiveRecord::FixtureSet.new(Account.connection, "courses", Course, fixture_path)
+ ActiveRecord::FixtureSet.new(nil, "courses", Course, fixture_path)
end
assert_equal "fixture key is not a hash: #{fixture_path}.yml, keys: [\"two\"]", error.to_s
end
@@ -525,7 +525,7 @@ class FixturesTest < ActiveRecord::TestCase
def test_omap_fixtures
assert_nothing_raised do
- fixtures = ActiveRecord::FixtureSet.new(Account.connection, "categories", Category, FIXTURES_ROOT + "/categories_ordered")
+ fixtures = ActiveRecord::FixtureSet.new(nil, "categories", Category, FIXTURES_ROOT + "/categories_ordered")
fixtures.each.with_index do |(name, fixture), i|
assert_equal "fixture_no_#{i}", name
@@ -596,7 +596,7 @@ class HasManyThroughFixture < ActiveRecord::TestCase
parrots = File.join FIXTURES_ROOT, "parrots"
- fs = ActiveRecord::FixtureSet.new parrot.connection, "parrots", parrot, parrots
+ fs = ActiveRecord::FixtureSet.new(nil, "parrots", parrot, parrots)
rows = fs.table_rows
assert_equal load_has_and_belongs_to_many["parrots_treasures"], rows["parrots_treasures"]
end
@@ -614,7 +614,7 @@ class HasManyThroughFixture < ActiveRecord::TestCase
parrots = File.join FIXTURES_ROOT, "parrots"
- fs = ActiveRecord::FixtureSet.new parrot.connection, "parrots", parrot, parrots
+ fs = ActiveRecord::FixtureSet.new(nil, "parrots", parrot, parrots)
rows = fs.table_rows
assert_equal load_has_and_belongs_to_many["parrots_treasures"], rows["parrot_treasures"]
end
@@ -629,7 +629,7 @@ class HasManyThroughFixture < ActiveRecord::TestCase
parrots = File.join FIXTURES_ROOT, "parrots"
- fs = ActiveRecord::FixtureSet.new parrot.connection, "parrots", parrot, parrots
+ fs = ActiveRecord::FixtureSet.new(nil, "parrots", parrot, parrots)
fs.table_rows
end
end
diff --git a/activerecord/test/cases/hot_compatibility_test.rb b/activerecord/test/cases/hot_compatibility_test.rb
index e7778af55b..7b388ebc5e 100644
--- a/activerecord/test/cases/hot_compatibility_test.rb
+++ b/activerecord/test/cases/hot_compatibility_test.rb
@@ -56,7 +56,7 @@ class HotCompatibilityTest < ActiveRecord::TestCase
assert_equal "bar", record.foo
end
- if current_adapter?(:PostgreSQLAdapter)
+ if current_adapter?(:PostgreSQLAdapter) && ActiveRecord::Base.connection.prepared_statements
test "cleans up after prepared statement failure in a transaction" do
with_two_connections do |original_connection, ddl_connection|
record = @klass.create! bar: "bar"
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 5d060c8899..661163b4a1 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -127,6 +127,36 @@ class MigrationTest < ActiveRecord::TestCase
assert_equal 20131219224947, migrator.current_version
end
+ def test_create_table_raises_if_already_exists
+ connection = Person.connection
+ connection.create_table :testings, force: true do |t|
+ t.string :foo
+ end
+
+ assert_raise(ActiveRecord::StatementInvalid) do
+ connection.create_table :testings do |t|
+ t.string :foo
+ end
+ end
+ ensure
+ connection.drop_table :testings, if_exists: true
+ end
+
+ def test_create_table_with_if_not_exists_true
+ connection = Person.connection
+ connection.create_table :testings, force: true do |t|
+ t.string :foo
+ end
+
+ assert_nothing_raised do
+ connection.create_table :testings, if_not_exists: true do |t|
+ t.string :foo
+ end
+ end
+ ensure
+ connection.drop_table :testings, if_exists: true
+ end
+
def test_create_table_with_force_true_does_not_drop_nonexisting_table
# using a copy as we need the drop_table method to
# continue to work for the ensure block of the test
diff --git a/activerecord/test/cases/numeric_data_test.rb b/activerecord/test/cases/numeric_data_test.rb
index 14db63890e..304714979c 100644
--- a/activerecord/test/cases/numeric_data_test.rb
+++ b/activerecord/test/cases/numeric_data_test.rb
@@ -25,7 +25,6 @@ class NumericDataTest < ActiveRecord::TestCase
assert m.save
m1 = NumericData.find(m.id)
- assert_not_nil m1
assert_kind_of Integer, m1.world_population
assert_equal 2**62, m1.world_population
@@ -50,7 +49,6 @@ class NumericDataTest < ActiveRecord::TestCase
assert m.save
m1 = NumericData.find(m.id)
- assert_not_nil m1
assert_kind_of Integer, m1.world_population
assert_equal 2**62, m1.world_population
@@ -64,4 +62,26 @@ class NumericDataTest < ActiveRecord::TestCase
assert_kind_of BigDecimal, m1.big_bank_balance
assert_equal BigDecimal("234000567.95"), m1.big_bank_balance
end
+
+ if current_adapter?(:PostgreSQLAdapter)
+ def test_numeric_fields_with_nan
+ m = NumericData.new(
+ bank_balance: BigDecimal("NaN"),
+ big_bank_balance: BigDecimal("NaN"),
+ world_population: 2**62,
+ my_house_population: 3
+ )
+ assert_predicate m.bank_balance, :nan?
+ assert_predicate m.big_bank_balance, :nan?
+ assert m.save
+
+ m1 = NumericData.find_by(
+ bank_balance: BigDecimal("NaN"),
+ big_bank_balance: BigDecimal("NaN")
+ )
+
+ assert_predicate m1.bank_balance, :nan?
+ assert_predicate m1.big_bank_balance, :nan?
+ end
+ end
end
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index c0be45eee7..aa6b7915a2 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -591,6 +591,17 @@ class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase
assert_equal [:before_commit, :after_commit], @topic.history
end
+ def test_commit_run_transactions_callbacks_with_nested_transactions
+ @topic.transaction do
+ @topic.transaction(requires_new: true) do
+ @topic.content = "foo"
+ @topic.save!
+ @topic.class.connection.add_transaction_record(@topic)
+ end
+ end
+ assert_equal [:before_commit, :after_commit], @topic.history
+ end
+
def test_rollback_does_not_run_transactions_callbacks_without_enrollment
@topic.transaction do
@topic.content = "foo"
diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb
index 4aad6a4498..03430154db 100644
--- a/activerecord/test/models/topic.rb
+++ b/activerecord/test/models/topic.rb
@@ -138,6 +138,10 @@ class BlankTopic < Topic
end
end
+class TitlePrimaryKeyTopic < Topic
+ self.primary_key = :title
+end
+
module Web
class Topic < ActiveRecord::Base
has_many :replies, dependent: :destroy, foreign_key: "parent_id", class_name: "Web::Reply"
diff --git a/activestorage/activestorage.gemspec b/activestorage/activestorage.gemspec
index cb1bb00a25..2c8816df25 100644
--- a/activestorage/activestorage.gemspec
+++ b/activestorage/activestorage.gemspec
@@ -25,6 +25,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/activestorage/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "actionpack", version
s.add_dependency "activerecord", version
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index aa695c98b2..448a2eeebb 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -27,6 +27,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/activesupport/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "i18n", ">= 0.7", "< 2"
s.add_dependency "tzinfo", "~> 1.1"
s.add_dependency "minitest", "~> 5.1"
diff --git a/activesupport/lib/active_support/testing/parallelization.rb b/activesupport/lib/active_support/testing/parallelization.rb
index c03a07873d..9c8dffa9d8 100644
--- a/activesupport/lib/active_support/testing/parallelization.rb
+++ b/activesupport/lib/active_support/testing/parallelization.rb
@@ -79,7 +79,14 @@ module ActiveSupport
reporter = job[2]
result = Minitest.run_one_method(klass, method)
- queue.record(reporter, result)
+ begin
+ queue.record(reporter, result)
+ rescue DRb::DRbConnError
+ result.failures.each do |failure|
+ failure.exception = DRb::DRbRemoteError.new(failure.exception)
+ end
+ queue.record(reporter, result)
+ end
end
ensure
run_cleanup(worker)
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index c98f24d786..0fda7c5cfd 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -538,7 +538,8 @@ end
If you want to be sure that an association is present, you'll need to test
whether the associated object itself is present, and not the foreign key used
-to map the association.
+to map the association. This way, it is not only checked that the foreign key
+is not empty but also that the referenced object exists.
```ruby
class LineItem < ApplicationRecord
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index ed47a0de0f..709a5146e9 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -324,6 +324,26 @@ $ cd actionmailer
$ bundle exec rake test
```
+#### For a Specific Directory
+
+If you want to run the tests located in a specific directory use the `TEST_DIR`
+environment variable. For example, this will run the tests in the
+`railties/test/generators` directory only:
+
+```bash
+$ cd railties
+$ TEST_DIR=generators bundle exec rake test
+```
+
+#### For a Specific File
+
+You can run the tests for a particular file by using:
+
+```bash
+$ cd actionpack
+$ bundle exec ruby -w -Itest test/template/form_helper_test.rb
+```
+
#### Running a Single Test
You can run a single test through ruby. For instance:
@@ -333,8 +353,7 @@ $ cd actionmailer
$ bundle exec ruby -w -Itest test/mail_layout_test.rb -n test_explicit_class_layout
```
-The `-n` option allows you to run a single method instead of the whole
-file.
+The `-n` option allows you to run a single method instead of the whole file.
#### Running tests with a specific seed
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index 7f7766e7d7..3a383cbd4d 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -232,7 +232,7 @@ irb(main):003:0> Article.pamplemousse
=> #<Comment id: 2, author: "1", body: "Well, actually...", article_id: 1, created_at: "2018-10-19 00:56:10", updated_at: "2018-10-19 00:56:10">
```
-Below each database statement you can see arrows pointing to the specific source filename (and line number) of the method that resulted in a database call. This can help you identity and address performance problems caused by N+1 queries: single database queries that generates multiple additional queries.
+Below each database statement you can see arrows pointing to the specific source filename (and line number) of the method that resulted in a database call. This can help you identify and address performance problems caused by N+1 queries: single database queries that generates multiple additional queries.
Verbose query logs are enabled by default in the development environment logs after Rails 5.2.
diff --git a/guides/source/development_dependencies_install.md b/guides/source/development_dependencies_install.md
index 07538a1cb7..d52946be08 100644
--- a/guides/source/development_dependencies_install.md
+++ b/guides/source/development_dependencies_install.md
@@ -8,8 +8,6 @@ This guide covers how to setup an environment for Ruby on Rails core development
After reading this guide, you will know:
* How to set up your machine for Rails development
-* How to run specific groups of unit tests from the Rails test suite
-* How the Active Record portion of the Rails test suite operates
--------------------------------------------------------------------------------
@@ -43,195 +41,131 @@ $ git clone https://github.com/rails/rails.git
$ cd rails
```
-### Set up and Run the Tests
+### Install Additional Tools and Services
-The test suite must pass with any submitted code. No matter whether you are writing a new patch, or evaluating someone else's, you need to be able to run the tests.
+Some Rails tests depend on additional tools that you need to install before running those specific tests.
-Install first SQLite3 and its development files for the `sqlite3` gem. On macOS
-users are done with:
+Here's the list of each gems' additional dependencies:
-```bash
-$ brew install sqlite3
-```
-
-In Ubuntu you're done with just:
-
-```bash
-$ sudo apt-get install sqlite3 libsqlite3-dev
-```
-
-If you are on Fedora or CentOS, you're done with
-
-```bash
-$ sudo yum install libsqlite3x libsqlite3x-devel
-```
-
-If you are on Arch Linux, you will need to run:
-
-```bash
-$ sudo pacman -S sqlite
-```
-
-For FreeBSD users, you're done with:
-
-```bash
-# pkg install sqlite3
-```
+* Action Cable depends on Redis
+* Active Record depends on SQLite3, MySQL and PostgreSQL
+* Active Storage depends on Yarn (additionally Yarn depends on
+ [Node.js](https://nodejs.org/)), ImageMagick, FFmpeg, muPDF, and on macOS
+ also XQuartz and Poppler.
+* Active Support depends on memcached and Redis
+* Railties depend on a JavaScript runtime environment, such as having
+ [Node.js](https://nodejs.org/) installed.
-Or compile the `databases/sqlite3` port.
+Install all the services you need to properly test the full gem you'll be
+making changes to.
-Get a recent version of [Bundler](https://bundler.io/)
+NOTE: Redis' documentation discourage installations with package managers as those are usually outdated. Installing from source and bringing the server up is straight forward and well documented on [Redis' documentation](https://redis.io/download#installation).
-```bash
-$ gem install bundler
-$ gem update bundler
-```
+NOTE: Active Record tests _must_ pass for at least MySQL, PostgreSQL, and SQLite3. Subtle differences between the various adapters have been behind the rejection of many patches that looked OK when tested only against single adapter.
-and run:
+Below you can find instructions on how to install all of the additional
+tools for different OSes.
-```bash
-$ bundle install --without db
-```
-
-This command will install all dependencies except the MySQL and PostgreSQL Ruby drivers. We will come back to these soon.
+#### macOS
-NOTE: If you would like to run the tests that use memcached, you need to ensure that you have it installed and running.
+On macOS you can use [Homebrew](https://brew.sh/) to install all of the
+additional tools.
-You can use [Homebrew](https://brew.sh/) to install memcached on macOS:
+To install all run:
```bash
-$ brew install memcached
+$ brew bundle
```
-On Ubuntu you can install it with apt-get:
+You'll also need to start each of the installed services. To list all
+available services run:
```bash
-$ sudo apt-get install memcached
+$ brew services list
```
-Or use yum on Fedora or CentOS:
+You can then start each of the services one by one like this:
```bash
-$ sudo yum install memcached
+$ brew services start mysql
```
-If you are running on Arch Linux:
-
-```bash
-$ sudo pacman -S memcached
-```
-
-For FreeBSD users, you're done with:
-
-```bash
-# pkg install memcached
-```
+Replace `mysql` with the name of the service you want to start.
-Alternatively, you can compile the `databases/memcached` port.
+#### Ubuntu
-With the dependencies now installed, you can run the test suite with:
+To install all run:
```bash
-$ bundle exec rake test
-```
-
-You can also run tests for a specific component, like Action Pack, by going into its directory and executing the same command:
+$ sudo apt-get update
+$ sudo apt-get install sqlite3 libsqlite3-dev
+ mysql-server libmysqlclient-dev
+ postgresql postgresql-client postgresql-contrib libpq-dev
+ redis-server memcached imagemagick ffmpeg mupdf mupdf-tools
-```bash
-$ cd actionpack
-$ bundle exec rake test
+# Install Yarn
+$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+$ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+$ sudo apt-get install yarn
```
-If you want to run the tests located in a specific directory use the `TEST_DIR` environment variable. For example, this will run the tests in the `railties/test/generators` directory only:
-
-```bash
-$ cd railties
-$ TEST_DIR=generators bundle exec rake test
-```
+#### Fedora or CentOS
-You can run the tests for a particular file by using:
+To install all run:
```bash
-$ cd actionpack
-$ bundle exec ruby -Itest test/template/form_helper_test.rb
-```
-
-Or, you can run a single test in a particular file:
+$ sudo dnf install sqlite-devel sqlite-libs
+ mysql-server mysql-devel
+ postgresql-server postgresql-devel
+ redis memcached imagemagick ffmpeg mupdf
-```bash
-$ cd actionpack
-$ bundle exec ruby -Itest path/to/test.rb -n test_name
+# Install Yarn
+# Use this command if you do not have Node.js installed
+$ curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
+# If you have Node.js installed, use this command instead
+$ curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
+$ sudo dnf install yarn
```
-### Railties Setup
-
-Some Railties tests depend on a JavaScript runtime environment, such as having [Node.js](https://nodejs.org/) installed.
-
-### Active Record Setup
-
-Active Record's test suite runs three times: once for SQLite3, once for MySQL, and once for PostgreSQL. We are going to see now how to set up the environment for them.
-
-WARNING: If you're working with Active Record code, you _must_ ensure that the tests pass for at least MySQL, PostgreSQL, and SQLite3. Subtle differences between the various adapters have been behind the rejection of many patches that looked OK when tested only against MySQL.
-
-#### Database Configuration
-
-The Active Record test suite requires a custom config file: `activerecord/test/config.yml`. An example is provided in `activerecord/test/config.example.yml` which can be copied and used as needed for your environment.
+#### Arch Linux
-#### MySQL and PostgreSQL
-
-To be able to run the suite for MySQL and PostgreSQL we need their gems. Install
-first the servers, their client libraries, and their development files.
-
-On macOS, you can run:
-
-```bash
-$ brew install mysql
-$ brew install postgresql
-```
-
-Follow the instructions given by Homebrew to start these.
-
-On Ubuntu, just run:
-
-```bash
-$ sudo apt-get install mysql-server libmysqlclient-dev
-$ sudo apt-get install postgresql postgresql-client postgresql-contrib libpq-dev
-```
-
-On Fedora or CentOS, just run:
+To install all run:
```bash
-$ sudo yum install mysql-server mysql-devel
-$ sudo yum install postgresql-server postgresql-devel
+$ sudo pacman -S sqlite
+ mariadb libmariadbclient mariadb-clients
+ postgresql postgresql-libs
+ redis memcached imagemagick ffmpeg mupdf mupdf-tools poppler
+ yarn
+$ sudo systemctl start redis
```
-If you are running Arch Linux, MySQL isn't supported anymore so you will need to
-use MariaDB instead (see [this announcement](https://www.archlinux.org/news/mariadb-replaces-mysql-in-repositories/)):
+NOTE: If you are running Arch Linux, MySQL isn't supported anymore so you will need to
+use MariaDB instead (see [this announcement](https://www.archlinux.org/news/mariadb-replaces-mysql-in-repositories/)).
-```bash
-$ sudo pacman -S mariadb libmariadbclient mariadb-clients
-$ sudo pacman -S postgresql postgresql-libs
-```
+#### FreeBSD
-FreeBSD users will have to run the following:
+To install all run:
```bash
-# pkg install mysql56-client mysql56-server
-# pkg install postgresql94-client postgresql94-server
+# pkg install sqlite3
+ mysql80-client mysql80-server
+ postgresql11-client postgresql11-server
+ memcached imagemagick ffmpeg mupdf
+ yarn
+# portmaster databases/redis
```
-Or install them through ports (they are located under the `databases` folder).
-If you run into troubles during the installation of MySQL, please see
-[the MySQL documentation](http://dev.mysql.com/doc/refman/5.1/en/freebsd-installation.html).
+Or install everyting through ports (these packages are located under the
+`databases` folder).
-After that, run:
+NOTE: If you run into troubles during the installation of MySQL, please see
+[the MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/freebsd-installation.html).
-```bash
-$ rm .bundle/config
-$ bundle install
-```
+### Database Configuration
-First, we need to delete `.bundle/config` because Bundler remembers in that file that we didn't want to install the "db" group (alternatively you can edit the file).
+There are couple of additional steps required to configure database engines
+required for running Active Record tests.
In order to be able to run the test suite against MySQL you need to create a user named `rails` with privileges on the test databases:
@@ -247,13 +181,6 @@ mysql> GRANT ALL PRIVILEGES ON inexistent_activerecord_unittest.*
to 'rails'@'localhost';
```
-and create the test databases:
-
-```bash
-$ cd activerecord
-$ bundle exec rake db:mysql:build
-```
-
PostgreSQL's authentication works differently. To setup the development environment
with your development account, on Linux or BSD, you just have to run:
@@ -267,21 +194,24 @@ and for macOS:
$ createuser --superuser $USER
```
-Then, you need to create the test databases with:
+Then, you need to create the test databases for both MySQL and PostgreSQL with:
```bash
$ cd activerecord
-$ bundle exec rake db:postgresql:build
+$ bundle exec rake db:create
```
-It is possible to build databases for both PostgreSQL and MySQL with:
+NOTE: You'll see the following warning (or localized warning) during activating HStore extension in PostgreSQL 9.1.x or earlier: "WARNING: => is deprecated as an operator".
+
+You can also create test databases for each database engine separately:
```bash
$ cd activerecord
-$ bundle exec rake db:create
+$ bundle exec rake db:mysql:build
+$ bundle exec rake db:postgresql:build
```
-You can cleanup the databases using:
+and you can drop the databases using:
```bash
$ cd activerecord
@@ -290,138 +220,40 @@ $ bundle exec rake db:drop
NOTE: Using the Rake task to create the test databases ensures they have the correct character set and collation.
-NOTE: You'll see the following warning (or localized warning) during activating HStore extension in PostgreSQL 9.1.x or earlier: "WARNING: => is deprecated as an operator".
-
If you're using another database, check the file `activerecord/test/config.yml` or `activerecord/test/config.example.yml` for default connection information. You can edit `activerecord/test/config.yml` to provide different credentials on your machine if you must, but obviously you should not push any such changes back to Rails.
-### Action Cable Setup
-
-Action Cable uses Redis as its default subscriptions adapter ([read more](action_cable_overview.html#broadcasting)). Thus, in order to have Action Cable's tests passing you need to install and have Redis running.
-
-#### Install Redis From Source
+### Install JavaScript dependencies
-Redis' documentation discourage installations with package managers as those are usually outdated. Installing from source and bringing the server up is straight forward and well documented on [Redis' documentation](https://redis.io/download#installation).
-
-#### Install Redis From Package Manager
-
-On macOS, you can run:
-
-```bash
-$ brew install redis
-```
-
-Follow the instructions given by Homebrew to start these.
-
-On Ubuntu, just run:
-
-```bash
-$ sudo apt-get install redis-server
-```
-
-On Fedora or CentOS (requires EPEL enabled), just run:
-
-```bash
-$ sudo yum install redis
-```
-
-If you are running Arch Linux, just run:
-
-```bash
-$ sudo pacman -S redis
-$ sudo systemctl start redis
-```
-
-FreeBSD users will have to run the following:
-
-```bash
-# portmaster databases/redis
-```
-
-### Active Storage Setup
-
-When working on Active Storage, it is important to note that you need to
-install its JavaScript dependencies while working on that section of the
-codebase. In order to install these dependencies, it is necessary to
-have Yarn, a Node.js package manager, available on your system. A
-prerequisite for installing this package manager is that
-[Node.js](https://nodejs.org) is installed.
-
-
-On macOS, you can run:
-
-```bash
-$ brew install yarn
-```
-
-On Ubuntu, you can run:
-
-```bash
-$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-$ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-
-$ sudo apt-get update && sudo apt-get install yarn
-```
-
-On Fedora or CentOS, just run:
-
-```bash
-$ sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
-
-$ sudo yum install yarn
-```
-
-Finally, after installing Yarn, you will need to run the following
-command inside of the `activestorage` directory to install the dependencies:
+If you installed Yarn, you will need to install the javascript dependencies:
```bash
+$ cd activestorage
$ yarn install
```
-Extracting previews, tested in Active Storage's test suite requires third-party
-applications, ImageMagick for images, FFmpeg for video and muPDF for PDFs, and on macOS also XQuartz
-and Poppler. Without these applications installed, Active Storage tests will
-raise errors.
+### Install Bundler gem
-On macOS you can run:
+Get a recent version of [Bundler](https://bundler.io/)
```bash
-$ brew install ffmpeg
-$ brew install imagemagick
-$ brew cask install xquartz
-$ brew install mupdf-tools
-$ brew install poppler
+$ gem install bundler
+$ gem update bundler
```
-On Ubuntu, you can run:
+and run:
```bash
-$ sudo apt-get update
-$ sudo apt-get install ffmpeg
-$ sudo apt-get install imagemagick
-$ sudo apt-get install mupdf mupdf-tools
+$ bundle install
```
-On Fedora or CentOS, just run:
+or:
```bash
-$ sudo yum install ffmpeg
-$ sudo yum install imagemagick
-$ sudo yum install mupdf
+$ bundle install --without db
```
-FreeBSD users can just run:
+if you don't need to run Active Record tests.
-```bash
-# pkg install imagemagick
-# pkg install ffmpeg
-# pkg install mupdf
-```
-
-On Arch Linux, you can run:
+### Contribute to Rails
-```bash
-$ sudo pacman -S ffmpeg
-$ sudo pacman -S imagemagick
-$ sudo pacman -S mupdf mupdf-tools
-$ sudo pacman -S poppler
-```
+After you've setup everything, read how you can start [contributing](contributing_to_ruby_on_rails.html#running-an-application-against-your-local-branch).
diff --git a/guides/source/ruby_on_rails_guides_guidelines.md b/guides/source/ruby_on_rails_guides_guidelines.md
index f5c0ba5b2d..4b56cf6296 100644
--- a/guides/source/ruby_on_rails_guides_guidelines.md
+++ b/guides/source/ruby_on_rails_guides_guidelines.md
@@ -107,8 +107,8 @@ HTML Guides
-----------
Before generating the guides, make sure that you have the latest version of
-Bundler installed on your system. As of this writing, you must install Bundler
-1.3.5 or later on your device.
+Bundler installed on your system. You can find the latest Bundler version
+[here](https://rubygems.org/gems/bundler). As of this writing, it's v1.17.1.
To install the latest version of Bundler, run `gem install bundler`.
diff --git a/guides/source/security.md b/guides/source/security.md
index bb996cc39c..dbec3cdd2d 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -1235,6 +1235,11 @@ version:
Rails.application.credentials.some_api_key! # => raises KeyError: :some_api_key is blank
```
+Dependency Management and CVEs
+------------------------------
+
+We don’t bump dependencies just to encourage use of new versions, including for security issues. This is because application owners need to manually update their gems regardless of our efforts. Use `bundle update --conservative gem_name` to safely update vulnerable dependencies.
+
Additional Resources
--------------------
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index f94b67a0ac..65dccbb3be 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,9 @@
+* Add JSON support to rails properties route (`/rails/info/properties`).
+
+ Now, `Rails::Info` properties may be accessed in JSON format at `/rails/info/properties.json`.
+
+ *Yoshiyuki Hirano*
+
* Use Ids instead of memory addresses when displaying references in scaffold views.
Fixes #29200.
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt
index d3bcaa5ec8..c517b0f96b 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt
@@ -11,6 +11,10 @@
# policy.object_src :none
# policy.script_src :self, :https
# policy.style_src :self, :https
+<%- unless options[:skip_javascript] -%>
+# # If you are using webpack-dev-server then specify webpack-dev-server host
+# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
+<%- end -%>
# # Specify URI for violation reports
# # policy.report_uri "/csp-violation-report-endpoint"
diff --git a/railties/lib/rails/generators/rails/app/templates/package.json.tt b/railties/lib/rails/generators/rails/app/templates/package.json.tt
index a654cba39c..7174116989 100644
--- a/railties/lib/rails/generators/rails/app/templates/package.json.tt
+++ b/railties/lib/rails/generators/rails/app/templates/package.json.tt
@@ -5,7 +5,7 @@
"rails-ujs": ">=5.2.1"<% unless options[:skip_turbolinks] %>,
"turbolinks": "5.1.1"<% end -%><% unless skip_active_storage? %>,
"activestorage": ">=5.2.1"<% end -%><% unless options[:skip_action_cable] %>,
- "actioncable": ">=5.2.1"<% end -%>
+ "actioncable": ">=5.2.1"<% end %>
},
"version": "0.1.0"
}
diff --git a/railties/lib/rails/info.rb b/railties/lib/rails/info.rb
index 3df36efc4c..b8173c8d11 100644
--- a/railties/lib/rails/info.rb
+++ b/railties/lib/rails/info.rb
@@ -54,6 +54,10 @@ module Rails
table << "</table>"
end
end
+
+ def to_json
+ Hash[properties].to_json
+ end
end
# The Rails version.
diff --git a/railties/lib/rails/info_controller.rb b/railties/lib/rails/info_controller.rb
index b4f4a5922a..50fe176946 100644
--- a/railties/lib/rails/info_controller.rb
+++ b/railties/lib/rails/info_controller.rb
@@ -14,8 +14,16 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
end
def properties
- @info = Rails::Info.to_html
- @page_title = "Properties"
+ respond_to do |format|
+ format.html do
+ @info = Rails::Info.to_html
+ @page_title = "Properties"
+ end
+
+ format.json do
+ render json: Rails::Info.to_json
+ end
+ end
end
def routes
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index 6fdb4648c2..4e4a504c97 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -30,6 +30,9 @@ Gem::Specification.new do |s|
"changelog_uri" => "https://github.com/rails/rails/blob/v#{version}/railties/CHANGELOG.md"
}
+ # NOTE: Please read our dependency guidelines before updating versions:
+ # https://edgeguides.rubyonrails.org/security.html#dependency-management-and-cves
+
s.add_dependency "activesupport", version
s.add_dependency "actionpack", version
diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb
index 6478e06250..ef99365e75 100644
--- a/railties/test/application/rake/multi_dbs_test.rb
+++ b/railties/test/application/rake/multi_dbs_test.rb
@@ -65,6 +65,27 @@ module ApplicationTests
end
end
+ def db_migrate_and_schema_cache_dump
+ Dir.chdir(app_path) do
+ generate_models_for_animals
+ rails "db:migrate"
+ rails "db:schema:cache:dump"
+ assert File.exist?("db/schema_cache.yml")
+ assert File.exist?("db/animals_schema_cache.yml")
+ end
+ end
+
+ def db_migrate_and_schema_cache_dump_and_schema_cache_clear
+ Dir.chdir(app_path) do
+ generate_models_for_animals
+ rails "db:migrate"
+ rails "db:schema:cache:dump"
+ rails "db:schema:cache:clear"
+ assert_not File.exist?("db/schema_cache.yml")
+ assert_not File.exist?("db/animals_schema_cache.yml")
+ end
+ end
+
def db_migrate_and_schema_dump_and_load(format)
Dir.chdir(app_path) do
generate_models_for_animals
@@ -92,7 +113,7 @@ module ApplicationTests
end
end
- def db_migrate_namespaced(namespace, expected_database)
+ def db_migrate_namespaced(namespace)
Dir.chdir(app_path) do
generate_models_for_animals
output = rails("db:migrate:#{namespace}")
@@ -104,7 +125,7 @@ module ApplicationTests
end
end
- def db_migrate_status_namespaced(namespace, expected_database)
+ def db_migrate_status_namespaced(namespace)
Dir.chdir(app_path) do
generate_models_for_animals
output = rails("db:migrate:status:#{namespace}")
@@ -178,7 +199,7 @@ module ApplicationTests
test "db:migrate:namespace works" do
require "#{app_path}/config/environment"
ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
- db_migrate_namespaced db_config.spec_name, db_config.config["database"]
+ db_migrate_namespaced db_config.spec_name
end
end
@@ -190,10 +211,20 @@ module ApplicationTests
test "db:migrate:status:namespace works" do
require "#{app_path}/config/environment"
ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
- db_migrate_namespaced db_config.spec_name, db_config.config["database"]
- db_migrate_status_namespaced db_config.spec_name, db_config.config["database"]
+ db_migrate_namespaced db_config.spec_name
+ db_migrate_status_namespaced db_config.spec_name
end
end
+
+ test "db:schema:cache:dump works on all databases" do
+ require "#{app_path}/config/environment"
+ db_migrate_and_schema_cache_dump
+ end
+
+ test "db:schema:cache:clear works on all databases" do
+ require "#{app_path}/config/environment"
+ db_migrate_and_schema_cache_dump_and_schema_cache_clear
+ end
end
end
end
diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb
index a0cdae898b..c38b91ef03 100644
--- a/railties/test/application/rake_test.rb
+++ b/railties/test/application/rake_test.rb
@@ -189,8 +189,10 @@ module ApplicationTests
rails "generate", "model", "Product"
rails "generate", "model", "Cart"
rails "generate", "scaffold", "LineItems", "product:references", "cart:belongs_to"
- with_rails_env("test") { rails("db:migrate") }
- rails("webpacker:compile")
+ with_rails_env("test") do
+ rails("db:migrate")
+ rails("webpacker:compile")
+ end
output = rails("test")
assert_match(/7 runs, 9 assertions, 0 failures, 0 errors/, output)
diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb
index 5c34b205c9..0046fec062 100644
--- a/railties/test/application/test_runner_test.rb
+++ b/railties/test/application/test_runner_test.rb
@@ -562,6 +562,30 @@ module ApplicationTests
assert_no_match "create_table(:users)", output
end
+ def test_run_in_parallel_with_unmarshable_exception
+ file = app_file "test/fail_test.rb", <<-RUBY
+ require "test_helper"
+ class FailTest < ActiveSupport::TestCase
+ class BadError < StandardError
+ def initialize
+ super
+ @proc = ->{ }
+ end
+ end
+
+ test "fail" do
+ raise BadError
+ assert true
+ end
+ end
+ RUBY
+
+ output = run_test_command(file)
+
+ assert_match "DRb::DRbRemoteError: FailTest::BadError", output
+ assert_match "1 runs, 0 assertions, 0 failures, 1 errors", output
+ end
+
def test_raise_error_when_specified_file_does_not_exist
error = capture(:stderr) { run_test_command("test/not_exists.rb", stderr: true) }
assert_match(%r{cannot load such file.+test/not_exists\.rb}, error)
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index bb3aaa9d14..32d00f3157 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -230,6 +230,14 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_equal "false\n", output
end
+ def test_csp_initializer_include_connect_src_example
+ run_generator
+
+ assert_file "config/initializers/content_security_policy.rb" do |content|
+ assert_match(/# policy\.connect_src/, content)
+ end
+ end
+
def test_app_update_keep_the_cookie_serializer_if_it_is_already_configured
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
@@ -807,6 +815,9 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
assert_no_gem "webpacker"
+ assert_file "config/initializers/content_security_policy.rb" do |content|
+ assert_no_match(/policy\.connect_src/, content)
+ end
end
def test_webpack_option_with_js_framework
diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb
index 878a238f8d..6ab68f8333 100644
--- a/railties/test/rails_info_controller_test.rb
+++ b/railties/test/rails_info_controller_test.rb
@@ -50,6 +50,11 @@ class InfoControllerTest < ActionController::TestCase
assert_select "table"
end
+ test "info controller renders json with properties" do
+ get :properties, format: :json
+ assert_equal Rails::Info.to_json, response.body
+ end
+
test "info controller renders with routes" do
get :routes
assert_response :success
diff --git a/railties/test/rails_info_test.rb b/railties/test/rails_info_test.rb
index 50522c1be6..d167a86e56 100644
--- a/railties/test/rails_info_test.rb
+++ b/railties/test/rails_info_test.rb
@@ -43,6 +43,18 @@ class InfoTest < ActiveSupport::TestCase
end
end
+ def test_json_includes_middleware
+ Rails::Info.module_eval do
+ property "Middleware", ["Rack::Lock", "Rack::Static"]
+ end
+
+ hash = JSON.parse(Rails::Info.to_json)
+ assert_includes hash.keys, "Middleware"
+ properties.value_for("Middleware").each do |value|
+ assert_includes hash["Middleware"], value
+ end
+ end
+
private
def properties
Rails::Info.properties