aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG.md7
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb1
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/dom.rb8
-rw-r--r--actionview/CHANGELOG.md14
-rw-r--r--actionview/lib/action_view/helpers/asset_tag_helper.rb9
-rw-r--r--actionview/lib/action_view/helpers/text_helper.rb10
-rw-r--r--actionview/test/template/javascript_helper_test.rb7
-rw-r--r--activemodel/lib/active_model/errors.rb8
-rw-r--r--activemodel/test/cases/railtie_test.rb2
-rw-r--r--activerecord/CHANGELOG.md4
-rw-r--r--activerecord/lib/active_record/associations/preloader/association.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb8
-rw-r--r--activerecord/lib/active_record/fixtures.rb4
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb83
-rw-r--r--activerecord/lib/active_record/scoping/named.rb8
-rw-r--r--activerecord/test/cases/adapters/postgresql/datatype_test.rb2
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb21
-rw-r--r--activerecord/test/cases/fixtures_test.rb4
l---------activerecord/test/fixtures/all/admin1
-rw-r--r--activerecord/test/fixtures/to_be_linked/accounts.yml2
-rw-r--r--activerecord/test/fixtures/to_be_linked/users.yml10
-rw-r--r--activerecord/test/models/column_name.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/date_and_time/calculations.rb20
-rw-r--r--activesupport/test/core_ext/time_with_zone_test.rb1
-rw-r--r--guides/rails_guides/helpers.rb2
-rw-r--r--guides/source/action_view_overview.md69
-rw-r--r--guides/source/active_record_validations.md5
-rw-r--r--guides/source/association_basics.md5
-rw-r--r--guides/source/getting_started.md31
-rw-r--r--guides/source/i18n.md2
-rw-r--r--guides/source/migrations.md16
-rw-r--r--guides/source/security.md2
-rw-r--r--railties/CHANGELOG.md8
-rw-r--r--railties/lib/rails/application/bootstrap.rb3
-rw-r--r--railties/lib/rails/rack/logger.rb4
-rw-r--r--railties/test/application/configuration_test.rb8
-rw-r--r--railties/test/rack_logger_test.rb2
38 files changed, 220 insertions, 179 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index f8308299fa..d848095e01 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,10 @@
+* Fix an issue where `assert_dom_equal` and `assert_dom_not_equal` were
+ ignoring the passed failure message argument.
+
+ Fixes #11751
+
+ *Ryan McGeary*
+
* Allow REMOTE_ADDR, HTTP_HOST and HTTP_USER_AGENT to be overridden from
the environment passed into `ActionDispatch::TestRequest.new`.
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 44703221f3..b279ef81a9 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -201,6 +201,7 @@ module ActionController
# You may declare that the parameter should be an array of permitted scalars
# by mapping it to an empty array:
#
+ # params = ActionController::Parameters.new(tags: ['rails', 'parameters'])
# params.permit(tags: [])
#
# You can also use +permit+ on nested parameters, like:
diff --git a/actionpack/lib/action_dispatch/testing/assertions/dom.rb b/actionpack/lib/action_dispatch/testing/assertions/dom.rb
index 8f90a1223e..241a39393a 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/dom.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/dom.rb
@@ -7,20 +7,20 @@ module ActionDispatch
#
# # assert that the referenced method generates the appropriate HTML string
# assert_dom_equal '<a href="http://www.example.com">Apples</a>', link_to("Apples", "http://www.example.com")
- def assert_dom_equal(expected, actual, message = "")
+ def assert_dom_equal(expected, actual, message = nil)
expected_dom = HTML::Document.new(expected).root
actual_dom = HTML::Document.new(actual).root
- assert_equal expected_dom, actual_dom
+ assert_equal expected_dom, actual_dom, message
end
# The negated form of +assert_dom_equivalent+.
#
# # assert that the referenced method does not generate the specified HTML string
# assert_dom_not_equal '<a href="http://www.example.com">Apples</a>', link_to("Oranges", "http://www.example.com")
- def assert_dom_not_equal(expected, actual, message = "")
+ def assert_dom_not_equal(expected, actual, message = nil)
expected_dom = HTML::Document.new(expected).root
actual_dom = HTML::Document.new(actual).root
- assert_not_equal expected_dom, actual_dom
+ assert_not_equal expected_dom, actual_dom, message
end
end
end
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index adbe8ac389..98b78a7114 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,3 +1,17 @@
+* Added an `extname` hash option for `javascript_include_tag` method.
+
+ Before:
+
+ javascript_include_tag('templates.jst')
+ # => <script src="/javascripts/templates.jst.js"></script>
+
+ After:
+
+ javascript_include_tag('templates.jst', extname: false )
+ # => <script src="/javascripts/templates.jst"></script>
+
+ *Nathan Stitt*
+
* Fix `current_page?` when the URL contains escaped characters and the
original URL is using the hexadecimal lowercased.
diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb
index 2b3a3c6a29..a13d0021ea 100644
--- a/actionview/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb
@@ -26,7 +26,8 @@ module ActionView
# to <tt>assets/javascripts</tt>, full paths are assumed to be relative to the document
# root. Relative paths are idiomatic, use absolute paths only when needed.
#
- # When passing paths, the ".js" extension is optional.
+ # When passing paths, the ".js" extension is optional. If you do not want ".js"
+ # appended to the path <tt>extname: false</tt> can be set on the options.
#
# You can modify the HTML attributes of the script tag by passing a hash as the
# last argument.
@@ -37,6 +38,9 @@ module ActionView
# javascript_include_tag "xmlhr"
# # => <script src="/assets/xmlhr.js?1284139606"></script>
#
+ # javascript_include_tag "template.jst", extname: false
+ # # => <script src="/assets/template.jst?1284139606"></script>
+ #
# javascript_include_tag "xmlhr.js"
# # => <script src="/assets/xmlhr.js?1284139606"></script>
#
@@ -51,8 +55,7 @@ module ActionView
# # => <script src="http://www.example.com/xmlhr.js"></script>
def javascript_include_tag(*sources)
options = sources.extract_options!.stringify_keys
- path_options = options.extract!('protocol').symbolize_keys
-
+ path_options = options.extract!('protocol', 'extname').symbolize_keys
sources.uniq.map { |source|
tag_options = {
"src" => path_to_javascript(source, path_options)
diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb
index e3d4eb1d74..3fc64fa8a5 100644
--- a/actionview/lib/action_view/helpers/text_helper.rb
+++ b/actionview/lib/action_view/helpers/text_helper.rb
@@ -157,10 +157,12 @@ module ActionView
return unless matches = text.match(regex)
phrase = matches[0]
- text.split(separator).each do |value|
- if value.match(regex)
- regex = phrase = value
- break
+ unless separator.empty?
+ text.split(separator).each do |value|
+ if value.match(regex)
+ regex = phrase = value
+ break
+ end
end
end
diff --git a/actionview/test/template/javascript_helper_test.rb b/actionview/test/template/javascript_helper_test.rb
index de6a6eaab3..4703111741 100644
--- a/actionview/test/template/javascript_helper_test.rb
+++ b/actionview/test/template/javascript_helper_test.rb
@@ -51,6 +51,13 @@ class JavaScriptHelperTest < ActionView::TestCase
assert_equal 'foo', output_buffer, 'javascript_tag without a block should not concat to output_buffer'
end
+ # Setting the :extname option will control what extension (if any) is appended to the url for assets
+ def test_javascript_include_tag
+ assert_dom_equal "<script src='/foo.js'></script>", javascript_include_tag('/foo')
+ assert_dom_equal "<script src='/foo'></script>", javascript_include_tag('/foo', extname: false )
+ assert_dom_equal "<script src='/foo.bar'></script>", javascript_include_tag('/foo', extname: '.bar' )
+ end
+
def test_javascript_tag_with_options
assert_dom_equal "<script id=\"the_js_tag\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>",
javascript_tag("alert('hello')", :id => "the_js_tag")
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index e608a649f8..cf7551e4f4 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -238,8 +238,8 @@ module ActiveModel
# object. You can pass the <tt>:full_messages</tt> option. This determines
# if the json object should contain full messages or not (false by default).
#
- # person.as_json # => {:name=>["can not be nil"]}
- # person.as_json(full_messages: true) # => {:name=>["name can not be nil"]}
+ # person.errors.as_json # => {:name=>["can not be nil"]}
+ # person.errors.as_json(full_messages: true) # => {:name=>["name can not be nil"]}
def as_json(options=nil)
to_hash(options && options[:full_messages])
end
@@ -247,8 +247,8 @@ module ActiveModel
# Returns a Hash of attributes with their error messages. If +full_messages+
# is +true+, it will contain full messages (see +full_message+).
#
- # person.to_hash # => {:name=>["can not be nil"]}
- # person.to_hash(true) # => {:name=>["name can not be nil"]}
+ # person.errors.to_hash # => {:name=>["can not be nil"]}
+ # person.errors.to_hash(true) # => {:name=>["name can not be nil"]}
def to_hash(full_messages = false)
if full_messages
messages = {}
diff --git a/activemodel/test/cases/railtie_test.rb b/activemodel/test/cases/railtie_test.rb
index 0643fa775d..96b3b07e50 100644
--- a/activemodel/test/cases/railtie_test.rb
+++ b/activemodel/test/cases/railtie_test.rb
@@ -8,7 +8,7 @@ class RailtieTest < ActiveModel::TestCase
require 'active_model/railtie'
# Set a fake logger to avoid creating the log directory automatically
- fake_logger = mock()
+ fake_logger = Logger.new(nil)
@app ||= Class.new(::Rails::Application) do
config.eager_load = false
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 74f2b2287f..f60ea9838b 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Create a directory for sqlite3 file if not present on the system.
+
+ *Richard Schneeman*
+
* Removed redundant override of `xml` column definition for PG,
in order to use `xml` column type instead of `text`.
diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb
index d31f7432cd..0cc836f991 100644
--- a/activerecord/lib/active_record/associations/preloader/association.rb
+++ b/activerecord/lib/active_record/associations/preloader/association.rb
@@ -77,7 +77,7 @@ module ActiveRecord
# Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
# Make several smaller queries if necessary or make one query if the adapter supports it
sliced = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
- records = sliced.map { |slice| records_for(slice).to_a }.flatten
+ records = sliced.flat_map { |slice| records_for(slice).to_a }
end
# Each record may have multiple owners, and vice-versa
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 1826d88500..fbe6ecf5f1 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -507,12 +507,12 @@ module ActiveRecord
cols = cache[:cols] ||= metadata.fetch_fields.map { |field|
field.name
}
+ metadata.free
end
result_set = ActiveRecord::Result.new(cols, stmt.to_a) if cols
affected_rows = stmt.affected_rows
- stmt.result_metadata.free if cols
stmt.free_result
stmt.close if binds.empty?
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 7d940fe1c9..e1475416eb 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -17,12 +17,14 @@ module ActiveRecord
# Allow database path relative to Rails.root, but only if
# the database path is not the special path that tells
# Sqlite to build a database only in memory.
- if defined?(Rails.root) && ':memory:' != config[:database]
- config[:database] = File.expand_path(config[:database], Rails.root)
+ if ':memory:' != config[:database]
+ config[:database] = File.expand_path(config[:database], Rails.root) if defined?(Rails.root)
+ dirname = File.dirname(config[:database])
+ Dir.mkdir(dirname) unless File.directory?(dirname)
end
db = SQLite3::Database.new(
- config[:database],
+ config[:database].to_s,
:results_as_hash => true
)
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 20ca4e3c91..b2a81a184a 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -637,7 +637,7 @@ module ActiveRecord
end
def read_fixture_files
- yaml_files = Dir["#{@path}/**/*.yml"].select { |f|
+ yaml_files = Dir["#{@path}/{**,*}/*.yml"].select { |f|
::File.file?(f)
} + [yaml_file_path]
@@ -756,7 +756,7 @@ module ActiveRecord
def fixtures(*fixture_set_names)
if fixture_set_names.first == :all
- fixture_set_names = Dir["#{fixture_path}/**/*.{yml}"]
+ fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
else
fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 49b632c4c7..9f2a039d94 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -119,14 +119,15 @@ module ActiveRecord
#
# User.includes(:posts).where('posts.name = ?', 'example').references(:posts)
def includes(*args)
- check_if_method_has_arguments!("includes", args)
+ check_if_method_has_arguments!(:includes, args)
spawn.includes!(*args)
end
def includes!(*args) # :nodoc:
- args.reject! {|a| a.blank? }
+ args.reject!(&:blank?)
+ args.flatten!
- self.includes_values = (includes_values + args).flatten.uniq
+ self.includes_values |= args
self
end
@@ -137,7 +138,7 @@ module ActiveRecord
# FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" =
# "users"."id"
def eager_load(*args)
- check_if_method_has_arguments!("eager_load", args)
+ check_if_method_has_arguments!(:eager_load, args)
spawn.eager_load!(*args)
end
@@ -151,7 +152,7 @@ module ActiveRecord
# User.preload(:posts)
# => SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1, 2, 3)
def preload(*args)
- check_if_method_has_arguments!("preload", args)
+ check_if_method_has_arguments!(:preload, args)
spawn.preload!(*args)
end
@@ -169,14 +170,15 @@ module ActiveRecord
# User.includes(:posts).where("posts.name = 'foo'").references(:posts)
# # => Query now knows the string references posts, so adds a JOIN
def references(*args)
- check_if_method_has_arguments!("references", args)
+ check_if_method_has_arguments!(:references, args)
spawn.references!(*args)
end
def references!(*args) # :nodoc:
args.flatten!
+ args.map!(&:to_s)
- self.references_values = (references_values + args.map!(&:to_s)).uniq
+ self.references_values |= args
self
end
@@ -229,7 +231,9 @@ module ActiveRecord
end
def select!(*fields) # :nodoc:
- self.select_values += fields.flatten
+ fields.flatten!
+
+ self.select_values += fields
self
end
@@ -249,7 +253,7 @@ module ActiveRecord
# User.group('name AS grouped_name, age')
# => [#<User id: 3, name: "Foo", age: 21, ...>, #<User id: 2, name: "Oscar", age: 21, ...>, #<User id: 5, name: "Foo", age: 23, ...>]
def group(*args)
- check_if_method_has_arguments!("group", args)
+ check_if_method_has_arguments!(:group, args)
spawn.group!(*args)
end
@@ -280,24 +284,22 @@ module ActiveRecord
# User.order(:name, email: :desc)
# => SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC
def order(*args)
- check_if_method_has_arguments!("order", args)
+ check_if_method_has_arguments!(:order, args)
spawn.order!(*args)
end
def order!(*args) # :nodoc:
args.flatten!
- validate_order_args args
+ validate_order_args(args)
references = args.grep(String)
references.map! { |arg| arg =~ /^([a-zA-Z]\w*)\.(\w+)/ && $1 }.compact!
references!(references) if references.any?
# if a symbol is given we prepend the quoted table name
- args.map! { |arg|
- arg.is_a?(Symbol) ?
- Arel::Nodes::Ascending.new(klass.arel_table[arg]) :
- arg
- }
+ args.map! do |arg|
+ arg.is_a?(Symbol) ? Arel::Nodes::Ascending.new(klass.arel_table[arg]) : arg
+ end
self.order_values += args
self
@@ -313,13 +315,13 @@ module ActiveRecord
#
# generates a query with 'ORDER BY id ASC, name ASC'.
def reorder(*args)
- check_if_method_has_arguments!("reorder", args)
+ check_if_method_has_arguments!(:reorder, args)
spawn.reorder!(*args)
end
def reorder!(*args) # :nodoc:
args.flatten!
- validate_order_args args
+ validate_order_args(args)
self.reordering_value = true
self.order_values = args
@@ -361,7 +363,7 @@ module ActiveRecord
#
# will still have an order if it comes from the default_scope on Comment.
def unscope(*args)
- check_if_method_has_arguments!("unscope", args)
+ check_if_method_has_arguments!(:unscope, args)
spawn.unscope!(*args)
end
@@ -400,8 +402,12 @@ module ActiveRecord
# User.joins("LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id")
# => SELECT "users".* FROM "users" LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id
def joins(*args)
- check_if_method_has_arguments!("joins", args)
- spawn.joins!(*args.compact.flatten)
+ check_if_method_has_arguments!(:joins, args)
+
+ args.compact!
+ args.flatten!
+
+ spawn.joins!(*args)
end
def joins!(*args) # :nodoc:
@@ -783,9 +789,10 @@ module ActiveRecord
end
def extending!(*modules, &block) # :nodoc:
- modules << Module.new(&block) if block_given?
+ modules << Module.new(&block) if block
+ modules.flatten!
- self.extending_values += modules.flatten
+ self.extending_values += modules
extend(*extending_values) if extending_values.any?
self
@@ -816,12 +823,12 @@ module ActiveRecord
collapse_wheres(arel, (where_values - ['']).uniq)
- arel.having(*having_values.uniq.reject{|h| h.blank?}) unless having_values.empty?
+ arel.having(*having_values.uniq.reject(&:blank?)) unless having_values.empty?
arel.take(connection.sanitize_limit(limit_value)) if limit_value
arel.skip(offset_value.to_i) if offset_value
- arel.group(*group_values.uniq.reject{|g| g.blank?}) unless group_values.empty?
+ arel.group(*group_values.uniq.reject(&:blank?)) unless group_values.empty?
build_order(arel)
@@ -870,11 +877,11 @@ module ActiveRecord
end
def custom_join_ast(table, joins)
- joins = joins.reject { |join| join.blank? }
+ joins = joins.reject(&:blank?)
return [] if joins.empty?
- joins.map do |join|
+ joins.map! do |join|
case join
when Array
join = Arel.sql(join.join(' ')) if array_of_strings?(join)
@@ -901,7 +908,7 @@ module ActiveRecord
when String, Array
[@klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))]
when Hash
- opts = PredicateBuilder.resolve_column_aliases klass, opts
+ opts = PredicateBuilder.resolve_column_aliases(klass, opts)
attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts)
attributes.values.grep(ActiveRecord::Relation) do |rel|
@@ -944,7 +951,7 @@ module ActiveRecord
association_joins = buckets[:association_join] || []
stashed_association_joins = buckets[:stashed_join] || []
join_nodes = (buckets[:join_node] || []).uniq
- string_joins = (buckets[:string_join] || []).map { |x| x.strip }.uniq
+ string_joins = (buckets[:string_join] || []).map(&:strip).uniq
join_list = join_nodes + custom_join_ast(manager, string_joins)
@@ -956,13 +963,12 @@ module ActiveRecord
join_dependency.graft(*stashed_association_joins)
- joins = join_dependency.join_associations.map { |association|
- association.join_constraints
- }.flatten
+ joins = join_dependency.join_associations.map!(&:join_constraints)
+ joins.flatten!
- joins.each { |join| manager.from join }
+ joins.each { |join| manager.from(join) }
- manager.join_sources.concat join_list
+ manager.join_sources.concat(join_list)
manager
end
@@ -983,7 +989,7 @@ module ActiveRecord
when Arel::Nodes::Ordering
o.reverse
when String
- o.to_s.split(',').collect do |s|
+ o.to_s.split(',').map! do |s|
s.strip!
s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
end
@@ -1000,14 +1006,15 @@ module ActiveRecord
end
def array_of_strings?(o)
- o.is_a?(Array) && o.all?{|obj| obj.is_a?(String)}
+ o.is_a?(Array) && o.all? { |obj| obj.is_a?(String) }
end
def build_order(arel)
- orders = order_values
+ orders = order_values.uniq
+ orders.reject!(&:blank?)
orders = reverse_sql_order(orders) if reverse_order_value
- orders = orders.uniq.reject(&:blank?).flat_map do |order|
+ orders = orders.flat_map do |order|
case order
when Symbol
table[order].asc
diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb
index 7c51aa6979..2a5718f388 100644
--- a/activerecord/lib/active_record/scoping/named.rb
+++ b/activerecord/lib/active_record/scoping/named.rb
@@ -142,12 +142,8 @@ module ActiveRecord
extension = Module.new(&block) if block
singleton_class.send(:define_method, name) do |*args|
- if body.respond_to?(:call)
- scope = all.scoping { body.call(*args) }
- scope = scope.extending(extension) if extension
- else
- scope = body
- end
+ scope = all.scoping { body.call(*args) }
+ scope = scope.extending(extension) if extension
scope || all
end
diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
index 36d7294bc8..e946b8bb22 100644
--- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
@@ -594,7 +594,7 @@ _SQL
@connection.reconnect!
@first_timestamp_with_zone = PostgresqlTimestampWithZone.find(1)
- assert_equal Time.utc(2010,1,1, 11,0,0), @first_timestamp_with_zone.time
+ assert_equal Time.local(2010,1,1, 11,0,0), @first_timestamp_with_zone.time
assert_instance_of Time, @first_timestamp_with_zone.time
ensure
ActiveRecord::Base.default_timezone = old_default_tz
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb
new file mode 100644
index 0000000000..5a4fe63580
--- /dev/null
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+require "cases/helper"
+require 'models/owner'
+
+module ActiveRecord
+ module ConnectionAdapters
+ class SQLite3CreateFolder < ActiveRecord::TestCase
+ def test_sqlite_creates_directory
+ Dir.mktmpdir do |dir|
+ dir = Pathname.new(dir)
+ @conn = Base.sqlite3_connection :database => dir.join("db/foo.sqlite3"),
+ :adapter => 'sqlite3',
+ :timeout => 100
+
+ assert Dir.exists? dir.join('db')
+ assert File.exist? dir.join('db/foo.sqlite3')
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 2aa56ebc55..c07c9c3b74 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -584,7 +584,7 @@ class LoadAllFixturesTest < ActiveRecord::TestCase
fixtures :all
def test_all_there
- assert_equal %w(developers people tasks), fixture_table_names.sort
+ assert_equal %w(admin/accounts admin/users developers people tasks), fixture_table_names.sort
end
end
@@ -593,7 +593,7 @@ class LoadAllFixturesWithPathnameTest < ActiveRecord::TestCase
fixtures :all
def test_all_there
- assert_equal %w(developers people tasks), fixture_table_names.sort
+ assert_equal %w(admin/accounts admin/users developers people tasks), fixture_table_names.sort
end
end
diff --git a/activerecord/test/fixtures/all/admin b/activerecord/test/fixtures/all/admin
new file mode 120000
index 0000000000..984d12a043
--- /dev/null
+++ b/activerecord/test/fixtures/all/admin
@@ -0,0 +1 @@
+../to_be_linked/ \ No newline at end of file
diff --git a/activerecord/test/fixtures/to_be_linked/accounts.yml b/activerecord/test/fixtures/to_be_linked/accounts.yml
new file mode 100644
index 0000000000..9e341a15af
--- /dev/null
+++ b/activerecord/test/fixtures/to_be_linked/accounts.yml
@@ -0,0 +1,2 @@
+signals37:
+ name: 37signals
diff --git a/activerecord/test/fixtures/to_be_linked/users.yml b/activerecord/test/fixtures/to_be_linked/users.yml
new file mode 100644
index 0000000000..e2884beda5
--- /dev/null
+++ b/activerecord/test/fixtures/to_be_linked/users.yml
@@ -0,0 +1,10 @@
+david:
+ name: David
+ account: signals37
+
+jamis:
+ name: Jamis
+ account: signals37
+ settings:
+ :symbol: symbol
+ string: string
diff --git a/activerecord/test/models/column_name.rb b/activerecord/test/models/column_name.rb
index ec07205a3a..460eb4fe20 100644
--- a/activerecord/test/models/column_name.rb
+++ b/activerecord/test/models/column_name.rb
@@ -1,3 +1,3 @@
class ColumnName < ActiveRecord::Base
- def self.table_name () "colnametests" end
-end \ No newline at end of file
+ self.table_name = "colnametests"
+end
diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
index 0d14cba7cc..c869a0e210 100644
--- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
@@ -78,7 +78,7 @@ module DateAndTime
# Returns a new date/time at the start of the month.
# DateTime objects will have a time set to 0:00.
def beginning_of_month
- first_hour{ change(:day => 1) }
+ first_hour(change(:day => 1))
end
alias :at_beginning_of_month :beginning_of_month
@@ -113,7 +113,7 @@ module DateAndTime
# which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
# when set. +DateTime+ objects have their time set to 0:00.
def next_week(given_day_in_next_week = Date.beginning_of_week)
- first_hour{ weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)) }
+ first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
end
# Short-hand for months_since(1).
@@ -136,7 +136,7 @@ module DateAndTime
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
# DateTime objects have their time set to 0:00.
def prev_week(start_day = Date.beginning_of_week)
- first_hour{ weeks_ago(1).beginning_of_week.days_since(days_span(start_day)) }
+ first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
end
alias_method :last_week, :prev_week
@@ -188,7 +188,7 @@ module DateAndTime
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
# DateTime objects have their time set to 23:59:59.
def end_of_week(start_day = Date.beginning_of_week)
- last_hour{ days_since(6 - days_to_week_start(start_day)) }
+ last_hour(days_since(6 - days_to_week_start(start_day)))
end
alias :at_end_of_week :end_of_week
@@ -202,7 +202,7 @@ module DateAndTime
# DateTime objects will have a time set to 23:59:59.
def end_of_month
last_day = ::Time.days_in_month(month, year)
- last_hour{ days_since(last_day - day) }
+ last_hour(days_since(last_day - day))
end
alias :at_end_of_month :end_of_month
@@ -215,14 +215,12 @@ module DateAndTime
private
- def first_hour
- result = yield
- acts_like?(:time) ? result.change(:hour => 0) : result
+ def first_hour(date_or_time)
+ date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
end
- def last_hour
- result = yield
- acts_like?(:time) ? result.end_of_day : result
+ def last_hour(date_or_time)
+ date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
end
def days_span(day)
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index baac9e07ce..5494824a40 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -1001,6 +1001,7 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < ActiveSupport::TestCase
with_env_tz 'Europe/London' do
time = Time.local(2000, 7, 1)
time_with_zone = time.in_time_zone('Eastern Time (US & Canada)')
+ assert_equal Time.utc(2000, 6, 30, 23, 0, 0), time_with_zone
assert_not time.utc?, 'time expected to be local, but is UTC'
end
end
diff --git a/guides/rails_guides/helpers.rb b/guides/rails_guides/helpers.rb
index a288d0f0f4..760b196abd 100644
--- a/guides/rails_guides/helpers.rb
+++ b/guides/rails_guides/helpers.rb
@@ -17,7 +17,7 @@ module RailsGuides
end
def documents_flat
- documents_by_section.map {|section| section['documents']}.flatten
+ documents_by_section.flat_map {|section| section['documents']}
end
def finished_documents(documents)
diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md
index 3542844f33..6fce5a1dc2 100644
--- a/guides/source/action_view_overview.md
+++ b/guides/source/action_view_overview.md
@@ -1542,72 +1542,3 @@ end
Then you could create special views like `app/views/posts/show.expert.html.erb` that would only be displayed to expert users.
You can read more about the Rails Internationalization (I18n) API [here](i18n.html).
-
-Using Action View outside of Rails
-----------------------------------
-
-Action View is a Rails component, but it can also be used without Rails. We can demonstrate this by creating a small [Rack](http://rack.rubyforge.org/) application that includes Action View functionality. This may be useful, for example, if you'd like access to Action View's helpers in a Rack application.
-
-Let's start by ensuring that you have the Action Pack and Rack gems installed:
-
-```bash
-$ gem install actionpack
-$ gem install rack
-```
-
-Now we'll create a simple "Hello World" application that uses the `titleize` method provided by Active Support.
-
-**hello_world.rb:**
-
-```ruby
-require 'active_support/core_ext/string/inflections'
-require 'rack'
-
-def hello_world(env)
- [200, {"Content-Type" => "text/html"}, "hello world".titleize]
-end
-
-Rack::Handler::Mongrel.run method(:hello_world), Port: 4567
-```
-
-We can see this all come together by starting up the application and then visiting `http://localhost:4567/`
-
-```bash
-$ ruby hello_world.rb
-```
-
-TODO needs a screenshot? I have one - not sure where to put it.
-
-Notice how 'hello world' has been converted into 'Hello World' by the `titleize` helper method.
-
-Action View can also be used with [Sinatra](http://www.sinatrarb.com/) in the same way.
-
-Let's start by ensuring that you have the Action Pack and Sinatra gems installed:
-
-```bash
-$ gem install actionpack
-$ gem install sinatra
-```
-
-Now we'll create the same "Hello World" application in Sinatra.
-
-**hello_world.rb:**
-
-```ruby
-require 'action_view'
-require 'sinatra'
-
-get '/' do
- erb 'hello world'.titleize
-end
-```
-
-Then, we can run the application:
-
-```bash
-$ ruby hello_world.rb
-```
-
-Once the application is running, you can see Sinatra and Action View working together by visiting `http://localhost:4567/`
-
-TODO needs a screenshot? I have one - not sure where to put it.
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index d95b587e78..8154d4e1cc 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -243,7 +243,7 @@ line of code you can add the same kind of validation to several attributes.
All of them accept the `:on` and `:message` options, which define when the
validation should be run and what message should be added to the `errors`
collection if it fails, respectively. The `:on` option takes one of the values
-`:save` (the default), `:create` or `:update`. There is a default error
+`:create` or `:update`. There is a default error
message for each one of the validation helpers. These messages are used when
the `:message` option isn't specified. Let's take a look at each one of the
available helpers.
@@ -765,10 +765,9 @@ class Person < ActiveRecord::Base
validates :age, numericality: true, on: :update
# the default (validates on both create and update)
- validates :name, presence: true, on: :save
+ validates :name, presence: true
end
```
-The last line is in review state and as of now, it is not running in any version of Rails 3.2.x as discussed in this [issue](https://github.com/rails/rails/issues/10248)
Strict Validations
------------------
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index e6a66f3fa1..9b80a65a44 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -1944,8 +1944,8 @@ While Rails uses intelligent defaults that will work well in most situations, th
```ruby
class Parts < ActiveRecord::Base
- has_and_belongs_to_many :assemblies, uniq: true,
- read_only: true
+ has_and_belongs_to_many :assemblies, autosave: true,
+ readonly: true
end
```
@@ -1957,6 +1957,7 @@ The `has_and_belongs_to_many` association supports these options:
* `:foreign_key`
* `:join_table`
* `:validate`
+* `:readonly`
##### `:association_foreign_key`
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 27768952cc..dabdb391b3 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -155,7 +155,7 @@ To begin with, let's get some text up on screen quickly. To do this, you need to
### Starting up the Web Server
-You actually have a functional Rails application already. To see it, you need to start a web server on your development machine. You can do this by running:
+You actually have a functional Rails application already. To see it, you need to start a web server on your development machine. You can do this by running the following in the root directory of your rails application:
```bash
$ rails server
@@ -416,7 +416,7 @@ edit_post GET /posts/:id/edit(.:format) posts#edit
The `posts_path` helper tells Rails to point the form
to the URI Pattern associated with the `posts` prefix; and
the form will (by default) send a `POST` request
-to that route. This is associated with the
+to that route. This is associated with the
`create` action of the current controller, the `PostsController`.
With the form and its associated route defined, you will be able to fill in the form and then click the submit button to begin the process of creating a new post, so go ahead and do that. When you submit the form, you should see a familiar error:
@@ -553,7 +553,7 @@ and change the `create` action to look like this:
```ruby
def create
@post = Post.new(params[:post])
-
+
@post.save
redirect_to @post
end
@@ -575,7 +575,7 @@ If you submit the form again now, Rails will complain about not finding
the `show` action. That's not very useful though, so let's add the
`show` action before proceeding.
-First we need to add a new `route` in `config/routes.rb`.
+As we have seen in the output of `rake routes`, the route for `show` action is as follows:
```ruby
post GET /posts/:id(.:format) posts#show
@@ -654,7 +654,7 @@ For more information, refer to
### Listing all posts
We still need a way to list all our posts, so let's do that.
-We'll use a specific route from `config/routes.rb`:
+The route for this as per output of `rake routes` is:
```ruby
posts GET /posts(.:format) posts#index
@@ -888,7 +888,7 @@ it look as follows:
```html+erb
<h1>Editing post</h1>
-<%= form_for :post, url: post_path(@post.id), method: :patch do |f| %>
+<%= form_for :post, url: post_path(@post), method: :patch do |f| %>
<% if @post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@post.errors.count, "error") %> prohibited
@@ -1039,7 +1039,7 @@ content:
```
Everything except for the `form_for` declaration remained the same.
-The reason we can use this shorter, simpler `form_for` declaration
+The reason we can use this shorter, simpler `form_for` declaration
to stand in for either of the other forms is that `@post` is a *resource*
corresponding to a full set of RESTful routes, and Rails is able to infer
which URI and method to use.
@@ -1071,7 +1071,7 @@ Then do the same for the `app/views/posts/edit.html.erb` view:
We're now ready to cover the "D" part of CRUD, deleting posts from the
database. Following the REST convention, the route for
-deleting posts in the `config/routes.rb` is:
+deleting posts as per output of `rake routes` is:
```ruby
DELETE /posts/:id(.:format) posts#destroy
@@ -1616,6 +1616,8 @@ end
Security
--------
+### Basic Authentication
+
If you were to publish your blog online, anybody would be able to add, edit and
delete posts or delete comments.
@@ -1663,6 +1665,19 @@ Authentication challenge
![Basic HTTP Authentication Challenge](images/getting_started/challenge.png)
+Other authentication methods are available for Rails applications. Two popular
+authentication add-ons for Rails are the [Devise](https://github.com/plataformatec/devise)
+rails engine and the [Authlogic](https://github.com/binarylogic/authlogic) gem,
+along with a number of others.
+
+
+### Other Security Considerations
+
+Security, especially in web applications, is a broad and detailed area. Security
+in your Rails application is covered in more depth in
+The [Ruby on Rails Security Guide](security.html)
+
+
What's Next?
------------
diff --git a/guides/source/i18n.md b/guides/source/i18n.md
index 046c7543f3..facfb96d98 100644
--- a/guides/source/i18n.md
+++ b/guides/source/i18n.md
@@ -97,7 +97,7 @@ en:
hello: "Hello world"
```
-This means, that in the `:en` locale, the key _hello_ will map to the _Hello world_ string. Every string inside Rails is internationalized in this way, see for instance Active Record validation messages in the [`activerecord/lib/active_record/locale/en.yml`](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml) file or time and date formats in the [`activesupport/lib/active_support/locale/en.yml`](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml) file. You can use YAML or standard Ruby Hashes to store translations in the default (Simple) backend.
+This means, that in the `:en` locale, the key _hello_ will map to the _Hello world_ string. Every string inside Rails is internationalized in this way, see for instance Active Model validation messages in the [`activemodel/lib/active_model/locale/en.yml`](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/locale/en.yml) file or time and date formats in the [`activesupport/lib/active_support/locale/en.yml`](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml) file. You can use YAML or standard Ruby Hashes to store translations in the default (Simple) backend.
The I18n library will use **English** as a **default locale**, i.e. if you don't set a different locale, `:en` will be used for looking up translations.
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index e6d1e71f5e..6100fc89c8 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -829,8 +829,7 @@ which contains a `Product` model:
Bob goes on vacation.
Alice creates a migration for the `products` table which adds a new column and
-initializes it. She also adds a validation to the `Product` model for the new
-column.
+initializes it:
```ruby
# db/migrate/20100513121110_add_flag_to_product.rb
@@ -845,6 +844,8 @@ class AddFlagToProduct < ActiveRecord::Migration
end
```
+She also adds a validation to the `Product` model for the new column:
+
```ruby
# app/models/product.rb
@@ -853,9 +854,8 @@ class Product < ActiveRecord::Base
end
```
-Alice adds a second migration which adds and initializes another column to the
-`products` table and also adds a validation to the `Product` model for the new
-column.
+Alice adds a second migration which adds another column to the `products`
+table and initializes it:
```ruby
# db/migrate/20100515121110_add_fuzz_to_product.rb
@@ -870,6 +870,8 @@ class AddFuzzToProduct < ActiveRecord::Migration
end
```
+She also adds a validation to the `Product` model for the new column:
+
```ruby
# app/models/product.rb
@@ -903,7 +905,7 @@ A fix for this is to create a local model within the migration. This keeps
Rails from running the validations, so that the migrations run to completion.
When using a local model, it's a good idea to call
-`Product.reset_column_information` to refresh the `ActiveRecord` cache for the
+`Product.reset_column_information` to refresh the Active Record cache for the
`Product` model prior to updating data in the database.
If Alice had done this instead, there would have been no problem:
@@ -956,7 +958,7 @@ other product attributes.
These migrations run just fine, but when Bob comes back from his vacation
and calls `rake db:migrate` to run all the outstanding migrations, he gets a
subtle bug: The descriptions have defaults, and the `fuzz` column is present,
-but `fuzz` is nil on all products.
+but `fuzz` is `nil` on all products.
The solution is again to use `Product.reset_column_information` before
referencing the Product model in a migration, ensuring the Active Record's
diff --git a/guides/source/security.md b/guides/source/security.md
index ad0546810d..e4db26c64e 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -93,7 +93,7 @@ Rails 2 introduced a new default session storage, CookieStore. CookieStore saves
* The client can see everything you store in a session, because it is stored in clear-text (actually Base64-encoded, so not encrypted). So, of course, _you don't want to store any secrets here_. To prevent session hash tampering, a digest is calculated from the session with a server-side secret and inserted into the end of the cookie.
-That means the security of this storage depends on this secret (and on the digest algorithm, which defaults to SHA512, which has not been compromised, yet). So _don't use a trivial secret, i.e. a word from a dictionary, or one which is shorter than 30 characters_.
+That means the security of this storage depends on this secret (and on the digest algorithm, which defaults to SHA1, for compatibility). So _don't use a trivial secret, i.e. a word from a dictionary, or one which is shorter than 30 characters_.
`config.secret_key_base` is used for specifying a key which allows sessions for the application to be verified against a known secure key to prevent tampering. Applications get `config.secret_key_base` initialized to a random key in `config/initializers/secret_token.rb`, e.g.:
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 30328a0c19..7a89e5c219 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,11 @@
+* Fix the event name of action_dispatch requests.
+
+ *Rafael Mendonça França*
+
+* Make `config.log_level` work with custom loggers.
+
+ *Max Shytikov*
+
* Changed stylesheet load order in the stylesheet manifest generator.
Fixes #11639.
diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb
index 62d57c0cc6..a26d41c0cf 100644
--- a/railties/lib/rails/application/bootstrap.rb
+++ b/railties/lib/rails/application/bootstrap.rb
@@ -42,7 +42,6 @@ INFO
logger = ActiveSupport::Logger.new f
logger.formatter = config.log_formatter
logger = ActiveSupport::TaggedLogging.new(logger)
- logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase)
logger
rescue StandardError
logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDERR))
@@ -53,6 +52,8 @@ INFO
)
logger
end
+
+ Rails.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase)
end
# Initialize cache early in the stack so railties can make use of it.
diff --git a/railties/lib/rails/rack/logger.rb b/railties/lib/rails/rack/logger.rb
index 6ed6722c44..ad5fdcf648 100644
--- a/railties/lib/rails/rack/logger.rb
+++ b/railties/lib/rails/rack/logger.rb
@@ -33,7 +33,7 @@ module Rails
logger.debug ''
end
- @instrumenter.start 'action_dispatch.request', request: request
+ @instrumenter.start 'request.action_dispatch', request: request
logger.info started_request_message(request)
resp = @app.call(env)
resp[2] = ::Rack::BodyProxy.new(resp[2]) { finish(request) }
@@ -70,7 +70,7 @@ module Rails
private
def finish(request)
- @instrumenter.finish 'action_dispatch.request', request: request
+ @instrumenter.finish 'request.action_dispatch', request: request
end
def development?
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 28839a9c4b..c51488e0e1 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -671,5 +671,13 @@ module ApplicationTests
end
end
end
+
+ test "config.log_level with custom logger" do
+ make_basic_app do |app|
+ app.config.logger = Logger.new(STDOUT)
+ app.config.log_level = :info
+ end
+ assert_equal Logger::INFO, Rails.logger.level
+ end
end
end
diff --git a/railties/test/rack_logger_test.rb b/railties/test/rack_logger_test.rb
index 3a9392fd26..cfd2c5b50a 100644
--- a/railties/test/rack_logger_test.rb
+++ b/railties/test/rack_logger_test.rb
@@ -38,7 +38,7 @@ module Rails
def setup
@subscriber = Subscriber.new
@notifier = ActiveSupport::Notifications.notifier
- notifier.subscribe 'action_dispatch.request', subscriber
+ notifier.subscribe 'request.action_dispatch', subscriber
end
def teardown