1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge branch 'master' into unlock-minitest

This commit is contained in:
Kasper Timm Hansen 2017-05-29 20:37:35 +02:00
commit e1758b5e8c
421 changed files with 3517 additions and 2199 deletions

View file

@ -18,27 +18,27 @@ Style/BracesAroundHashParameters:
Enabled: true
# Align `when` with `case`.
Style/CaseIndentation:
Layout/CaseIndentation:
Enabled: true
# Align comments with method definitions.
Style/CommentIndentation:
Layout/CommentIndentation:
Enabled: true
# No extra empty lines.
Style/EmptyLines:
Layout/EmptyLines:
Enabled: true
# In a regular class definition, no empty lines around the body.
Style/EmptyLinesAroundClassBody:
Layout/EmptyLinesAroundClassBody:
Enabled: true
# In a regular method definition, no empty lines around the body.
Style/EmptyLinesAroundMethodBody:
Layout/EmptyLinesAroundMethodBody:
Enabled: true
# In a regular module definition, no empty lines around the body.
Style/EmptyLinesAroundModuleBody:
Layout/EmptyLinesAroundModuleBody:
Enabled: true
# Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
@ -47,30 +47,30 @@ Style/HashSyntax:
# Method definitions after `private` or `protected` isolated calls need one
# extra level of indentation.
Style/IndentationConsistency:
Layout/IndentationConsistency:
Enabled: true
EnforcedStyle: rails
# Two spaces, no tabs (for indentation).
Style/IndentationWidth:
Layout/IndentationWidth:
Enabled: true
Style/SpaceAfterColon:
Layout/SpaceAfterColon:
Enabled: true
Style/SpaceAfterComma:
Layout/SpaceAfterComma:
Enabled: true
Style/SpaceAroundEqualsInParameterDefault:
Layout/SpaceAroundEqualsInParameterDefault:
Enabled: true
Style/SpaceAroundKeyword:
Layout/SpaceAroundKeyword:
Enabled: true
Style/SpaceAroundOperators:
Layout/SpaceAroundOperators:
Enabled: true
Style/SpaceBeforeFirstArg:
Layout/SpaceBeforeFirstArg:
Enabled: true
# Defining a method with parameters needs parentheses.
@ -78,18 +78,18 @@ Style/MethodDefParentheses:
Enabled: true
# Use `foo {}` not `foo{}`.
Style/SpaceBeforeBlockBraces:
Layout/SpaceBeforeBlockBraces:
Enabled: true
# Use `foo { bar }` not `foo {bar}`.
Style/SpaceInsideBlockBraces:
Layout/SpaceInsideBlockBraces:
Enabled: true
# Use `{ a: 1 }` not `{a:1}`.
Style/SpaceInsideHashLiteralBraces:
Layout/SpaceInsideHashLiteralBraces:
Enabled: true
Style/SpaceInsideParens:
Layout/SpaceInsideParens:
Enabled: true
# Check quotes usage according to lint rule below.
@ -98,15 +98,15 @@ Style/StringLiterals:
EnforcedStyle: double_quotes
# Detect hard tabs, no hard tabs.
Style/Tab:
Layout/Tab:
Enabled: true
# Blank lines should not have any spaces.
Style/TrailingBlankLines:
Layout/TrailingBlankLines:
Enabled: true
# No trailing whitespace.
Style/TrailingWhitespace:
Layout/TrailingWhitespace:
Enabled: true
# Use quotes for string literals when they are enough.

View file

@ -98,17 +98,17 @@ matrix:
- "GEM=ar:postgresql POSTGRES=9.2"
addons:
postgresql: "9.2"
- rvm: jruby-9.1.8.0
- rvm: jruby-9.1.10.0
jdk: oraclejdk8
env:
- "GEM=ap"
- rvm: jruby-9.1.8.0
- rvm: jruby-9.1.10.0
jdk: oraclejdk8
env:
- "GEM=am,amo,aj"
allow_failures:
- rvm: ruby-head
- rvm: jruby-9.1.8.0
- rvm: jruby-9.1.10.0
- env: "GEM=ac:integration"
fast_finish: true

12
Gemfile
View file

@ -16,7 +16,7 @@ gem "rake", ">= 11.1"
# be loaded after loading the test library.
gem "mocha", "~> 0.14", require: false
gem "capybara", "~> 2.13.0"
gem "capybara", "~> 2.13"
gem "rack-cache", "~> 1.2"
gem "jquery-rails"
@ -33,8 +33,8 @@ gem "bcrypt", "~> 3.1.11", require: false
# sprockets.
gem "uglifier", ">= 1.3.0", require: false
# FIXME: Remove this fork after https://github.com/nex3/rb-inotify/pull/49 is fixed.
gem "rb-inotify", github: "matthewd/rb-inotify", branch: "close-handling", require: false
# FIXME: Pending rb-inotify 0.9.9 release
gem "rb-inotify", github: "guard/rb-inotify", branch: "master", require: false
# Explicitly avoid 1.x that doesn't support Ruby 2.4+
gem "json", ">= 2.0.0"
@ -90,7 +90,7 @@ group :cable do
end
# Add your own local bundler stuff.
local_gemfile = File.dirname(__FILE__) + "/.Gemfile"
local_gemfile = File.expand_path(".Gemfile", __dir__)
instance_eval File.read local_gemfile if File.exist? local_gemfile
group :test do
@ -153,3 +153,7 @@ end
gem "ibm_db" if ENV["IBM_DB"]
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem "wdm", ">= 0.1.0", platforms: [:mingw, :mswin, :x64_mingw, :mswin64]
platforms :ruby_25 do
gem "mathn"
end

View file

@ -7,12 +7,12 @@ GIT
pg (>= 0.17, < 0.20)
GIT
remote: https://github.com/matthewd/rb-inotify.git
revision: 90553518d1fb79aedc98a3036c59bd2b6731ac40
branch: close-handling
remote: https://github.com/guard/rb-inotify.git
revision: 7e3c714a09ae2b38d2620835e794150d8857cd49
branch: master
specs:
rb-inotify (0.9.7)
ffi (>= 0.5.0)
rb-inotify (0.9.9)
ffi (~> 1.0)
GIT
remote: https://github.com/matthewd/websocket-client-simple.git
@ -25,7 +25,7 @@ GIT
GIT
remote: https://github.com/rails/arel.git
revision: 437aa3a4bb8ad4f3f4eba299dbb1112852f9c7ac
revision: 5db56a513286814991c27000af2c0243cc19d1e2
specs:
arel (8.0.0)
@ -91,7 +91,7 @@ PATH
GEM
remote: https://rubygems.org/
specs:
addressable (2.5.0)
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
amq-protocol (2.1.0)
ast (2.3.0)
@ -125,7 +125,7 @@ GEM
bunny (2.6.2)
amq-protocol (>= 2.0.1)
byebug (9.0.6)
capybara (2.13.0)
capybara (2.14.0)
addressable
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@ -148,10 +148,10 @@ GEM
daemons (1.2.4)
dalli (2.7.6)
dante (0.2.0)
delayed_job (4.1.2)
activesupport (>= 3.0, < 5.1)
delayed_job_active_record (4.1.1)
activerecord (>= 3.0, < 5.1)
delayed_job (4.1.3)
activesupport (>= 3.0, < 5.2)
delayed_job_active_record (4.1.2)
activerecord (>= 3.0, < 5.2)
delayed_job (>= 3.0, < 5)
em-hiredis (0.3.1)
eventmachine (~> 1.0)
@ -207,8 +207,9 @@ GEM
ruby_dep (~> 1.2)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.4)
mail (2.6.5)
mime-types (>= 1.16, < 4)
mathn (0.1.0)
metaclass (0.0.4)
method_source (0.8.2)
mime-types (3.1)
@ -227,16 +228,17 @@ GEM
multi_json (1.12.1)
multipart-post (2.0.0)
mustache (1.0.3)
mysql2 (0.4.5)
mysql2 (0.4.5-x64-mingw32)
mysql2 (0.4.5-x86-mingw32)
mysql2 (0.4.6)
mysql2 (0.4.6-x64-mingw32)
mysql2 (0.4.6-x86-mingw32)
nio4r (2.0.0)
nokogiri (1.7.0.1)
nokogiri (1.7.1)
mini_portile2 (~> 2.1.0)
nokogiri (1.7.0.1-x64-mingw32)
nokogiri (1.7.1-x64-mingw32)
mini_portile2 (~> 2.1.0)
nokogiri (1.7.0.1-x86-mingw32)
nokogiri (1.7.1-x86-mingw32)
mini_portile2 (~> 2.1.0)
parallel (1.11.2)
parser (2.4.0.0)
ast (~> 2.2)
path_expander (1.0.1)
@ -255,10 +257,10 @@ GEM
simple_uuid
que (0.12.0)
racc (1.4.14)
rack (2.0.1)
rack (2.0.3)
rack-cache (1.6.1)
rack (>= 0.4)
rack-protection (1.5.3)
rack-protection (2.0.0)
rack
rack-test (0.6.3)
rack (>= 1.0)
@ -267,12 +269,13 @@ GEM
nokogiri (~> 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
rainbow (2.2.1)
rainbow (2.2.2)
rake
rake (12.0.0)
rb-fsevent (0.9.8)
rdoc (5.1.0)
redcarpet (3.2.3)
redis (3.3.2)
redis (3.3.3)
redis-namespace (1.5.2)
redis (~> 3.0, >= 3.0.4)
resque (1.27.0)
@ -286,7 +289,8 @@ GEM
redis (~> 3.3)
resque (~> 1.26)
rufus-scheduler (~> 3.2)
rubocop (0.48.1)
rubocop (0.49.0)
parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
@ -313,11 +317,11 @@ GEM
sequel (4.42.1)
serverengine (1.5.11)
sigdump (~> 0.2.2)
sidekiq (4.2.9)
sidekiq (5.0.0)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0)
redis (~> 3.2, >= 3.2.1)
redis (~> 3.3, >= 3.3.3)
sigdump (0.2.4)
simple_uuid (0.4.0)
sinatra (1.0)
@ -389,7 +393,7 @@ DEPENDENCIES
blade
blade-sauce_labs_plugin
byebug
capybara (~> 2.13.0)
capybara (~> 2.13)
coffee-rails
dalli (>= 2.2.1)
delayed_job
@ -402,6 +406,7 @@ DEPENDENCIES
kindlerb (~> 1.2.0)
libxml-ruby
listen (>= 3.0.5, < 3.2)
mathn
minitest-bisect
mocha (~> 0.14)
mysql2 (>= 0.4.4)
@ -439,4 +444,4 @@ DEPENDENCIES
websocket-client-simple!
BUNDLED WITH
1.14.6
1.15.0

View file

@ -1,6 +1,6 @@
require "net/http"
$:.unshift File.expand_path("..", __FILE__)
$:.unshift __dir__
require "tasks/release"
require "railties/lib/rails/api/task"

View file

@ -3,5 +3,6 @@
Previously any socket errors were ignored and this made it hard to diagnose socket issues (e.g. as discussed in #28362).
*Edward Poot*
Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/actioncable/CHANGELOG.md) for previous changes.

View file

