aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.rubocop.yml4
-rw-r--r--.travis.yml6
-rw-r--r--Gemfile.lock10
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb4
-rw-r--r--actionpack/test/controller/http_digest_authentication_test.rb9
-rw-r--r--actionpack/test/controller/routing_test.rb2
-rw-r--r--actionview/lib/action_view/helpers/debug_helper.rb2
-rw-r--r--activejob/lib/active_job/serializers.rb18
-rw-r--r--activejob/lib/active_job/serializers/object_serializer.rb32
-rw-r--r--activejob/lib/active_job/serializers/time_with_zone_serializer.rb21
-rw-r--r--activejob/test/cases/argument_serialization_test.rb8
-rw-r--r--activejob/test/cases/serializers_test.rb2
-rw-r--r--activerecord/lib/active_record/railties/databases.rake2
-rw-r--r--activerecord/lib/active_record/tasks/database_tasks.rb4
-rw-r--r--activerecord/test/cases/base_test.rb2
-rw-r--r--activerecord/test/cases/fixtures_test.rb2
-rw-r--r--activerecord/test/cases/tasks/database_tasks_test.rb16
-rw-r--r--activestorage/app/models/active_storage/blob/identifiable.rb7
-rw-r--r--activestorage/app/models/active_storage/identification.rb13
-rw-r--r--activestorage/test/controllers/direct_uploads_controller_test.rb2
-rw-r--r--activestorage/test/service/s3_service_test.rb2
-rwxr-xr-xactivesupport/bin/generate_tables141
-rw-r--r--activesupport/lib/active_support/multibyte/unicode.rb287
-rw-r--r--activesupport/lib/active_support/values/unicode_tables.datbin1116857 -> 0 bytes
-rw-r--r--activesupport/lib/active_support/xml_mini.rb2
-rw-r--r--activesupport/test/multibyte_unicode_database_test.rb26
-rw-r--r--guides/rails_guides/kindle.rb4
-rw-r--r--guides/source/active_job_basics.md27
-rw-r--r--guides/source/active_storage_overview.md2
-rw-r--r--railties/lib/rails/application/configuration.rb1
-rw-r--r--railties/lib/rails/generators/rails/controller/controller_generator.rb1
-rw-r--r--railties/test/generators/api_app_generator_test.rb2
-rw-r--r--railties/test/generators/app_generator_test.rb17
-rw-r--r--railties/test/generators/controller_generator_test.rb7
-rw-r--r--railties/test/generators/shared_generator_tests.rb2
35 files changed, 145 insertions, 542 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index f2f079b0de..3c765d5b1d 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -156,3 +156,7 @@ Style/RedundantReturn:
Style/Semicolon:
Enabled: true
AllowAsExpressionSeparator: true
+
+# Prefer Foo.method over Foo::method
+Style/ColonMethodCall:
+ Enabled: true
diff --git a/.travis.yml b/.travis.yml
index 164f0c9c7f..2513e87114 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -99,17 +99,17 @@ matrix:
- "GEM=ar:postgresql POSTGRES=9.2"
addons:
postgresql: "9.2"
- - rvm: jruby-9.1.15.0
+ - rvm: jruby-head
jdk: oraclejdk8
env:
- "GEM=ap"
- - rvm: jruby-9.1.15.0
+ - rvm: jruby-head
jdk: oraclejdk8
env:
- "GEM=am,amo,aj"
allow_failures:
- rvm: ruby-head
- - rvm: jruby-9.1.15.0
+ - rvm: jruby-head
- env: "GEM=ac:integration"
fast_finish: true
diff --git a/Gemfile.lock b/Gemfile.lock
index 5c4e853296..87c991253b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -321,7 +321,7 @@ GEM
multi_json (1.12.2)
multipart-post (2.0.0)
mustache (1.0.5)
- mustermann (1.0.0)
+ mustermann (1.0.2)
mysql2 (0.4.10)
mysql2 (0.4.10-x64-mingw32)
mysql2 (0.4.10-x86-mingw32)
@@ -352,10 +352,10 @@ GEM
selenium-webdriver
thor
racc (1.4.14)
- rack (2.0.3)
+ rack (2.0.4)
rack-cache (1.7.0)
rack (>= 0.4)
- rack-protection (2.0.0)
+ rack-protection (2.0.1)
rack
rack-test (0.8.0)
rack (>= 1.0, < 3)
@@ -432,10 +432,10 @@ GEM
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
- sinatra (2.0.0)
+ sinatra (2.0.1)
mustermann (~> 1.0)
rack (~> 2.0)
- rack-protection (= 2.0.0)
+ rack-protection (= 2.0.1)
tilt (~> 2.0)
sneakers (2.5.0)
bunny (~> 2.6.4)
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index ff6998ae31..a29a5a04ef 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -153,13 +153,13 @@ module ActionDispatch
url_name = :"#{name}_url"
@path_helpers_module.module_eval do
- define_method(path_name) do |*args|
+ redefine_method(path_name) do |*args|
helper.call(self, args, true)
end
end
@url_helpers_module.module_eval do
- define_method(url_name) do |*args|
+ redefine_method(url_name) do |*args|
helper.call(self, args, false)
end
end
diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb
index 76ff784926..560157dc61 100644
--- a/actionpack/test/controller/http_digest_authentication_test.rb
+++ b/actionpack/test/controller/http_digest_authentication_test.rb
@@ -9,7 +9,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
before_action :authenticate_with_request, only: :display
USERS = { "lifo" => "world", "pretty" => "please",
- "dhh" => ::Digest::MD5::hexdigest(["dhh", "SuperSecret", "secret"].join(":")) }
+ "dhh" => ::Digest::MD5.hexdigest(["dhh", "SuperSecret", "secret"].join(":")) }
def index
render plain: "Hello Secret"
@@ -181,9 +181,10 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
end
test "authentication request with password stored as ha1 digest hash" do
- @request.env["HTTP_AUTHORIZATION"] = encode_credentials(username: "dhh",
- password: ::Digest::MD5::hexdigest(["dhh", "SuperSecret", "secret"].join(":")),
- password_is_ha1: true)
+ @request.env["HTTP_AUTHORIZATION"] = encode_credentials(
+ username: "dhh",
+ password: ::Digest::MD5.hexdigest(["dhh", "SuperSecret", "secret"].join(":")),
+ password_is_ha1: true)
get :display
assert_response :success
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index ec939e946a..9c0e101f7c 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -676,7 +676,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
token = "\321\202\320\265\320\272\321\201\321\202".dup # 'text' in Russian
token.force_encoding(Encoding::BINARY)
- escaped_token = CGI::escape(token)
+ escaped_token = CGI.escape(token)
assert_equal "/page/" + escaped_token, url_for(rs, controller: "content", action: "show_page", id: token)
assert_equal({ controller: "content", action: "show_page", id: token }, rs.recognize_path("/page/#{escaped_token}"))
diff --git a/actionview/lib/action_view/helpers/debug_helper.rb b/actionview/lib/action_view/helpers/debug_helper.rb
index 52dff1f750..88ceba414b 100644
--- a/actionview/lib/action_view/helpers/debug_helper.rb
+++ b/actionview/lib/action_view/helpers/debug_helper.rb
@@ -24,7 +24,7 @@ module ActionView
# created_at:
# </pre>
def debug(object)
- Marshal::dump(object)
+ Marshal.dump(object)
object = ERB::Util.html_escape(object.to_yaml)
content_tag(:pre, object, class: "debug_dump")
rescue # errors from Marshal or YAML
diff --git a/activejob/lib/active_job/serializers.rb b/activejob/lib/active_job/serializers.rb
index 9930ae0823..df66e66659 100644
--- a/activejob/lib/active_job/serializers.rb
+++ b/activejob/lib/active_job/serializers.rb
@@ -4,17 +4,18 @@ require "set"
module ActiveJob
# The <tt>ActiveJob::Serializers</tt> module is used to store a list of known serializers
- # and to add new ones. It also has helpers to serialize/deserialize objects
- module Serializers
+ # and to add new ones. It also has helpers to serialize/deserialize objects.
+ module Serializers # :nodoc:
extend ActiveSupport::Autoload
extend ActiveSupport::Concern
autoload :ObjectSerializer
autoload :SymbolSerializer
autoload :DurationSerializer
+ autoload :DateTimeSerializer
autoload :DateSerializer
+ autoload :TimeWithZoneSerializer
autoload :TimeSerializer
- autoload :DateTimeSerializer
mattr_accessor :_additional_serializers
self._additional_serializers = Set.new
@@ -22,7 +23,7 @@ module ActiveJob
class << self
# Returns serialized representative of the passed object.
# Will look up through all known serializers.
- # Raises `ActiveJob::SerializationError` if it can't find a proper serializer.
+ # Raises <tt>ActiveJob::SerializationError</tt> if it can't find a proper serializer.
def serialize(argument)
serializer = serializers.detect { |s| s.serialize?(argument) }
raise SerializationError.new("Unsupported argument type: #{argument.class.name}") unless serializer
@@ -31,23 +32,23 @@ module ActiveJob
# Returns deserialized object.
# Will look up through all known serializers.
- # If no serializers found will raise `ArgumentError`
+ # If no serializer found will raise <tt>ArgumentError</tt>.
def deserialize(argument)
serializer_name = argument[Arguments::OBJECT_SERIALIZER_KEY]
raise ArgumentError, "Serializer name is not present in the argument: #{argument.inspect}" unless serializer_name
serializer = serializer_name.safe_constantize
- raise ArgumentError, "Serializer #{serializer_name} is not know" unless serializer
+ raise ArgumentError, "Serializer #{serializer_name} is not known" unless serializer
serializer.deserialize(argument)
end
- # Returns list of known serializers
+ # Returns list of known serializers.
def serializers
self._additional_serializers
end
- # Adds a new serializer to a list of known serializers
+ # Adds new serializers to a list of known serializers.
def add_serializers(*new_serializers)
self._additional_serializers += new_serializers.flatten
end
@@ -57,6 +58,7 @@ module ActiveJob
DurationSerializer,
DateTimeSerializer,
DateSerializer,
+ TimeWithZoneSerializer,
TimeSerializer
end
end
diff --git a/activejob/lib/active_job/serializers/object_serializer.rb b/activejob/lib/active_job/serializers/object_serializer.rb
index 9f59e8236f..1dfd1e44be 100644
--- a/activejob/lib/active_job/serializers/object_serializer.rb
+++ b/activejob/lib/active_job/serializers/object_serializer.rb
@@ -2,25 +2,25 @@
module ActiveJob
module Serializers
- # Base class for serializing and deserializing custom times.
+ # Base class for serializing and deserializing custom objects.
#
- # Example
+ # Example:
#
- # class MoneySerializer < ActiveJob::Serializers::ObjectSerializer
- # def serialize(money)
- # super("cents" => money.cents, "currency" => money.currency)
- # end
+ # class MoneySerializer < ActiveJob::Serializers::ObjectSerializer
+ # def serialize(money)
+ # super("amount" => money.amount, "currency" => money.currency)
+ # end
#
- # def deserialize(hash)
- # Money.new(hash["cents"], hash["currency"])
- # end
+ # def deserialize(hash)
+ # Money.new(hash["amount"], hash["currency"])
+ # end
#
- # private
+ # private
#
- # def klass
- # Money
- # end
- # end
+ # def klass
+ # Money
+ # end
+ # end
class ObjectSerializer
include Singleton
@@ -43,10 +43,10 @@ module ActiveJob
raise NotImplementedError
end
- protected
+ private
# The class of the object that will be serialized.
- def klass
+ def klass # :doc:
raise NotImplementedError
end
end
diff --git a/activejob/lib/active_job/serializers/time_with_zone_serializer.rb b/activejob/lib/active_job/serializers/time_with_zone_serializer.rb
new file mode 100644
index 0000000000..43017fc75b
--- /dev/null
+++ b/activejob/lib/active_job/serializers/time_with_zone_serializer.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module ActiveJob
+ module Serializers
+ class TimeWithZoneSerializer < ObjectSerializer # :nodoc:
+ def serialize(time)
+ super("value" => time.iso8601)
+ end
+
+ def deserialize(hash)
+ Time.iso8601(hash["value"]).in_time_zone
+ end
+
+ private
+
+ def klass
+ ActiveSupport::TimeWithZone
+ end
+ end
+ end
+end
diff --git a/activejob/test/cases/argument_serialization_test.rb b/activejob/test/cases/argument_serialization_test.rb
index 5d27813832..e5f1f087fe 100644
--- a/activejob/test/cases/argument_serialization_test.rb
+++ b/activejob/test/cases/argument_serialization_test.rb
@@ -102,6 +102,14 @@ class ArgumentSerializationTest < ActiveSupport::TestCase
assert_instance_of ActiveSupport::HashWithIndifferentAccess, perform_round_trip([indifferent_access]).first
end
+ test "should maintain time with zone" do
+ Time.use_zone "Alaska" do
+ time_with_zone = Time.new(2002, 10, 31, 2, 2, 2).in_time_zone
+ assert_instance_of ActiveSupport::TimeWithZone, perform_round_trip([time_with_zone]).first
+ assert_arguments_unchanged time_with_zone
+ end
+ end
+
test "should disallow non-string/symbol hash keys" do
assert_raises ActiveJob::SerializationError do
ActiveJob::Arguments.serialize [ { 1 => 2 } ]
diff --git a/activejob/test/cases/serializers_test.rb b/activejob/test/cases/serializers_test.rb
index a86f168d03..bee0c061bd 100644
--- a/activejob/test/cases/serializers_test.rb
+++ b/activejob/test/cases/serializers_test.rb
@@ -73,7 +73,7 @@ class SerializersTest < ActiveSupport::TestCase
ActiveJob::Serializers.deserialize(hash)
end
assert_equal(
- "Serializer DoNotExist is not know",
+ "Serializer DoNotExist is not known",
error.message
)
end
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 2e55713311..662a8bc720 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -229,7 +229,7 @@ db_namespace = namespace :db do
base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
Dir["#{base_dir}/**/*.yml"].each do |file|
- if data = YAML::load(ERB.new(IO.read(file)).result)
+ if data = YAML.load(ERB.new(IO.read(file)).result)
data.each_key do |key|
key_id = ActiveRecord::FixtureSet.identify(key)
diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb
index d8e0cd1e30..0883e80d23 100644
--- a/activerecord/lib/active_record/tasks/database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/database_tasks.rb
@@ -315,16 +315,12 @@ module ActiveRecord
environments << "test" if environment == "development"
ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
- next unless configuration["database"]
-
yield configuration, configuration_environment
end
end
def each_local_configuration
ActiveRecord::Base.configurations.each_value do |configuration|
- next unless configuration["database"]
-
if local_database?(configuration)
yield configuration
else
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 983a3d366a..7dfb05a6a5 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1501,7 +1501,7 @@ class BasicsTest < ActiveRecord::TestCase
query = Developer.from("developers").to_sql
quoted_id = "#{Developer.quoted_table_name}.#{Developer.quoted_primary_key}"
- assert_match(/SELECT #{quoted_id}.* FROM developers/, query)
+ assert_match(/SELECT #{Regexp.escape(quoted_id)}.* FROM developers/, query)
end
test "using table name qualified column names unless having SELECT list explicitly" do
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index c92edc6f45..184b750161 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -1186,7 +1186,7 @@ class CustomNameForFixtureOrModelTest < ActiveRecord::TestCase
end
def test_table_name_is_defined_in_the_model
- assert_equal "randomly_named_table2", ActiveRecord::FixtureSet::all_loaded_fixtures["admin/randomly_named_a9"].table_name
+ assert_equal "randomly_named_table2", ActiveRecord::FixtureSet.all_loaded_fixtures["admin/randomly_named_a9"].table_name
assert_equal "randomly_named_table2", Admin::ClassNameThatDoesNotFollowCONVENTIONS1.table_name
end
end
diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb
index 21226352ff..da7ca27f13 100644
--- a/activerecord/test/cases/tasks/database_tasks_test.rb
+++ b/activerecord/test/cases/tasks/database_tasks_test.rb
@@ -124,14 +124,6 @@ module ActiveRecord
ActiveRecord::Base.connection_handler.stubs(:establish_connection)
end
- def test_ignores_configurations_without_databases
- @configurations["development"].merge!("database" => nil)
-
- ActiveRecord::Tasks::DatabaseTasks.expects(:create).never
-
- ActiveRecord::Tasks::DatabaseTasks.create_all
- end
-
def test_ignores_remote_databases
@configurations["development"].merge!("host" => "my.server.tld")
$stderr.stubs(:puts).returns(nil)
@@ -250,14 +242,6 @@ module ActiveRecord
ActiveRecord::Base.stubs(:configurations).returns(@configurations)
end
- def test_ignores_configurations_without_databases
- @configurations[:development].merge!("database" => nil)
-
- ActiveRecord::Tasks::DatabaseTasks.expects(:drop).never
-
- ActiveRecord::Tasks::DatabaseTasks.drop_all
- end
-
def test_ignores_remote_databases
@configurations[:development].merge!("host" => "my.server.tld")
$stderr.stubs(:puts).returns(nil)
diff --git a/activestorage/app/models/active_storage/blob/identifiable.rb b/activestorage/app/models/active_storage/blob/identifiable.rb
index 40ca84ac70..dbe03cfa6c 100644
--- a/activestorage/app/models/active_storage/blob/identifiable.rb
+++ b/activestorage/app/models/active_storage/blob/identifiable.rb
@@ -2,10 +2,15 @@
module ActiveStorage::Blob::Identifiable
def identify
- ActiveStorage::Identification.new(self).apply
+ update!(content_type: identification.content_type, identified: true) unless identified?
end
def identified?
identified
end
+
+ private
+ def identification
+ ActiveStorage::Identification.new self
+ end
end
diff --git a/activestorage/app/models/active_storage/identification.rb b/activestorage/app/models/active_storage/identification.rb
index bf1d8f5624..8d334ae1ea 100644
--- a/activestorage/app/models/active_storage/identification.rb
+++ b/activestorage/app/models/active_storage/identification.rb
@@ -2,26 +2,21 @@
require "net/http"
-class ActiveStorage::Identification
+class ActiveStorage::Identification #:nodoc:
attr_reader :blob
def initialize(blob)
@blob = blob
end
- def apply
- blob.update!(content_type: content_type, identified: true) unless blob.identified?
+ def content_type
+ Marcel::MimeType.for(identifiable_chunk, name: filename, declared_type: declared_content_type)
end
private
- def content_type
- Marcel::MimeType.for(identifiable_chunk, name: filename, declared_type: declared_content_type)
- end
-
-
def identifiable_chunk
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |client|
- client.get(uri, "Range" => "0-4096").body
+ client.get(uri, "Range" => "bytes=0-4095").body
end
end
diff --git a/activestorage/test/controllers/direct_uploads_controller_test.rb b/activestorage/test/controllers/direct_uploads_controller_test.rb
index 888767086c..dfffb6bb9c 100644
--- a/activestorage/test/controllers/direct_uploads_controller_test.rb
+++ b/activestorage/test/controllers/direct_uploads_controller_test.rb
@@ -27,7 +27,7 @@ if SERVICE_CONFIGURATIONS[:s3] && SERVICE_CONFIGURATIONS[:s3][:access_key_id].pr
assert_equal checksum, details["checksum"]
assert_equal "text/plain", details["content_type"]
assert_match SERVICE_CONFIGURATIONS[:s3][:bucket], details["direct_upload"]["url"]
- assert_match(/s3\.(\S+)?amazonaws\.com/, details["direct_upload"]["url"])
+ assert_match(/s3(-[-a-z0-9]+)?\.(\S+)?amazonaws\.com/, details["direct_upload"]["url"])
assert_equal({ "Content-Type" => "text/plain", "Content-MD5" => checksum }, details["direct_upload"]["headers"])
end
end
diff --git a/activestorage/test/service/s3_service_test.rb b/activestorage/test/service/s3_service_test.rb
index c3818422aa..d6996209d2 100644
--- a/activestorage/test/service/s3_service_test.rb
+++ b/activestorage/test/service/s3_service_test.rb
@@ -35,7 +35,7 @@ if SERVICE_CONFIGURATIONS[:s3] && SERVICE_CONFIGURATIONS[:s3][:access_key_id].pr
url = @service.url(FIXTURE_KEY, expires_in: 5.minutes,
disposition: :inline, filename: ActiveStorage::Filename.new("avatar.png"), content_type: "image/png")
- assert_match(/s3\.(\S+)?amazonaws.com.*response-content-disposition=inline.*avatar\.png.*response-content-type=image%2Fpng/, url)
+ assert_match(/s3(-[-a-z0-9]+)?\.(\S+)?amazonaws.com.*response-content-disposition=inline.*avatar\.png.*response-content-type=image%2Fpng/, url)
assert_match SERVICE_CONFIGURATIONS[:s3][:bucket], url
end
diff --git a/activesupport/bin/generate_tables b/activesupport/bin/generate_tables
deleted file mode 100755
index 18199b2171..0000000000
--- a/activesupport/bin/generate_tables
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-begin
- $:.unshift(File.expand_path("../lib", __dir__))
- require "active_support"
-rescue IOError
-end
-
-require "open-uri"
-require "tmpdir"
-require "fileutils"
-
-module ActiveSupport
- module Multibyte
- module Unicode
- class UnicodeDatabase
- def load; end
- end
-
- class DatabaseGenerator
- BASE_URI = "http://www.unicode.org/Public/#{UNICODE_VERSION}/ucd/"
- SOURCES = {
- codepoints: BASE_URI + "UnicodeData.txt",
- composition_exclusion: BASE_URI + "CompositionExclusions.txt",
- grapheme_break_property: BASE_URI + "auxiliary/GraphemeBreakProperty.txt",
- cp1252: "http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT"
- }
-
- def initialize
- @ucd = Unicode::UnicodeDatabase.new
- end
-
- def parse_codepoints(line)
- codepoint = Codepoint.new
- raise "Could not parse input." unless line =~ /^
- ([0-9A-F]+); # code
- ([^;]+); # name
- ([A-Z]+); # general category
- ([0-9]+); # canonical combining class
- ([A-Z]+); # bidi class
- (<([A-Z]*)>)? # decomposition type
- ((\ ?[0-9A-F]+)*); # decomposition mapping
- ([0-9]*); # decimal digit
- ([0-9]*); # digit
- ([^;]*); # numeric
- ([YN]*); # bidi mirrored
- ([^;]*); # unicode 1.0 name
- ([^;]*); # iso comment
- ([0-9A-F]*); # simple uppercase mapping
- ([0-9A-F]*); # simple lowercase mapping
- ([0-9A-F]*)$/ix # simple titlecase mapping
- codepoint.code = $1.hex
- codepoint.combining_class = Integer($4)
- codepoint.decomp_type = $7
- codepoint.decomp_mapping = ($8 == "") ? nil : $8.split.collect(&:hex)
- codepoint.uppercase_mapping = ($16 == "") ? 0 : $16.hex
- codepoint.lowercase_mapping = ($17 == "") ? 0 : $17.hex
- @ucd.codepoints[codepoint.code] = codepoint
- end
-
- def parse_grapheme_break_property(line)
- if line =~ /^([0-9A-F.]+)\s*;\s*([\w]+)\s*#/
- type = $2.downcase.intern
- @ucd.boundary[type] ||= []
- if $1.include? ".."
- parts = $1.split ".."
- @ucd.boundary[type] << (parts[0].hex..parts[1].hex)
- else
- @ucd.boundary[type] << $1.hex
- end
- end
- end
-
- def parse_composition_exclusion(line)
- if line =~ /^([0-9A-F]+)/i
- @ucd.composition_exclusion << $1.hex
- end
- end
-
- def parse_cp1252(line)
- if line =~ /^([0-9A-Fx]+)\s([0-9A-Fx]+)/i
- @ucd.cp1252[$1.hex] = $2.hex
- end
- end
-
- def create_composition_map
- @ucd.codepoints.each do |_, cp|
- if !cp.nil? && cp.combining_class == 0 && cp.decomp_type.nil? && !cp.decomp_mapping.nil? && cp.decomp_mapping.length == 2 && @ucd.codepoints[cp.decomp_mapping[0]].combining_class == 0 && !@ucd.composition_exclusion.include?(cp.code)
- @ucd.composition_map[cp.decomp_mapping[0]] ||= {}
- @ucd.composition_map[cp.decomp_mapping[0]][cp.decomp_mapping[1]] = cp.code
- end
- end
- end
-
- def normalize_boundary_map
- @ucd.boundary.each do |k, v|
- if [:lf, :cr].include? k
- @ucd.boundary[k] = v[0]
- end
- end
- end
-
- def parse
- SOURCES.each do |type, url|
- filename = File.join(Dir.tmpdir, UNICODE_VERSION, "#{url.split('/').last}")
- unless File.exist?(filename)
- $stderr.puts "Downloading #{url.split('/').last}"
- FileUtils.mkdir_p(File.dirname(filename))
- File.open(filename, "wb") do |target|
- open(url) do |source|
- source.each_line { |line| target.write line }
- end
- end
- end
- File.open(filename) do |file|
- file.each_line { |line| send "parse_#{type}".intern, line }
- end
- end
- create_composition_map
- normalize_boundary_map
- end
-
- def dump_to(filename)
- File.open(filename, "wb") do |f|
- f.write Marshal.dump([@ucd.codepoints, @ucd.composition_exclusion, @ucd.composition_map, @ucd.boundary, @ucd.cp1252])
- end
- end
- end
- end
- end
-end
-
-if __FILE__ == $0
- filename = ActiveSupport::Multibyte::Unicode::UnicodeDatabase.filename
- generator = ActiveSupport::Multibyte::Unicode::DatabaseGenerator.new
- generator.parse
- print "Writing to: #{filename}"
- generator.dump_to filename
- puts " (#{File.size(filename)} bytes)"
-end
diff --git a/activesupport/lib/active_support/multibyte/unicode.rb b/activesupport/lib/active_support/multibyte/unicode.rb
index f923061fae..4f0e1165ef 100644
--- a/activesupport/lib/active_support/multibyte/unicode.rb
+++ b/activesupport/lib/active_support/multibyte/unicode.rb
@@ -11,7 +11,7 @@ module ActiveSupport
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
# The Unicode version that is supported by the implementation
- UNICODE_VERSION = "9.0.0"
+ UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]
# The default normalization used for operations that require
# normalization. It can be set to any of the normalizations
@@ -21,96 +21,13 @@ module ActiveSupport
attr_accessor :default_normalization_form
@default_normalization_form = :kc
- # Hangul character boundaries and properties
- HANGUL_SBASE = 0xAC00
- HANGUL_LBASE = 0x1100
- HANGUL_VBASE = 0x1161
- HANGUL_TBASE = 0x11A7
- HANGUL_LCOUNT = 19
- HANGUL_VCOUNT = 21
- HANGUL_TCOUNT = 28
- HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
- HANGUL_SCOUNT = 11172
- HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
-
- # Detect whether the codepoint is in a certain character class. Returns
- # +true+ when it's in the specified character class and +false+ otherwise.
- # Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>,
- # <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>.
- #
- # Primarily used by the grapheme cluster support.
- def in_char_class?(codepoint, classes)
- classes.detect { |c| database.boundary[c] === codepoint } ? true : false
- end
-
# Unpack the string at grapheme boundaries. Returns a list of character
# lists.
#
# Unicode.unpack_graphemes('क्षि') # => [[2325, 2381], [2359], [2367]]
# Unicode.unpack_graphemes('Café') # => [[67], [97], [102], [233]]
def unpack_graphemes(string)
- codepoints = string.codepoints.to_a
- unpacked = []
- pos = 0
- marker = 0
- eoc = codepoints.length
- while (pos < eoc)
- pos += 1
- previous = codepoints[pos - 1]
- current = codepoints[pos]
-
- # See http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules
- should_break =
- if pos == eoc
- true
- # GB3. CR X LF
- elsif previous == database.boundary[:cr] && current == database.boundary[:lf]
- false
- # GB4. (Control|CR|LF) ÷
- elsif previous && in_char_class?(previous, [:control, :cr, :lf])
- true
- # GB5. ÷ (Control|CR|LF)
- elsif in_char_class?(current, [:control, :cr, :lf])
- true
- # GB6. L X (L|V|LV|LVT)
- elsif database.boundary[:l] === previous && in_char_class?(current, [:l, :v, :lv, :lvt])
- false
- # GB7. (LV|V) X (V|T)
- elsif in_char_class?(previous, [:lv, :v]) && in_char_class?(current, [:v, :t])
- false
- # GB8. (LVT|T) X (T)
- elsif in_char_class?(previous, [:lvt, :t]) && database.boundary[:t] === current
- false
- # GB9. X (Extend | ZWJ)
- elsif in_char_class?(current, [:extend, :zwj])
- false
- # GB9a. X SpacingMark
- elsif database.boundary[:spacingmark] === current
- false
- # GB9b. Prepend X
- elsif database.boundary[:prepend] === previous
- false
- # GB10. (E_Base | EBG) Extend* X E_Modifier
- elsif (marker...pos).any? { |i| in_char_class?(codepoints[i], [:e_base, :e_base_gaz]) && codepoints[i + 1...pos].all? { |c| database.boundary[:extend] === c } } && database.boundary[:e_modifier] === current
- false
- # GB11. ZWJ X (Glue_After_Zwj | EBG)
- elsif database.boundary[:zwj] === previous && in_char_class?(current, [:glue_after_zwj, :e_base_gaz])
- false
- # GB12. ^ (RI RI)* RI X RI
- # GB13. [^RI] (RI RI)* RI X RI
- elsif codepoints[marker..pos].all? { |c| database.boundary[:regional_indicator] === c } && codepoints[marker..pos].count { |c| database.boundary[:regional_indicator] === c }.even?
- false
- # GB999. Any ÷ Any
- else
- true
- end
-
- if should_break
- unpacked << codepoints[marker..pos - 1]
- marker = pos
- end
- end
- unpacked
+ string.scan(/\X/).map(&:codepoints)
end
# Reverse operation of unpack_graphemes.
@@ -120,100 +37,18 @@ module ActiveSupport
unpacked.flatten.pack("U*")
end
- # Re-order codepoints so the string becomes canonical.
- def reorder_characters(codepoints)
- length = codepoints.length - 1
- pos = 0
- while pos < length do
- cp1, cp2 = database.codepoints[codepoints[pos]], database.codepoints[codepoints[pos + 1]]
- if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
- codepoints[pos..pos + 1] = cp2.code, cp1.code
- pos += (pos > 0 ? -1 : 1)
- else
- pos += 1
- end
- end
- codepoints
- end
-
# Decompose composed characters to the decomposed form.
def decompose(type, codepoints)
- codepoints.inject([]) do |decomposed, cp|
- # if it's a hangul syllable starter character
- if HANGUL_SBASE <= cp && cp < HANGUL_SLAST
- sindex = cp - HANGUL_SBASE
- ncp = [] # new codepoints
- ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
- ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
- tindex = sindex % HANGUL_TCOUNT
- ncp << (HANGUL_TBASE + tindex) unless tindex == 0
- decomposed.concat ncp
- # if the codepoint is decomposable in with the current decomposition type
- elsif (ncp = database.codepoints[cp].decomp_mapping) && (!database.codepoints[cp].decomp_type || type == :compatibility)
- decomposed.concat decompose(type, ncp.dup)
- else
- decomposed << cp
- end
+ if type == :compatibility
+ codepoints.pack("U*").unicode_normalize(:nfkd).codepoints
+ else
+ codepoints.pack("U*").unicode_normalize(:nfd).codepoints
end
end
# Compose decomposed characters to the composed form.
def compose(codepoints)
- pos = 0
- eoa = codepoints.length - 1
- starter_pos = 0
- starter_char = codepoints[0]
- previous_combining_class = -1
- while pos < eoa
- pos += 1
- lindex = starter_char - HANGUL_LBASE
- # -- Hangul
- if 0 <= lindex && lindex < HANGUL_LCOUNT
- vindex = codepoints[starter_pos + 1] - HANGUL_VBASE rescue vindex = -1
- if 0 <= vindex && vindex < HANGUL_VCOUNT
- tindex = codepoints[starter_pos + 2] - HANGUL_TBASE rescue tindex = -1
- if 0 <= tindex && tindex < HANGUL_TCOUNT
- j = starter_pos + 2
- eoa -= 2
- else
- tindex = 0
- j = starter_pos + 1
- eoa -= 1
- end
- codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
- end
- starter_pos += 1
- starter_char = codepoints[starter_pos]
- # -- Other characters
- else
- current_char = codepoints[pos]
- current = database.codepoints[current_char]
- if current.combining_class > previous_combining_class
- if ref = database.composition_map[starter_char]
- composition = ref[current_char]
- else
- composition = nil
- end
- unless composition.nil?
- codepoints[starter_pos] = composition
- starter_char = composition
- codepoints.delete_at pos
- eoa -= 1
- pos -= 1
- previous_combining_class = -1
- else
- previous_combining_class = current.combining_class
- end
- else
- previous_combining_class = current.combining_class
- end
- if current.combining_class == 0
- starter_pos = pos
- starter_char = codepoints[pos]
- end
- end
- end
- codepoints
+ codepoints.pack("U*").unicode_normalize(:nfc).codepoints
end
# Rubinius' String#scrub, however, doesn't support ASCII-incompatible chars.
@@ -266,129 +101,37 @@ module ActiveSupport
def normalize(string, form = nil)
form ||= @default_normalization_form
# See http://www.unicode.org/reports/tr15, Table 1
- codepoints = string.codepoints.to_a
case form
when :d
- reorder_characters(decompose(:canonical, codepoints))
+ string.unicode_normalize(:nfd)
when :c
- compose(reorder_characters(decompose(:canonical, codepoints)))
+ string.unicode_normalize(:nfc)
when :kd
- reorder_characters(decompose(:compatibility, codepoints))
+ string.unicode_normalize(:nfkd)
when :kc
- compose(reorder_characters(decompose(:compatibility, codepoints)))
+ string.unicode_normalize(:nfkc)
else
raise ArgumentError, "#{form} is not a valid normalization variant", caller
- end.pack("U*".freeze)
+ end
end
def downcase(string)
- apply_mapping string, :lowercase_mapping
+ string.downcase
end
def upcase(string)
- apply_mapping string, :uppercase_mapping
+ string.upcase
end
def swapcase(string)
- apply_mapping string, :swapcase_mapping
- end
-
- # Holds data about a codepoint in the Unicode database.
- class Codepoint
- attr_accessor :code, :combining_class, :decomp_type, :decomp_mapping, :uppercase_mapping, :lowercase_mapping
-
- # Initializing Codepoint object with default values
- def initialize
- @combining_class = 0
- @uppercase_mapping = 0
- @lowercase_mapping = 0
- end
-
- def swapcase_mapping
- uppercase_mapping > 0 ? uppercase_mapping : lowercase_mapping
- end
- end
-
- # Holds static data from the Unicode database.
- class UnicodeDatabase
- ATTRIBUTES = :codepoints, :composition_exclusion, :composition_map, :boundary, :cp1252
-
- attr_writer(*ATTRIBUTES)
-
- def initialize
- @codepoints = Hash.new(Codepoint.new)
- @composition_exclusion = []
- @composition_map = {}
- @boundary = {}
- @cp1252 = {}
- end
-
- # Lazy load the Unicode database so it's only loaded when it's actually used
- ATTRIBUTES.each do |attr_name|
- class_eval(<<-EOS, __FILE__, __LINE__ + 1)
- def #{attr_name} # def codepoints
- load # load
- @#{attr_name} # @codepoints
- end # end
- EOS
- end
-
- # Loads the Unicode database and returns all the internal objects of
- # UnicodeDatabase.
- def load
- begin
- @codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, "rb") { |f| Marshal.load f.read }
- rescue => e
- raise IOError.new("Couldn't load the Unicode tables for UTF8Handler (#{e.message}), ActiveSupport::Multibyte is unusable")
- end
-
- # Redefine the === method so we can write shorter rules for grapheme cluster breaks
- @boundary.each_key do |k|
- @boundary[k].instance_eval do
- def ===(other)
- detect { |i| i === other } ? true : false
- end
- end if @boundary[k].kind_of?(Array)
- end
-
- # define attr_reader methods for the instance variables
- class << self
- attr_reader(*ATTRIBUTES)
- end
- end
-
- # Returns the directory in which the data files are stored.
- def self.dirname
- File.expand_path("../values", __dir__)
- end
-
- # Returns the filename for the data file for this version.
- def self.filename
- File.expand_path File.join(dirname, "unicode_tables.dat")
- end
+ string.swapcase
end
private
- def apply_mapping(string, mapping)
- database.codepoints
- string.each_codepoint.map do |codepoint|
- cp = database.codepoints[codepoint]
- if cp && (ncp = cp.send(mapping)) && ncp > 0
- ncp
- else
- codepoint
- end
- end.pack("U*")
- end
-
def recode_windows1252_chars(string)
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
end
-
- def database
- @database ||= UnicodeDatabase.new
- end
end
end
end
diff --git a/activesupport/lib/active_support/values/unicode_tables.dat b/activesupport/lib/active_support/values/unicode_tables.dat
deleted file mode 100644
index f7d9c48bbe..0000000000
--- a/activesupport/lib/active_support/values/unicode_tables.dat
+++ /dev/null
Binary files differ
diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb
index d0659aeaae..e42eee07a3 100644
--- a/activesupport/lib/active_support/xml_mini.rb
+++ b/activesupport/lib/active_support/xml_mini.rb
@@ -79,7 +79,7 @@ module ActiveSupport
end,
"boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.to_s.strip) },
"string" => Proc.new { |string| string.to_s },
- "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
+ "yaml" => Proc.new { |yaml| YAML.load(yaml) rescue yaml },
"base64Binary" => Proc.new { |bin| ::Base64.decode64(bin) },
"binary" => Proc.new { |bin, entity| _parse_binary(bin, entity) },
"file" => Proc.new { |file, entity| _parse_file(file, entity) }
diff --git a/activesupport/test/multibyte_unicode_database_test.rb b/activesupport/test/multibyte_unicode_database_test.rb
deleted file mode 100644
index 540a34493d..0000000000
--- a/activesupport/test/multibyte_unicode_database_test.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require "abstract_unit"
-
-class MultibyteUnicodeDatabaseTest < ActiveSupport::TestCase
- include ActiveSupport::Multibyte::Unicode
-
- def setup
- @ucd = UnicodeDatabase.new
- end
-
- UnicodeDatabase::ATTRIBUTES.each do |attribute|
- define_method "test_lazy_loading_on_attribute_access_of_#{attribute}" do
- assert_called(@ucd, :load) do
- @ucd.send(attribute)
- end
- end
- end
-
- def test_load
- @ucd.load
- UnicodeDatabase::ATTRIBUTES.each do |attribute|
- assert @ucd.send(attribute).length > 1
- end
- end
-end
diff --git a/guides/rails_guides/kindle.rb b/guides/rails_guides/kindle.rb
index 87a369a15a..5c4f7d159c 100644
--- a/guides/rails_guides/kindle.rb
+++ b/guides/rails_guides/kindle.rb
@@ -58,9 +58,9 @@ module Kindle
end
def generate_sections(html_pages)
- FileUtils::rm_rf("sections/")
+ FileUtils.rm_rf("sections/")
html_pages.each_with_index do |page, section_idx|
- FileUtils::mkdir_p("sections/%03d" % section_idx)
+ FileUtils.mkdir_p("sections/%03d" % section_idx)
doc = Nokogiri::HTML(File.open(page))
title = doc.at("title").inner_text.gsub("Ruby on Rails Guides: ", "")
title = page.capitalize.gsub(".html", "") if title.strip == ""
diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md
index f6bbdeccd6..97d98efba0 100644
--- a/guides/source/active_job_basics.md
+++ b/guides/source/active_job_basics.md
@@ -346,12 +346,12 @@ ActiveJob supports the following types of arguments by default:
- Basic types (`NilClass`, `String`, `Integer`, `Float`, `BigDecimal`, `TrueClass`, `FalseClass`)
- `Symbol`
- - `ActiveSupport::Duration`
- `Date`
- `Time`
- `DateTime`
- `ActiveSupport::TimeWithZone`
- - `Hash`. Keys should be of `String` or `Symbol` type
+ - `ActiveSupport::Duration`
+ - `Hash` (Keys should be of `String` or `Symbol` type)
- `ActiveSupport::HashWithIndifferentAccess`
- `Array`
@@ -385,39 +385,38 @@ by default has been mixed into Active Record classes.
### Serializers
-You can extend list of supported types for arguments. You just need to define your own serializer.
+You can extend the list of supported argument types. You just need to define your own serializer:
```ruby
class MoneySerializer < ActiveJob::Serializers::ObjectSerializer
- # Check if this object should be serialized using this serializer.
+ # Checks if an argument should be serialized by this serializer.
def serialize?(argument)
argument.is_a? Money
end
- # Convert an object to a simpler representative using supported object types.
+ # Converts an object to a simpler representative using supported object types.
# The recommended representative is a Hash with a specific key. Keys can be of basic types only.
- # You should call `super` to add the custom serializer type to the hash
- def serialize(object)
+ # You should call `super` to add the custom serializer type to the hash.
+ def serialize(money)
super(
- "cents" => object.cents,
- "currency" => object.currency
+ "amount" => money.amount,
+ "currency" => money.currency
)
end
- # Convert serialized value into a proper object
+ # Converts serialized value into a proper object.
def deserialize(hash)
- Money.new hash["cents"], hash["currency"]
+ Money.new(hash["amount"], hash["currency"])
end
end
```
-And now you just need to add this serializer to a list:
+and add this serializer to the list:
```ruby
-Rails.application.config.active_job.custom_serializers << MySpecialSerializer
+Rails.application.config.active_job.custom_serializers << MoneySerializer
```
-
Exceptions
----------
diff --git a/guides/source/active_storage_overview.md b/guides/source/active_storage_overview.md
index c72a38b1de..a7cb14c52a 100644
--- a/guides/source/active_storage_overview.md
+++ b/guides/source/active_storage_overview.md
@@ -121,6 +121,8 @@ Add the [`aws-sdk-s3`](https://github.com/aws/aws-sdk-ruby) gem to your `Gemfile
gem "aws-sdk-s3", require: false
```
+NOTE: The core features of Active Storage require the following permissions: `s3:ListBucket`, `s3:PutObject`, `s3:GetObject`, and `s3:DeleteObject`. If you have additional upload options configured such as setting ACLs then additional permissions may be required.
+
### Microsoft Azure Storage Service
Declare an Azure Storage service in `config/storage.yml`:
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index b42ffe50d8..1bdaf91c46 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -179,6 +179,7 @@ module Rails
values.reverse_merge!(shared)
end
end
+ loaded_yaml.reject! { |_, values| !values["database"] }
Hash.new(shared).merge(loaded_yaml)
elsif ENV["DATABASE_URL"]
# Value from ENV['DATABASE_URL'] is set to default database connection
diff --git a/railties/lib/rails/generators/rails/controller/controller_generator.rb b/railties/lib/rails/generators/rails/controller/controller_generator.rb
index 6d45d6e8f8..6e2495d45f 100644
--- a/railties/lib/rails/generators/rails/controller/controller_generator.rb
+++ b/railties/lib/rails/generators/rails/controller/controller_generator.rb
@@ -16,6 +16,7 @@ module Rails
def add_routes
return if options[:skip_routes]
+ return if actions.empty?
route generate_routing_code
end
diff --git a/railties/test/generators/api_app_generator_test.rb b/railties/test/generators/api_app_generator_test.rb
index 857124b23a..9c523ad372 100644
--- a/railties/test/generators/api_app_generator_test.rb
+++ b/railties/test/generators/api_app_generator_test.rb
@@ -13,7 +13,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
Rails.application = TestApp::Application
super
- Kernel::silence_warnings do
+ Kernel.silence_warnings do
Thor::Base.shell.send(:attr_accessor, :always_force)
@shell = Thor::Base.shell.new
@shell.send(:always_force=, true)
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index cc4a376d31..99790e602d 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -315,6 +315,15 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "Gemfile", /^# gem 'mini_magick'/
end
+ def test_mini_magick_gem_when_skip_active_storage_is_given
+ app_root = File.join(destination_root, "myapp")
+ run_generator [app_root, "--skip-active-storage"]
+
+ assert_file "#{app_root}/Gemfile" do |content|
+ assert_no_match(/gem 'mini_magick'/, content)
+ end
+ end
+
def test_app_update_does_not_generate_active_storage_contents_when_skip_active_storage_is_given
app_root = File.join(destination_root, "myapp")
run_generator [app_root, "--skip-active-storage"]
@@ -336,10 +345,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
assert_no_file "#{app_root}/config/storage.yml"
-
- assert_file "#{app_root}/Gemfile" do |content|
- assert_no_match(/gem 'mini_magick'/, content)
- end
end
def test_app_update_does_not_generate_active_storage_contents_when_skip_active_record_is_given
@@ -363,10 +368,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
assert_no_file "#{app_root}/config/storage.yml"
-
- assert_file "#{app_root}/Gemfile" do |content|
- assert_no_match(/gem 'mini_magick'/, content)
- end
end
def test_app_update_does_not_change_config_target_version
diff --git a/railties/test/generators/controller_generator_test.rb b/railties/test/generators/controller_generator_test.rb
index a3218951a6..91e4a86775 100644
--- a/railties/test/generators/controller_generator_test.rb
+++ b/railties/test/generators/controller_generator_test.rb
@@ -109,4 +109,11 @@ class ControllerGeneratorTest < Rails::Generators::TestCase
assert_match(/^ namespace :admin do\n get 'dashboard\/index'\n get 'dashboard\/show'\n end$/, route)
end
end
+
+ def test_does_not_add_routes_when_action_is_not_specified
+ run_generator ["admin/dashboard"]
+ assert_file "config/routes.rb" do |routes|
+ assert_no_match(/namespace :admin/, routes)
+ end
+ end
end
diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb
index 97d43af60a..aa577e4234 100644
--- a/railties/test/generators/shared_generator_tests.rb
+++ b/railties/test/generators/shared_generator_tests.rb
@@ -9,7 +9,7 @@ module SharedGeneratorTests
super
Rails::Generators::AppGenerator.instance_variable_set("@desc", nil)
- Kernel::silence_warnings do
+ Kernel.silence_warnings do
Thor::Base.shell.send(:attr_accessor, :always_force)
@shell = Thor::Base.shell.new
@shell.send(:always_force=, true)