aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml25
-rw-r--r--actionpack/lib/action_controller/metal/flash.rb8
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb20
-rw-r--r--actionpack/test/controller/flash_test.rb9
-rw-r--r--activerecord/CHANGELOG.md12
-rw-r--r--activerecord/lib/active_record/associations.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb19
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb13
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb36
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb19
-rw-r--r--activestorage/CHANGELOG.md4
-rw-r--r--activestorage/config/routes.rb25
-rw-r--r--activestorage/lib/active_storage.rb1
-rw-r--r--activestorage/lib/active_storage/engine.rb1
-rw-r--r--guides/source/configuring.md10
-rw-r--r--railties/lib/rails/generators/app_base.rb2
-rw-r--r--railties/test/application/configuration_test.rb18
-rw-r--r--railties/test/generators/app_generator_test.rb2
19 files changed, 176 insertions, 51 deletions
diff --git a/.travis.yml b/.travis.yml
index c18a24bea7..6943a67ffe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -40,9 +40,6 @@ before_install:
- "[[ $GEM != 'av:ujs' ]] || nvm install node"
- "[[ $GEM != 'av:ujs' ]] || node --version"
- "[[ $GEM != 'av:ujs' ]] || (cd actionview && npm install)"
- - "[[ $GEM != 'ar:mysql2' ]] || [[ $MYSQL == 'mariadb' ]] || sudo mysql -e \"use mysql; update user set authentication_string='' where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;\""
- - "[[ $GEM != 'ar:mysql2' ]] || [[ $MYSQL == 'mariadb' ]] || sudo mysql_upgrade"
- - "[[ $GEM != 'ar:mysql2' ]] || [[ $MYSQL == 'mariadb' ]] || sudo service mysql restart"
before_script:
# Set Sauce Labs username and access key. Obfuscated, purposefully not encrypted.
@@ -60,7 +57,6 @@ env:
- "GEM=ap,ac"
- "GEM=am,amo,as,av,aj,ast"
- "GEM=as PRESERVE_TIMEZONES=1"
- - "GEM=ar:mysql2"
- "GEM=ar:sqlite3"
- "GEM=ar:postgresql"
- "GEM=guides"
@@ -93,6 +89,27 @@ matrix:
- memcached
- redis-server
- rabbitmq
+ - rvm: 2.4.4
+ env: "GEM=ar:mysql2"
+ sudo: required
+ before_install:
+ - "sudo mysql -e \"use mysql; update user set authentication_string='' where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;\""
+ - "sudo mysql_upgrade"
+ - "sudo service mysql restart"
+ - rvm: 2.5.1
+ env: "GEM=ar:mysql2"
+ sudo: required
+ before_install:
+ - "sudo mysql -e \"use mysql; update user set authentication_string='' where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;\""
+ - "sudo mysql_upgrade"
+ - "sudo service mysql restart"
+ - rvm: ruby-head
+ env: "GEM=ar:mysql2"
+ sudo: required
+ before_install:
+ - "sudo mysql -e \"use mysql; update user set authentication_string='' where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;\""
+ - "sudo mysql_upgrade"
+ - "sudo service mysql restart"
- rvm: 2.5.1
env:
- "GEM=ar:mysql2 MYSQL=mariadb"
diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb
index 1ecee811fb..380f2e9591 100644
--- a/actionpack/lib/action_controller/metal/flash.rb
+++ b/actionpack/lib/action_controller/metal/flash.rb
@@ -33,12 +33,10 @@ module ActionController #:nodoc:
types.each do |type|
next if _flash_types.include?(type)
- if respond_to? :helper_method
- define_method(type) do
- request.flash[type]
- end
- helper_method type
+ define_method(type) do
+ request.flash[type]
end
+ helper_method(type) if respond_to?(:helper_method)
self._flash_types += [type]
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 7e50cb6d23..885dc0ecba 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -224,16 +224,6 @@ module ActionDispatch # :nodoc:
@status = Rack::Utils.status_code(status)
end
- # Sets the HTTP content type.
- def content_type=(content_type)
- return unless content_type
- new_header_info = parse_content_type(content_type.to_s)
- prev_header_info = parsed_content_type_header
- charset = new_header_info.charset || prev_header_info.charset
- charset ||= self.class.default_charset unless prev_header_info.mime_type
- set_content_type new_header_info.mime_type, charset
- end
-
# Sets the HTTP response's content MIME type. For example, in the controller
# you could write this:
#
@@ -242,7 +232,17 @@ module ActionDispatch # :nodoc:
# If a character set has been defined for this response (see charset=) then
# the character set information will also be included in the content type
# information.
+ def content_type=(content_type)
+ return unless content_type
+ new_header_info = parse_content_type(content_type.to_s)
+ prev_header_info = parsed_content_type_header
+ charset = new_header_info.charset || prev_header_info.charset
+ charset ||= self.class.default_charset unless prev_header_info.mime_type
+ set_content_type new_header_info.mime_type, charset
+ end
+ # Content type of response.
+ # It returns just MIME type and does NOT contain charset part.
def content_type
parsed_content_type_header.mime_type
end
diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb
index a4330897cf..409a4ec2e6 100644
--- a/actionpack/test/controller/flash_test.rb
+++ b/actionpack/test/controller/flash_test.rb
@@ -343,11 +343,18 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest
end
def test_flash_usable_in_metal_without_helper
+ controller_class = nil
+
assert_nothing_raised do
- Class.new ActionController::Metal do
+ controller_class = Class.new(ActionController::Metal) do
include ActionController::Flash
end
end
+
+ controller = controller_class.new
+
+ assert_respond_to controller, :alert
+ assert_respond_to controller, :notice
end
private
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index bfdc978005..477bc1b54a 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,15 @@
+* SQLite3 adapter supports expression indexes.
+
+ ```
+ create_table :users do |t|
+ t.string :email
+ end
+
+ add_index :users, 'lower(email)', name: 'index_users_on_email', unique: true
+ ```
+
+ *Gray Kemmey*
+
* Allow subclasses to redefine autosave callbacks for associated records.
Fixes #33305.
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 1ee52945ea..70b2ca7d7e 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1524,6 +1524,7 @@ module ActiveRecord
# Returns the associated object. +nil+ is returned if none is found.
# [association=(associate)]
# Assigns the associate object, extracts the primary key, and sets it as the foreign key.
+ # No modification or deletion of existing records takes place.
# [build_association(attributes = {})]
# Returns a new object of the associated type that has been instantiated
# with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index 92f15de219..10c8c8e8ab 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -3,7 +3,7 @@
require "active_record/connection_adapters/abstract_mysql_adapter"
require "active_record/connection_adapters/mysql/database_statements"
-gem "mysql2", ">= 0.4.4", "< 0.6.0"
+gem "mysql2", ">= 0.4.4"
require "mysql2"
module ActiveRecord
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb
index 24e7bc65fa..46ca7e07a9 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements.rb
@@ -21,19 +21,24 @@ module ActiveRecord
WHERE name = #{quote(row['name'])} AND type = 'index'
SQL
- /\sWHERE\s+(?<where>.+)$/i =~ index_sql
+ /\bON\b\s*"?(\w+?)"?\s*\((?<expressions>.+?)\)(?:\s*WHERE\b\s*(?<where>.+))?\z/i =~ index_sql
columns = exec_query("PRAGMA index_info(#{quote(row['name'])})", "SCHEMA").map do |col|
col["name"]
end
- # Add info on sort order for columns (only desc order is explicitly specified, asc is
- # the default)
orders = {}
- if index_sql # index_sql can be null in case of primary key indexes
- index_sql.scan(/"(\w+)" DESC/).flatten.each { |order_column|
- orders[order_column] = :desc
- }
+
+ if columns.any?(&:nil?) # index created with an expression
+ columns = expressions
+ else
+ # Add info on sort order for columns (only desc order is explicitly specified,
+ # asc is the default)
+ if index_sql # index_sql can be null in case of primary key indexes
+ index_sql.scan(/"(\w+)" DESC/).flatten.each { |order_column|
+ orders[order_column] = :desc
+ }
+ end
end
IndexDefinition.new(
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index efe454fa7f..d32fd5ea09 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -125,6 +125,10 @@ module ActiveRecord
true
end
+ def supports_expression_index?
+ sqlite_version >= "3.9.0"
+ end
+
def requires_reloading?
true
end
@@ -483,9 +487,12 @@ module ActiveRecord
name = name[1..-1]
end
- to_column_names = columns(to).map(&:name)
- columns = index.columns.map { |c| rename[c] || c }.select do |column|
- to_column_names.include?(column)
+ columns = index.columns
+ if columns.is_a?(Array)
+ to_column_names = columns(to).map(&:name)
+ columns = columns.map { |c| rename[c] || c }.select do |column|
+ to_column_names.include?(column)
+ end
end
unless columns.empty?
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index d1d4d545a3..7b73621ed9 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -345,6 +345,42 @@ module ActiveRecord
end
end
+ if ActiveRecord::Base.connection.supports_expression_index?
+ def test_expression_index
+ with_example_table do
+ @conn.add_index "ex", "max(id, number)", name: "expression"
+ index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
+ assert_equal "max(id, number)", index.columns
+ end
+ end
+
+ def test_expression_index_with_where
+ with_example_table do
+ @conn.add_index "ex", "id % 10, max(id, number)", name: "expression", where: "id > 1000"
+ index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
+ assert_equal "id % 10, max(id, number)", index.columns
+ assert_equal "id > 1000", index.where
+ end
+ end
+
+ def test_complicated_expression
+ with_example_table do
+ @conn.execute "CREATE INDEX expression ON ex (id % 10, (CASE WHEN number > 0 THEN max(id, number) END))WHERE(id > 1000)"
+ index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
+ assert_equal "id % 10, (CASE WHEN number > 0 THEN max(id, number) END)", index.columns
+ assert_equal "(id > 1000)", index.where
+ end
+ end
+
+ def test_not_everything_an_expression
+ with_example_table do
+ @conn.add_index "ex", "id, max(id, number)", name: "expression"
+ index = @conn.indexes("ex").find { |idx| idx.name == "expression" }
+ assert_equal "id, max(id, number)", index.columns
+ end
+ end
+ end
+
def test_primary_key
with_example_table do
assert_equal "id", @conn.primary_key("ex")
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 75b68b521c..db13f20a39 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -226,6 +226,20 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{t\.float\s+"temperature"$}, output
end
+ if ActiveRecord::Base.connection.supports_expression_index?
+ def test_schema_dump_expression_indices
+ index_definition = dump_table_schema("companies").split(/\n/).grep(/t\.index.*company_expression_index/).first.strip
+
+ if current_adapter?(:PostgreSQLAdapter)
+ assert_match %r{CASE.+lower\(\(name\)::text\)}i, index_definition
+ elsif current_adapter?(:SQLite3Adapter)
+ assert_match %r{CASE.+lower\(name\)}i, index_definition
+ else
+ assert false
+ end
+ end
+ end
+
if current_adapter?(:Mysql2Adapter)
def test_schema_dump_includes_length_for_mysql_binary_fields
output = standard_dump
@@ -278,11 +292,6 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{t\.decimal\s+"decimal_array_default",\s+default: \["1.23", "3.45"\],\s+array: true}, output
end
- def test_schema_dump_expression_indices
- index_definition = dump_table_schema("companies").split(/\n/).grep(/t\.index.*company_expression_index/).first.strip
- assert_match %r{CASE.+lower\(\(name\)::text\)}i, index_definition
- end
-
def test_schema_dump_interval_type
output = dump_table_schema "postgresql_times"
assert_match %r{t\.interval\s+"time_interval"$}, output
diff --git a/activestorage/CHANGELOG.md b/activestorage/CHANGELOG.md
index 92e300a440..f4e2826dc6 100644
--- a/activestorage/CHANGELOG.md
+++ b/activestorage/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Add `ActiveStorage.routes_prefix` for configuring generated routes.
+
+ *Chris Bisnett*
+
* `ActiveStorage::Service::AzureStorageService` only handles specifically
relevant types of `Azure::Core::Http::HTTPError`. It previously obscured
other types of `HTTPError`, which is the azure-storage gem’s catch-all
diff --git a/activestorage/config/routes.rb b/activestorage/config/routes.rb
index 20d19f334a..3af7361cff 100644
--- a/activestorage/config/routes.rb
+++ b/activestorage/config/routes.rb
@@ -1,17 +1,15 @@
# frozen_string_literal: true
Rails.application.routes.draw do
- get "/rails/active_storage/blobs/:signed_id/*filename" => "active_storage/blobs#show", as: :rails_service_blob
-
- direct :rails_blob do |blob, options|
- route_for(:rails_service_blob, blob.signed_id, blob.filename, options)
- end
-
- resolve("ActiveStorage::Blob") { |blob, options| route_for(:rails_blob, blob, options) }
- resolve("ActiveStorage::Attachment") { |attachment, options| route_for(:rails_blob, attachment.blob, options) }
+ scope ActiveStorage.routes_prefix do
+ get "/blobs/:signed_id/*filename" => "active_storage/blobs#show", as: :rails_service_blob
+ get "/representations/:signed_blob_id/:variation_key/*filename" => "active_storage/representations#show", as: :rails_blob_representation
- get "/rails/active_storage/representations/:signed_blob_id/:variation_key/*filename" => "active_storage/representations#show", as: :rails_blob_representation
+ get "/disk/:encoded_key/*filename" => "active_storage/disk#show", as: :rails_disk_service
+ put "/disk/:encoded_token" => "active_storage/disk#update", as: :update_rails_disk_service
+ post "/direct_uploads" => "active_storage/direct_uploads#create", as: :rails_direct_uploads
+ end
direct :rails_representation do |representation, options|
signed_blob_id = representation.blob.signed_id
@@ -25,7 +23,10 @@ Rails.application.routes.draw do
resolve("ActiveStorage::Preview") { |preview, options| route_for(:rails_representation, preview, options) }
- get "/rails/active_storage/disk/:encoded_key/*filename" => "active_storage/disk#show", as: :rails_disk_service
- put "/rails/active_storage/disk/:encoded_token" => "active_storage/disk#update", as: :update_rails_disk_service
- post "/rails/active_storage/direct_uploads" => "active_storage/direct_uploads#create", as: :rails_direct_uploads
+ direct :rails_blob do |blob, options|
+ route_for(:rails_service_blob, blob.signed_id, blob.filename, options)
+ end
+
+ resolve("ActiveStorage::Blob") { |blob, options| route_for(:rails_blob, blob, options) }
+ resolve("ActiveStorage::Attachment") { |attachment, options| route_for(:rails_blob, attachment.blob, options) }
end
diff --git a/activestorage/lib/active_storage.rb b/activestorage/lib/active_storage.rb
index d3e3a2f49b..a94ef626f2 100644
--- a/activestorage/lib/active_storage.rb
+++ b/activestorage/lib/active_storage.rb
@@ -50,6 +50,7 @@ module ActiveStorage
mattr_accessor :variable_content_types, default: []
mattr_accessor :content_types_to_serve_as_binary, default: []
mattr_accessor :service_urls_expire_in, default: 5.minutes
+ mattr_accessor :routes_prefix, default: "/rails/active_storage"
module Transformers
extend ActiveSupport::Autoload
diff --git a/activestorage/lib/active_storage/engine.rb b/activestorage/lib/active_storage/engine.rb
index 9d6a27eabe..7eb93b5e16 100644
--- a/activestorage/lib/active_storage/engine.rb
+++ b/activestorage/lib/active_storage/engine.rb
@@ -51,6 +51,7 @@ module ActiveStorage
ActiveStorage.previewers = app.config.active_storage.previewers || []
ActiveStorage.analyzers = app.config.active_storage.analyzers || []
ActiveStorage.paths = app.config.active_storage.paths || {}
+ ActiveStorage.routes_prefix = app.config.active_storage.routes_prefix || "/rails/active_storage"
ActiveStorage.variable_content_types = app.config.active_storage.variable_content_types || []
ActiveStorage.content_types_to_serve_as_binary = app.config.active_storage.content_types_to_serve_as_binary || []
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 4c508f77f1..e372b3a816 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -69,7 +69,7 @@ These configuration methods are to be called on a `Rails::Railtie` object, such
* `config.beginning_of_week` sets the default beginning of week for the
application. Accepts a valid week day symbol (e.g. `:monday`).
-* `config.cache_store` configures which cache store to use for Rails caching. Options include one of the symbols `:memory_store`, `:file_store`, `:mem_cache_store`, `:null_store`, or an object that implements the cache API. Defaults to `:file_store`.
+* `config.cache_store` configures which cache store to use for Rails caching. Options include one of the symbols `:memory_store`, `:file_store`, `:mem_cache_store`, `:null_store`, `:redis_cache_store`, or an object that implements the cache API. Defaults to `:file_store`.
* `config.colorize_logging` specifies whether or not to use ANSI color codes when logging information. Defaults to `true`.
@@ -832,6 +832,14 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla
The default is 5 minutes.
+* `config.active_storage.routes_prefix` can be used to set the route prefix for the routes served by Active Storage. Accepts a string that will be prepended to the generated routes.
+
+ ```ruby
+ config.active_storage.routes_prefix = '/files'
+ ```
+
+ The default is `/rails/active_storage`
+
### Configuring a Database
Just about every Rails application will interact with a database. You can connect to the database by setting an environment variable `ENV['DATABASE_URL']` or by using a configuration file called `config/database.yml`.
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index a6dc60342c..8991c547ca 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -299,7 +299,7 @@ module Rails
def gem_for_database
# %w( mysql postgresql sqlite3 oracle frontbase ibm_db sqlserver jdbcmysql jdbcsqlite3 jdbcpostgresql )
case options[:database]
- when "mysql" then ["mysql2", [">= 0.4.4", "< 0.6.0"]]
+ when "mysql" then ["mysql2", [">= 0.4.4"]]
when "postgresql" then ["pg", [">= 0.18", "< 2.0"]]
when "oracle" then ["activerecord-oracle_enhanced-adapter", nil]
when "frontbase" then ["ruby-frontbase", nil]
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 44f6af5d4a..11cd6dd1e6 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -2053,6 +2053,24 @@ module ApplicationTests
assert_equal [ "password", "credit_card_number" ].to_set, ActiveRecord::Base.filter_attributes
end
+ test "ActiveStorage.routes_prefix can be configured via config.active_storage.routes_prefix" do
+ app_file "config/environments/development.rb", <<-RUBY
+ Rails.application.configure do
+ config.active_storage.routes_prefix = '/files'
+ end
+ RUBY
+
+ output = rails("routes", "-g", "active_storage")
+ assert_equal <<~MESSAGE, output
+ Prefix Verb URI Pattern Controller#Action
+ rails_service_blob GET /files/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
+ rails_blob_representation GET /files/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
+ rails_disk_service GET /files/disk/:encoded_key/*filename(.:format) active_storage/disk#show
+ update_rails_disk_service PUT /files/disk/:encoded_token(.:format) active_storage/disk#update
+ rails_direct_uploads POST /files/direct_uploads(.:format) active_storage/direct_uploads#create
+ MESSAGE
+ end
+
private
def force_lazy_load_hooks
yield # Tasty clarifying sugar, homie! We only need to reference a constant to load it.
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index f33a7bd99d..14cdd8b5c9 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -492,7 +492,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
if defined?(JRUBY_VERSION)
assert_gem "activerecord-jdbcmysql-adapter"
else
- assert_gem "mysql2", "'>= 0.4.4', '< 0.6.0'"
+ assert_gem "mysql2", "'>= 0.4.4'"
end
end