@ -409,7 +409,7 @@ application. The recommended basic setup is as follows:
```ruby
# cable/config.ru
require ::File.expand_path('../../config/environment', __FILE__)
require ::File.expand_path('../config/environment', __dir__)
Rails.application.eager_load!
run ActionCable.server

View file

@ -3,15 +3,13 @@ require "pathname"
require "open3"
require "action_cable"
dir = File.dirname(__FILE__)
task default: :test
task package: %w( assets:compile assets:verify )
Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = Dir.glob("#{dir}/test/**/*_test.rb")
t.test_files = Dir.glob("#{__dir__}/test/**/*_test.rb")
t.warning = true
t.verbose = true
t.ruby_opts = ["--dev"] if defined?(JRUBY_VERSION)
@ -46,7 +44,7 @@ namespace :assets do
desc "Verify compiled Action Cable assets"
task :verify do
file = "lib/assets/compiled/action_cable.js"
pathname = Pathname.new("#{dir}/#{file}")
pathname = Pathname.new("#{__dir__}/#{file}")
print "[verify] #{file} exists "
if pathname.exist?
@ -64,8 +62,8 @@ namespace :assets do
fail
end
print "[verify] #{dir} can be required as a module "
stdout, stderr, status = Open3.capture3("node", "--print", "window = {}; require('#{dir}');")
print "[verify] #{__dir__} can be required as a module "
_, stderr, status = Open3.capture3("node", "--print", "window = {}; require('#{__dir__}');")
if status.success?
puts "[OK]"
else

View file

@ -1,4 +1,4 @@
version = File.read(File.expand_path("../../RAILS_VERSION", __FILE__)).strip
version = File.read(File.expand_path("../RAILS_VERSION", __dir__)).strip
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY

View file

@ -4,8 +4,7 @@ module ActionCable
extend ActiveSupport::Concern
included do
class_attribute :periodic_timers, instance_reader: false
self.periodic_timers = []
class_attribute :periodic_timers, instance_reader: false, default: []
after_subscribe :start_periodic_timers
after_unsubscribe :stop_periodic_timers

View file

@ -6,8 +6,7 @@ module ActionCable
extend ActiveSupport::Concern
included do
class_attribute :identifiers
self.identifiers = Set.new
class_attribute :identifiers, default: Set.new
end
class_methods do

View file

@ -45,7 +45,7 @@ module ActionCable
end
# Returns all the identifiers that were applied to this connection.
def identifiers
redefine_method :identifiers do
server.connection_identifiers
end

View file

@ -1,7 +1,7 @@
module Rails
module Generators
class ChannelGenerator < NamedBase
source_root File.expand_path("../templates", __FILE__)
source_root File.expand_path("templates", __dir__)
argument :actions, type: :array, default: [], banner: "method method"

View file

@ -11,7 +11,7 @@ rescue LoadError
end
# Require all the stubs and models
Dir[File.dirname(__FILE__) + "/stubs/*.rb"].each { |file| require file }
Dir[File.expand_path("stubs/*.rb", __dir__)].each { |file| require file }
class ActionCable::TestCase < ActiveSupport::TestCase
def wait_for_async

View file

@ -1,4 +1,4 @@
version = File.read(File.expand_path("../../RAILS_VERSION", __FILE__)).strip
version = File.read(File.expand_path("../RAILS_VERSION", __dir__)).strip
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY

View file

@ -25,6 +25,7 @@ require "abstract_controller"
require "action_mailer/version"
# Common Active Support usage in Action Mailer
require "active_support"
require "active_support/rails"
require "active_support/core_ext/class"
require "active_support/core_ext/module/attr_internal"

View file

@ -459,8 +459,7 @@ module ActionMailer
helper ActionMailer::MailHelper
class_attribute :default_params
self.default_params = {
class_attribute :default_params, default: {
mime_version: "1.0",
charset: "UTF-8",
content_type: "text/plain",

View file

@ -7,8 +7,6 @@ module ActionMailer
extend ActiveSupport::Concern
included do
class_attribute :delivery_methods, :delivery_method
# Do not make this inheritable, because we always want it to propagate
cattr_accessor :raise_delivery_errors
self.raise_delivery_errors = true
@ -19,8 +17,8 @@ module ActionMailer
cattr_accessor :deliver_later_queue_name
self.deliver_later_queue_name = :mailers
self.delivery_methods = {}.freeze
self.delivery_method = :smtp
class_attribute :delivery_methods, default: {}.freeze
class_attribute :delivery_method, default: :smtp
add_delivery_method :smtp, Mail::SMTP,
address: "localhost",

View file

@ -1,7 +1,7 @@
module Rails
module Generators
class MailerGenerator < NamedBase
source_root File.expand_path("../templates", __FILE__)
source_root File.expand_path("templates", __dir__)
argument :actions, type: :array, default: [], banner: "method method"

View file

@ -9,7 +9,7 @@ end
module Rails
def self.root
File.expand_path("../", File.dirname(__FILE__))
File.expand_path("..", __dir__)
end
end
@ -28,7 +28,7 @@ ActiveSupport::Deprecation.debug = true
# Disable available locale checks to avoid warnings running the test suite.
I18n.enforce_available_locales = false
FIXTURE_LOAD_PATH = File.expand_path("fixtures", File.dirname(__FILE__))
FIXTURE_LOAD_PATH = File.expand_path("fixtures", __dir__)
ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH
class ActiveSupport::TestCase

View file

@ -5,7 +5,7 @@ require "mailers/caching_mailer"
CACHE_DIR = "test_cache"
# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed
FILE_STORE_PATH = File.join(File.dirname(__FILE__), "/../temp/", CACHE_DIR)
FILE_STORE_PATH = File.join(__dir__, "/../temp/", CACHE_DIR)
class FragmentCachingMailer < ActionMailer::Base
abstract!
@ -21,10 +21,6 @@ class BaseCachingTest < ActiveSupport::TestCase
@mailer.perform_caching = true
@mailer.cache_store = @store
end
def test_fragment_cache_key
assert_equal "views/what a key", @mailer.fragment_cache_key("what a key")
end
end
class FragmentCachingTest < BaseCachingTest
@ -126,7 +122,7 @@ class FunctionalFragmentCachingTest < BaseCachingTest
assert_match expected_body, email.body.encoded
assert_match expected_body,
@store.read("views/caching/#{template_digest("caching_mailer/fragment_cache")}")
@store.read("views/caching_mailer/fragment_cache:#{template_digest("caching_mailer/fragment_cache")}/caching")
end
def test_fragment_caching_in_partials
@ -135,7 +131,7 @@ class FunctionalFragmentCachingTest < BaseCachingTest
assert_match(expected_body, email.body.encoded)
assert_match(expected_body,
@store.read("views/caching/#{template_digest("caching_mailer/_partial")}"))
@store.read("views/caching_mailer/_partial:#{template_digest("caching_mailer/_partial")}/caching"))
end
def test_skip_fragment_cache_digesting
@ -185,7 +181,7 @@ class FunctionalFragmentCachingTest < BaseCachingTest
end
assert_equal "caching_mailer", payload[:mailer]
assert_equal "views/caching/#{template_digest("caching_mailer/fragment_cache")}", payload[:key]
assert_equal [ :views, "caching_mailer/fragment_cache:#{template_digest("caching_mailer/fragment_cache")}", :caching ], payload[:key]
ensure
@mailer.enable_fragment_cache_logging = true
end

View file

@ -26,7 +26,7 @@ class AMLogSubscriberTest < ActionMailer::TestCase
wait
assert_equal(1, @logger.logged(:info).size)
assert_match(/Sent mail to system@test.lindsaar.net/, @logger.logged(:info).first)
assert_match(/Sent mail to system@test\.lindsaar\.net/, @logger.logged(:info).first)
assert_equal(2, @logger.logged(:debug).size)
assert_match(/BaseMailer#welcome: processed outbound mail in [\d.]+ms/, @logger.logged(:debug).first)
@ -36,7 +36,7 @@ class AMLogSubscriberTest < ActionMailer::TestCase
end
def test_receive_is_notified
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email")
fixture = File.read(File.expand_path("fixtures/raw_email", __dir__))
TestMailer.receive(fixture)
wait
assert_equal(1, @logger.logged(:info).size)

View file

@ -1,4 +1,27 @@
* Add `action_controller_api` and `action_controller_base` load hooks to be called in `ActiveSupport.on_load`
* AEAD encrypted cookies and sessions with GCM
Encrypted cookies now use AES-GCM which couples authentication and
encryption in one faster step and produces shorter ciphertexts. Cookies
encrypted using AES in CBC HMAC mode will be seamlessly upgraded when
this new mode is enabled via the
`action_dispatch.use_authenticated_cookie_encryption` configuration value.
*Michael J Coyne*
* Change the cache key format for fragments to make it easier to debug key churn. The new format is:
views/template/action.html.erb:7a1156131a6928cb0026877f8b749ac9/projects/123
^template path ^template tree digest ^class ^id
*DHH*
* Add support for recyclable cache keys with fragment caching. This uses the new versioned entries in the
`ActiveSupport::Cache` stores and relies on the fact that Active Record has split `#cache_key` and `#cache_version`
to support it.
*DHH*
* Add `action_controller_api` and `action_controller_base` load hooks to be called in `ActiveSupport.on_load`
`ActionController::Base` and `ActionController::API` have differing implementations. This means that
the one umbrella hook `action_controller` is not able to address certain situations where a method
@ -10,4 +33,5 @@
*Julian Nadeau*
Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/actionpack/CHANGELOG.md) for previous changes.

View file

@ -26,7 +26,7 @@ namespace :test do
end
task :lines do
load File.expand_path("..", File.dirname(__FILE__)) + "/tools/line_statistics"
load File.expand_path("..", __dir__) + "/tools/line_statistics"
files = FileList["lib/**/*.rb"]
CodeTools::LineStatistics.new(files).print_loc
end

View file

@ -1,4 +1,4 @@
version = File.read(File.expand_path("../../RAILS_VERSION", __FILE__)).strip
version = File.read(File.expand_path("../RAILS_VERSION", __dir__)).strip
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY

View file

@ -14,8 +14,16 @@ module AbstractController
# expected to provide their own +render+ method, since rendering means
# different things depending on the context.
class Base
##
# Returns the body of the HTTP response sent by the controller.
attr_internal :response_body
##
# Returns the name of the action this controller is processing.
attr_internal :action_name
##
# Returns the formats that can be processed by the controller.
attr_internal :formats
include ActiveSupport::Configurable

View file

@ -37,8 +37,7 @@ module AbstractController
config_accessor :enable_fragment_cache_logging
self.enable_fragment_cache_logging = false
class_attribute :_view_cache_dependencies
self._view_cache_dependencies = []
class_attribute :_view_cache_dependencies, default: []
helper_method :view_cache_dependencies if respond_to?(:helper_method)
end

View file

@ -25,7 +25,10 @@ module AbstractController
self.fragment_cache_keys = []
helper_method :fragment_cache_key if respond_to?(:helper_method)
if respond_to?(:helper_method)
helper_method :fragment_cache_key
helper_method :combined_fragment_cache_key
end
end
module ClassMethods
@ -62,17 +65,36 @@ module AbstractController
# with the specified +key+ value. The key is expanded using
# ActiveSupport::Cache.expand_cache_key.
def fragment_cache_key(key)
ActiveSupport::Deprecation.warn(<<-MSG.squish)
Calling fragment_cache_key directly is deprecated and will be removed in Rails 6.0.
All fragment accessors now use the combined_fragment_cache_key method that retains the key as an array,
such that the caching stores can interrogate the parts for cache versions used in
recyclable cache keys.
MSG
head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
ActiveSupport::Cache.expand_cache_key([*head, *tail], :views)
end
# Given a key (as described in +expire_fragment+), returns
# a key array suitable for use in reading, writing, or expiring a
# cached fragment. All keys begin with <tt>:views</tt>,
# followed by ENV["RAILS_CACHE_ID"] or ENV["RAILS_APP_VERSION"] if set,
# followed by any controller-wide key prefix values, ending
# with the specified +key+ value.
def combined_fragment_cache_key(key)
head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
[ :views, (ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]), *head, *tail ].compact
end
# Writes +content+ to the location signified by
# +key+ (see +expire_fragment+ for acceptable formats).
def write_fragment(key, content, options = nil)
return content unless cache_configured?
key = fragment_cache_key(key)
key = combined_fragment_cache_key(key)
instrument_fragment_cache :write_fragment, key do
content = content.to_str
cache_store.write(key, content, options)
@ -85,7 +107,7 @@ module AbstractController
def read_fragment(key, options = nil)
return unless cache_configured?
key = fragment_cache_key(key)
key = combined_fragment_cache_key(key)
instrument_fragment_cache :read_fragment, key do
result = cache_store.read(key, options)
result.respond_to?(:html_safe) ? result.html_safe : result
@ -96,7 +118,7 @@ module AbstractController
# +key+ exists (see +expire_fragment+ for acceptable formats).
def fragment_exist?(key, options = nil)
return unless cache_configured?
key = fragment_cache_key(key)
key = combined_fragment_cache_key(key)
instrument_fragment_cache :exist_fragment?, key do
cache_store.exist?(key, options)
@ -123,7 +145,7 @@ module AbstractController
# method (or <tt>delete_matched</tt>, for Regexp keys).
def expire_fragment(key, options = nil)
return unless cache_configured?
key = fragment_cache_key(key) unless key.is_a?(Regexp)
key = combined_fragment_cache_key(key) unless key.is_a?(Regexp)
instrument_fragment_cache :expire_fragment, key do
if key.is_a?(Regexp)
@ -135,8 +157,7 @@ module AbstractController
end
def instrument_fragment_cache(name, key) # :nodoc:
payload = instrument_payload(key)
ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", payload) { yield }
ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key)) { yield }
end
end
end

