aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb30
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb40
-rw-r--r--actionpack/test/dispatch/exception_wrapper_test.rb97
-rw-r--r--activejob/lib/active_job/queue_adapters.rb1
-rw-r--r--activerecord/lib/active_record/attribute_methods/primary_key.rb1
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb2
-rw-r--r--activerecord/lib/active_record/attribute_set.rb14
-rw-r--r--activerecord/lib/active_record/attribute_set/builder.rb96
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb6
-rw-r--r--activerecord/lib/active_record/core.rb2
-rw-r--r--activerecord/lib/active_record/inheritance.rb12
-rw-r--r--activerecord/lib/active_record/model_schema.rb2
-rw-r--r--activerecord/lib/active_record/persistence.rb28
-rw-r--r--activerecord/lib/active_record/querying.rb2
-rw-r--r--activerecord/lib/active_record/result.rb9
-rw-r--r--activerecord/lib/active_record/scoping/named.rb2
-rw-r--r--activerecord/lib/active_record/type/serialized.rb2
-rw-r--r--activerecord/test/cases/adapters/mysql2/explain_test.rb1
-rw-r--r--activerecord/test/cases/adapters/postgresql/explain_test.rb1
-rw-r--r--activerecord/test/cases/adapters/sqlite3/explain_test.rb1
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb1
-rw-r--r--activerecord/test/cases/associations/callbacks_test.rb1
-rw-r--r--activerecord/test/cases/associations/eager_test.rb1
-rw-r--r--activerecord/test/cases/associations/extension_test.rb1
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb1
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb1
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb1
-rw-r--r--activerecord/test/cases/associations_test.rb1
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb1
-rw-r--r--activerecord/test/cases/attribute_set_test.rb19
-rw-r--r--activerecord/test/cases/autosave_association_test.rb1
-rw-r--r--activerecord/test/cases/base_test.rb1
-rw-r--r--activerecord/test/cases/callbacks_test.rb2
-rw-r--r--activerecord/test/cases/finder_test.rb1
-rw-r--r--activerecord/test/cases/fixtures_test.rb1
-rw-r--r--activerecord/test/cases/integration_test.rb1
-rw-r--r--activerecord/test/cases/migration_test.rb1
-rw-r--r--activerecord/test/cases/modules_test.rb1
-rw-r--r--activerecord/test/cases/persistence_test.rb1
-rw-r--r--activerecord/test/cases/readonly_test.rb1
-rw-r--r--activerecord/test/cases/relation/merging_test.rb1
-rw-r--r--activerecord/test/cases/relations_test.rb1
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb1
-rw-r--r--activerecord/test/cases/scoping/named_scoping_test.rb1
-rw-r--r--activerecord/test/cases/scoping/relation_scoping_test.rb1
-rw-r--r--activerecord/test/cases/timestamp_test.rb1
-rw-r--r--activerecord/test/cases/transactions_test.rb1
-rw-r--r--activerecord/test/cases/validations_test.rb1
-rw-r--r--activesupport/lib/active_support/message_verifier.rb12
-rw-r--r--activesupport/lib/active_support/multibyte/unicode.rb2
-rw-r--r--activesupport/lib/active_support/values/unicode_tables.datbin904640 -> 1001806 bytes
-rw-r--r--guides/source/active_job_basics.md2
-rw-r--r--guides/source/active_support_core_extensions.md2
-rw-r--r--guides/source/getting_started.md2
-rw-r--r--guides/source/testing.md22
-rw-r--r--railties/CHANGELOG.md16
-rw-r--r--railties/lib/rails/application/bootstrap.rb13
-rw-r--r--railties/lib/rails/application/configuration.rb13
-rw-r--r--railties/lib/rails/engine.rb4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt5
-rw-r--r--railties/lib/rails/paths.rb4
63 files changed, 342 insertions, 157 deletions
diff --git a/Gemfile b/Gemfile
index 931c8e85bc..fa17d217c9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -81,7 +81,7 @@ platforms :ruby do
gem 'sqlite3', '~> 1.3.6'
group :db do
- gem 'pg', '>= 0.11.0'
+ gem 'pg', '>= 0.15.0'
gem 'mysql', '>= 2.9.0'
gem 'mysql2', '>= 0.3.13'
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 798c087d64..c1562fcc0d 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -38,7 +38,7 @@ module ActionDispatch
traces = wrapper.traces
trace_to_show = 'Application Trace'
- if traces[trace_to_show].empty?
+ if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
trace_to_show = 'Full Trace'
end
@@ -53,7 +53,7 @@ module ActionDispatch
show_source_idx: source_to_show_id,
trace_to_show: trace_to_show,
routes_inspector: routes_inspector(exception),
- source_extract: wrapper.source_extract,
+ source_extracts: wrapper.source_extracts,
line_number: wrapper.line_number,
file: wrapper.file
)
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index e0140b0692..a4862e33aa 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -62,14 +62,16 @@ module ActionDispatch
framework_trace_with_ids = []
full_trace_with_ids = []
- if full_trace
- full_trace.each_with_index do |trace, idx|
- trace_with_id = { id: idx, trace: trace }
+ full_trace.each_with_index do |trace, idx|
+ trace_with_id = { id: idx, trace: trace }
- appplication_trace_with_ids << trace_with_id if application_trace.include?(trace)
- framework_trace_with_ids << trace_with_id if framework_trace.include?(trace)
- full_trace_with_ids << trace_with_id
+ if application_trace.include?(trace)
+ appplication_trace_with_ids << trace_with_id
+ else
+ framework_trace_with_ids << trace_with_id
end
+
+ full_trace_with_ids << trace_with_id
end
{
@@ -83,20 +85,24 @@ module ActionDispatch
Rack::Utils.status_code(@@rescue_responses[class_name])
end
- def source_extract
- exception.backtrace.map do |trace|
+ def source_extracts
+ backtrace.map do |trace|
file, line = trace.split(":")
line_number = line.to_i
+
{
code: source_fragment(file, line_number),
- file: file,
line_number: line_number
}
- end if exception.backtrace
+ end
end
private
+ def backtrace
+ Array(@exception.backtrace)
+ end
+
def original_exception(exception)
if registered_original_exception?(exception)
exception.original_exception
@@ -111,9 +117,9 @@ module ActionDispatch
def clean_backtrace(*args)
if backtrace_cleaner
- backtrace_cleaner.clean(@exception.backtrace, *args)
+ backtrace_cleaner.clean(backtrace, *args)
else
- @exception.backtrace
+ backtrace
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
index eabac3a9d2..e7b913bbe4 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
@@ -1,29 +1,27 @@
-<% if @source_extract %>
- <% @source_extract.each_with_index do |extract_source, index| %>
- <% if extract_source[:code] %>
- <div class="source <%="hidden" if @show_source_idx != index%>" id="frame-source-<%=index%>">
- <div class="info">
- Extracted source (around line <strong>#<%= extract_source[:line_number] %></strong>):
- </div>
- <div class="data">
- <table cellpadding="0" cellspacing="0" class="lines">
- <tr>
- <td>
- <pre class="line_numbers">
- <% extract_source[:code].each_key do |line_number| %>
+<% @source_extracts.each_with_index do |source_extract, index| %>
+ <% if source_extract[:code] %>
+ <div class="source <%="hidden" if @show_source_idx != index%>" id="frame-source-<%=index%>">
+ <div class="info">
+ Extracted source (around line <strong>#<%= source_extract[:line_number] %></strong>):
+ </div>
+ <div class="data">
+ <table cellpadding="0" cellspacing="0" class="lines">
+ <tr>
+ <td>
+ <pre class="line_numbers">
+ <% source_extract[:code].each_key do |line_number| %>
<span><%= line_number -%></span>
- <% end %>
- </pre>
- </td>
+ <% end %>
+ </pre>
+ </td>
<td width="100%">
<pre>
-<% extract_source[:code].each do |line, source| -%><div class="line<%= " active" if line == extract_source[:line_number] -%>"><%= source -%></div><% end -%>
+<% source_extract[:code].each do |line, source| -%><div class="line<%= " active" if line == source_extract[:line_number] -%>"><%= source -%></div><% end -%>
</pre>
</td>
- </tr>
- </table>
- </div>
+ </tr>
+ </table>
</div>
- <% end %>
+ </div>
<% end %>
<% end %>
diff --git a/actionpack/test/dispatch/exception_wrapper_test.rb b/actionpack/test/dispatch/exception_wrapper_test.rb
new file mode 100644
index 0000000000..d7408164ba
--- /dev/null
+++ b/actionpack/test/dispatch/exception_wrapper_test.rb
@@ -0,0 +1,97 @@
+require 'abstract_unit'
+
+module ActionDispatch
+ class ExceptionWrapperTest < ActionDispatch::IntegrationTest
+ class TestError < StandardError
+ attr_reader :backtrace
+
+ def initialize(*backtrace)
+ @backtrace = backtrace.flatten
+ end
+ end
+
+ class BadlyDefinedError < StandardError
+ def backtrace
+ nil
+ end
+ end
+
+ setup do
+ Rails.stubs(:root).returns(Pathname.new('.'))
+
+ cleaner = ActiveSupport::BacktraceCleaner.new
+ cleaner.add_silencer { |line| line !~ /^lib/ }
+
+ @environment = { 'action_dispatch.backtrace_cleaner' => cleaner }
+ end
+
+ test '#source_extracts fetches source fragments for every backtrace entry' do
+ exception = TestError.new("lib/file.rb:42:in `index'")
+ wrapper = ExceptionWrapper.new({}, exception)
+
+ wrapper.expects(:source_fragment).with('lib/file.rb', 42).returns('foo')
+
+ assert_equal [ code: 'foo', line_number: 42 ], wrapper.source_extracts
+ end
+
+
+ test '#application_trace returns traces only from the application' do
+ exception = TestError.new(caller.prepend("lib/file.rb:42:in `index'"))
+ wrapper = ExceptionWrapper.new(@environment, exception)
+
+ assert_equal [ "lib/file.rb:42:in `index'" ], wrapper.application_trace
+ end
+
+ test '#application_trace cannot be nil' do
+ nil_backtrace_wrapper = ExceptionWrapper.new(@environment, BadlyDefinedError.new)
+ nil_cleaner_wrapper = ExceptionWrapper.new({}, BadlyDefinedError.new)
+
+ assert_equal [], nil_backtrace_wrapper.application_trace
+ assert_equal [], nil_cleaner_wrapper.application_trace
+ end
+
+ test '#framework_trace returns traces outside the application' do
+ exception = TestError.new(caller.prepend("lib/file.rb:42:in `index'"))
+ wrapper = ExceptionWrapper.new(@environment, exception)
+
+ assert_equal caller, wrapper.framework_trace
+ end
+
+ test '#framework_trace cannot be nil' do
+ nil_backtrace_wrapper = ExceptionWrapper.new(@environment, BadlyDefinedError.new)
+ nil_cleaner_wrapper = ExceptionWrapper.new({}, BadlyDefinedError.new)
+
+ assert_equal [], nil_backtrace_wrapper.framework_trace
+ assert_equal [], nil_cleaner_wrapper.framework_trace
+ end
+
+ test '#full_trace returns application and framework traces' do
+ exception = TestError.new(caller.prepend("lib/file.rb:42:in `index'"))
+ wrapper = ExceptionWrapper.new(@environment, exception)
+
+ assert_equal exception.backtrace, wrapper.full_trace
+ end
+
+ test '#full_trace cannot be nil' do
+ nil_backtrace_wrapper = ExceptionWrapper.new(@environment, BadlyDefinedError.new)
+ nil_cleaner_wrapper = ExceptionWrapper.new({}, BadlyDefinedError.new)
+
+ assert_equal [], nil_backtrace_wrapper.full_trace
+ assert_equal [], nil_cleaner_wrapper.full_trace
+ end
+
+ test '#traces returns every trace by category enumerated with an index' do
+ exception = TestError.new("lib/file.rb:42:in `index'", "/gems/rack.rb:43:in `index'")
+ wrapper = ExceptionWrapper.new(@environment, exception)
+
+ assert_equal({
+ 'Application Trace' => [ id: 0, trace: "lib/file.rb:42:in `index'" ],
+ 'Framework Trace' => [ id: 1, trace: "/gems/rack.rb:43:in `index'" ],
+ 'Full Trace' => [
+ { id: 0, trace: "lib/file.rb:42:in `index'" },
+ { id: 1, trace: "/gems/rack.rb:43:in `index'" }
+ ]
+ }, wrapper.traces)
+ end
+ end
+end
diff --git a/activejob/lib/active_job/queue_adapters.rb b/activejob/lib/active_job/queue_adapters.rb
index f22b0502dc..4b91c93dbe 100644
--- a/activejob/lib/active_job/queue_adapters.rb
+++ b/activejob/lib/active_job/queue_adapters.rb
@@ -19,6 +19,7 @@ module ActiveJob
# |-------------------|-------|--------|-----------|------------|---------|---------|
# | Backburner | Yes | Yes | Yes | Yes | Job | Global |
# | Delayed Job | Yes | Yes | Yes | Job | Global | Global |
+ # | Qu | Yes | Yes | No | No | No | Global |
# | Que | Yes | Yes | Yes | Job | No | Job |
# | queue_classic | Yes | Yes | No* | No | No | No |
# | Resque | Yes | Yes | Yes (Gem) | Queue | Global | Yes |
diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb
index 9bd333bbac..104d84a1f8 100644
--- a/activerecord/lib/active_record/attribute_methods/primary_key.rb
+++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb
@@ -120,6 +120,7 @@ module ActiveRecord
def primary_key=(value)
@primary_key = value && value.to_s
@quoted_primary_key = nil
+ @attributes_builder = nil
end
end
end
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index b7fe079ef5..33d9d2002c 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -1,7 +1,7 @@
module ActiveRecord
module AttributeMethods
module TimeZoneConversion
- class TimeZoneConverter < SimpleDelegator # :nodoc:
+ class TimeZoneConverter < DelegateClass(Type::Value) # :nodoc:
include Type::Decorator
def type_cast_from_database(value)
diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb
index 98ac63c7e1..21c58cbf1d 100644
--- a/activerecord/lib/active_record/attribute_set.rb
+++ b/activerecord/lib/active_record/attribute_set.rb
@@ -2,8 +2,6 @@ require 'active_record/attribute_set/builder'
module ActiveRecord
class AttributeSet # :nodoc:
- delegate :keys, to: :initialized_attributes
-
def initialize(attributes)
@attributes = attributes
end
@@ -25,6 +23,10 @@ module ActiveRecord
attributes.key?(name) && self[name].initialized?
end
+ def keys
+ attributes.initialized_keys
+ end
+
def fetch_value(name, &block)
self[name].value(&block)
end
@@ -43,7 +45,7 @@ module ActiveRecord
end
def initialize_dup(_)
- @attributes = attributes.transform_values(&:dup)
+ @attributes = attributes.dup
super
end
@@ -58,12 +60,6 @@ module ActiveRecord
end
end
- def ensure_initialized(key)
- unless self[key].initialized?
- write_from_database(key, nil)
- end
- end
-
protected
attr_reader :attributes
diff --git a/activerecord/lib/active_record/attribute_set/builder.rb b/activerecord/lib/active_record/attribute_set/builder.rb
index 0a62c68bfb..73b77d2eda 100644
--- a/activerecord/lib/active_record/attribute_set/builder.rb
+++ b/activerecord/lib/active_record/attribute_set/builder.rb
@@ -1,50 +1,88 @@
module ActiveRecord
class AttributeSet # :nodoc:
class Builder # :nodoc:
- attr_reader :types
+ attr_reader :types, :always_initialized
- def initialize(types)
+ def initialize(types, always_initialized = nil)
@types = types
+ @always_initialized = always_initialized
end
def build_from_database(values = {}, additional_types = {})
- build_from_database_pairs(values.keys, values.values, additional_types)
- end
+ if always_initialized && !values.key?(always_initialized)
+ values[always_initialized] = nil
+ end
- def build_from_database_pairs(columns, values, additional_types)
- attributes = build_attributes_from_values(columns, values, additional_types)
- add_uninitialized_attributes(attributes)
+ attributes = LazyAttributeHash.new(types, values, additional_types)
AttributeSet.new(attributes)
end
private
+ end
+ end
- def build_attributes_from_values(columns, values, additional_types)
- # We are performing manual iteration here as this method is a performance
- # hotspot
- hash = {}
- index = 0
- length = columns.length
-
- while index < length
- name = columns[index]
- value = values[index]
- type = additional_types.fetch(name, types[name])
- hash[name] = Attribute.from_database(name, value, type)
- index += 1
- end
+ class LazyAttributeHash
+ delegate :select, :transform_values, to: :materialize
+
+ def initialize(types, values, additional_types)
+ @types = types
+ @values = values
+ @additional_types = additional_types
+ @materialized = false
+ @delegate_hash = {}
+ end
- hash
+ def key?(key)
+ delegate_hash.key?(key) || values.key?(key) || types.key?(key)
+ end
+
+ def [](key)
+ if delegate_hash.key?(key)
+ delegate_hash[key]
+ else
+ assign_default_value(key)
end
+ end
- def add_uninitialized_attributes(attributes)
- types.each_key do |name|
- next if attributes.key? name
- type = types[name]
- attributes[name] =
- Attribute.uninitialized(name, type)
- end
+ def []=(key, value)
+ if frozen?
+ raise RuntimeError, "Can't modify frozen hash"
+ end
+ delegate_hash[key] = value
+ end
+
+ def initialized_keys
+ delegate_hash.keys | values.keys
+ end
+
+ def initialize_dup(_)
+ @delegate_hash = delegate_hash.transform_values(&:dup)
+ super
+ end
+
+ protected
+
+ attr_reader :types, :values, :additional_types, :delegate_hash
+
+ private
+
+ def assign_default_value(name)
+ type = additional_types.fetch(name, types[name])
+
+ if values.key?(name)
+ delegate_hash[name] = Attribute.from_database(name, values[name], type)
+ elsif types.key?(name)
+ delegate_hash[name] = Attribute.uninitialized(name, type)
+ end
+ end
+
+ def materialize
+ unless @materialized
+ values.each_key { |key| self[key] }
+ types.each_key { |key| self[key] }
+ @materialized = true
end
+ delegate_hash
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 9941f74766..6310d70192 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -13,7 +13,7 @@ require 'active_record/connection_adapters/postgresql/database_statements'
require 'arel/visitors/bind_visitor'
# Make sure we're using pg high enough for PGResult#values
-gem 'pg', '~> 0.11'
+gem 'pg', '~> 0.15'
require 'pg'
require 'ipaddr'
@@ -596,9 +596,7 @@ module ActiveRecord
}
log(sql, name, type_casted_binds, stmt_key) do
- @connection.send_query_prepared(stmt_key, type_casted_binds.map { |_, val| val })
- @connection.block
- @connection.get_last_result
+ @connection.exec_prepared(stmt_key, type_casted_binds.map { |_, val| val })
end
rescue ActiveRecord::StatementInvalid => e
pgerror = e.original_exception
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 952aeaa703..89d8932e9e 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -536,8 +536,6 @@ module ActiveRecord
end
def init_internals
- @attributes.ensure_initialized(self.class.primary_key)
-
@aggregation_cache = {}
@association_cache = {}
@readonly = false
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index 4aad3217cb..f58145ab05 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -165,19 +165,15 @@ module ActiveRecord
# record instance. For single-table inheritance, we check the record
# for a +type+ column and return the corresponding class.
def discriminate_class_for_record(record)
- discriminate_class_for_value(record[inheritance_column])
- end
-
- def discriminate_class_for_value(value)
- if using_single_table_inheritance?(value)
- find_sti_class(value)
+ if using_single_table_inheritance?(record)
+ find_sti_class(record[inheritance_column])
else
super
end
end
- def using_single_table_inheritance?(value)
- value.present? && columns_hash.include?(inheritance_column)
+ def using_single_table_inheritance?(record)
+ record[inheritance_column].present? && columns_hash.include?(inheritance_column)
end
def find_sti_class(type_name)
diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb
index a444aac23c..adad7774b9 100644
--- a/activerecord/lib/active_record/model_schema.rb
+++ b/activerecord/lib/active_record/model_schema.rb
@@ -231,7 +231,7 @@ module ActiveRecord
end
def attributes_builder # :nodoc:
- @attributes_builder ||= AttributeSet::Builder.new(column_types)
+ @attributes_builder ||= AttributeSet::Builder.new(column_types, primary_key)
end
def column_types # :nodoc:
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 06c8bceb30..507faf2879 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -65,41 +65,19 @@ module ActiveRecord
# how this "single-table" inheritance mapping is implemented.
def instantiate(attributes, column_types = {})
klass = discriminate_class_for_record(attributes)
- klass.instantiate_pairs(attributes.keys, attributes.values, column_types)
- end
-
- def instantiate_pairs(columns, values, column_types = {}) # :nodoc:
- attributes = attributes_builder.build_from_database_pairs(columns, values, column_types)
- allocate.init_with('attributes' => attributes, 'new_record' => false)
- end
-
- def instantiate_result_set(result_set, column_types = {}) # :nodoc:
- inheritance_column_index = inheritance_column && result_set.columns.find_index(inheritance_column)
-
- result_set.each_pair.map do |columns, values|
- inheritance_value = inheritance_column_index && values[inheritance_column_index]
- klass = discriminate_class_for_value(inheritance_value)
- klass.instantiate_pairs(columns, values, column_types)
- end
+ attributes = klass.attributes_builder.build_from_database(attributes, column_types)
+ klass.allocate.init_with('attributes' => attributes, 'new_record' => false)
end
private
# Called by +instantiate+ to decide which class to use for a new
# record instance.
#
- # See +ActiveRecord::Inheritance#discriminate_class_for_value+ for
+ # See +ActiveRecord::Inheritance#discriminate_class_for_record+ for
# the single-table inheritance discriminator.
- def discriminate_class_for_value(*)
- self
- end
-
def discriminate_class_for_record(record)
self
end
-
- def inheritance_column
- nil
- end
end
# Returns true if this object hasn't been saved yet -- that is, a record
diff --git a/activerecord/lib/active_record/querying.rb b/activerecord/lib/active_record/querying.rb
index 9d4df81b07..e8de4db3a7 100644
--- a/activerecord/lib/active_record/querying.rb
+++ b/activerecord/lib/active_record/querying.rb
@@ -47,7 +47,7 @@ module ActiveRecord
}
message_bus.instrument('instantiation.active_record', payload) do
- instantiate_result_set(result_set, column_types)
+ result_set.map { |record| instantiate(record, column_types) }
end
end
diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb
index c84ad586e2..3a3e65ef32 100644
--- a/activerecord/lib/active_record/result.rb
+++ b/activerecord/lib/active_record/result.rb
@@ -54,15 +54,6 @@ module ActiveRecord
end
end
- def each_pair
- return to_enum(__method__) unless block_given?
-
- columns = @columns.map { |c| c.dup.freeze }
- @rows.each do |row|
- yield columns, row
- end
- end
-
def to_hash
hash_rows
end
diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb
index ec1edf0e01..35420e6551 100644
--- a/activerecord/lib/active_record/scoping/named.rb
+++ b/activerecord/lib/active_record/scoping/named.rb
@@ -139,7 +139,7 @@ module ActiveRecord
# Article.published.featured.latest_article
# Article.featured.titles
def scope(name, body, &block)
- unless body.respond_to?:call
+ unless body.respond_to?(:call)
raise ArgumentError, 'The scope body needs to be callable.'
end
diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb
index 17004b3593..3191a868ef 100644
--- a/activerecord/lib/active_record/type/serialized.rb
+++ b/activerecord/lib/active_record/type/serialized.rb
@@ -1,6 +1,6 @@
module ActiveRecord
module Type
- class Serialized < SimpleDelegator # :nodoc:
+ class Serialized < DelegateClass(Type::Value) # :nodoc:
include Mutable
include Decorator
diff --git a/activerecord/test/cases/adapters/mysql2/explain_test.rb b/activerecord/test/cases/adapters/mysql2/explain_test.rb
index 675703caa1..f67f21fab1 100644
--- a/activerecord/test/cases/adapters/mysql2/explain_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/explain_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'models/developer'
+require 'models/computer'
module ActiveRecord
module ConnectionAdapters
diff --git a/activerecord/test/cases/adapters/postgresql/explain_test.rb b/activerecord/test/cases/adapters/postgresql/explain_test.rb
index 19053b6732..d2dd04b84b 100644
--- a/activerecord/test/cases/adapters/postgresql/explain_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/explain_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'models/developer'
+require 'models/computer'
module ActiveRecord
module ConnectionAdapters
diff --git a/activerecord/test/cases/adapters/sqlite3/explain_test.rb b/activerecord/test/cases/adapters/sqlite3/explain_test.rb
index f1d6119d2e..de6e35ef57 100644
--- a/activerecord/test/cases/adapters/sqlite3/explain_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/explain_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'models/developer'
+require 'models/computer'
module ActiveRecord
module ConnectionAdapters
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index bcd0cf82d5..17394cb6f7 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -1,5 +1,6 @@
require 'cases/helper'
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/company'
require 'models/topic'
diff --git a/activerecord/test/cases/associations/callbacks_test.rb b/activerecord/test/cases/associations/callbacks_test.rb
index 5b7e462f64..a531e0e02c 100644
--- a/activerecord/test/cases/associations/callbacks_test.rb
+++ b/activerecord/test/cases/associations/callbacks_test.rb
@@ -3,6 +3,7 @@ require 'models/post'
require 'models/author'
require 'models/project'
require 'models/developer'
+require 'models/computer'
require 'models/company'
class AssociationCallbacksTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 8234ee95be..4539b99504 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -17,6 +17,7 @@ require 'models/subscriber'
require 'models/subscription'
require 'models/book'
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/member'
require 'models/membership'
diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb
index 4c1fdfdd9a..9d373cd73b 100644
--- a/activerecord/test/cases/associations/extension_test.rb
+++ b/activerecord/test/cases/associations/extension_test.rb
@@ -3,6 +3,7 @@ require 'models/post'
require 'models/comment'
require 'models/project'
require 'models/developer'
+require 'models/computer'
require 'models/company_in_module'
class AssociationsExtensionsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 69f7bde4bc..5a963b6458 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/company'
require 'models/contract'
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index cddf1a1f72..df4a30ae9b 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -15,6 +15,7 @@ require 'models/toy'
require 'models/contract'
require 'models/company'
require 'models/developer'
+require 'models/computer'
require 'models/subscriber'
require 'models/book'
require 'models/subscription'
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index d412b3168e..2ecfcb521d 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/company'
require 'models/ship'
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index 9b0cf4c18f..04ef50e58a 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -1,6 +1,7 @@
require "cases/helper"
require 'models/computer'
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/company'
require 'models/categorization'
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index c3e8ceb0da..731d433706 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -1,6 +1,7 @@
require "cases/helper"
require 'models/minimalistic'
require 'models/developer'
+require 'models/computer'
require 'models/auto_id'
require 'models/boolean'
require 'models/computer'
diff --git a/activerecord/test/cases/attribute_set_test.rb b/activerecord/test/cases/attribute_set_test.rb
index dc20c3c676..de63672963 100644
--- a/activerecord/test/cases/attribute_set_test.rb
+++ b/activerecord/test/cases/attribute_set_test.rb
@@ -109,7 +109,15 @@ module ActiveRecord
test "fetch_value returns nil for unknown attributes" do
attributes = attributes_with_uninitialized_key
- assert_nil attributes.fetch_value(:wibble)
+ assert_nil attributes.fetch_value(:wibble) { "hello" }
+ end
+
+ test "fetch_value returns nil for unknown attributes when types has a default" do
+ types = Hash.new(Type::Value.new)
+ builder = AttributeSet::Builder.new(types)
+ attributes = builder.build_from_database
+
+ assert_nil attributes.fetch_value(:wibble) { "hello" }
end
test "fetch_value uses the given block for uninitialized attributes" do
@@ -123,6 +131,15 @@ module ActiveRecord
assert_nil attributes.fetch_value(:bar)
end
+ test "the primary_key is always initialized" do
+ builder = AttributeSet::Builder.new({ foo: Type::Integer.new }, :foo)
+ attributes = builder.build_from_database
+
+ assert attributes.key?(:foo)
+ assert_equal [:foo], attributes.keys
+ assert attributes[:foo].initialized?
+ end
+
class MyType
def type_cast_from_user(value)
return if value.nil?
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 734fd5fe18..71c34d816a 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -4,6 +4,7 @@ require 'models/comment'
require 'models/company'
require 'models/customer'
require 'models/developer'
+require 'models/computer'
require 'models/invoice'
require 'models/line_item'
require 'models/order'
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 3675401555..098d5b8451 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -10,6 +10,7 @@ require 'models/category'
require 'models/company'
require 'models/customer'
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/default'
require 'models/auto_id'
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index c8f56e3c73..5e07f8a03c 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -1,4 +1,6 @@
require "cases/helper"
+require 'models/developer'
+require 'models/computer'
class CallbackDeveloper < ActiveRecord::Base
self.table_name = 'developers'
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index dc73faa5be..33a59d4678 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -10,6 +10,7 @@ require 'models/reply'
require 'models/entrant'
require 'models/project'
require 'models/developer'
+require 'models/computer'
require 'models/customer'
require 'models/toy'
require 'models/matey'
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 7141d3ee7f..4b0ebe13d1 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -10,6 +10,7 @@ require 'models/company'
require 'models/computer'
require 'models/course'
require 'models/developer'
+require 'models/computer'
require 'models/joke'
require 'models/matey'
require 'models/parrot'
diff --git a/activerecord/test/cases/integration_test.rb b/activerecord/test/cases/integration_test.rb
index dfb8a608cb..0021988083 100644
--- a/activerecord/test/cases/integration_test.rb
+++ b/activerecord/test/cases/integration_test.rb
@@ -3,6 +3,7 @@
require 'cases/helper'
require 'models/company'
require 'models/developer'
+require 'models/computer'
require 'models/owner'
require 'models/pet'
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 6b7a0a9000..3192b797b4 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -5,6 +5,7 @@ require 'bigdecimal/util'
require 'models/person'
require 'models/topic'
require 'models/developer'
+require 'models/computer'
require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
require MIGRATIONS_ROOT + "/rename/1_we_need_things"
diff --git a/activerecord/test/cases/modules_test.rb b/activerecord/test/cases/modules_test.rb
index e87773df94..6f65bf80eb 100644
--- a/activerecord/test/cases/modules_test.rb
+++ b/activerecord/test/cases/modules_test.rb
@@ -2,6 +2,7 @@ require "cases/helper"
require 'models/company_in_module'
require 'models/shop'
require 'models/developer'
+require 'models/computer'
class ModulesTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :projects, :developers, :collections, :products, :variants
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 2170fe6118..2bcd496415 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -8,6 +8,7 @@ require 'models/reply'
require 'models/category'
require 'models/company'
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/minimalistic'
require 'models/warehouse_thing'
diff --git a/activerecord/test/cases/readonly_test.rb b/activerecord/test/cases/readonly_test.rb
index 5b903e4f2c..1c919f0b57 100644
--- a/activerecord/test/cases/readonly_test.rb
+++ b/activerecord/test/cases/readonly_test.rb
@@ -3,6 +3,7 @@ require 'models/author'
require 'models/post'
require 'models/comment'
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/reader'
require 'models/person'
diff --git a/activerecord/test/cases/relation/merging_test.rb b/activerecord/test/cases/relation/merging_test.rb
index 8f40a1890d..eb76ef6328 100644
--- a/activerecord/test/cases/relation/merging_test.rb
+++ b/activerecord/test/cases/relation/merging_test.rb
@@ -2,6 +2,7 @@ require 'cases/helper'
require 'models/author'
require 'models/comment'
require 'models/developer'
+require 'models/computer'
require 'models/post'
require 'models/project'
require 'models/rating'
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 410b5ba5a3..8ac4a4ca36 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -7,6 +7,7 @@ require 'models/comment'
require 'models/author'
require 'models/entrant'
require 'models/developer'
+require 'models/computer'
require 'models/reply'
require 'models/company'
require 'models/bird'
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index a5c4404175..880d0e8293 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -2,6 +2,7 @@ require 'cases/helper'
require 'models/post'
require 'models/comment'
require 'models/developer'
+require 'models/computer'
class DefaultScopingTest < ActiveRecord::TestCase
fixtures :developers, :posts, :comments
diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb
index c2816c3670..41f3449828 100644
--- a/activerecord/test/cases/scoping/named_scoping_test.rb
+++ b/activerecord/test/cases/scoping/named_scoping_test.rb
@@ -5,6 +5,7 @@ require 'models/comment'
require 'models/reply'
require 'models/author'
require 'models/developer'
+require 'models/computer'
class NamedScopingTest < ActiveRecord::TestCase
fixtures :posts, :authors, :topics, :comments, :author_addresses
diff --git a/activerecord/test/cases/scoping/relation_scoping_test.rb b/activerecord/test/cases/scoping/relation_scoping_test.rb
index 73835c85a8..d7bcbf6203 100644
--- a/activerecord/test/cases/scoping/relation_scoping_test.rb
+++ b/activerecord/test/cases/scoping/relation_scoping_test.rb
@@ -2,6 +2,7 @@ require "cases/helper"
require 'models/post'
require 'models/author'
require 'models/developer'
+require 'models/computer'
require 'models/project'
require 'models/comment'
require 'models/category'
diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb
index abf6becc17..db474c63a4 100644
--- a/activerecord/test/cases/timestamp_test.rb
+++ b/activerecord/test/cases/timestamp_test.rb
@@ -1,6 +1,7 @@
require 'cases/helper'
require 'support/ddl_helper'
require 'models/developer'
+require 'models/computer'
require 'models/owner'
require 'models/pet'
require 'models/toy'
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index 5cccf2dda5..7160e8324d 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -2,6 +2,7 @@ require "cases/helper"
require 'models/topic'
require 'models/reply'
require 'models/developer'
+require 'models/computer'
require 'models/book'
require 'models/author'
require 'models/post'
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index 55804f9576..db8159eff8 100644
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -4,6 +4,7 @@ require 'models/topic'
require 'models/reply'
require 'models/person'
require 'models/developer'
+require 'models/computer'
require 'models/parrot'
require 'models/company'
diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb
index 4e0796f4f8..a8a8de5672 100644
--- a/activesupport/lib/active_support/message_verifier.rb
+++ b/activesupport/lib/active_support/message_verifier.rb
@@ -40,7 +40,7 @@ module ActiveSupport
data, digest = signed_message.split("--")
if data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data))
begin
- @serializer.load(::Base64.strict_decode64(data))
+ @serializer.load(decode(data))
rescue ArgumentError => argument_error
raise InvalidSignature if argument_error.message =~ %r{invalid base64}
raise
@@ -51,11 +51,19 @@ module ActiveSupport
end
def generate(value)
- data = ::Base64.strict_encode64(@serializer.dump(value))
+ data = encode(@serializer.dump(value))
"#{data}--#{generate_digest(data)}"
end
private
+ def encode(data)
+ ::Base64.strict_encode64(data)
+ end
+
+ def decode(data)
+ ::Base64.strict_decode64(data)
+ end
+
def generate_digest(data)
require 'openssl' unless defined?(OpenSSL)
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data)
diff --git a/activesupport/lib/active_support/multibyte/unicode.rb b/activesupport/lib/active_support/multibyte/unicode.rb
index 7d45961515..7ab6293b60 100644
--- a/activesupport/lib/active_support/multibyte/unicode.rb
+++ b/activesupport/lib/active_support/multibyte/unicode.rb
@@ -11,7 +11,7 @@ module ActiveSupport
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
# The Unicode version that is supported by the implementation
- UNICODE_VERSION = '6.3.0'
+ UNICODE_VERSION = '7.0.0'
# The default normalization used for operations that require
# normalization. It can be set to any of the normalizations
diff --git a/activesupport/lib/active_support/values/unicode_tables.dat b/activesupport/lib/active_support/values/unicode_tables.dat
index 394ee95f4b..760be4c07a 100644
--- a/activesupport/lib/active_support/values/unicode_tables.dat
+++ b/activesupport/lib/active_support/values/unicode_tables.dat
Binary files differ
diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md
index ca851371a9..0e9e4eff1d 100644
--- a/guides/source/active_job_basics.md
+++ b/guides/source/active_job_basics.md
@@ -248,7 +248,7 @@ end
```
-ActionMailer
+Action Mailer
------------
One of the most common jobs in a modern web application is sending emails outside
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index f6f96b79c6..616b813817 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -1011,7 +1011,7 @@ self.default_params = {
}.freeze
```
-They can be also accessed and overridden at the instance level.
+They can also be accessed and overridden at the instance level.
```ruby
A.x = 1
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 92f8ef5b08..1996158e27 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -2049,7 +2049,7 @@ command-line utility:
in your web browser to explore the API documentation.
TIP: To be able to generate the Rails Guides locally with the `doc:guides` rake
-task you need to install the RedCloth gem. Add it to your `Gemfile` and run
+task you need to install the RedCloth and Nokogiri gems. Add it to your `Gemfile` and run
`bundle install` and you're ready to go.
Configuration Gotchas
diff --git a/guides/source/testing.md b/guides/source/testing.md
index ce815156a7..b4c70dfa1d 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -82,7 +82,7 @@ Each fixture is given a name followed by an indented list of colon-separated key
If you are working with [associations](/association_basics.html), you can simply
define a reference node between two different fixtures. Here's an example with
-a belongs_to/has_many association:
+a `belongs_to`/`has_many` association:
```yaml
# In fixtures/categories.yml
@@ -785,14 +785,13 @@ end
Rake Tasks for Running your Tests
---------------------------------
-You don't need to set up and run your tests by hand on a test-by-test basis.
-Rails comes with a number of commands to help in testing.
-The table below lists all commands that come along in the default Rakefile
-when you initiate a Rails project.
+Rails comes with a number of built-in rake tasks to help with testing. The
+table below lists the commands included in the default Rakefile when a Rails
+project is created.
| Tasks | Description |
| ----------------------- | ----------- |
-| `rake test` | Runs all tests in the test folder. You can also simply run `rake` as Rails will run all the tests by default |
+| `rake test` | Runs all tests in the `test` folder. You can also simply run `rake` as Rails will run all the tests by default |
| `rake test:controllers` | Runs all the controller tests from `test/controllers` |
| `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional` |
| `rake test:helpers` | Runs all the helper tests from `test/helpers` |
@@ -801,10 +800,10 @@ when you initiate a Rails project.
| `rake test:mailers` | Runs all the mailer tests from `test/mailers` |
| `rake test:models` | Runs all the model tests from `test/models` |
| `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit` |
-| `rake test:db` | Runs all tests and resets the db |
+| `rake test:db` | Runs all tests in the `test` folder and resets the db |
-Brief Note About `Minitest`
+A Brief Note About Minitest
-----------------------------
Ruby ships with a vast Standard Library for all common use-cases including testing. Since version 1.9, Ruby provides `Minitest`, a framework for testing. All the basic assertions such as `assert_equal` discussed above are actually defined in `Minitest::Assertions`. The classes `ActiveSupport::TestCase`, `ActionController::TestCase`, `ActionMailer::TestCase`, `ActionView::TestCase` and `ActionDispatch::IntegrationTest` - which we have been inheriting in our test classes - include `Minitest::Assertions`, allowing us to use all of the basic assertions in our tests.
@@ -901,13 +900,17 @@ end
Testing Routes
--------------
-Like everything else in your Rails application, it is recommended that you test your routes. An example test for a route in the default `show` action of `Articles` controller above should look like:
+Like everything else in your Rails application, it is recommended that you test your routes. Below are example tests for the routes of default `show` and `create` action of `Articles` controller above and it should look like:
```ruby
class ArticleRoutesTest < ActionController::TestCase
test "should route to article" do
assert_routing '/articles/1', { controller: "articles", action: "show", id: "1" }
end
+
+ test "should route to create article" do
+ assert_routing({ method: 'post', path: '/articles' }, { controller: "articles", action: "create" })
+ end
end
```
@@ -1117,3 +1120,4 @@ The built-in `minitest` based testing is not the only way to test Rails applicat
* [MiniTest::Spec Rails](https://github.com/metaskills/minitest-spec-rails), use the MiniTest::Spec DSL within your rails tests.
* [Shoulda](http://www.thoughtbot.com/projects/shoulda), an extension to `test/unit` with additional helpers, macros, and assertions.
* [RSpec](http://relishapp.com/rspec), a behavior-driven development framework
+* [Capybara](http://jnicklas.github.com/capybara/), Acceptance test framework for web applications
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index d1da34588b..f267be5eb8 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,13 @@
+* `Rails::Paths::Path.unshift` now has the same interface as `Array.unshift`.
+
+ *Igor Kapkov*
+
+* Make `rake test` run all tests in test folder.
+
+ Deprecate `rake test:all` and replace `rake test:all:db` with `rake test:db`
+
+ *David Geukers*
+
* `secret_token` is now saved in `Rails.application.secrets.secret_token`
and it falls back to the value of `config.secret_token` when it is not
present in `config/secrets.yml`.
@@ -181,10 +191,4 @@
*Yves Senn*, *Carlos Antonio da Silva*, *Robin Dupret*
-* Make `rake test` run all tests in test folder.
-
- Deprecate `rake test:all` and replace `rake test:all:db` with `rake test:db`
-
- *David Geukers*
-
Please check [4-1-stable](https://github.com/rails/rails/blob/4-1-stable/railties/CHANGELOG.md) for previous changes.
diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb
index 0f4d932749..92ecc29a5f 100644
--- a/railties/lib/rails/application/bootstrap.rb
+++ b/railties/lib/rails/application/bootstrap.rb
@@ -1,5 +1,6 @@
require "active_support/notifications"
require "active_support/dependencies"
+require "active_support/deprecation"
require "active_support/descendants_tracker"
module Rails
@@ -54,6 +55,18 @@ INFO
logger
end
+ if Rails.env.production? && !config.has_explicit_log_level?
+ ActiveSupport::Deprecation.warn \
+ "You did not specify a `log_level` in `production.rb`. Currently, " \
+ "the default value for `log_leve` is `:info` for the production " \
+ "environment and `:debug` in all other environments. In Rails 5 " \
+ "the default value will be unified to `:debug` across all " \
+ "environments. To preserve the current setting, add the following " \
+ "line to your `production.rb`:\n" \
+ "\n" \
+ " config.log_level = :info\n\n"
+ end
+
Rails.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase)
end
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 786dcee007..268ef2c7aa 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -15,7 +15,6 @@ module Rails
:time_zone, :reload_classes_only_on_change,
:beginning_of_week, :filter_redirect, :x
- attr_writer :log_level
attr_reader :encoding
def initialize(*)
@@ -34,6 +33,7 @@ module Rails
@session_options = {}
@time_zone = "UTC"
@beginning_of_week = :monday
+ @has_explicit_log_level = false
@log_level = nil
@middleware = app_middleware
@generators = app_generators
@@ -117,8 +117,17 @@ module Rails
raise e, "Cannot load `Rails.application.database_configuration`:\n#{e.message}", e.backtrace
end
+ def has_explicit_log_level? # :nodoc:
+ @has_explicit_log_level
+ end
+
+ def log_level=(level)
+ @has_explicit_log_level = !!(level)
+ @log_level = level
+ end
+
def log_level
- @log_level ||= :debug
+ @log_level ||= (Rails.env.production? ? :info : :debug)
end
def colorize_logging
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index d985518fd9..023ea98145 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -110,8 +110,8 @@ module Rails
#
# == Endpoint
#
- # An engine can be also a rack application. It can be useful if you have a rack application that
- # you would like to wrap with +Engine+ and provide some of the +Engine+'s features.
+ # An engine can also be a rack application. It can be useful if you have a rack application that
+ # you would like to wrap with +Engine+ and provide with some of the +Engine+'s features.
#
# To do that, use the +endpoint+ method:
#
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
index 92ff0de030..ddc04d446c 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -45,8 +45,9 @@ Rails.application.configure do
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
- # Decrease the log volume.
- # config.log_level = :info
+ # Use the lowest log level to ensure availability of diagnostic information
+ # when problems arise.
+ config.log_level = :debug
# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index 3eb66c07af..d11804af17 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -167,8 +167,8 @@ module Rails
@paths.concat paths
end
- def unshift(path)
- @paths.unshift path
+ def unshift(*paths)
+ @paths.unshift(*paths)
end
def to_ary