aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile.lock4
-rw-r--r--actionpack/lib/abstract_controller/callbacks.rb10
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb2
-rw-r--r--actionview/lib/action_view/renderer/renderer.rb2
-rw-r--r--activerecord/lib/active_record/associations/association.rb9
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/reflection.rb2
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb8
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb15
-rw-r--r--activerecord/test/cases/relation_test.rb4
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb24
-rw-r--r--activerecord/test/models/bulb.rb1
-rw-r--r--activerecord/test/models/car.rb1
-rw-r--r--activerecord/test/schema/schema.rb2
-rw-r--r--activesupport/CHANGELOG.md2
-rw-r--r--activesupport/activesupport.gemspec2
-rw-r--r--activesupport/lib/active_support/cache.rb17
-rw-r--r--activesupport/lib/active_support/cache/file_store.rb28
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb16
-rw-r--r--activesupport/lib/active_support/cache/strategy/local_cache.rb7
-rw-r--r--activesupport/test/caching_test.rb10
-rw-r--r--guides/source/configuring.md2
-rw-r--r--guides/source/engines.md21
-rw-r--r--guides/source/testing.md26
-rw-r--r--railties/CHANGELOG.md5
-rw-r--r--railties/lib/rails/application/configuration.rb4
-rw-r--r--railties/lib/rails/application/default_middleware_stack.rb2
-rw-r--r--railties/test/application/middleware/static_test.rb8
29 files changed, 153 insertions, 85 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index 0f5a48e524..fdd4946c4a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -137,7 +137,7 @@ PATH
activesupport (= 5.0.0.alpha)
arel (= 7.0.0.alpha)
activesupport (5.0.0.alpha)
- concurrent-ruby (~> 1.0.0.pre5, < 2.0.0)
+ concurrent-ruby (~> 1.0)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
method_source
@@ -201,7 +201,7 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.9.1.1)
- concurrent-ruby (1.0.0.pre5)
+ concurrent-ruby (1.0.0)
connection_pool (2.2.0)
dalli (2.7.4)
dante (0.2.0)
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb
index 287550db42..d5317e4717 100644
--- a/actionpack/lib/abstract_controller/callbacks.rb
+++ b/actionpack/lib/abstract_controller/callbacks.rb
@@ -39,8 +39,8 @@ module AbstractController
# except: :index, if: -> { true } # the :except option will be ignored.
#
# ==== Options
- # * <tt>only</tt> - The callback should be run only for this action
- # * <tt>except</tt> - The callback should be run for all actions except this action
+ # * <tt>only</tt> - The callback should be run only for this action.
+ # * <tt>except</tt> - The callback should be run for all actions except this action.
def _normalize_callback_options(options)
_normalize_callback_option(options, :only, :if)
_normalize_callback_option(options, :except, :unless)
@@ -59,7 +59,7 @@ module AbstractController
# * <tt>names</tt> - A list of valid names that could be used for
# callbacks. Note that skipping uses Ruby equality, so it's
# impossible to skip a callback defined using an anonymous proc
- # using #skip_action_callback
+ # using #skip_action_callback.
def skip_action_callback(*names)
ActiveSupport::Deprecation.warn('`skip_action_callback` is deprecated and will be removed in Rails 5.1. Please use skip_before_action, skip_after_action or skip_around_action instead.')
skip_before_action(*names, raise: false)
@@ -82,8 +82,8 @@ module AbstractController
# * <tt>block</tt> - A proc that should be added to the callbacks.
#
# ==== Block Parameters
- # * <tt>name</tt> - The callback to be added
- # * <tt>options</tt> - A hash of options to be used when adding the callback
+ # * <tt>name</tt> - The callback to be added.
+ # * <tt>options</tt> - A hash of options to be used when adding the callback.
def _insert_callbacks(callbacks, block = nil)
options = callbacks.extract_options!
_normalize_callback_options(options)
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index 89d589c486..d86a793e4c 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -66,7 +66,7 @@ module ActionController
#
# You can also pass an object that responds to +maximum+, such as a
# collection of active records. In this case +last_modified+ will be set by
- # calling +maximum(:updated_at)+ on the collection (the timestamp of the
+ # calling <tt>maximum(:updated_at)</tt> on the collection (the timestamp of the
# most recently updated record) and the +etag+ by passing the object itself.
#
# def index
diff --git a/actionview/lib/action_view/renderer/renderer.rb b/actionview/lib/action_view/renderer/renderer.rb
index 1bee35d80d..2a3b89aebf 100644
--- a/actionview/lib/action_view/renderer/renderer.rb
+++ b/actionview/lib/action_view/renderer/renderer.rb
@@ -15,7 +15,7 @@ module ActionView
@lookup_context = lookup_context
end
- # Main render entry point shared by AV and AC.
+ # Main render entry point shared by Action View and Action Controller.
def render(context, options)
if options.key?(:partial)
render_partial(context, options)
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index c7b396f3d4..d64ab64c99 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -163,9 +163,12 @@ module ActiveRecord
@reflection = @owner.class._reflect_on_association(reflection_name)
end
- def initialize_attributes(record) #:nodoc:
+ def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
+ except_from_scope_attributes ||= {}
skip_assign = [reflection.foreign_key, reflection.type].compact
- attributes = create_scope.except(*(record.changed - skip_assign))
+ assigned_keys = record.changed
+ assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
+ attributes = create_scope.except(*(assigned_keys - skip_assign))
record.assign_attributes(attributes)
set_inverse_instance(record)
end
@@ -248,7 +251,7 @@ module ActiveRecord
def build_record(attributes)
reflection.build_association(attributes) do |record|
- initialize_attributes(record)
+ initialize_attributes(record, attributes)
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index b6e17ad4ef..c75c9ab3b5 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -134,9 +134,7 @@ module ActiveRecord
time: { name: "time" },
date: { name: "date" },
binary: { name: "blob" },
- blob: { name: "blob" },
boolean: { name: "tinyint", limit: 1 },
- bigint: { name: "bigint" },
json: { name: "json" },
}
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index ed6ab8235f..3eefab8f44 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -72,7 +72,6 @@ module ActiveRecord
NATIVE_DATABASE_TYPES = {
primary_key: "serial primary key",
- bigserial: "bigserial",
string: { name: "character varying" },
text: { name: "text" },
integer: { name: "integer" },
@@ -89,7 +88,6 @@ module ActiveRecord
int8range: { name: "int8range" },
binary: { name: "bytea" },
boolean: { name: "boolean" },
- bigint: { name: "bigint" },
xml: { name: "xml" },
tsvector: { name: "tsvector" },
hstore: { name: "hstore" },
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 5b9d45d871..a549b28f16 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -371,7 +371,7 @@ module ActiveRecord
end
def foreign_key
- @foreign_key ||= options[:foreign_key] || derive_foreign_key
+ @foreign_key ||= options[:foreign_key] || derive_foreign_key.freeze
end
def association_foreign_key
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index 5c3318651a..ee509b98d4 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -12,6 +12,7 @@ module ActiveRecord
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
# Returns an array representing the intersection of the resulting records with <tt>other</tt>, if <tt>other</tt> is an array.
+ #
# Post.where(published: true).joins(:comments).merge( Comment.where(spam: false) )
# # Performs a single join query with both where conditions.
#
@@ -37,11 +38,12 @@ module ActiveRecord
end
def merge!(other) # :nodoc:
- if !other.is_a?(Relation) && other.respond_to?(:to_proc)
+ if other.is_a?(Hash)
+ Relation::HashMerger.new(self, other).merge
+ elsif other.respond_to?(:to_proc)
instance_exec(&other)
else
- klass = other.is_a?(Hash) ? Relation::HashMerger : Relation::Merger
- klass.new(self, other).merge
+ Relation::Merger.new(self, other).merge
end
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index eb94870a35..50ca6537cc 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -203,9 +203,22 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
bulb = car.bulbs.create
assert_equal 'defaulty', bulb.name
+ end
+
+ def test_build_and_create_from_association_should_respect_passed_attributes_over_default_scope
+ car = Car.create(name: 'honda')
+
+ bulb = car.bulbs.build(name: 'exotic')
+ assert_equal 'exotic', bulb.name
- bulb = car.bulbs.create(:name => 'exotic')
+ bulb = car.bulbs.create(name: 'exotic')
assert_equal 'exotic', bulb.name
+
+ bulb = car.awesome_bulbs.build(frickinawesome: false)
+ assert_equal false, bulb.frickinawesome
+
+ bulb = car.awesome_bulbs.create(frickinawesome: false)
+ assert_equal false, bulb.frickinawesome
end
def test_build_from_association_should_respect_scope
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 8794bc8043..b58052a962 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -24,6 +24,10 @@ module ActiveRecord
def self.sanitize_sql_for_order(sql)
sql
end
+
+ def self.arel_table
+ Post.arel_table
+ end
end
def test_construction
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 677b5dbdf3..43f133b12d 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -354,29 +354,29 @@ class SchemaDumperTest < ActiveRecord::TestCase
$stdout = original
end
- class CreateCatMigration < ActiveRecord::Migration
- def change
- create_table("cats") do |t|
- end
- create_table("fu_cats") do |t|
- end
- end
- end
-
def test_schema_dump_with_table_name_prefix_and_ignoring_tables
original, $stdout = $stdout, StringIO.new
+ create_cat_migration = Class.new(ActiveRecord::Migration) do
+ def change
+ create_table("cats") do |t|
+ end
+ create_table("omg_cats") do |t|
+ end
+ end
+ end
+
original_table_name_prefix = ActiveRecord::Base.table_name_prefix
original_schema_dumper_ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
- ActiveRecord::Base.table_name_prefix = 'fu_'
+ ActiveRecord::Base.table_name_prefix = 'omg_'
ActiveRecord::SchemaDumper.ignore_tables = ["cats"]
- migration = CreateCatMigration.new
+ migration = create_cat_migration.new
migration.migrate(:up)
stream = StringIO.new
output = ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream).string
- assert_match %r{create_table "fu_cats"}, output
+ assert_match %r{create_table "omg_cats"}, output
refute_match %r{create_table "cats"}, output
ensure
migration.migrate(:down)
diff --git a/activerecord/test/models/bulb.rb b/activerecord/test/models/bulb.rb
index a6e83fe353..c1e491e5c5 100644
--- a/activerecord/test/models/bulb.rb
+++ b/activerecord/test/models/bulb.rb
@@ -1,6 +1,7 @@
class Bulb < ActiveRecord::Base
default_scope { where(:name => 'defaulty') }
belongs_to :car, :touch => true
+ scope :awesome, -> { where(frickinawesome: true) }
attr_reader :scope_after_initialize, :attributes_after_initialize
diff --git a/activerecord/test/models/car.rb b/activerecord/test/models/car.rb
index 81263b79d1..778c22b1f6 100644
--- a/activerecord/test/models/car.rb
+++ b/activerecord/test/models/car.rb
@@ -4,6 +4,7 @@ class Car < ActiveRecord::Base
has_many :funky_bulbs, class_name: 'FunkyBulb', dependent: :destroy
has_many :failed_bulbs, class_name: 'FailedBulb', dependent: :destroy
has_many :foo_bulbs, -> { where(:name => 'foo') }, :class_name => "Bulb"
+ has_many :awesome_bulbs, -> { awesome }, class_name: "Bulb"
has_one :bulb
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 66a1f5aa8a..99098017d7 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -114,7 +114,7 @@ ActiveRecord::Schema.define do
create_table :bulbs, force: true do |t|
t.integer :car_id
t.string :name
- t.boolean :frickinawesome
+ t.boolean :frickinawesome, default: false
t.string :color
end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 9a00825247..5a73ce9b28 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -9,7 +9,7 @@
*Puneet Agarwal* and *Xavier Noria*
-* Added `Time#days_in_year` to return the number of days in the given year, or the
+* Added `Time.days_in_year` to return the number of days in the given year, or the
current year if no argument is provided.
*Jon Pascoe*
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index 404c16b29f..32e28c0212 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -24,6 +24,6 @@ Gem::Specification.new do |s|
s.add_dependency 'json', '~> 1.7', '>= 1.7.7'
s.add_dependency 'tzinfo', '~> 1.1'
s.add_dependency 'minitest', '~> 5.1'
- s.add_dependency 'concurrent-ruby', '~> 1.0.0.pre5', '< 2.0.0'
+ s.add_dependency 'concurrent-ruby', '~> 1.0'
s.add_dependency 'method_source'
end
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index d0e53eaf05..402a35e198 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -275,7 +275,7 @@ module ActiveSupport
def fetch(name, options = nil)
if block_given?
options = merged_options(options)
- key = namespaced_key(name, options)
+ key = normalize_key(name, options)
instrument(:read, name, options) do |payload|
cached_entry = read_entry(key, options) unless options[:force]
@@ -302,7 +302,7 @@ module ActiveSupport
# Options are passed to the underlying cache implementation.
def read(name, options = nil)
options = merged_options(options)
- key = namespaced_key(name, options)
+ key = normalize_key(name, options)
instrument(:read, name, options) do |payload|
entry = read_entry(key, options)
if entry
@@ -334,7 +334,7 @@ module ActiveSupport
instrument_multi(:read, names, options) do |payload|
results = {}
names.each do |name|
- key = namespaced_key(name, options)
+ key = normalize_key(name, options)
entry = read_entry(key, options)
if entry
if entry.expired?
@@ -386,7 +386,7 @@ module ActiveSupport
instrument(:write, name, options) do
entry = Entry.new(value, options)
- write_entry(namespaced_key(name, options), entry, options)
+ write_entry(normalize_key(name, options), entry, options)
end
end
@@ -397,7 +397,7 @@ module ActiveSupport
options = merged_options(options)
instrument(:delete, name) do
- delete_entry(namespaced_key(name, options), options)
+ delete_entry(normalize_key(name, options), options)
end
end
@@ -408,7 +408,7 @@ module ActiveSupport
options = merged_options(options)
instrument(:exist?, name) do
- entry = read_entry(namespaced_key(name, options), options)
+ entry = read_entry(normalize_key(name, options), options)
(entry && !entry.expired?) || false
end
end
@@ -529,16 +529,17 @@ module ActiveSupport
# Prefix a key with the namespace. Namespace and key will be delimited
# with a colon.
- def namespaced_key(key, options)
+ def normalize_key(key, options)
key = expanded_key(key)
namespace = options[:namespace] if options
prefix = namespace.is_a?(Proc) ? namespace.call : namespace
key = "#{prefix}:#{key}" if prefix
key
end
+ alias namespaced_key normalize_key
def instrument(operation, key, options = nil)
- log { "Cache #{operation}: #{namespaced_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}" }
+ log { "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}" }
payload = { :key => key }
payload.merge!(options) if options.is_a?(Hash)
diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb
index 9a88fc286a..9488b95214 100644
--- a/activesupport/lib/active_support/cache/file_store.rb
+++ b/activesupport/lib/active_support/cache/file_store.rb
@@ -60,7 +60,7 @@ module ActiveSupport
matcher = key_matcher(matcher, options)
search_dir(cache_path) do |path|
key = file_path_key(path)
- delete_entry(key, options) if key.match(matcher)
+ delete_entry(path, options) if key.match(matcher)
end
end
end
@@ -68,9 +68,8 @@ module ActiveSupport
protected
def read_entry(key, options)
- file_name = key_file_path(key)
- if File.exist?(file_name)
- File.open(file_name) { |f| Marshal.load(f) }
+ if File.exist?(key)
+ File.open(key) { |f| Marshal.load(f) }
end
rescue => e
logger.error("FileStoreError (#{e}): #{e.message}") if logger
@@ -78,23 +77,21 @@ module ActiveSupport
end
def write_entry(key, entry, options)
- file_name = key_file_path(key)
- return false if options[:unless_exist] && File.exist?(file_name)
- ensure_cache_path(File.dirname(file_name))
- File.atomic_write(file_name, cache_path) {|f| Marshal.dump(entry, f)}
+ return false if options[:unless_exist] && File.exist?(key)
+ ensure_cache_path(File.dirname(key))
+ File.atomic_write(key, cache_path) {|f| Marshal.dump(entry, f)}
true
end
def delete_entry(key, options)
- file_name = key_file_path(key)
- if File.exist?(file_name)
+ if File.exist?(key)
begin
- File.delete(file_name)
- delete_empty_directories(File.dirname(file_name))
+ File.delete(key)
+ delete_empty_directories(File.dirname(key))
true
rescue => e
# Just in case the error was caused by another process deleting the file first.
- raise e if File.exist?(file_name)
+ raise e if File.exist?(key)
false
end
end
@@ -118,7 +115,8 @@ module ActiveSupport
end
# Translate a key into a file path.
- def key_file_path(key)
+ def normalize_key(key, options)
+ key = super
fname = URI.encode_www_form_component(key)
if fname.size > FILEPATH_MAX_SIZE
@@ -175,7 +173,7 @@ module ActiveSupport
# Modifies the amount of an already existing integer value that is stored in the cache.
# If the key is not found nothing is done.
def modify_value(name, amount, options)
- file_name = key_file_path(namespaced_key(name, options))
+ file_name = normalize_key(name, options)
lock_file(file_name) do
options = merged_options(options)
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index e2f536ef1e..5eaf68a244 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -97,7 +97,7 @@ module ActiveSupport
options = merged_options(options)
instrument_multi(:read, names, options) do
- keys_to_names = Hash[names.map{|name| [escape_key(namespaced_key(name, options)), name]}]
+ keys_to_names = Hash[names.map{|name| [normalize_key(name, options), name]}]
raw_values = @data.get_multi(keys_to_names.keys, :raw => true)
values = {}
raw_values.each do |key, value|
@@ -115,7 +115,7 @@ module ActiveSupport
def increment(name, amount = 1, options = nil) # :nodoc:
options = merged_options(options)
instrument(:increment, name, :amount => amount) do
- @data.incr(escape_key(namespaced_key(name, options)), amount)
+ @data.incr(normalize_key(name, options), amount)
end
rescue Dalli::DalliError => e
logger.error("DalliError (#{e}): #{e.message}") if logger
@@ -129,7 +129,7 @@ module ActiveSupport
def decrement(name, amount = 1, options = nil) # :nodoc:
options = merged_options(options)
instrument(:decrement, name, :amount => amount) do
- @data.decr(escape_key(namespaced_key(name, options)), amount)
+ @data.decr(normalize_key(name, options), amount)
end
rescue Dalli::DalliError => e
logger.error("DalliError (#{e}): #{e.message}") if logger
@@ -153,7 +153,7 @@ module ActiveSupport
protected
# Read an entry from the cache.
def read_entry(key, options) # :nodoc:
- deserialize_entry(@data.get(escape_key(key), options))
+ deserialize_entry(@data.get(key, options))
rescue Dalli::DalliError => e
logger.error("DalliError (#{e}): #{e.message}") if logger
nil
@@ -168,7 +168,7 @@ module ActiveSupport
# Set the memcache expire a few minutes in the future to support race condition ttls on read
expires_in += 5.minutes
end
- @data.send(method, escape_key(key), value, expires_in, options)
+ @data.send(method, key, value, expires_in, options)
rescue Dalli::DalliError => e
logger.error("DalliError (#{e}): #{e.message}") if logger
false
@@ -176,7 +176,7 @@ module ActiveSupport
# Delete an entry from the cache.
def delete_entry(key, options) # :nodoc:
- @data.delete(escape_key(key))
+ @data.delete(key)
rescue Dalli::DalliError => e
logger.error("DalliError (#{e}): #{e.message}") if logger
false
@@ -187,8 +187,8 @@ module ActiveSupport
# Memcache keys are binaries. So we need to force their encoding to binary
# before applying the regular expression to ensure we are escaping all
# characters properly.
- def escape_key(key)
- key = key.to_s.dup
+ def normalize_key(key, options)
+ key = super.dup
key = key.force_encoding(Encoding::ASCII_8BIT)
key = key.gsub(ESCAPE_KEY_CHARS){ |match| "%#{match.getbyte(0).to_s(16).upcase}" }
key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb
index fa007aad56..46d5c6879d 100644
--- a/activesupport/lib/active_support/cache/strategy/local_cache.rb
+++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb
@@ -93,14 +93,14 @@ module ActiveSupport
def increment(name, amount = 1, options = nil) # :nodoc:
return super unless local_cache
value = bypass_local_cache{super}
- set_cache_value(value, name, amount, options)
+ set_cache_value(name, value, options)
value
end
def decrement(name, amount = 1, options = nil) # :nodoc:
return super unless local_cache
value = bypass_local_cache{super}
- set_cache_value(value, name, amount, options)
+ set_cache_value(name, value, options)
value
end
@@ -123,7 +123,8 @@ module ActiveSupport
super
end
- def set_cache_value(value, name, amount, options) # :nodoc:
+ def set_cache_value(name, value, options) # :nodoc:
+ name = normalize_key(name, options)
cache = local_cache
cache.mute do
if value
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index 3629f5e64b..3f9682231f 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -416,7 +416,7 @@ module CacheStoreBehavior
def test_race_condition_protection_skipped_if_not_defined
@cache.write('foo', 'bar')
- time = @cache.send(:read_entry, 'foo', {}).expires_at
+ time = @cache.send(:read_entry, @cache.send(:normalize_key, 'foo', {}), {}).expires_at
Time.stub(:now, Time.at(time)) do
result = @cache.fetch('foo') do
@@ -783,13 +783,13 @@ class FileStoreTest < ActiveSupport::TestCase
end
def test_key_transformation
- key = @cache.send(:key_file_path, "views/index?id=1")
+ key = @cache.send(:normalize_key, "views/index?id=1", {})
assert_equal "views/index?id=1", @cache.send(:file_path_key, key)
end
def test_key_transformation_with_pathname
FileUtils.touch(File.join(cache_dir, "foo"))
- key = @cache_with_pathname.send(:key_file_path, "views/index?id=1")
+ key = @cache_with_pathname.send(:normalize_key, "views/index?id=1", {})
assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key)
end
@@ -797,7 +797,7 @@ class FileStoreTest < ActiveSupport::TestCase
# remain valid
def test_filename_max_size
key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}"
- path = @cache.send(:key_file_path, key)
+ path = @cache.send(:normalize_key, key, {})
Dir::Tmpname.create(path) do |tmpname, n, opts|
assert File.basename(tmpname+'.lock').length <= 255, "Temp filename too long: #{File.basename(tmpname+'.lock').length}"
end
@@ -807,7 +807,7 @@ class FileStoreTest < ActiveSupport::TestCase
# If filename is 'AAAAB', where max size is 4, the returned path should be AAAA/B
def test_key_transformation_max_filename_size
key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}B"
- path = @cache.send(:key_file_path, key)
+ path = @cache.send(:normalize_key, key, {})
assert path.split('/').all? { |dir_name| dir_name.size <= ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}
assert_equal 'B', File.basename(path)
end
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index ee3f742367..729d1cc661 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -199,7 +199,7 @@ The full set of methods that can be used in this block are as follows:
Every Rails application comes with a standard set of middleware which it uses in this order in the development environment:
* `ActionDispatch::SSL` forces every request to be under HTTPS protocol. Will be available if `config.force_ssl` is set to `true`. Options passed to this can be configured by using `config.ssl_options`.
-* `ActionDispatch::Static` is used to serve static assets. Disabled if `config.public_file_server.enabled` is `false`. Set `config.static_index` if you need to serve a static directory index file that is not named `index`. For example, to serve `main.html` instead of `index.html` for directory requests, set `config.static_index` to `"main"`.
+* `ActionDispatch::Static` is used to serve static assets. Disabled if `config.public_file_server.enabled` is `false`. Set `config.public_file_server.index_name` if you need to serve a static directory index file that is not named `index`. For example, to serve `main.html` instead of `index.html` for directory requests, set `config.public_file_server.index_name` to `"main"`.
* `Rack::Lock` wraps the app in mutex so it can only be called by a single thread at a time. Only enabled when `config.cache_classes` is `false`.
* `ActiveSupport::Cache::Strategy::LocalCache` serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
* `Rack::Runtime` sets an `X-Runtime` header, containing the time (in seconds) taken to execute the request.
diff --git a/guides/source/engines.md b/guides/source/engines.md
index f961b799f1..359796b1ff 100644
--- a/guides/source/engines.md
+++ b/guides/source/engines.md
@@ -239,6 +239,27 @@ NOTE: The `ApplicationController` class inside an engine is named just like a
Rails application in order to make it easier for you to convert your
applications into engines.
+NOTE: Because of the way that Ruby does constant lookup you may run into a situation
+where your engine controller is inheriting from the main application controller and
+not your engine's application controller. Ruby is able to resolve the `ApplicationController` constant, and therefore the autoloading mechanism is not triggered. See the section [When Constants Aren't Missed](autoloading_and_reloading_constants.html#when-constants-aren-t-missed) of the [Autoloading and Reloading Constants](autoloading_and_reloading_constants.html) guide for further details. The best way to prevent this from
+happening is to use `require_dependency` to ensure that the engine's application
+controller is loaded. For example:
+
+``` ruby
+# app/controllers/blorgh/articles_controller.rb:
+require_dependency "blorgh/application_controller"
+
+module Blorgh
+ class ArticlesController < ApplicationController
+ ...
+ end
+end
+```
+
+WARNING: Don't use `require` because it will break the automatic reloading of classes
+in the development environment - using `require_dependency` ensures that classes are
+loaded and unloaded in the correct manner.
+
Lastly, the `app/views` directory contains a `layouts` folder, which contains a
file at `blorgh/application.html.erb`. This file allows you to specify a layout
for the engine. If this engine is to be used as a stand-alone engine, then you
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 2f941a8280..f63ea49955 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -155,7 +155,7 @@ Failed assertion, no message given.
1 tests, 1 assertions, 1 failures, 0 errors, 0 skips
```
-In the output, `F` denotes a failure. You can see the corresponding trace shown under `1)` along with the name of the failing test. The next few lines contain the stack trace followed by a message which mentions the actual value and the expected value by the assertion. The default assertion messages provide just enough information to help pinpoint the error. To make the assertion failure message more readable, every assertion provides an optional message parameter, as shown here:
+In the output, `F` denotes a failure. You can see the corresponding trace shown under `1)` along with the name of the failing test. The next few lines contain the stack trace followed by a message that mentions the actual value and the expected value by the assertion. The default assertion messages provide just enough information to help pinpoint the error. To make the assertion failure message more readable, every assertion provides an optional message parameter, as shown here:
```ruby
test "should not save article without title" do
@@ -523,7 +523,7 @@ Model tests don't have their own superclass like `ActionMailer::TestCase` instea
Integration Testing
-------------------
-Integration tests are used to test how various parts of your application interact. They are generally used to test important work flows within your application.
+Integration tests are used to test how various parts of your application interact. They are generally used to test important workflows within your application.
For creating Rails integration tests, we use the 'test/integration' directory for your application. Rails provides a generator to create an integration test skeleton for you.
@@ -1232,3 +1232,25 @@ class ProductTest < ActiveJob::TestCase
end
end
```
+
+Testing Time-Dependent Code
+---------------------------
+
+Rails provides inbuilt helper methods that enable you to assert that your time-sensitve code works as expected.
+
+Here is an example using the [`travel_to`](http://api.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html#method-i-travel_to) helper:
+
+```ruby
+# Lets say that a user is eligible for gifting a month after they register.
+user = User.create(name: 'Gaurish', activation_date: Date.new(2004, 10, 24))
+assert_not user.applicable_for_gifting?
+travel_to Date.new(2004, 11, 24) do
+ assert_equal Date.new(2004, 10, 24), user.activation_date # inside the travel_to block `Date.current` is mocked
+ assert user.applicable_for_gifting?
+end
+assert_equal Date.new(2004, 10, 24), user.activation_date # The change was visible only inside the `travel_to` block.
+```
+
+Please see [`ActiveSupport::TimeHelpers` API Documentation](http://api.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html)
+for in-depth information about the available time helpers.
+
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 2fedeac292..aa12708669 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Make `static_index` part of the `config.public_file_server` config and
+ call it `public_file_server.index_name`.
+
+ *Yuki Nishijima*
+
* Generated `Gemfile`s for new applications include a new dependency on
[listen](https://github.com/guard/listen) commented out.
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 6d89caf514..80733c2d90 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -14,7 +14,7 @@ module Rails
:eager_load, :exceptions_app, :file_watcher, :filter_parameters,
:force_ssl, :helpers_paths, :logger, :log_formatter, :log_tags,
:railties_order, :relative_url_root, :secret_key_base, :secret_token,
- :ssl_options, :static_index, :public_file_server,
+ :ssl_options, :public_file_server,
:session_options, :time_zone, :reload_classes_only_on_change,
:beginning_of_week, :filter_redirect, :x
@@ -29,9 +29,9 @@ module Rails
@filter_parameters = []
@filter_redirect = []
@helpers_paths = []
- @static_index = "index"
@public_file_server = ActiveSupport::OrderedOptions.new
@public_file_server.enabled = true
+ @public_file_server.index_name = "index"
@force_ssl = false
@ssl_options = {}
@session_store = :cookie_store
diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb
index b0d481c21a..5cb5bfb8b7 100644
--- a/railties/lib/rails/application/default_middleware_stack.rb
+++ b/railties/lib/rails/application/default_middleware_stack.rb
@@ -21,7 +21,7 @@ module Rails
headers = config.public_file_server.headers || {}
headers['Cache-Control'.freeze] = config.static_cache_control if config.static_cache_control
- middleware.use ::ActionDispatch::Static, paths["public"].first, index: config.static_index, headers: headers
+ middleware.use ::ActionDispatch::Static, paths["public"].first, index: config.public_file_server.index_name, headers: headers
end
if rack_cache = load_rack_cache
diff --git a/railties/test/application/middleware/static_test.rb b/railties/test/application/middleware/static_test.rb
index 5366537dc2..1246e20d94 100644
--- a/railties/test/application/middleware/static_test.rb
+++ b/railties/test/application/middleware/static_test.rb
@@ -44,7 +44,7 @@ module ApplicationTests
assert_equal 'public, max-age=60', last_response.headers["Cache-Control"]
end
- test "static_index defaults to 'index'" do
+ test "public_file_server.index_name defaults to 'index'" do
app_file "public/index.html", "/index.html"
require "#{app_path}/config/environment"
@@ -54,10 +54,10 @@ module ApplicationTests
assert_equal "/index.html\n", last_response.body
end
- test "static_index configurable" do
+ test "public_file_server.index_name configurable" do
app_file "public/other-index.html", "/other-index.html"
- add_to_config "config.static_index = 'other-index'"
-
+ add_to_config "config.public_file_server.index_name = 'other-index'"
+
require "#{app_path}/config/environment"
get '/'