View file

@ -1,4 +1,24 @@
module AbstractController
# = Abstract Controller Callbacks
#
# Abstract Controller provides hooks during the life cycle of a controller action.
# Callbacks allow you to trigger logic during this cycle. Available callbacks are:
#
# * <tt>after_action</tt>
# * <tt>append_after_action</tt>
# * <tt>append_around_action</tt>
# * <tt>append_before_action</tt>
# * <tt>around_action</tt>
# * <tt>before_action</tt>
# * <tt>prepend_after_action</tt>
# * <tt>prepend_around_action</tt>
# * <tt>prepend_before_action</tt>
# * <tt>skip_after_action</tt>
# * <tt>skip_around_action</tt>
# * <tt>skip_before_action</tt>
#
# NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
#
module Callbacks
extend ActiveSupport::Concern

View file

@ -5,11 +5,8 @@ module AbstractController
extend ActiveSupport::Concern
included do
class_attribute :_helpers
self._helpers = Module.new
class_attribute :_helper_methods
self._helper_methods = Array.new
class_attribute :_helpers, default: Module.new
class_attribute :_helper_methods, default: Array.new
end
class MissingHelperError < LoadError

View file

@ -60,9 +60,9 @@ module ActionController
class_eval <<-METHOD, __FILE__, __LINE__ + 1
def #{method}(event)
return unless logger.info? && ActionController::Base.enable_fragment_cache_logging
key_or_path = event.payload[:key] || event.payload[:path]
key = ActiveSupport::Cache.expand_cache_key(event.payload[:key] || event.payload[:path])
human_name = #{method.to_s.humanize.inspect}
info("\#{human_name} \#{key_or_path} (\#{event.duration.round(1)}ms)")
info("\#{human_name} \#{key} (\#{event.duration.round(1)}ms)")
end
METHOD
end

View file

@ -208,8 +208,7 @@ module ActionController
@_request.reset_session
end
class_attribute :middleware_stack
self.middleware_stack = ActionController::MiddlewareStack.new
class_attribute :middleware_stack, default: ActionController::MiddlewareStack.new
def self.inherited(base) # :nodoc:
base.middleware_stack = middleware_stack.dup

View file

@ -7,8 +7,7 @@ module ActionController
include Head
included do
class_attribute :etaggers
self.etaggers = []
class_attribute :etaggers, default: []
end
module ClassMethods

View file

@ -22,8 +22,7 @@ module ActionController
include ActionController::ConditionalGet
included do
class_attribute :etag_with_template_digest
self.etag_with_template_digest = true
class_attribute :etag_with_template_digest, default: true
ActiveSupport.on_load :action_view, yield: true do
etag do |options|

View file

@ -3,8 +3,7 @@ module ActionController #:nodoc:
extend ActiveSupport::Concern
included do
class_attribute :_flash_types, instance_accessor: false
self._flash_types = []
class_attribute :_flash_types, instance_accessor: false, default: []
delegate :flash, to: :request
add_flash_types(:alert, :notice)

View file

@ -53,9 +53,8 @@ module ActionController
include AbstractController::Helpers
included do
class_attribute :helpers_path, :include_all_helpers
self.helpers_path ||= []
self.include_all_helpers = true
class_attribute :helpers_path, default: []
class_attribute :include_all_helpers, default: true
end
module ClassMethods

View file

@ -159,8 +159,7 @@ module ActionController
end
included do
class_attribute :_wrapper_options
self._wrapper_options = Options.from_hash(format: [])
class_attribute :_wrapper_options, default: Options.from_hash(format: [])
end
module ClassMethods

View file

@ -26,8 +26,7 @@ module ActionController
RENDERERS = Set.new
included do
class_attribute :_renderers
self._renderers = Set.new.freeze
class_attribute :_renderers, default: Set.new.freeze
end
# Used in <tt>ActionController::Base</tt>

View file

@ -666,8 +666,8 @@ module ActionController
# to key. If the key is not found, returns the default value. If the
# optional code block is given and the key is not found, pass in the key
# and return the result of block.
def delete(key)
convert_value_to_parameters(@parameters.delete(key))
def delete(key, &block)
convert_value_to_parameters(@parameters.delete(key, &block))
end
# Returns a new instance of <tt>ActionController::Parameters</tt> with only

View file

@ -27,14 +27,18 @@ module ActionDispatch
@tempfile = hash[:tempfile]
raise(ArgumentError, ":tempfile is required") unless @tempfile
@original_filename = hash[:filename]
if @original_filename
if hash[:filename]
@original_filename = hash[:filename].dup
begin
@original_filename.encode!(Encoding::UTF_8)
rescue EncodingError
@original_filename.force_encoding(Encoding::UTF_8)
end
else
@original_filename = nil
end
@content_type = hash[:type]
@headers = hash[:head]
end

View file

@ -18,14 +18,6 @@ module ActionDispatch
@tt = transition_table
end
def simulate(string)
ms = memos(string) { return }
MatchData.new(ms)
end
alias :=~ :simulate
alias :match :simulate
def memos(string)
input = StringScanner.new(string)
state = [0]

View file

@ -82,7 +82,7 @@ module ActionDispatch
end
def visualizer(paths, title = "FSM")
viz_dir = File.join File.dirname(__FILE__), "..", "visualizer"
viz_dir = File.join __dir__, "..", "visualizer"
fsm_js = File.read File.join(viz_dir, "fsm.js")
fsm_css = File.read File.join(viz_dir, "fsm.css")
erb = File.read File.join(viz_dir, "index.html.erb")

View file

@ -13,11 +13,13 @@ module ActionDispatch
# normalize_path("") # => "/"
# normalize_path("/%ab") # => "/%AB"
def self.normalize_path(path)
encoding = path.encoding
path = "/#{path}"
path.squeeze!("/".freeze)
path.sub!(%r{/+\Z}, "".freeze)
path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase }
path = "/" if path == "".freeze
path.force_encoding(encoding)
path
end
@ -59,11 +61,11 @@ module ActionDispatch
end
private
def escape(component, pattern) # :doc:
def escape(component, pattern)
component.gsub(pattern) { |unsafe| percent_encode(unsafe) }.force_encoding(US_ASCII)
end
def percent_encode(unsafe) # :doc:
def percent_encode(unsafe)
safe = EMPTY.dup
unsafe.each_byte { |b| safe << DEC2HEX[b] }
safe
@ -84,6 +86,10 @@ module ActionDispatch
ENCODER.escape_fragment(fragment.to_s)
end
# Replaces any escaped sequences with their unescaped representations.
#
# uri = "/topics?title=Ruby%20on%20Rails"
# unescape_uri(uri) #=> "/topics?title=Ruby on Rails"
def self.unescape_uri(uri)
ENCODER.unescape_uri(uri)
end

View file

@ -43,6 +43,10 @@ module ActionDispatch
get_header Cookies::ENCRYPTED_SIGNED_COOKIE_SALT
end
def authenticated_encrypted_cookie_salt
get_header Cookies::AUTHENTICATED_ENCRYPTED_COOKIE_SALT
end
def secret_token
get_header Cookies::SECRET_TOKEN
end
@ -149,6 +153,7 @@ module ActionDispatch
SIGNED_COOKIE_SALT = "action_dispatch.signed_cookie_salt".freeze
ENCRYPTED_COOKIE_SALT = "action_dispatch.encrypted_cookie_salt".freeze
ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt".freeze
AUTHENTICATED_ENCRYPTED_COOKIE_SALT = "action_dispatch.authenticated_encrypted_cookie_salt".freeze
SECRET_TOKEN = "action_dispatch.secret_token".freeze
SECRET_KEY_BASE = "action_dispatch.secret_key_base".freeze
COOKIES_SERIALIZER = "action_dispatch.cookies_serializer".freeze
@ -207,6 +212,9 @@ module ActionDispatch
# If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
# legacy cookies signed with the old key generator will be transparently upgraded.
#
# If +config.action_dispatch.encrypted_cookie_salt+ and +config.action_dispatch.encrypted_signed_cookie_salt+
# are both set, legacy cookies encrypted with HMAC AES-256-CBC will be transparently upgraded.
#
# This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
#
# Example:
@ -219,6 +227,8 @@ module ActionDispatch
@encrypted ||=
if upgrade_legacy_signed_cookies?
UpgradeLegacyEncryptedCookieJar.new(self)
elsif upgrade_legacy_hmac_aes_cbc_cookies?
UpgradeLegacyHmacAesCbcCookieJar.new(self)
else
EncryptedCookieJar.new(self)
end
@ -240,6 +250,13 @@ module ActionDispatch
def upgrade_legacy_signed_cookies?
request.secret_token.present? && request.secret_key_base.present?
end
def upgrade_legacy_hmac_aes_cbc_cookies?
request.secret_key_base.present? &&
request.authenticated_encrypted_cookie_salt.present? &&
request.encrypted_signed_cookie_salt.present? &&
request.encrypted_cookie_salt.present?
end
end
# Passing the ActiveSupport::MessageEncryptor::NullSerializer downstream
@ -576,9 +593,11 @@ module ActionDispatch
"Read the upgrade documentation to learn more about this new config option."
end
secret = key_generator.generate_key(request.encrypted_cookie_salt || "")[0, ActiveSupport::MessageEncryptor.key_len]
sign_secret = key_generator.generate_key(request.encrypted_signed_cookie_salt || "")
@encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
cipher = "aes-256-gcm"
key_len = ActiveSupport::MessageEncryptor.key_len(cipher)
secret = key_generator.generate_key(request.authenticated_encrypted_cookie_salt || "")[0, key_len]
@encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
end
private
@ -603,6 +622,32 @@ module ActionDispatch
include VerifyAndUpgradeLegacySignedMessage
end
# UpgradeLegacyHmacAesCbcCookieJar is used by ActionDispatch::Session::CookieStore
# to upgrade cookies encrypted with AES-256-CBC with HMAC to AES-256-GCM
class UpgradeLegacyHmacAesCbcCookieJar < EncryptedCookieJar
def initialize(parent_jar)
super
secret = key_generator.generate_key(request.encrypted_cookie_salt || "")[0, ActiveSupport::MessageEncryptor.key_len]
sign_secret = key_generator.generate_key(request.encrypted_signed_cookie_salt || "")
@legacy_encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
end
def decrypt_and_verify_legacy_encrypted_message(name, signed_message)
deserialize(name, @legacy_encryptor.decrypt_and_verify(signed_message)).tap do |value|
self[name] = { value: value }
end
rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage
nil
end
private
def parse(name, signed_message)
super || decrypt_and_verify_legacy_encrypted_message(name, signed_message)
end
end
def initialize(app)
@app = app
end

View file

@ -10,7 +10,7 @@ module ActionDispatch
# This middleware is responsible for logging exceptions and
# showing a debugging page in case the request is local.
class DebugExceptions
RESCUES_TEMPLATE_PATH = File.expand_path("../templates", __FILE__)
RESCUES_TEMPLATE_PATH = File.expand_path("templates", __dir__)
class DebugView < ActionView::Base
def debug_params(params)

View file

@ -16,6 +16,7 @@ module ActionDispatch
config.action_dispatch.signed_cookie_salt = "signed cookie"
config.action_dispatch.encrypted_cookie_salt = "encrypted cookie"
config.action_dispatch.encrypted_signed_cookie_salt = "signed encrypted cookie"
config.action_dispatch.use_authenticated_cookie_encryption = false
config.action_dispatch.perform_deep_munge = true
config.action_dispatch.default_headers = {
@ -36,6 +37,8 @@ module ActionDispatch
ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses)
ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates)
config.action_dispatch.authenticated_encrypted_cookie_salt = "authenticated encrypted cookie" if config.action_dispatch.use_authenticated_cookie_encryption
config.action_dispatch.always_write_cookie = Rails.env.development? if config.action_dispatch.always_write_cookie.nil?
ActionDispatch::Cookies::CookieJar.always_write_cookie = config.action_dispatch.always_write_cookie

View file

@ -101,11 +101,13 @@ module ActionDispatch
# Returns keys of the session as Array.
def keys
load_for_read!
@delegate.keys
end
# Returns values of the session as Array.
def values
load_for_read!
@delegate.values
end

View file

@ -2,7 +2,12 @@ module ActionDispatch
module SystemTesting
module TestHelpers
module SetupAndTeardown # :nodoc:
DEFAULT_HOST = "127.0.0.1"
DEFAULT_HOST = "http://127.0.0.1"
def host!(host)
super
Capybara.app_host = host
end
def before_setup
host! DEFAULT_HOST

View file

@ -1,6 +1,6 @@
$:.unshift(File.dirname(__FILE__) + "/lib")
$:.unshift(File.dirname(__FILE__) + "/fixtures/helpers")
$:.unshift(File.dirname(__FILE__) + "/fixtures/alternate_helpers")
$:.unshift File.expand_path("lib", __dir__)
$:.unshift File.expand_path("fixtures/helpers", __dir__)
$:.unshift File.expand_path("fixtures/alternate_helpers", __dir__)
require "active_support/core_ext/kernel/reporting"
@ -56,7 +56,7 @@ ActiveSupport::Deprecation.debug = true
# Disable available locale checks to avoid warnings running the test suite.
I18n.enforce_available_locales = false
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), "fixtures")
FIXTURE_LOAD_PATH = File.join(__dir__, "fixtures")
SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
@ -156,7 +156,7 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
end
def with_autoload_path(path)
path = File.join(File.dirname(__FILE__), "fixtures", path)
path = File.join(__dir__, "fixtures", path)
if ActiveSupport::Dependencies.autoload_paths.include?(path)
yield
else

View file

@ -83,7 +83,7 @@ class ActionPackAssertionsController < ActionController::Base
end
def render_file_absolute_path
render file: File.expand_path("../../../README.rdoc", __FILE__)
render file: File.expand_path("../../README.rdoc", __dir__)
end
def render_file_relative_path

View file

@ -1,7 +1,7 @@
require "abstract_unit"
module TestApiFileUtils
def file_path() File.expand_path(__FILE__) end
def file_path() __FILE__ end
def file_data() @data ||= File.open(file_path, "rb") { |f| f.read } end
end

View file

@ -4,7 +4,7 @@ require "lib/controller/fake_models"
CACHE_DIR = "test_cache"
# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed
FILE_STORE_PATH = File.join(File.dirname(__FILE__), "/../temp/", CACHE_DIR)
FILE_STORE_PATH = File.join(__dir__, "../temp/", CACHE_DIR)
class FragmentCachingMetalTestController < ActionController::Metal
abstract!
@ -26,10 +26,6 @@ class FragmentCachingMetalTest < ActionController::TestCase
@controller.request = @request
@controller.response = @response
end
def test_fragment_cache_key
assert_equal "views/what a key", @controller.fragment_cache_key("what a key")
end
end
class CachingController < ActionController::Base
@ -43,6 +39,8 @@ class FragmentCachingTestController < CachingController
end
class FragmentCachingTest < ActionController::TestCase
ModelWithKeyAndVersion = Struct.new(:cache_key, :cache_version)
def setup
super
@store = ActiveSupport::Cache::MemoryStore.new
@ -53,12 +51,25 @@ class FragmentCachingTest < ActionController::TestCase
@controller.params = @params
@controller.request = @request
@controller.response = @response
@m1v1 = ModelWithKeyAndVersion.new("model/1", "1")
@m1v2 = ModelWithKeyAndVersion.new("model/1", "2")
@m2v1 = ModelWithKeyAndVersion.new("model/2", "1")
@m2v2 = ModelWithKeyAndVersion.new("model/2", "2")
end
def test_fragment_cache_key
assert_equal "views/what a key", @controller.fragment_cache_key("what a key")
assert_equal "views/test.host/fragment_caching_test/some_action",
@controller.fragment_cache_key(controller: "fragment_caching_test", action: "some_action")
assert_deprecated do
assert_equal "views/what a key", @controller.fragment_cache_key("what a key")
assert_equal "views/test.host/fragment_caching_test/some_action",
@controller.fragment_cache_key(controller: "fragment_caching_test", action: "some_action")
end
end
def test_combined_fragment_cache_key
assert_equal [ :views, "what a key" ], @controller.combined_fragment_cache_key("what a key")
assert_equal [ :views, "test.host/fragment_caching_test/some_action" ],
@controller.combined_fragment_cache_key(controller: "fragment_caching_test", action: "some_action")
end
def test_read_fragment_with_caching_enabled
@ -72,6 +83,12 @@ class FragmentCachingTest < ActionController::TestCase
assert_nil @controller.read_fragment("name")
end
def test_read_fragment_with_versioned_model
@controller.write_fragment([ "stuff", @m1v1 ], "hello")
assert_equal "hello", @controller.read_fragment([ "stuff", @m1v1 ])
assert_nil @controller.read_fragment([ "stuff", @m1v2 ])
end
def test_fragment_exist_with_caching_enabled
@store.write("views/name", "value")
assert @controller.fragment_exist?("name")
@ -198,7 +215,7 @@ CACHED
assert_equal expected_body, @response.body
assert_equal "This bit's fragment cached",
@store.read("views/test.host/functional_caching/fragment_cached/#{template_digest("functional_caching/fragment_cached")}")
@store.read("views/functional_caching/fragment_cached:#{template_digest("functional_caching/fragment_cached")}/fragment")
end
def test_fragment_caching_in_partials
@ -207,7 +224,7 @@ CACHED
assert_match(/Old fragment caching in a partial/, @response.body)
assert_match("Old fragment caching in a partial",
@store.read("views/test.host/functional_caching/html_fragment_cached_with_partial/#{template_digest("functional_caching/_partial")}"))
@store.read("views/functional_caching/_partial:#{template_digest("functional_caching/_partial")}/test.host/functional_caching/html_fragment_cached_with_partial"))
end
def test_skipping_fragment_cache_digesting
@ -237,7 +254,7 @@ CACHED
assert_match(/Some inline content/, @response.body)
assert_match(/Some cached content/, @response.body)
assert_match("Some cached content",
@store.read("views/test.host/functional_caching/inline_fragment_cached/#{template_digest("functional_caching/inline_fragment_cached")}"))
@store.read("views/functional_caching/inline_fragment_cached:#{template_digest("functional_caching/inline_fragment_cached")}/test.host/functional_caching/inline_fragment_cached"))
end
def test_fragment_cache_instrumentation
@ -264,7 +281,7 @@ CACHED
assert_equal expected_body, @response.body
assert_equal "<p>ERB</p>",
@store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached")}")
@store.read("views/functional_caching/formatted_fragment_cached:#{template_digest("functional_caching/formatted_fragment_cached")}/fragment")
end
def test_xml_formatted_fragment_caching
@ -275,7 +292,7 @@ CACHED
assert_equal expected_body, @response.body
assert_equal " <p>Builder</p>\n",
@store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached")}")
@store.read("views/functional_caching/formatted_fragment_cached:#{template_digest("functional_caching/formatted_fragment_cached")}/fragment")
end
def test_fragment_caching_with_variant
@ -286,7 +303,7 @@ CACHED
assert_equal expected_body, @response.body
assert_equal "<p>PHONE</p>",
@store.read("views/test.host/functional_caching/formatted_fragment_cached_with_variant/#{template_digest("functional_caching/formatted_fragment_cached_with_variant")}")
@store.read("views/functional_caching/formatted_fragment_cached_with_variant:#{template_digest("functional_caching/formatted_fragment_cached_with_variant")}/fragment")
end
private
@ -412,7 +429,7 @@ class CollectionCacheTest < ActionController::TestCase
def test_collection_fetches_cached_views
get :index
assert_equal 1, @controller.partial_rendered_times
assert_customer_cached "david/1", "david, 1"
assert_match "david, 1", ActionView::PartialRenderer.collection_cache.read("views/customers/_customer:7c228ab609f0baf0b1f2367469210937/david/1")
get :index
assert_equal 1, @controller.partial_rendered_times
@ -444,14 +461,8 @@ class CollectionCacheTest < ActionController::TestCase
def test_caching_with_callable_cache_key
get :index_with_callable_cache_key
assert_customer_cached "cached_david", "david, 1"
assert_match "david, 1", ActionView::PartialRenderer.collection_cache.read("views/customers/_customer:7c228ab609f0baf0b1f2367469210937/cached_david")
end
private
def assert_customer_cached(key, content)
assert_match content,
ActionView::PartialRenderer.collection_cache.read("views/#{key}/7c228ab609f0baf0b1f2367469210937")
end
end
class FragmentCacheKeyTestController < CachingController
@ -470,11 +481,21 @@ class FragmentCacheKeyTest < ActionController::TestCase
@controller.cache_store = @store
end
def test_fragment_cache_key
def test_combined_fragment_cache_key
@controller.account_id = "123"
assert_equal "views/v1/123/what a key", @controller.fragment_cache_key("what a key")
assert_equal [ :views, "v1", "123", "what a key" ], @controller.combined_fragment_cache_key("what a key")
@controller.account_id = nil
assert_equal "views/v1//what a key", @controller.fragment_cache_key("what a key")
assert_equal [ :views, "v1", "what a key" ], @controller.combined_fragment_cache_key("what a key")
end
def test_combined_fragment_cache_key_with_envs
ENV["RAILS_APP_VERSION"] = "55"
assert_equal [ :views, "55", "v1", "what a key" ], @controller.combined_fragment_cache_key("what a key")
ENV["RAILS_CACHE_ID"] = "66"
assert_equal [ :views, "66", "v1", "what a key" ], @controller.combined_fragment_cache_key("what a key")
ensure
ENV["RAILS_CACHE_ID"] = ENV["RAILS_APP_VERSION"] = nil
end
end

View file

@ -1,6 +1,6 @@
require "abstract_unit"
ActionController::Base.helpers_path = File.expand_path("../../fixtures/helpers", __FILE__)
ActionController::Base.helpers_path = File.expand_path("../fixtures/helpers", __dir__)
module Fun
class GamesController < ActionController::Base
@ -48,7 +48,7 @@ end
class HelpersPathsController < ActionController::Base
paths = ["helpers2_pack", "helpers1_pack"].map do |path|
File.join(File.expand_path("../../fixtures", __FILE__), path)
File.join(File.expand_path("../fixtures", __dir__), path)
end
$:.unshift(*paths)
@ -61,7 +61,7 @@ class HelpersPathsController < ActionController::Base
end
class HelpersTypoController < ActionController::Base
path = File.expand_path("../../fixtures/helpers_typo", __FILE__)
path = File.expand_path("../fixtures/helpers_typo", __dir__)
$:.unshift(path)
self.helpers_path = path
end
@ -178,7 +178,7 @@ class HelperTest < ActiveSupport::TestCase
end
def test_all_helpers_with_alternate_helper_dir
@controller_class.helpers_path = File.expand_path("../../fixtures/alternate_helpers", __FILE__)
@controller_class.helpers_path = File.expand_path("../fixtures/alternate_helpers", __dir__)
# Reload helpers
@controller_class._helpers = Module.new

View file

@ -1091,7 +1091,7 @@ class IntegrationFileUploadTest < ActionDispatch::IntegrationTest
end
def self.fixture_path
File.dirname(__FILE__) + "/../fixtures/multipart"
File.expand_path("../fixtures/multipart", __dir__)
end
routes.draw do

View file

@ -152,7 +152,7 @@ module ActionController
end
def write_sleep_autoload
path = File.join(File.dirname(__FILE__), "../fixtures")
path = File.expand_path("../fixtures", __dir__)
ActiveSupport::Dependencies.autoload_paths << path
response.headers["Content-Type"] = "text/event-stream"

View file

@ -29,7 +29,7 @@ class StarStarMimeControllerTest < ActionController::TestCase
end
class AbstractPostController < ActionController::Base
self.view_paths = File.dirname(__FILE__) + "/../../fixtures/post_test/"
self.view_paths = File.expand_path("../../fixtures/post_test", __dir__)
end
# For testing layouts which are set automatically

View file

@ -2,15 +2,15 @@ require "abstract_unit"
module RenderFile
class BasicController < ActionController::Base
self.view_paths = File.dirname(__FILE__)
self.view_paths = __dir__
def index
render file: File.join(File.dirname(__FILE__), *%w[.. .. fixtures test hello_world])
render file: File.expand_path("../../fixtures/test/hello_world", __dir__)
end
def with_instance_variables
@secret = "in the sauce"
render file: File.join(File.dirname(__FILE__), "../../fixtures/test/render_file_with_ivar")
render file: File.expand_path("../../fixtures/test/render_file_with_ivar", __dir__)
end
def relative_path
@ -25,11 +25,11 @@ module RenderFile
def pathname
@secret = "in the sauce"
render file: Pathname.new(File.dirname(__FILE__)).join(*%w[.. .. fixtures test dot.directory render_file_with_ivar])
render file: Pathname.new(__dir__).join(*%w[.. .. fixtures test dot.directory render_file_with_ivar])
end
def with_locals
path = File.join(File.dirname(__FILE__), "../../fixtures/test/render_file_with_locals")
path = File.expand_path("../../fixtures/test/render_file_with_locals", __dir__)
render file: path, locals: { secret: "in the sauce" }
end
end

View file

@ -6,7 +6,7 @@ module RenderImplicitAction
"render_implicit_action/simple/hello_world.html.erb" => "Hello world!",
"render_implicit_action/simple/hyphen-ated.html.erb" => "Hello hyphen-ated!",
"render_implicit_action/simple/not_implemented.html.erb" => "Not Implemented"
), ActionView::FileSystemResolver.new(File.expand_path("../../../controller", __FILE__))]
), ActionView::FileSystemResolver.new(File.expand_path("../../controller", __dir__))]
def hello_world() end
end

View file

@ -25,6 +25,27 @@ class ParametersMutatorsTest < ActiveSupport::TestCase
assert_not @params.delete(:person).permitted?
end
test "delete returns the value when the key is present" do
assert_equal "32", @params[:person].delete(:age)
end
test "delete removes the entry when the key present" do
@params[:person].delete(:age)
assert_not @params[:person].key?(:age)
end
test "delete returns nil when the key is not present" do
assert_equal nil, @params[:person].delete(:first_name)
end
test "delete returns the value of the given block when the key is not present" do
assert_equal "David", @params[:person].delete(:first_name) { "David" }
end
test "delete yields the key to the given block when the key is not present" do
assert_equal "first_name: David", @params[:person].delete(:first_name) { |k| "#{k}: David" }
end
test "delete_if retains permitted status" do
@params.permit!
assert @params.delete_if { |k| k == "person" }.permitted?

View file

@ -257,7 +257,7 @@ end
module TemplateModificationHelper
private
def modify_template(name)
path = File.expand_path("../../fixtures/#{name}.erb", __FILE__)
path = File.expand_path("../fixtures/#{name}.erb", __dir__)
original = File.read(path)
File.write(path, "#{original} Modified!")
ActionView::LookupContext::DetailsKey.clear
@ -287,9 +287,9 @@ class ExpiresInRenderTest < ActionController::TestCase
def test_dynamic_render_with_file
# This is extremely bad, but should be possible to do.
assert File.exist?(File.join(File.dirname(__FILE__), "../../test/abstract_unit.rb"))
assert File.exist?(File.expand_path("../../test/abstract_unit.rb", __dir__))
response = get :dynamic_render_with_file, params: { id: '../\\../test/abstract_unit.rb' }
assert_equal File.read(File.join(File.dirname(__FILE__), "../../test/abstract_unit.rb")),
assert_equal File.read(File.expand_path("../../test/abstract_unit.rb", __dir__)),
response.body
end
@ -306,16 +306,16 @@ class ExpiresInRenderTest < ActionController::TestCase
end
def test_dynamic_render
assert File.exist?(File.join(File.dirname(__FILE__), "../../test/abstract_unit.rb"))
assert File.exist?(File.expand_path("../../test/abstract_unit.rb", __dir__))
assert_raises ActionView::MissingTemplate do
get :dynamic_render, params: { id: '../\\../test/abstract_unit.rb' }
end
end
def test_permitted_dynamic_render_file_hash
assert File.exist?(File.join(File.dirname(__FILE__), "../../test/abstract_unit.rb"))
assert File.exist?(File.expand_path("../../test/abstract_unit.rb", __dir__))
response = get :dynamic_render_permit, params: { id: { file: '../\\../test/abstract_unit.rb' } }
assert_equal File.read(File.join(File.dirname(__FILE__), "../../test/abstract_unit.rb")),
assert_equal File.read(File.expand_path("../../test/abstract_unit.rb", __dir__)),
response.body
end

View file

@ -2,7 +2,7 @@ require "abstract_unit"
module TestFileUtils
def file_name() File.basename(__FILE__) end
def file_path() File.expand_path(__FILE__) end
def file_path() __FILE__ end
def file_data() @data ||= File.open(file_path, "rb") { |f| f.read } end
end

View file

@ -122,7 +122,7 @@ XML
end
def test_send_file
send_file(File.expand_path(__FILE__))
send_file(__FILE__)
end
def redirect_to_same_controller
@ -780,7 +780,7 @@ XML
end
end
FILES_DIR = File.dirname(__FILE__) + "/../fixtures/multipart"
FILES_DIR = File.expand_path("../fixtures/multipart", __dir__)
READ_BINARY = "rb:binary"
READ_PLAIN = "r:binary"
@ -855,7 +855,7 @@ XML
end
def test_fixture_file_upload_ignores_fixture_path_given_full_path
TestCaseTest.stub :fixture_path, File.dirname(__FILE__) do
TestCaseTest.stub :fixture_path, __dir__ do
uploaded_file = fixture_file_upload("#{FILES_DIR}/ruby_on_rails.jpg", "image/jpg")
assert_equal File.open("#{FILES_DIR}/ruby_on_rails.jpg", READ_PLAIN).read, uploaded_file.read
end

View file

@ -288,8 +288,7 @@ class CookiesTest < ActionController::TestCase
@request.env["action_dispatch.key_generator"] = ActiveSupport::KeyGenerator.new(SALT, iterations: 2)
@request.env["action_dispatch.signed_cookie_salt"] =
@request.env["action_dispatch.encrypted_cookie_salt"] =
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = SALT
@request.env["action_dispatch.authenticated_encrypted_cookie_salt"] = SALT
@request.host = "www.nextangle.com"
end
@ -531,9 +530,7 @@ class CookiesTest < ActionController::TestCase
get :set_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "bar", cookies[:foo]
assert_raise TypeError do
cookies.signed[:foo]
end
assert_nil cookies.signed[:foo]
assert_equal "bar", cookies.encrypted[:foo]
end
@ -542,9 +539,7 @@ class CookiesTest < ActionController::TestCase
get :set_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "bar", cookies[:foo]
assert_raises TypeError do
cookies.signed[:foo]
end
assert_nil cookies.signed[:foo]
assert_equal "bar", cookies.encrypted[:foo]
end
@ -553,9 +548,7 @@ class CookiesTest < ActionController::TestCase
get :set_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "bar", cookies[:foo]
assert_raises ::JSON::ParserError do
cookies.signed[:foo]
end
assert_nil cookies.signed[:foo]
assert_equal "bar", cookies.encrypted[:foo]
end
@ -564,9 +557,7 @@ class CookiesTest < ActionController::TestCase
get :set_wrapped_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "wrapped: bar", cookies[:foo]
assert_raises ::JSON::ParserError do
cookies.signed[:foo]
end
assert_nil cookies.signed[:foo]
assert_equal "wrapped: bar", cookies.encrypted[:foo]
end
@ -577,38 +568,16 @@ class CookiesTest < ActionController::TestCase
assert_equal "bar was dumped and loaded", cookies.encrypted[:foo]
end
def test_encrypted_cookie_using_custom_digest
@request.env["action_dispatch.cookies_digest"] = "SHA256"
get :set_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "bar", cookies[:foo]
assert_equal "bar", cookies.encrypted[:foo]
sign_secret = @request.env["action_dispatch.key_generator"].generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
sha1_verifier = ActiveSupport::MessageVerifier.new(sign_secret, serializer: ActiveSupport::MessageEncryptor::NullSerializer, digest: "SHA1")
sha256_verifier = ActiveSupport::MessageVerifier.new(sign_secret, serializer: ActiveSupport::MessageEncryptor::NullSerializer, digest: "SHA256")
assert_raises(ActiveSupport::MessageVerifier::InvalidSignature) do
sha1_verifier.verify(cookies[:foo])
end
assert_nothing_raised do
sha256_verifier.verify(cookies[:foo])
end
end
def test_encrypted_cookie_using_hybrid_serializer_can_migrate_marshal_dumped_value_to_json
@request.env["action_dispatch.cookies_serializer"] = :hybrid
key_generator = @request.env["action_dispatch.key_generator"]
encrypted_cookie_salt = @request.env["action_dispatch.encrypted_cookie_salt"]
encrypted_signed_cookie_salt = @request.env["action_dispatch.encrypted_signed_cookie_salt"]
secret = key_generator.generate_key(encrypted_cookie_salt)
sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)
cipher = "aes-256-gcm"
salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len(cipher)]
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: Marshal)
marshal_value = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret, serializer: Marshal).encrypt_and_sign("bar")
@request.headers["Cookie"] = "foo=#{marshal_value}"
marshal_value = encryptor.encrypt_and_sign("bar")
@request.headers["Cookie"] = "foo=#{::Rack::Utils.escape marshal_value}"
get :get_encrypted_cookie
@ -616,20 +585,21 @@ class CookiesTest < ActionController::TestCase
assert_not_equal "bar", cookies[:foo]
assert_equal "bar", cookies.encrypted[:foo]
encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret, serializer: JSON)
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
json_encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
assert_not_nil @response.cookies["foo"]
assert_equal "bar", json_encryptor.decrypt_and_verify(@response.cookies["foo"])
end
def test_encrypted_cookie_using_hybrid_serializer_can_read_from_json_dumped_value
@request.env["action_dispatch.cookies_serializer"] = :hybrid
key_generator = @request.env["action_dispatch.key_generator"]
encrypted_cookie_salt = @request.env["action_dispatch.encrypted_cookie_salt"]
encrypted_signed_cookie_salt = @request.env["action_dispatch.encrypted_signed_cookie_salt"]
secret = key_generator.generate_key(encrypted_cookie_salt)
sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)
json_value = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret, serializer: JSON).encrypt_and_sign("bar")
@request.headers["Cookie"] = "foo=#{json_value}"
cipher = "aes-256-gcm"
salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len(cipher)]
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
json_value = encryptor.encrypt_and_sign("bar")
@request.headers["Cookie"] = "foo=#{::Rack::Utils.escape json_value}"
get :get_encrypted_cookie
@ -640,19 +610,6 @@ class CookiesTest < ActionController::TestCase
assert_nil @response.cookies["foo"]
end
def test_compat_encrypted_cookie_using_64_byte_key
# Cookie generated with 64 bytes secret
message = ["566d4e75536d686e633246564e6b493062557079626c566d51574d30515430394c53315665564a694e4563786555744f57537454576b396a5a31566a626e52525054303d2d2d34663234333330623130623261306163363562316266323335396164666364613564643134623131"].pack("H*")
@request.headers["Cookie"] = "foo=#{message}"
get :get_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "bar", cookies[:foo]
assert_equal "bar", cookies.encrypted[:foo]
assert_nil @response.cookies["foo"]
end
def test_accessing_nonexistent_encrypted_cookie_should_not_raise_invalid_message
get :set_encrypted_cookie
assert_nil @controller.send(:cookies).encrypted[:non_existent_attribute]
@ -813,10 +770,10 @@ class CookiesTest < ActionController::TestCase
assert_equal "bar", @controller.send(:cookies).encrypted[:foo]
key_generator = @request.env["action_dispatch.key_generator"]
secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_cookie_salt"])
sign_secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret)
cipher = "aes-256-gcm"
salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len(cipher)]
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: Marshal)
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
end
@ -842,8 +799,6 @@ class CookiesTest < ActionController::TestCase
@request.env["action_dispatch.cookies_serializer"] = :json
@request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
@request.env["action_dispatch.secret_key_base"] = "c3b95688f35581fad38df788add315ff"
@request.env["action_dispatch.encrypted_cookie_salt"] = "4433796b79d99a7735553e316522acee"
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = "00646eb40062e1b1deff205a27cd30f9"
legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33", serializer: JSON).generate("bar")
@ -852,10 +807,10 @@ class CookiesTest < ActionController::TestCase
assert_equal "bar", @controller.send(:cookies).encrypted[:foo]
key_generator = @request.env["action_dispatch.key_generator"]
secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_cookie_salt"])
sign_secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret, serializer: JSON)
cipher = "aes-256-gcm"
salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len(cipher)]
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
end
@ -881,8 +836,6 @@ class CookiesTest < ActionController::TestCase
@request.env["action_dispatch.cookies_serializer"] = :hybrid
@request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
@request.env["action_dispatch.secret_key_base"] = "c3b95688f35581fad38df788add315ff"
@request.env["action_dispatch.encrypted_cookie_salt"] = "4433796b79d99a7735553e316522acee"
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = "00646eb40062e1b1deff205a27cd30f9"
legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33", serializer: JSON).generate("bar")
@ -891,10 +844,10 @@ class CookiesTest < ActionController::TestCase
assert_equal "bar", @controller.send(:cookies).encrypted[:foo]
key_generator = @request.env["action_dispatch.key_generator"]
secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_cookie_salt"])
sign_secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret, serializer: JSON)
cipher = "aes-256-gcm"
salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len(cipher)]
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
end
@ -920,8 +873,6 @@ class CookiesTest < ActionController::TestCase
@request.env["action_dispatch.cookies_serializer"] = :hybrid
@request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
@request.env["action_dispatch.secret_key_base"] = "c3b95688f35581fad38df788add315ff"
@request.env["action_dispatch.encrypted_cookie_salt"] = "4433796b79d99a7735553e316522acee"
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = "00646eb40062e1b1deff205a27cd30f9"
legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33").generate("bar")
@ -930,10 +881,10 @@ class CookiesTest < ActionController::TestCase
assert_equal "bar", @controller.send(:cookies).encrypted[:foo]
key_generator = @request.env["action_dispatch.key_generator"]
secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_cookie_salt"])
sign_secret = key_generator.generate_key(@request.env["action_dispatch.encrypted_signed_cookie_salt"])
encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret, serializer: JSON)
cipher = "aes-256-gcm"
salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len(cipher)]
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
end
@ -959,6 +910,89 @@ class CookiesTest < ActionController::TestCase
assert_nil @response.cookies["foo"]
end
def test_legacy_hmac_aes_cbc_encrypted_marshal_cookie_is_upgraded_to_authenticated_encrypted_cookie
@request.env["action_dispatch.secret_key_base"] = "c3b95688f35581fad38df788add315ff"
@request.env["action_dispatch.encrypted_cookie_salt"] =
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = SALT
key_generator = @request.env["action_dispatch.key_generator"]
encrypted_cookie_salt = @request.env["action_dispatch.encrypted_cookie_salt"]
encrypted_signed_cookie_salt = @request.env["action_dispatch.encrypted_signed_cookie_salt"]
secret = key_generator.generate_key(encrypted_cookie_salt)
sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)
marshal_value = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret, serializer: Marshal).encrypt_and_sign("bar")
@request.headers["Cookie"] = "foo=#{marshal_value}"
get :get_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "bar", cookies[:foo]
assert_equal "bar", cookies.encrypted[:foo]
aead_cipher = "aes-256-gcm"
aead_salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
aead_secret = key_generator.generate_key(aead_salt)[0, ActiveSupport::MessageEncryptor.key_len(aead_cipher)]
aead_encryptor = ActiveSupport::MessageEncryptor.new(aead_secret, cipher: aead_cipher, serializer: Marshal)
assert_equal "bar", aead_encryptor.decrypt_and_verify(@response.cookies["foo"])
end
def test_legacy_hmac_aes_cbc_encrypted_json_cookie_is_upgraded_to_authenticated_encrypted_cookie
@request.env["action_dispatch.cookies_serializer"] = :json
@request.env["action_dispatch.secret_key_base"] = "c3b95688f35581fad38df788add315ff"
@request.env["action_dispatch.encrypted_cookie_salt"] =
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = SALT
key_generator = @request.env["action_dispatch.key_generator"]
encrypted_cookie_salt = @request.env["action_dispatch.encrypted_cookie_salt"]
encrypted_signed_cookie_salt = @request.env["action_dispatch.encrypted_signed_cookie_salt"]
secret = key_generator.generate_key(encrypted_cookie_salt)
sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)
marshal_value = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len], sign_secret, serializer: JSON).encrypt_and_sign("bar")
@request.headers["Cookie"] = "foo=#{marshal_value}"
get :get_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "bar", cookies[:foo]
assert_equal "bar", cookies.encrypted[:foo]
aead_cipher = "aes-256-gcm"
aead_salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
aead_secret = key_generator.generate_key(aead_salt)[0, ActiveSupport::MessageEncryptor.key_len(aead_cipher)]
aead_encryptor = ActiveSupport::MessageEncryptor.new(aead_secret, cipher: aead_cipher, serializer: JSON)
assert_equal "bar", aead_encryptor.decrypt_and_verify(@response.cookies["foo"])
end
def test_legacy_hmac_aes_cbc_encrypted_cookie_using_64_byte_key_is_upgraded_to_authenticated_encrypted_cookie
@request.env["action_dispatch.secret_key_base"] = "c3b95688f35581fad38df788add315ff"
@request.env["action_dispatch.encrypted_cookie_salt"] =
@request.env["action_dispatch.encrypted_signed_cookie_salt"] = SALT
# Cookie generated with 64 bytes secret
message = ["566d4e75536d686e633246564e6b493062557079626c566d51574d30515430394c53315665564a694e4563786555744f57537454576b396a5a31566a626e52525054303d2d2d34663234333330623130623261306163363562316266323335396164666364613564643134623131"].pack("H*")
@request.headers["Cookie"] = "foo=#{message}"
get :get_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal "bar", cookies[:foo]
assert_equal "bar", cookies.encrypted[:foo]
cipher = "aes-256-gcm"
salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len(cipher)]
encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: Marshal)
assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
end
def test_cookie_with_all_domain_option
get :set_cookie_with_domain
assert_response :success

View file

@ -21,7 +21,7 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest
end
end
FIXTURE_PATH = File.dirname(__FILE__) + "/../../fixtures/multipart"
FIXTURE_PATH = File.expand_path("../../fixtures/multipart", __dir__)
def teardown
TestController.last_request_parameters = nil

View file

@ -54,6 +54,11 @@ module ActionDispatch
assert_equal %w[rails adequate], s.keys
end
def test_keys_with_deferred_loading
s = Session.create(store_with_data, req, {})
assert_equal %w[sample_key], s.keys
end
def test_values
s = Session.create(store, req, {})
s["rails"] = "ftw"
@ -61,6 +66,11 @@ module ActionDispatch
assert_equal %w[ftw awesome], s.values
end
def test_values_with_deferred_loading
s = Session.create(store_with_data, req, {})
assert_equal %w[sample_value], s.values
end
def test_clear
s = Session.create(store, req, {})
s["rails"] = "ftw"
@ -113,6 +123,14 @@ module ActionDispatch
def delete_session(env, id, options); 123; end
}.new
end
def store_with_data
Class.new {
def load_session(env); [1, { "sample_key" => "sample_value" }]; end
def session_exists?(env); true; end
def delete_session(env, id, options); 123; end
}.new
end
end
class SessionIntegrationTest < ActionDispatch::IntegrationTest

View file

@ -107,7 +107,7 @@ class UrlEncodedParamsParsingTest < ActionDispatch::IntegrationTest
query = [
"customers[boston][first][name]=David",
"something_else=blah",
"logo=#{File.expand_path(__FILE__)}"
"logo=#{__FILE__}"
].join("&")
expected = {
"customers" => {
@ -118,7 +118,7 @@ class UrlEncodedParamsParsingTest < ActionDispatch::IntegrationTest
}
},
"something_else" => "blah",
"logo" => File.expand_path(__FILE__),
"logo" => __FILE__,
}
assert_parses expected, query
end

View file

@ -110,8 +110,8 @@ class RequestIP < BaseRequestTest
request.remote_ip
}
assert_match(/IP spoofing attack/, e.message)
assert_match(/HTTP_X_FORWARDED_FOR="1.1.1.1"/, e.message)
assert_match(/HTTP_CLIENT_IP="2.2.2.2"/, e.message)
assert_match(/HTTP_X_FORWARDED_FOR="1\.1\.1\.1"/, e.message)
assert_match(/HTTP_CLIENT_IP="2\.2\.2\.2"/, e.message)
end
test "remote ip with spoof detection disabled" do

View file

@ -4419,7 +4419,7 @@ class TestInvalidUrls < ActionDispatch::IntegrationTest
end
end
test "invalid UTF-8 encoding returns a 400 Bad Request" do
test "invalid UTF-8 encoding is treated as ASCII 8BIT encode" do
with_routing do |set|
set.draw do
get "/bar/:id", to: redirect("/foo/show/%{id}")
@ -4435,19 +4435,19 @@ class TestInvalidUrls < ActionDispatch::IntegrationTest
end
get "/%E2%EF%BF%BD%A6"
assert_response :bad_request
assert_response :not_found
get "/foo/%E2%EF%BF%BD%A6"
assert_response :bad_request
assert_response :not_found
get "/foo/show/%E2%EF%BF%BD%A6"
assert_response :bad_request
assert_response :ok
get "/bar/%E2%EF%BF%BD%A6"
assert_response :bad_request
assert_response :redirect
get "/foobar/%E2%EF%BF%BD%A6"
assert_response :bad_request
assert_response :ok
end
end
end

View file

@ -19,3 +19,15 @@ class SetDriverToSeleniumTest < DrivenBySeleniumWithChrome
assert_equal :selenium, Capybara.current_driver
end
end
class SetHostTest < DrivenByRackTest
test "sets default host" do
assert_equal "http://127.0.0.1", Capybara.app_host
end
test "overrides host" do
host! "http://example.com"
assert_equal "http://example.com", Capybara.app_host
end
end

View file

@ -13,6 +13,12 @@ module ActionDispatch
assert_equal "foo", uf.original_filename
end
def test_filename_is_different_object
file_str = "foo"
uf = Http::UploadedFile.new(filename: file_str, tempfile: Object.new)
assert_not_equal file_str.object_id , uf.original_filename.object_id
end
def test_filename_should_be_in_utf_8
uf = Http::UploadedFile.new(filename: "foo", tempfile: Object.new)
assert_equal "UTF-8", uf.original_filename.encoding.to_s

View file

@ -1,3 +1,3 @@
<body>
<%= cache do %><p>ERB</p><% end %>
<%= cache("fragment") do %><p>ERB</p><% end %>
</body>

View file

@ -1,5 +1,5 @@
xml.body do
cache do
cache("fragment") do
xml.p "Builder"
end
end

View file

@ -1,3 +1,3 @@
<body>
<%= cache do %><p>PHONE</p><% end %>
<%= cache("fragment") do %><p>PHONE</p><% end %>
</body>

View file

@ -1,3 +1,3 @@
Hello
<%= cache do %>This bit's fragment cached<% end %>
<%= cache "fragment" do %>This bit's fragment cached<% end %>
<%= 'Ciao' %>

View file

@ -35,25 +35,25 @@ module ActionDispatch
def test_simulate_gt
sim = simulator_for ["/foo", "/bar"]
assert_match sim, "/foo"
assert_match_route sim, "/foo"
end
def test_simulate_gt_regexp
sim = simulator_for [":foo"]
assert_match sim, "foo"
assert_match_route sim, "foo"
end
def test_simulate_gt_regexp_mix
sim = simulator_for ["/get", "/:method/foo"]
assert_match sim, "/get"
assert_match sim, "/get/foo"
assert_match_route sim, "/get"
assert_match_route sim, "/get/foo"
end
def test_simulate_optional
sim = simulator_for ["/foo(/bar)"]
assert_match sim, "/foo"
assert_match sim, "/foo/bar"
assert_no_match sim, "/foo/"
assert_match_route sim, "/foo"
assert_match_route sim, "/foo/bar"
assert_no_match_route sim, "/foo/"
end
def test_match_data
@ -65,11 +65,11 @@ module ActionDispatch
sim = GTG::Simulator.new tt
match = sim.match "/get"
assert_equal [paths.first], match.memos
memos = sim.memos "/get"
assert_equal [paths.first], memos
match = sim.match "/get/foo"
assert_equal [paths.last], match.memos
memos = sim.memos "/get/foo"
assert_equal [paths.last], memos
end
def test_match_data_ambiguous
@ -86,8 +86,8 @@ module ActionDispatch
builder = GTG::Builder.new ast
sim = GTG::Simulator.new builder.transition_table
match = sim.match "/articles/new"
assert_equal [paths[1], paths[3]], match.memos
memos = sim.memos "/articles/new"
assert_equal [paths[1], paths[3]], memos
end
private
@ -109,6 +109,14 @@ module ActionDispatch
def simulator_for(paths)
GTG::Simulator.new tt(paths)
end
def assert_match_route(simulator, path)
assert simulator.memos(path), "Simulator should match #{path}."
end
def assert_no_match_route(simulator, path)
assert_not simulator.memos(path) { nil }, "Simulator should not match #{path}."
end
end
end
end

View file

@ -31,6 +31,11 @@ module ActionDispatch
def test_normalize_path_uppercase
assert_equal "/foo%AAbar%AAbaz", Utils.normalize_path("/foo%aabar%aabaz")
end
def test_normalize_path_maintains_string_encoding
path = "/foo%AAbar%AAbaz".b
assert_equal Encoding::ASCII_8BIT, Utils.normalize_path(path).encoding
end
end
end
end

View file

@ -26,6 +26,10 @@ Customer = Struct.new(:name, :id) do
def persisted?
id.present?
end
def cache_key
"#{name}/#{id}"
end
end
Post = Struct.new(:title, :author_name, :body, :secret, :persisted, :written_on, :cost) do

View file

@ -1 +1,11 @@
* Add `:json` type to `auto_discovery_link_tag` to support [JSON Feeds](https://jsonfeed.org/version/1)
*Mike Gunderloy*
* Update `distance_of_time_in_words` helper to display better error messages
for bad input.
*Jay Hayes*
Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/actionview/CHANGELOG.md) for previous changes.

View file

@ -2,8 +2,6 @@ require "rake/testtask"
require "fileutils"
require "open3"
dir = File.dirname(__FILE__)
desc "Default Task"
task default: :test
@ -95,7 +93,7 @@ namespace :assets do
desc "Verify compiled Action View assets"
task :verify do
file = "lib/assets/compiled/rails-ujs.js"
pathname = Pathname.new("#{dir}/#{file}")
pathname = Pathname.new("#{__dir__}/#{file}")
print "[verify] #{file} exists "
if pathname.exist?
@ -113,13 +111,13 @@ namespace :assets do
fail
end
print "[verify] #{dir} can be required as a module "
print "[verify] #{__dir__} can be required as a module "
js = <<-JS
window = { Event: class {} }
class Element {}
require('#{dir}')
require('#{__dir__}')
JS
stdout, stderr, status = Open3.capture3("node", "--print", js)
_, stderr, status = Open3.capture3("node", "--print", js)
if status.success?
puts "[OK]"
else
@ -130,7 +128,7 @@ namespace :assets do
end
task :lines do
load File.expand_path("..", File.dirname(__FILE__)) + "/tools/line_statistics"
load File.join(File.expand_path("..", __dir__), "/tools/line_statistics")
files = FileList["lib/**/*.rb"]
CodeTools::LineStatistics.new(files).print_loc
end

View file

@ -1,4 +1,4 @@
version = File.read(File.expand_path("../../RAILS_VERSION", __FILE__)).strip
version = File.read(File.expand_path("../RAILS_VERSION", __dir__)).strip
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY

View file

@ -36,10 +36,20 @@ Require `rails-ujs` into your application.js manifest.
//= require rails-ujs
```
Usage with yarn
------------
When using with Webpacker gem or your preferred JavaScript bundler. Just add the following to your main JS file and compile.
```javascript
import Rails from 'rails-ujs';
Rails.start()
```
How to run tests
------------
Run `bundle exec rake ujs:server` first, and then run the web tests by visiting [[http://localhost:4567]] in your browser.
Run `bundle exec rake ujs:server` first, and then run the web tests by visiting http://localhost:4567 in your browser.
## License
rails-ujs is released under the [MIT License](MIT-LICENSE).

View file

@ -14,7 +14,7 @@ AcceptHeaders =
Rails.ajax = (options) ->
options = prepareOptions(options)
xhr = createXHR options, ->
response = processResponse(xhr.response, xhr.getResponseHeader('Content-Type'))
response = processResponse(xhr.response ? xhr.responseText, xhr.getResponseHeader('Content-Type'))
if xhr.status // 100 == 2
options.success?(response, xhr.statusText, xhr)
else

View file

@ -92,5 +92,5 @@ end
require "active_support/core_ext/string/output_safety"
ActiveSupport.on_load(:i18n) do
I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml"
I18n.load_path << File.expand_path("action_view/locale/en.yml", __dir__)
end

View file

@ -122,9 +122,9 @@ module ActionView
end
# Returns a link tag that browsers and feed readers can use to auto-detect
# an RSS or Atom feed. The +type+ can either be <tt>:rss</tt> (default) or
# <tt>:atom</tt>. Control the link options in url_for format using the
# +url_options+. You can modify the LINK tag itself in +tag_options+.
# an RSS, Atom, or JSON feed. The +type+ can be <tt>:rss</tt> (default),
# <tt>:atom</tt>, or <tt>:json</tt>. Control the link options in url_for format
# using the +url_options+. You can modify the LINK tag itself in +tag_options+.
#
# ==== Options
#
@ -138,6 +138,8 @@ module ActionView
# # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/action" />
# auto_discovery_link_tag(:atom)
# # => <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.currenthost.com/controller/action" />
# auto_discovery_link_tag(:json)
# # => <link rel="alternate" type="application/json" title="JSON" href="http://www.currenthost.com/controller/action" />
# auto_discovery_link_tag(:rss, {action: "feed"})
# # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/feed" />
# auto_discovery_link_tag(:rss, {action: "feed"}, {title: "My RSS"})
@ -147,8 +149,8 @@ module ActionView
# auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {title: "Example RSS"})
# # => <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed.rss" />
def auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {})
if !(type == :rss || type == :atom) && tag_options[:type].blank?
raise ArgumentError.new("You should pass :type tag_option key explicitly, because you have passed #{type} type other than :rss or :atom.")
if !(type == :rss || type == :atom || type == :json) && tag_options[:type].blank?
raise ArgumentError.new("You should pass :type tag_option key explicitly, because you have passed #{type} type other than :rss, :atom, or :json.")
end
tag(

View file

@ -8,10 +8,9 @@ module ActionView
# fragments, and so on. This method takes a block that contains
# the content you wish to cache.
#
# The best way to use this is by doing key-based cache expiration
# on top of a cache store like Memcached that'll automatically
# kick out old entries. For more on key-based expiration, see:
# http://signalvnoise.com/posts/3113-how-key-based-cache-expiration-works
# The best way to use this is by doing recyclable key-based cache expiration
# on top of a cache store like Memcached or Redis that'll automatically
# kick out old entries.
#
# When using this method, you list the cache dependency as the name of the cache, like so:
#
@ -23,10 +22,14 @@ module ActionView
# This approach will assume that when a new topic is added, you'll touch
# the project. The cache key generated from this call will be something like:
#
# views/projects/123-20120806214154/7a1156131a6928cb0026877f8b749ac9
# ^class ^id ^updated_at ^template tree digest
# views/template/action.html.erb:7a1156131a6928cb0026877f8b749ac9/projects/123
# ^template path ^template tree digest ^class ^id
#
# The cache is thus automatically bumped whenever the project updated_at is touched.
# This cache key is stable, but it's combined with a cache version derived from the project
# record. When the project updated_at is touched, the #cache_version changes, even
# if the key stays stable. This means that unlike a traditional key-based cache expiration
# approach, you won't be generating cache trash, unused keys, simply because the dependent
# record is updated.
#
# If your template cache depends on multiple sources (try to avoid this to keep things simple),
# you can name all these dependencies as part of an array:
@ -217,10 +220,15 @@ module ActionView
def fragment_name_with_digest(name, virtual_path)
virtual_path ||= @virtual_path
if virtual_path
name = controller.url_for(name).split("://").last if name.is_a?(Hash)
digest = Digestor.digest name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies
[ name, digest ]
if digest = Digestor.digest(name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies).presence
[ "#{virtual_path}:#{digest}", name ]
else
[ virtual_path, name ]
end
else
name
end

View file

@ -95,8 +95,8 @@ module ActionView
scope: :'datetime.distance_in_words'
}.merge!(options)
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
from_time = normalize_distance_of_time_argument_to_time(from_time)
to_time = normalize_distance_of_time_argument_to_time(to_time)
from_time, to_time = to_time, from_time if from_time > to_time
distance_in_minutes = ((to_time - from_time) / 60.0).round
distance_in_seconds = (to_time - from_time).round
@ -130,22 +130,18 @@ module ActionView
# 60 days up to 365 days
when 86400...525600 then locale.t :x_months, count: (distance_in_minutes.to_f / 43200.0).round
else
if from_time.acts_like?(:time) && to_time.acts_like?(:time)
fyear = from_time.year
fyear += 1 if from_time.month >= 3
tyear = to_time.year
tyear -= 1 if to_time.month < 3
leap_years = (fyear > tyear) ? 0 : (fyear..tyear).count { |x| Date.leap?(x) }
minute_offset_for_leap_year = leap_years * 1440
# Discount the leap year days when calculating year distance.
# e.g. if there are 20 leap year days between 2 dates having the same day
# and month then the based on 365 days calculation
# the distance in years will come out to over 80 years when in written
# English it would read better as about 80 years.
minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
else
minutes_with_offset = distance_in_minutes
end
from_year = from_time.year
from_year += 1 if from_time.month >= 3
to_year = to_time.year
to_year -= 1 if to_time.month < 3
leap_years = (from_year > to_year) ? 0 : (from_year..to_year).count { |x| Date.leap?(x) }
minute_offset_for_leap_year = leap_years * 1440
# Discount the leap year days when calculating year distance.
# e.g. if there are 20 leap year days between 2 dates having the same day
# and month then the based on 365 days calculation
# the distance in years will come out to over 80 years when in written
# English it would read better as about 80 years.
minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
remainder = (minutes_with_offset % MINUTES_IN_YEAR)
distance_in_years = (minutes_with_offset.div MINUTES_IN_YEAR)
if remainder < MINUTES_IN_QUARTER_YEAR
@ -687,6 +683,18 @@ module ActionView
content_tag("time".freeze, content, options.reverse_merge(datetime: datetime), &block)
end
private
def normalize_distance_of_time_argument_to_time(value)
if value.is_a?(Numeric)
Time.at(value)
elsif value.respond_to?(:to_time)
value.to_time
else
raise ArgumentError, "#{value.inspect} can't be converted to a Time value"
end
end
end
class DateTimeSelector #:nodoc:

View file

@ -1606,14 +1606,15 @@ module ActionView
include ModelNaming
# The methods which wrap a form helper call.
class_attribute :field_helpers
self.field_helpers = [:fields_for, :fields, :label, :text_field, :password_field,
:hidden_field, :file_field, :text_area, :check_box,
:radio_button, :color_field, :search_field,
:telephone_field, :phone_field, :date_field,
:time_field, :datetime_field, :datetime_local_field,
:month_field, :week_field, :url_field, :email_field,
:number_field, :range_field]
class_attribute :field_helpers, default: [
:fields_for, :fields, :label, :text_field, :password_field,
:hidden_field, :file_field, :text_area, :check_box,
:radio_button, :color_field, :search_field,
:telephone_field, :phone_field, :date_field,
:time_field, :datetime_field, :datetime_local_field,
:month_field, :week_field, :url_field, :email_field,
:number_field, :range_field
]
attr_accessor :object_name, :object, :options

View file

@ -149,7 +149,7 @@ module ActionView
end
value = options.fetch(:selected) { value(object) }
select = content_tag("select", add_options(option_tags, options, value), html_options)
select = content_tag("select", add_options(option_tags, options, value), html_options.except!("skip_default_ids", "allow_method_names_outside_object"))
if html_options["multiple"] && options.fetch(:include_hidden, true)
tag("input", disabled: html_options["disabled"], name: html_options["name"], type: "hidden", value: "") + select

View file

@ -33,7 +33,7 @@ module ActionView
# [nil, []]
# { nil => [] }
def grouped_choices?
!@choices.empty? && @choices.first.respond_to?(:last) && Array === @choices.first.last
!@choices.blank? && @choices.first.respond_to?(:last) && Array === @choices.first.last
end
end
end

View file

@ -204,9 +204,9 @@ module ActionView
include ActionView::Rendering
included do
class_attribute :_layout, :_layout_conditions, instance_accessor: false
self._layout = nil
self._layout_conditions = {}
class_attribute :_layout, instance_accessor: false
class_attribute :_layout_conditions, instance_accessor: false, default: {}
_write_layout_method
end

View file

@ -38,7 +38,7 @@ module ActionView
end
def expanded_cache_key(key)
key = @view.fragment_cache_key(@view.cache_fragment_name(key, virtual_path: @template.virtual_path))
key = @view.combined_fragment_cache_key(@view.cache_fragment_name(key, virtual_path: @template.virtual_path))
key.frozen? ? key.dup : key # #read_multi & #write may require mutability, Dalli 2.6.0.
end

View file

@ -1,9 +1,7 @@
module ActionView
module Template::Handlers
class Builder
# Default format used by Builder.
class_attribute :default_format
self.default_format = :xml
class_attribute :default_format, default: :xml
def call(template)
require_engine
@ -14,7 +12,6 @@ module ActionView
end
private
def require_engine # :doc:
@required ||= begin
require "builder"

View file

@ -9,16 +9,13 @@ module ActionView
# Specify trim mode for the ERB compiler. Defaults to '-'.
# See ERB documentation for suitable values.
class_attribute :erb_trim_mode
self.erb_trim_mode = "-"
class_attribute :erb_trim_mode, default: "-"
# Default implementation used.
class_attribute :erb_implementation
self.erb_implementation = Erubi
class_attribute :erb_implementation, default: Erubi
# Do not escape templates of these mime types.
class_attribute :escape_whitelist
self.escape_whitelist = ["text/plain"]
class_attribute :escape_whitelist, default: ["text/plain"]
ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")

View file

@ -3,9 +3,7 @@ module ActionView
extend ActiveSupport::Concern
included do
class_attribute :_view_paths
self._view_paths = ActionView::PathSet.new
_view_paths.freeze
class_attribute :_view_paths, default: ActionView::PathSet.new.freeze
end
delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,

View file

@ -1,8 +1,8 @@
$:.unshift(File.dirname(__FILE__) + "/lib")
$:.unshift(File.dirname(__FILE__) + "/fixtures/helpers")
$:.unshift(File.dirname(__FILE__) + "/fixtures/alternate_helpers")
$:.unshift File.expand_path("lib", __dir__)
$:.unshift File.expand_path("fixtures/helpers", __dir__)
$:.unshift File.expand_path("fixtures/alternate_helpers", __dir__)
ENV["TMPDIR"] = File.join(File.dirname(__FILE__), "tmp")
ENV["TMPDIR"] = File.expand_path("tmp", __dir__)
require "active_support/core_ext/kernel/reporting"
@ -47,7 +47,7 @@ I18n.backend.store_translations "da", {}
I18n.backend.store_translations "pt-BR", {}
ORIGINAL_LOCALES = I18n.available_locales.map(&:to_s).sort
FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), "fixtures")
FIXTURE_LOAD_PATH = File.expand_path("fixtures", __dir__)
module RenderERBUtils
def view
@ -133,7 +133,7 @@ class BasicController
def config
@config ||= ActiveSupport::InheritableOptions.new(ActionController::Base.config).tap do |config|
# VIEW TODO: View tests should not require a controller
public_dir = File.expand_path("../fixtures/public", __FILE__)
public_dir = File.expand_path("fixtures/public", __dir__)
config.assets_dir = public_dir
config.javascripts_dir = "#{public_dir}/javascripts"
config.stylesheets_dir = "#{public_dir}/stylesheets"
@ -196,7 +196,7 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
end
def with_autoload_path(path)
path = File.join(File.dirname(__FILE__), "fixtures", path)
path = File.join(File.expand_path("fixtures", __dir__), path)
if ActiveSupport::Dependencies.autoload_paths.include?(path)
yield
else

View file

@ -42,7 +42,7 @@ module AbstractController
super
end
append_view_path File.expand_path(File.join(File.dirname(__FILE__), "views"))
append_view_path File.expand_path("views", __dir__)
end
class Me2 < RenderingController
@ -152,7 +152,7 @@ module AbstractController
class OverridingLocalPrefixes < AbstractController::Base
include AbstractController::Rendering
include ActionView::Rendering
append_view_path File.expand_path(File.join(File.dirname(__FILE__), "views"))
append_view_path File.expand_path("views", __dir__)
def index
render

View file

@ -1,6 +1,6 @@
require "abstract_unit"
ActionController::Base.helpers_path = File.expand_path("../../../fixtures/helpers", __FILE__)
ActionController::Base.helpers_path = File.expand_path("../../fixtures/helpers", __dir__)
module AbstractController
module Testing
@ -51,7 +51,7 @@ module AbstractController
class AbstractInvalidHelpers < AbstractHelpers
include ActionController::Helpers
path = File.expand_path("../../../fixtures/helpers_missing", __FILE__)
path = File.expand_path("../../fixtures/helpers_missing", __dir__)
$:.unshift(path)
self.helpers_path = path
end

View file

@ -2,7 +2,7 @@ require "abstract_unit"
require "active_support/logger"
class CaptureController < ActionController::Base
self.view_paths = [ File.dirname(__FILE__) + "/../../fixtures/actionpack" ]
self.view_paths = [ File.expand_path("../../fixtures/actionpack", __dir__) ]
def self.controller_name; "test"; end
def self.controller_path; "test"; end

View file

@ -5,7 +5,7 @@ require "active_support/core_ext/array/extract_options"
# method has access to the view_paths array when looking for a layout to automatically assign.
old_load_paths = ActionController::Base.view_paths
ActionController::Base.view_paths = [ File.dirname(__FILE__) + "/../../fixtures/actionpack/layout_tests/" ]
ActionController::Base.view_paths = [ File.expand_path("../../fixtures/actionpack/layout_tests", __dir__) ]
class LayoutTest < ActionController::Base
def self.controller_path; "views" end
@ -96,7 +96,7 @@ class StreamingLayoutController < LayoutTest
end
class AbsolutePathLayoutController < LayoutTest
layout File.expand_path(File.expand_path(__FILE__) + "/../../../fixtures/actionpack/layout_tests/layouts/layout_test")
layout File.expand_path("../../fixtures/actionpack/layout_tests/layouts/layout_test", __dir__)
end
class HasOwnLayoutController < LayoutTest
@ -117,7 +117,7 @@ end
class PrependsViewPathController < LayoutTest
def hello
prepend_view_path File.dirname(__FILE__) + "/../../fixtures/actionpack/layout_tests/alt/"
prepend_view_path File.expand_path("../../fixtures/actionpack/layout_tests/alt", __dir__)
render layout: "alt"
end
end

View file

@ -56,7 +56,7 @@ class TestController < ApplicationController
end
def hello_world_file
render file: File.expand_path("../../../fixtures/actionpack/hello", __FILE__), formats: [:html]
render file: File.expand_path("../../fixtures/actionpack/hello", __dir__), formats: [:html]
end
# :ported:
@ -125,7 +125,7 @@ class TestController < ApplicationController
# :ported:
def render_file_with_instance_variables
@secret = "in the sauce"
path = File.join(File.dirname(__FILE__), "../../fixtures/test/render_file_with_ivar")
path = File.expand_path("../../fixtures/test/render_file_with_ivar", __dir__)
render file: path
end
@ -142,21 +142,21 @@ class TestController < ApplicationController
def render_file_using_pathname
@secret = "in the sauce"
render file: Pathname.new(File.dirname(__FILE__)).join("..", "..", "fixtures", "test", "dot.directory", "render_file_with_ivar")
render file: Pathname.new(__dir__).join("..", "..", "fixtures", "test", "dot.directory", "render_file_with_ivar")
end
def render_file_from_template
@secret = "in the sauce"
@path = File.expand_path(File.join(File.dirname(__FILE__), "../../fixtures/test/render_file_with_ivar"))
@path = File.expand_path("../../fixtures/test/render_file_with_ivar", __dir__)
end
def render_file_with_locals
path = File.join(File.dirname(__FILE__), "../../fixtures/test/render_file_with_locals")
path = File.expand_path("../../fixtures/test/render_file_with_locals", __dir__)
render file: path, locals: { secret: "in the sauce" }
end
def render_file_as_string_with_locals
path = File.expand_path(File.join(File.dirname(__FILE__), "../../fixtures/test/render_file_with_locals"))
path = File.expand_path("../../fixtures/test/render_file_with_locals", __dir__)
render file: path, locals: { secret: "in the sauce" }
end

Some files were not shown because too many files have changed in this diff Show more