aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--RELEASING_RAILS.rdoc3
-rw-r--r--actionpack/CHANGELOG.md28
-rw-r--r--actionpack/RUNNING_UNIT_TESTS.rdoc (renamed from actionpack/RUNNING_UNIT_TESTS)0
-rw-r--r--actionpack/lib/action_controller/metal.rb1
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb2
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb1
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb2
-rw-r--r--actionpack/lib/action_controller/test_case.rb7
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb7
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb1
-rw-r--r--actionpack/lib/action_dispatch/routing/routes_proxy.rb2
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb1
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb1
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb1
-rw-r--r--actionpack/lib/action_view/test_case.rb6
-rw-r--r--actionpack/test/controller/layout_test.rb1
-rw-r--r--actionpack/test/controller/resources_test.rb1
-rw-r--r--actionpack/test/dispatch/routing_test.rb49
-rw-r--r--actionpack/test/fixtures/test/_directory/_partial_with_locales.html.erb1
-rw-r--r--actionpack/test/fixtures/test/render_partial_inside_directory.html.erb1
-rw-r--r--actionpack/test/template/test_case_test.rb21
-rw-r--r--activemodel/lib/active_model/callbacks.rb2
-rw-r--r--activemodel/test/cases/validations/length_validation_test.rb117
-rw-r--r--activerecord/CHANGELOG.md16
-rw-r--r--activerecord/RUNNING_UNIT_TESTS.rdoc (renamed from activerecord/RUNNING_UNIT_TESTS)0
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb27
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb4
-rw-r--r--activerecord/lib/active_record/tasks/database_tasks.rb4
-rw-r--r--activerecord/test/cases/adapters/postgresql/hstore_test.rb9
-rw-r--r--activerecord/test/cases/connection_specification/resolver_test.rb48
-rw-r--r--activerecord/test/cases/tasks/database_tasks_test.rb6
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb1
-rw-r--r--activesupport/lib/active_support/message_encryptor.rb1
-rw-r--r--activesupport/test/ordered_hash_test.rb1
-rw-r--r--guides/source/caching_with_rails.md6
-rw-r--r--guides/source/command_line.md2
-rw-r--r--guides/source/configuring.md5
-rw-r--r--guides/source/engines.md2
-rw-r--r--guides/source/generators.md2
-rw-r--r--guides/source/plugins.md2
-rw-r--r--guides/source/rails_on_rack.md6
-rw-r--r--guides/source/routing.md13
-rw-r--r--guides/source/upgrading_ruby_on_rails.md2
-rw-r--r--railties/CHANGELOG.md8
-rw-r--r--railties/lib/rails/commands/application.rb19
-rw-r--r--railties/lib/rails/generators/app_base.rb6
-rw-r--r--railties/lib/rails/test_unit/testing.rake12
-rw-r--r--railties/test/generators/app_generator_test.rb2
-rw-r--r--railties/test/isolation/abstract_unit.rb2
50 files changed, 354 insertions, 111 deletions
diff --git a/.gitignore b/.gitignore
index 854fdbf450..a3a5304ecd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,8 +4,7 @@
debug.log
.Gemfile
/.bundle
-/.rbenv-version
-/.rvmrc
+/.ruby-version
/Gemfile.lock
/pkg
/dist
diff --git a/RELEASING_RAILS.rdoc b/RELEASING_RAILS.rdoc
index 9af79f73e2..b065be4922 100644
--- a/RELEASING_RAILS.rdoc
+++ b/RELEASING_RAILS.rdoc
@@ -42,6 +42,9 @@ addressed, and that can impact your release date.
Ruby implementors have high stakes in making sure Rails works. Be kind and
give them a heads up that Rails will be released soonish.
+This only needs done for major and minor releases, bugfix releases aren't a
+big enough deal, and are supposed to be backwards compatible.
+
Send an email just giving a heads up about the upcoming release to these
lists:
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 82438cb766..d6a2687037 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,30 @@
## Rails 4.0.0 (unreleased) ##
+* We don't support the `:controller` option for route definitions
+ with the ruby constant notation. This will now result in an
+ `ArgumentError`.
+
+ Example:
+ # This raises an ArgumentError:
+ resources :posts, :controller => "Admin::Posts"
+
+ # Use directory notation instead:
+ resources :posts, :controller => "admin/posts"
+
+ *Yves Senn*
+
+* `assert_template` can be used to verify the locals of partials,
+ which live inside a directory.
+ Fixes #8516.
+
+ # Prefixed partials inside directories worked and still work.
+ assert_template partial: 'directory/_partial', locals: {name: 'John'}
+
+ # This did not work but does now.
+ assert_template partial: 'directory/partial', locals: {name: 'John'}
+
+ *Yves Senn*
+
* Fix `content_tag_for` with array html option.
It would embed array as string instead of joining it like `content_tag` does:
@@ -248,7 +273,8 @@
* More descriptive error messages when calling `render :partial` with
an invalid `:layout` argument.
- #8376
+
+ Fixes #8376.
render partial: 'partial', layout: true
diff --git a/actionpack/RUNNING_UNIT_TESTS b/actionpack/RUNNING_UNIT_TESTS.rdoc
index 1b29abd2d1..1b29abd2d1 100644
--- a/actionpack/RUNNING_UNIT_TESTS
+++ b/actionpack/RUNNING_UNIT_TESTS.rdoc
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 832dec7b2a..143b3e0cbd 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -1,3 +1,4 @@
+require 'active_support/core_ext/array/extract_options'
require 'action_dispatch/middleware/stack'
module ActionController
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index eddee08545..6e0cd51d8b 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/hash/keys'
+
module ActionController
module ConditionalGet
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index d04fbae150..93568da9ef 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -1,3 +1,4 @@
+require 'active_support/core_ext/array/extract_options'
require 'abstract_controller/collector'
module ActionController #:nodoc:
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index 59b91a240e..e9031f3fac 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -88,7 +88,7 @@ module ActionController
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
# characters; and is terminated by a colon (":").
# The protocol relative scheme starts with a double slash "//"
- when %r{^(\w[\w+.-]*:|//).*}
+ when %r{\A(\w[\w+.-]*:|//).*}
options
when String
request.protocol + request.host_with_port + options
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index e9cf4372e4..bba1f1e201 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -1,6 +1,7 @@
require 'rack/session/abstract/id'
require 'active_support/core_ext/object/to_query'
require 'active_support/core_ext/module/anonymous'
+require 'active_support/core_ext/hash/keys'
module ActionController
module TemplateAssertions
@@ -125,7 +126,11 @@ module ActionController
if expected_partial = options[:partial]
if expected_locals = options[:locals]
if defined?(@_rendered_views)
- view = expected_partial.to_s.sub(/^_/,'')
+ view = expected_partial.to_s.sub(/^_/, '').sub(/\/_(?=[^\/]+\z)/, '/')
+
+ partial_was_not_rendered_msg = "expected %s to be rendered but it was not." % view
+ assert_includes @_rendered_views.rendered_views, view, partial_was_not_rendered_msg
+
msg = 'expecting %s to be rendered with %s but was with %s' % [expected_partial,
expected_locals,
@_rendered_views.locals_for(view)]
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 3a86432622..34f5f80d4d 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -2,6 +2,7 @@ require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/enumerable'
+require 'active_support/core_ext/array/extract_options'
require 'active_support/inflector'
require 'action_dispatch/routing/redirection'
@@ -245,6 +246,12 @@ module ActionDispatch
raise ArgumentError, "missing :action"
end
+ if controller.is_a?(String) && controller !~ /\A[a-z_\/]+\z/
+ message = "'#{controller}' is not a supported controller name. This can lead to potential routing problems."
+ message << " See http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use"
+ raise ArgumentError, message
+ end
+
hash = {}
hash[:controller] = controller unless controller.blank?
hash[:action] = action unless action.blank?
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index e9d34314d3..ff86f87d49 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -4,6 +4,7 @@ require 'thread_safe'
require 'active_support/core_ext/object/to_query'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/module/remove_method'
+require 'active_support/core_ext/array/extract_options'
require 'action_controller/metal/exceptions'
module ActionDispatch
diff --git a/actionpack/lib/action_dispatch/routing/routes_proxy.rb b/actionpack/lib/action_dispatch/routing/routes_proxy.rb
index 73af5920ed..e2393d3799 100644
--- a/actionpack/lib/action_dispatch/routing/routes_proxy.rb
+++ b/actionpack/lib/action_dispatch/routing/routes_proxy.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/array/extract_options'
+
module ActionDispatch
module Routing
class RoutesProxy #:nodoc:
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index da8a9dafe4..61f939bff1 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -1,5 +1,6 @@
require 'date'
require 'action_view/helpers/tag_helper'
+require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/date/conversions'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/object/with_options'
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 3dc5bb42e2..3dae1fc87a 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -8,7 +8,6 @@ require 'action_view/model_naming'
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/string/output_safety'
-require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/string/inflections'
module ActionView
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index 89c24956a3..8b3a37a853 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -2,6 +2,7 @@ require 'cgi'
require 'erb'
require 'action_view/helpers/form_helper'
require 'active_support/core_ext/string/output_safety'
+require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/array/wrap'
module ActionView
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 4479da5bc4..463f192d0c 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -122,7 +122,7 @@ module ActionView
class RenderedViewsCollection
def initialize
- @rendered_views ||= {}
+ @rendered_views ||= Hash.new { |hash, key| hash[key] = [] }
end
def add(view, locals)
@@ -134,6 +134,10 @@ module ActionView
@rendered_views[view]
end
+ def rendered_views
+ @rendered_views.keys
+ end
+
def view_rendered?(view, expected_locals)
locals_for(view).any? do |actual_locals|
expected_locals.all? {|key, value| value == actual_locals[key] }
diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb
index 365fa04570..71bcfd664e 100644
--- a/actionpack/test/controller/layout_test.rb
+++ b/actionpack/test/controller/layout_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'rbconfig'
+require 'active_support/core_ext/array/extract_options'
# The view_paths array must be set on Base and not LayoutTest so that LayoutTest's inherited
# method has access to the view_paths array when looking for a layout to automatically assign.
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index 305659b219..9aea7e860a 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -1,6 +1,7 @@
require 'abstract_unit'
require 'active_support/core_ext/object/try'
require 'active_support/core_ext/object/with_options'
+require 'active_support/core_ext/array/extract_options'
class ResourcesTest < ActionController::TestCase
def test_default_restful_routes
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 9f31ce8127..fb1b8526d0 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -2833,21 +2833,52 @@ class TestNamespaceWithControllerOption < ActionDispatch::IntegrationTest
end
end
- DefaultScopeRoutes = ActionDispatch::Routing::RouteSet.new
- DefaultScopeRoutes.draw do
- namespace :admin do
- resources :storage_files, :controller => "StorageFiles"
- end
+ def draw(&block)
+ @app = ActionDispatch::Routing::RouteSet.new
+ @app.draw(&block)
end
- def app
- DefaultScopeRoutes
- end
+ def test_valid_controller_options_inside_namespace
+ draw do
+ namespace :admin do
+ resources :storage_files, :controller => "storage_files"
+ end
+ end
- def test_controller_options
get '/admin/storage_files'
assert_equal "admin/storage_files#index", @response.body
end
+
+ def test_resources_with_valid_namespaced_controller_option
+ draw do
+ resources :storage_files, :controller => 'admin/storage_files'
+ end
+
+ get 'storage_files'
+ assert_equal "admin/storage_files#index", @response.body
+ end
+
+ def test_warn_with_ruby_constant_syntax_controller_option
+ e = assert_raise(ArgumentError) do
+ draw do
+ namespace :admin do
+ resources :storage_files, :controller => "StorageFiles"
+ end
+ end
+ end
+
+ assert_match "'admin/StorageFiles' is not a supported controller name", e.message
+ end
+
+ def test_warn_with_ruby_constant_syntax_namespaced_controller_option
+ e = assert_raise(ArgumentError) do
+ draw do
+ resources :storage_files, :controller => 'Admin::StorageFiles'
+ end
+ end
+
+ assert_match "'Admin::StorageFiles' is not a supported controller name", e.message
+ end
end
class TestDefaultScope < ActionDispatch::IntegrationTest
diff --git a/actionpack/test/fixtures/test/_directory/_partial_with_locales.html.erb b/actionpack/test/fixtures/test/_directory/_partial_with_locales.html.erb
new file mode 100644
index 0000000000..1cc8d41475
--- /dev/null
+++ b/actionpack/test/fixtures/test/_directory/_partial_with_locales.html.erb
@@ -0,0 +1 @@
+Hello <%= name %>
diff --git a/actionpack/test/fixtures/test/render_partial_inside_directory.html.erb b/actionpack/test/fixtures/test/render_partial_inside_directory.html.erb
new file mode 100644
index 0000000000..1461b95186
--- /dev/null
+++ b/actionpack/test/fixtures/test/render_partial_inside_directory.html.erb
@@ -0,0 +1 @@
+<%= render partial: 'test/_directory/partial_with_locales', locals: {'name' => 'Jane'} %>
diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb
index c7231d9cd5..acd002ce73 100644
--- a/actionpack/test/template/test_case_test.rb
+++ b/actionpack/test/template/test_case_test.rb
@@ -329,6 +329,27 @@ module ActionView
assert_template partial: '_partial', locals: { 'second' => '2' }
end
+ test 'raises descriptive error message when template was not rendered' do
+ controller.controller_path = "test"
+ render(template: "test/hello_world_with_partial")
+ e = assert_raise ActiveSupport::TestCase::Assertion do
+ assert_template partial: 'i_was_never_rendered', locals: { 'did_not' => 'happen' }
+ end
+ assert_match "i_was_never_rendered to be rendered but it was not.", e.message
+ assert_match 'Expected ["/test/partial"] to include "i_was_never_rendered"', e.message
+ end
+
+ test 'specifying locals works when the partial is inside a directory with underline prefix' do
+ controller.controller_path = "test"
+ render(template: 'test/render_partial_inside_directory')
+ assert_template partial: 'test/_directory/_partial_with_locales', locals: { 'name' => 'Jane' }
+ end
+
+ test 'specifying locals works when the partial is inside a directory without underline prefix' do
+ controller.controller_path = "test"
+ render(template: 'test/render_partial_inside_directory')
+ assert_template partial: 'test/_directory/partial_with_locales', locals: { 'name' => 'Jane' }
+ end
end
module AHelperWithInitialize
diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb
index c52e4947ae..b5562dda2e 100644
--- a/activemodel/lib/active_model/callbacks.rb
+++ b/activemodel/lib/active_model/callbacks.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/array/extract_options'
+
module ActiveModel
# == Active \Model \Callbacks
#
diff --git a/activemodel/test/cases/validations/length_validation_test.rb b/activemodel/test/cases/validations/length_validation_test.rb
index 1a40ca8efc..8b2f886cc4 100644
--- a/activemodel/test/cases/validations/length_validation_test.rb
+++ b/activemodel/test/cases/validations/length_validation_test.rb
@@ -5,13 +5,12 @@ require 'models/topic'
require 'models/person'
class LengthValidationTest < ActiveModel::TestCase
-
def teardown
Topic.reset_callbacks(:validate)
end
def test_validates_length_of_with_allow_nil
- Topic.validates_length_of( :title, :is => 5, :allow_nil => true )
+ Topic.validates_length_of( :title, is: 5, allow_nil: true )
assert Topic.new("title" => "ab").invalid?
assert Topic.new("title" => "").invalid?
@@ -20,7 +19,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_with_allow_blank
- Topic.validates_length_of( :title, :is => 5, :allow_blank => true )
+ Topic.validates_length_of( :title, is: 5, allow_blank: true )
assert Topic.new("title" => "ab").invalid?
assert Topic.new("title" => "").valid?
@@ -29,7 +28,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_minimum
- Topic.validates_length_of :title, :minimum => 5
+ Topic.validates_length_of :title, minimum: 5
t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
@@ -51,13 +50,13 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_maximum_should_allow_nil
- Topic.validates_length_of :title, :maximum => 10
+ Topic.validates_length_of :title, maximum: 10
t = Topic.new
assert t.valid?
end
def test_optionally_validates_length_of_using_minimum
- Topic.validates_length_of :title, :minimum => 5, :allow_nil => true
+ Topic.validates_length_of :title, minimum: 5, allow_nil: true
t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
@@ -67,7 +66,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_maximum
- Topic.validates_length_of :title, :maximum => 5
+ Topic.validates_length_of :title, maximum: 5
t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
@@ -82,7 +81,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_optionally_validates_length_of_using_maximum
- Topic.validates_length_of :title, :maximum => 5, :allow_nil => true
+ Topic.validates_length_of :title, maximum: 5, allow_nil: true
t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
@@ -92,7 +91,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_within
- Topic.validates_length_of(:title, :content, :within => 3..5)
+ Topic.validates_length_of(:title, :content, within: 3..5)
t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long")
assert t.invalid?
@@ -111,7 +110,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_within_with_exclusive_range
- Topic.validates_length_of(:title, :within => 4...10)
+ Topic.validates_length_of(:title, within: 4...10)
t = Topic.new("title" => "9 chars!!")
assert t.valid?
@@ -125,7 +124,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_optionally_validates_length_of_using_within
- Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true
+ Topic.validates_length_of :title, :content, within: 3..5, allow_nil: true
t = Topic.new('title' => 'abc', 'content' => 'abcd')
assert t.valid?
@@ -135,7 +134,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_is
- Topic.validates_length_of :title, :is => 5
+ Topic.validates_length_of :title, is: 5
t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
@@ -153,7 +152,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_optionally_validates_length_of_using_is
- Topic.validates_length_of :title, :is => 5, :allow_nil => true
+ Topic.validates_length_of :title, is: 5, allow_nil: true
t = Topic.new("title" => "valid", "content" => "whatever")
assert t.valid?
@@ -167,25 +166,25 @@ class LengthValidationTest < ActiveModel::TestCase
bigmax = 2 ** 32
bigrange = bigmin...bigmax
assert_nothing_raised do
- Topic.validates_length_of :title, :is => bigmin + 5
- Topic.validates_length_of :title, :within => bigrange
- Topic.validates_length_of :title, :in => bigrange
- Topic.validates_length_of :title, :minimum => bigmin
- Topic.validates_length_of :title, :maximum => bigmax
+ Topic.validates_length_of :title, is: bigmin + 5
+ Topic.validates_length_of :title, within: bigrange
+ Topic.validates_length_of :title, in: bigrange
+ Topic.validates_length_of :title, minimum: bigmin
+ Topic.validates_length_of :title, maximum: bigmax
end
end
def test_validates_length_of_nasty_params
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is => -6) }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within => 6) }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum => "a") }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :maximum => "a") }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within => "a") }
- assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is => "a") }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, is: -6) }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, within: 6) }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, minimum: "a") }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, maximum: "a") }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, within: "a") }
+ assert_raise(ArgumentError) { Topic.validates_length_of(:title, is: "a") }
end
def test_validates_length_of_custom_errors_for_minimum_with_message
- Topic.validates_length_of( :title, :minimum => 5, :message => "boo %{count}" )
+ Topic.validates_length_of( :title, minimum: 5, message: "boo %{count}" )
t = Topic.new("title" => "uhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -193,7 +192,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_minimum_with_too_short
- Topic.validates_length_of( :title, :minimum => 5, :too_short => "hoo %{count}" )
+ Topic.validates_length_of( :title, minimum: 5, too_short: "hoo %{count}" )
t = Topic.new("title" => "uhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -201,7 +200,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_maximum_with_message
- Topic.validates_length_of( :title, :maximum => 5, :message => "boo %{count}" )
+ Topic.validates_length_of( :title, maximum: 5, message: "boo %{count}" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -209,7 +208,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_in
- Topic.validates_length_of(:title, :in => 10..20, :message => "hoo %{count}")
+ Topic.validates_length_of(:title, in: 10..20, message: "hoo %{count}")
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -222,7 +221,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_maximum_with_too_long
- Topic.validates_length_of( :title, :maximum => 5, :too_long => "hoo %{count}" )
+ Topic.validates_length_of( :title, maximum: 5, too_long: "hoo %{count}" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -230,21 +229,21 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_both_too_short_and_too_long
- Topic.validates_length_of :title, :minimum => 3, :maximum => 5, :too_short => 'too short', :too_long => 'too long'
+ Topic.validates_length_of :title, minimum: 3, maximum: 5, too_short: 'too short', too_long: 'too long'
- t = Topic.new(:title => 'a')
+ t = Topic.new(title: 'a')
assert t.invalid?
assert t.errors[:title].any?
assert_equal ['too short'], t.errors['title']
- t = Topic.new(:title => 'aaaaaa')
+ t = Topic.new(title: 'aaaaaa')
assert t.invalid?
assert t.errors[:title].any?
assert_equal ['too long'], t.errors['title']
end
def test_validates_length_of_custom_errors_for_is_with_message
- Topic.validates_length_of( :title, :is => 5, :message => "boo %{count}" )
+ Topic.validates_length_of( :title, is: 5, message: "boo %{count}" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -252,7 +251,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_custom_errors_for_is_with_wrong_length
- Topic.validates_length_of( :title, :is => 5, :wrong_length => "hoo %{count}" )
+ Topic.validates_length_of( :title, is: 5, wrong_length: "hoo %{count}" )
t = Topic.new("title" => "uhohuhoh", "content" => "whatever")
assert t.invalid?
assert t.errors[:title].any?
@@ -260,7 +259,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_minimum_utf8
- Topic.validates_length_of :title, :minimum => 5
+ Topic.validates_length_of :title, minimum: 5
t = Topic.new("title" => "一二三四五", "content" => "whatever")
assert t.valid?
@@ -272,7 +271,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_maximum_utf8
- Topic.validates_length_of :title, :maximum => 5
+ Topic.validates_length_of :title, maximum: 5
t = Topic.new("title" => "一二三四五", "content" => "whatever")
assert t.valid?
@@ -284,7 +283,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_within_utf8
- Topic.validates_length_of(:title, :content, :within => 3..5)
+ Topic.validates_length_of(:title, :content, within: 3..5)
t = Topic.new("title" => "一二", "content" => "12三四五六七")
assert t.invalid?
@@ -296,12 +295,12 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_optionally_validates_length_of_using_within_utf8
- Topic.validates_length_of :title, :within => 3..5, :allow_nil => true
+ Topic.validates_length_of :title, within: 3..5, allow_nil: true
- t = Topic.new(:title => "一二三四五")
+ t = Topic.new(title: "一二三四五")
assert t.valid?, t.errors.inspect
- t = Topic.new(:title => "一二三")
+ t = Topic.new(title: "一二三")
assert t.valid?, t.errors.inspect
t.title = nil
@@ -309,7 +308,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_is_utf8
- Topic.validates_length_of :title, :is => 5
+ Topic.validates_length_of :title, is: 5
t = Topic.new("title" => "一二345", "content" => "whatever")
assert t.valid?
@@ -321,9 +320,9 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_with_block
- Topic.validates_length_of :content, :minimum => 5, :too_short => "Your essay must be at least %{count} words.",
- :tokenizer => lambda {|str| str.scan(/\w+/) }
- t = Topic.new(:content => "this content should be long enough")
+ Topic.validates_length_of :content, minimum: 5, too_short: "Your essay must be at least %{count} words.",
+ tokenizer: lambda {|str| str.scan(/\w+/) }
+ t = Topic.new(content: "this content should be long enough")
assert t.valid?
t.content = "not long enough"
@@ -333,18 +332,18 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_for_fixnum
- Topic.validates_length_of(:approved, :is => 4)
+ Topic.validates_length_of(:approved, is: 4)
- t = Topic.new("title" => "uhohuhoh", "content" => "whatever", :approved => 1)
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever", approved: 1)
assert t.invalid?
assert t.errors[:approved].any?
- t = Topic.new("title" => "uhohuhoh", "content" => "whatever", :approved => 1234)
+ t = Topic.new("title" => "uhohuhoh", "content" => "whatever", approved: 1234)
assert t.valid?
end
def test_validates_length_of_for_ruby_class
- Person.validates_length_of :karma, :minimum => 5
+ Person.validates_length_of :karma, minimum: 5
p = Person.new
p.karma = "Pix"
@@ -359,7 +358,7 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_for_infinite_maxima
- Topic.validates_length_of(:title, :within => 5..Float::INFINITY)
+ Topic.validates_length_of(:title, within: 5..Float::INFINITY)
t = Topic.new("title" => "1234")
assert t.invalid?
@@ -368,7 +367,7 @@ class LengthValidationTest < ActiveModel::TestCase
t.title = "12345"
assert t.valid?
- Topic.validates_length_of(:author_name, :maximum => Float::INFINITY)
+ Topic.validates_length_of(:author_name, maximum: Float::INFINITY)
assert t.valid?
@@ -377,13 +376,13 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_maximum_should_not_allow_nil_when_nil_not_allowed
- Topic.validates_length_of :title, :maximum => 10, :allow_nil => false
+ Topic.validates_length_of :title, maximum: 10, allow_nil: false
t = Topic.new
assert t.invalid?
end
def test_validates_length_of_using_maximum_should_not_allow_nil_and_empty_string_when_blank_not_allowed
- Topic.validates_length_of :title, :maximum => 10, :allow_blank => false
+ Topic.validates_length_of :title, maximum: 10, allow_blank: false
t = Topic.new
assert t.invalid?
@@ -392,13 +391,13 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_both_minimum_and_maximum_should_not_allow_nil
- Topic.validates_length_of :title, :minimum => 5, :maximum => 10
+ Topic.validates_length_of :title, minimum: 5, maximum: 10
t = Topic.new
assert t.invalid?
end
def test_validates_length_of_using_minimum_0_should_not_allow_nil
- Topic.validates_length_of :title, :minimum => 0
+ Topic.validates_length_of :title, minimum: 0
t = Topic.new
assert t.invalid?
@@ -407,11 +406,19 @@ class LengthValidationTest < ActiveModel::TestCase
end
def test_validates_length_of_using_is_0_should_not_allow_nil
- Topic.validates_length_of :title, :is => 0
+ Topic.validates_length_of :title, is: 0
t = Topic.new
assert t.invalid?
t.title = ""
assert t.valid?
end
+
+ def test_validates_with_diff_in_option
+ Topic.validates_length_of(:title, is: 5)
+ Topic.validates_length_of(:title, is: 5, if: Proc.new { false } )
+
+ assert Topic.new("title" => "david").valid?
+ assert Topic.new("title" => "david2").invalid?
+ end
end
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index b987104dd0..f8931677ed 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,6 +1,18 @@
## Rails 4.0.0 (unreleased) ##
-* Relation#merge now only overwrites where values on the LHS of the
+* The `DATABASE_URL` environment variable now converts ints, floats, and
+ the strings true and false to Ruby types. For example, SQLite requires
+ that the timeout value is an integer, and PostgreSQL requires that the
+ prepared_statements option is a boolean. These now work as expected:
+
+ Example:
+
+ DATABASE_URL=sqlite3://localhost/test_db?timeout=500
+ DATABASE_URL=postgresql://localhost/test_db?prepared_statements=false
+
+ *Aaron Stone*
+
+* `Relation#merge` now only overwrites where values on the LHS of the
merge. Consider:
left = Person.where(age: [13, 14, 15])
@@ -59,7 +71,7 @@
Example:
- relation.uniq.count # => SELECT COUNT(DISTINCT *)
+ relation.uniq.count # => SELECT COUNT(DISTINCT *)
*Yves Senn + Kaspar Schiess*
diff --git a/activerecord/RUNNING_UNIT_TESTS b/activerecord/RUNNING_UNIT_TESTS.rdoc
index bdd8834dcb..bdd8834dcb 100644
--- a/activerecord/RUNNING_UNIT_TESTS
+++ b/activerecord/RUNNING_UNIT_TESTS.rdoc
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
index 09250d3c01..577a362568 100644
--- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -62,6 +62,10 @@ module ActiveRecord
ConnectionSpecification.new(spec, adapter_method)
end
+ # For DATABASE_URL, accept a limited concept of ints and floats
+ SIMPLE_INT = /\A\d+\z/
+ SIMPLE_FLOAT = /\A\d+\.\d+\z/
+
def connection_url_to_hash(url) # :nodoc:
config = URI.parse url
adapter = config.scheme
@@ -72,15 +76,38 @@ module ActiveRecord
:port => config.port,
:database => config.path.sub(%r{^/},""),
:host => config.host }
+
spec.reject!{ |_,value| value.blank? }
+
uri_parser = URI::Parser.new
+
spec.map { |key,value| spec[key] = uri_parser.unescape(value) if value.is_a?(String) }
+
if config.query
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
+
+ options.each { |key, value| options[key] = type_cast_value(value) }
+
spec.merge!(options)
end
+
spec
end
+
+ def type_cast_value(value)
+ case value
+ when SIMPLE_INT
+ value.to_i
+ when SIMPLE_FLOAT
+ value.to_f
+ when 'true'
+ true
+ when 'false'
+ false
+ else
+ value
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index f4aa9d215a..e09319890a 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -84,7 +84,7 @@ module ActiveRecord
@subtype = subtype
end
- def exctract_bounds(value)
+ def extract_bounds(value)
from, to = value[1..-2].split(',')
{
from: (value[1] == ',' || from == '-infinity') ? infinity(:negative => true) : from,
@@ -110,7 +110,7 @@ module ActiveRecord
return if value.nil? || value == 'empty'
return value if value.is_a?(::Range)
- extracted = exctract_bounds(value)
+ extracted = extract_bounds(value)
case @subtype
when :date
diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb
index 67c7e714e6..4fa7cf8a7d 100644
--- a/activerecord/lib/active_record/tasks/database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/database_tasks.rb
@@ -1,6 +1,7 @@
module ActiveRecord
module Tasks # :nodoc:
class DatabaseAlreadyExists < StandardError; end # :nodoc:
+ class DatabaseNotSupported < StandardError; end # :nodoc:
module DatabaseTasks # :nodoc:
extend self
@@ -121,6 +122,9 @@ module ActiveRecord
def class_for_adapter(adapter)
key = @tasks.keys.detect { |pattern| adapter[pattern] }
+ unless key
+ raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
+ end
@tasks[key]
end
diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb
index 9498c829dc..331e3f7e4d 100644
--- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb
@@ -11,11 +11,18 @@ class PostgresqlHstoreTest < ActiveRecord::TestCase
def setup
@connection = ActiveRecord::Base.connection
+
+ unless @connection.supports_extensions?
+ return skip "do not test on PG without hstore"
+ end
+
unless @connection.extension_enabled?('hstore')
@connection.enable_extension 'hstore'
- return skip "do not test on PG without hstore"
+ @connection.commit_db_transaction
end
+ @connection.reconnect!
+
@connection.transaction do
@connection.create_table('hstores') do |t|
t.hstore 'tags', :default => ''
diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb
index 52de0efe7f..f0a2cdca1a 100644
--- a/activerecord/test/cases/connection_specification/resolver_test.rb
+++ b/activerecord/test/cases/connection_specification/resolver_test.rb
@@ -8,40 +8,66 @@ module ActiveRecord
Resolver.new(spec, {}).spec.config
end
+ def test_url_invalid_adapter
+ assert_raises(LoadError) do
+ resolve 'ridiculous://foo?encoding=utf8'
+ end
+ end
+
+ # The abstract adapter is used simply to bypass the bit of code that
+ # checks that the adapter file can be required in.
+
def test_url_host_no_db
- skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
- spec = resolve 'mysql://foo?encoding=utf8'
+ spec = resolve 'abstract://foo?encoding=utf8'
assert_equal({
- :adapter => "mysql",
+ :adapter => "abstract",
:host => "foo",
:encoding => "utf8" }, spec)
end
def test_url_host_db
- skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
- spec = resolve 'mysql://foo/bar?encoding=utf8'
+ spec = resolve 'abstract://foo/bar?encoding=utf8'
assert_equal({
- :adapter => "mysql",
+ :adapter => "abstract",
:database => "bar",
:host => "foo",
:encoding => "utf8" }, spec)
end
def test_url_port
- skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
- spec = resolve 'mysql://foo:123?encoding=utf8'
+ spec = resolve 'abstract://foo:123?encoding=utf8'
assert_equal({
- :adapter => "mysql",
+ :adapter => "abstract",
:port => 123,
:host => "foo",
:encoding => "utf8" }, spec)
end
+ def test_url_query_numeric
+ spec = resolve 'abstract://foo:123?encoding=utf8&int=500&float=10.9'
+ assert_equal({
+ :adapter => "abstract",
+ :port => 123,
+ :int => 500,
+ :float => 10.9,
+ :host => "foo",
+ :encoding => "utf8" }, spec)
+ end
+
+ def test_url_query_boolean
+ spec = resolve 'abstract://foo:123?true=true&false=false'
+ assert_equal({
+ :adapter => "abstract",
+ :port => 123,
+ :true => true,
+ :false => false,
+ :host => "foo" }, spec)
+ end
+
def test_encoded_password
- skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
password = 'am@z1ng_p@ssw0rd#!'
encoded_password = URI.encode_www_form_component(password)
- spec = resolve "mysql://foo:#{encoded_password}@localhost/bar"
+ spec = resolve "abstract://foo:#{encoded_password}@localhost/bar"
assert_equal password, spec[:password]
end
end
diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb
index 659d5eae72..3bfbc92afd 100644
--- a/activerecord/test/cases/tasks/database_tasks_test.rb
+++ b/activerecord/test/cases/tasks/database_tasks_test.rb
@@ -31,6 +31,12 @@ module ActiveRecord
ActiveRecord::Tasks::DatabaseTasks.register_task(/foo/, klazz)
ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => :foo}, "awesome-file.sql")
end
+
+ def test_unregistered_task
+ assert_raise(ActiveRecord::Tasks::DatabaseNotSupported) do
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => :bar}, "awesome-file.sql")
+ end
+ end
end
class DatabaseTasksCreateTest < ActiveRecord::TestCase
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index c7dbfc95dc..512296554f 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -7,6 +7,7 @@ end
require 'digest/md5'
require 'active_support/core_ext/marshal'
+require 'active_support/core_ext/array/extract_options'
module ActiveSupport
module Cache
diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb
index b7dc0689b0..ce40a7d689 100644
--- a/activesupport/lib/active_support/message_encryptor.rb
+++ b/activesupport/lib/active_support/message_encryptor.rb
@@ -1,5 +1,6 @@
require 'openssl'
require 'base64'
+require 'active_support/core_ext/array/extract_options'
module ActiveSupport
# MessageEncryptor is a simple way to encrypt values which get stored
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index 14ba4e0076..6aea9d56f1 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -2,6 +2,7 @@ require 'abstract_unit'
require 'active_support/json'
require 'active_support/core_ext/object/to_json'
require 'active_support/core_ext/hash/indifferent_access'
+require 'active_support/core_ext/array/extract_options'
class OrderedHashTest < ActiveSupport::TestCase
def setup
diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md
index e52264f296..a270ec7a7e 100644
--- a/guides/source/caching_with_rails.md
+++ b/guides/source/caching_with_rails.md
@@ -99,14 +99,14 @@ end
This method generates a cache key that depends on all products and can be used in the view:
-```ruby
+```erb
<% cache(cache_key_for_products) do %>
All available products:
<% end %>
```
You can also use an Active Record model as the cache key:
-```ruby
+```erb
<% Product.all.each do |p| %>
<% cache(p) do %>
<%= link_to p.name, product_url(p) %>
@@ -118,7 +118,7 @@ Behind the scenes, a method called `cache_key` will be invoked on the model and
You can also combine the two schemes which is called "Russian Doll Caching":
-```ruby
+```erb
<% cache(cache_key_for_products) do %>
All available products:
<% Product.all.each do |p| %>
diff --git a/guides/source/command_line.md b/guides/source/command_line.md
index 2790a4740a..9d1fb03fab 100644
--- a/guides/source/command_line.md
+++ b/guides/source/command_line.md
@@ -378,7 +378,7 @@ Active Record version 4.0.0.beta
Action Pack version 4.0.0.beta
Action Mailer version 4.0.0.beta
Active Support version 4.0.0.beta
-Middleware ActionDispatch::Static, Rack::Lock, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::RemoteIp, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::Migration::CheckPending, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::EncryptedCookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, Rack::Head, Rack::ConditionalGet, Rack::ETag, ActionDispatch::BestStandardsSupport
+Middleware ActionDispatch::Static, Rack::Lock, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::RemoteIp, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::Migration::CheckPending, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::EncryptedCookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, Rack::Head, Rack::ConditionalGet, Rack::ETag
Application root /home/foobar/commandsapp
Environment development
Database adapter sqlite3
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index c1f31fd2b0..be46e15078 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -207,7 +207,6 @@ Every Rails application comes with a standard set of middleware which it uses in
* `ActionDispatch::ParamsParser` parses out parameters from the request into `params`.
* `Rack::MethodOverride` allows the method to be overridden if `params[:_method]` is set. This is the middleware which supports the PATCH, PUT, and DELETE HTTP method types.
* `ActionDispatch::Head` converts HEAD requests to GET requests and serves them as so.
-* `ActionDispatch::BestStandardsSupport` enables "best standards support" so that IE8 renders some elements correctly.
Besides these usual middleware, you can add your own by using the `config.middleware.use` method:
@@ -230,13 +229,13 @@ config.middleware.insert_after ActionDispatch::Head, Magical::Unicorns
Middlewares can also be completely swapped out and replaced with others:
```ruby
-config.middleware.swap ActionDispatch::BestStandardsSupport, Magical::Unicorns
+config.middleware.swap ActionController::Failsafe, Lifo::Failsafe
```
They can also be removed from the stack completely:
```ruby
-config.middleware.delete ActionDispatch::BestStandardsSupport
+config.middleware.delete "Rack::MethodOverride"
```
### Configuring i18n
diff --git a/guides/source/engines.md b/guides/source/engines.md
index 459aa8d57e..58c6870d4a 100644
--- a/guides/source/engines.md
+++ b/guides/source/engines.md
@@ -28,7 +28,7 @@ Engines can also be isolated from their host applications. This means that an ap
It's important to keep in mind at all times that the application should **always** take precedence over its engines. An application is the object that has final say in what goes on in the universe (with the universe being the application's environment) where the engine should only be enhancing it, rather than changing it drastically.
-To see demonstrations of other engines, check out [Devise](https://github.com/plataformatec/devise), an engine that provides authentication for its parent applications, or [Forem](https://github.com/radar/forem), an engine that provides forum functionality. There's also [Spree](https://github.com/spree/spree) which provides an e-commerce platform, and [RefineryCMS](https://github.com/resolve/refinerycms), a CMS engine.
+To see demonstrations of other engines, check out [Devise](https://github.com/plataformatec/devise), an engine that provides authentication for its parent applications, or [Forem](https://github.com/radar/forem), an engine that provides forum functionality. There's also [Spree](https://github.com/spree/spree) which provides an e-commerce platform, and [RefineryCMS](https://github.com/refinery/refinerycms), a CMS engine.
Finally, engines would not have been possible without the work of James Adam, Piotr Sarnacki, the Rails Core Team, and a number of other people. If you ever meet them, don't forget to say thanks!
diff --git a/guides/source/generators.md b/guides/source/generators.md
index 8b91dfc5a5..1a08eb420a 100644
--- a/guides/source/generators.md
+++ b/guides/source/generators.md
@@ -310,7 +310,7 @@ In Rails 3.0 and above, generators don't just look in the source root for templa
```erb
module <%= class_name %>Helper
- attr_reader :<%= plural_name %>, <%= plural_name.singularize %>
+ attr_reader :<%= plural_name %>, :<%= plural_name.singularize %>
end
```
diff --git a/guides/source/plugins.md b/guides/source/plugins.md
index f8f04c3c67..695f25f8a9 100644
--- a/guides/source/plugins.md
+++ b/guides/source/plugins.md
@@ -86,7 +86,7 @@ Run `rake` to run the test. This test should fail because we haven't implemented
Great - now you are ready to start development.
-Then in `lib/yaffle.rb` require `lib/core_ext`:
+Then in `lib/yaffle.rb` add `require "yaffle/core_ext"`:
```ruby
# yaffle/lib/yaffle.rb
diff --git a/guides/source/rails_on_rack.md b/guides/source/rails_on_rack.md
index a6119eb433..d8477d89e3 100644
--- a/guides/source/rails_on_rack.md
+++ b/guides/source/rails_on_rack.md
@@ -137,7 +137,6 @@ use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
-use ActionDispatch::BestStandardsSupport
run MyApp::Application.routes
```
@@ -215,7 +214,6 @@ And to remove browser related middleware,
```ruby
# config/application.rb
-config.middleware.delete "ActionDispatch::BestStandardsSupport"
config.middleware.delete "Rack::MethodOverride"
```
@@ -307,10 +305,6 @@ Much of Action Controller's functionality is implemented as Middlewares. The fol
* Adds ETag header on all String bodies. ETags are used to validate cache.
- **`ActionDispatch::BestStandardsSupport`**
-
-* Enables “best standards support” so that IE8 renders some elements correctly.
-
TIP: It's possible to use any of the above middlewares in your custom Rack stack.
### Using Rack Builder
diff --git a/guides/source/routing.md b/guides/source/routing.md
index 14f23d4020..4614169653 100644
--- a/guides/source/routing.md
+++ b/guides/source/routing.md
@@ -832,6 +832,19 @@ will recognize incoming paths beginning with `/photos` but route to the `Images`
NOTE: Use `photos_path`, `new_photo_path`, etc. to generate paths for this resource.
+For namespaced controllers you can use the directory notation. For example:
+
+```ruby
+resources :user_permissions, controller: 'admin/user_permissions'
+```
+
+This will route to the `Admin::UserPermissions` controller.
+
+NOTE: Only the directory notation is supported. specifying the
+controller with ruby constant notation (eg. `:controller =>
+'Admin::UserPermissions'`) can lead to routing problems and results in
+a warning.
+
### Specifying Constraints
You can use the `:constraints` option to specify a required format on the implicit `id`. For example:
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index b4a59fe3da..59e21e9be2 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -82,6 +82,8 @@ becomes
get 'こんにちは', controller: 'welcome', action: 'index'
```
+* Rails 4.0 has removed ActionDispatch::BestStandardsSupport middleware, !DOCTYPE html already triggers standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx and ChromeFrame header has been moved to `config.action_dispatch.default_headers`
+
### Active Support
Rails 4.0 removes the `j` alias for `ERB::Util#json_escape` since `j` is already used for `ActionView::Helpers::JavaScriptHelper#escape_javascript`.
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index c6ffe30ad3..f86baee4c3 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,5 +1,13 @@
## Rails 4.0.0 (unreleased) ##
+* Add --rc option to support the load of a custom rc file during the generation of a new app.
+
+ *Amparo Luna*
+
+* Add --no-rc option to skip the loading of railsrc file during the generation of a new app.
+
+ *Amparo Luna*
+
* Fixes database.yml when creating a new rails application with '.'
Fix #8304
diff --git a/railties/lib/rails/commands/application.rb b/railties/lib/rails/commands/application.rb
index 2d9708e5b5..2ff29418c6 100644
--- a/railties/lib/rails/commands/application.rb
+++ b/railties/lib/rails/commands/application.rb
@@ -9,12 +9,19 @@ if ARGV.first != "new"
ARGV[0] = "--help"
else
ARGV.shift
- railsrc = File.join(File.expand_path("~"), ".railsrc")
- if File.exist?(railsrc)
- extra_args_string = File.open(railsrc).read
- extra_args = extra_args_string.split(/\n+/).map {|l| l.split}.flatten
- puts "Using #{extra_args.join(" ")} from #{railsrc}"
- ARGV.insert(1, *extra_args)
+ unless ARGV.delete("--no-rc")
+ customrc = ARGV.index{ |x| x.include?("--rc=") }
+ railsrc = if customrc
+ File.expand_path(ARGV.delete_at(customrc).gsub(/--rc=/, ""))
+ else
+ File.join(File.expand_path("~"), '.railsrc')
+ end
+ if File.exist?(railsrc)
+ extra_args_string = File.read(railsrc)
+ extra_args = extra_args_string.split(/\n+/).map {|l| l.split}.flatten
+ puts "Using #{extra_args.join(" ")} from #{railsrc}"
+ ARGV.insert(1, *extra_args)
+ end
end
end
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index ca3652c703..c61fc388f0 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -61,6 +61,12 @@ module Rails
class_option :skip_test_unit, type: :boolean, aliases: '-T', default: false,
desc: 'Skip Test::Unit files'
+ class_option :rc, type: :string, default: false,
+ desc: "Path to file containing extra configuration options for rails command"
+
+ class_option :no_rc, type: :boolean, default: false,
+ desc: 'Skip loading of extra configuration options from .railsrc file'
+
class_option :help, type: :boolean, aliases: '-h', group: :rails,
desc: 'Show this help message and quit'
end
diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake
index f0d46fd959..44485d9b14 100644
--- a/railties/lib/rails/test_unit/testing.rake
+++ b/railties/lib/rails/test_unit/testing.rake
@@ -71,6 +71,18 @@ namespace :test do
end
end
+ # Inspired by: http://ngauthier.com/2012/02/quick-tests-with-bash.html
+ desc "Run tests quickly by merging all types and not resetting db"
+ Rake::TestTask.new(:all) do |t|
+ t.libs << "test"
+ t.pattern = "test/**/*_test.rb"
+ end
+
+ namespace :all do
+ desc "Run tests quickly, but also reset db"
+ task :db => %w[db:test:prepare test:all]
+ end
+
Rake::TestTask.new(recent: "test:prepare") do |t|
since = TEST_CHANGES_SINCE
touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index b2deeb011d..83f43d1025 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -70,7 +70,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
def test_application_new_exits_with_non_zero_code_on_invalid_application_name
- quietly { system 'rails new test' }
+ quietly { system 'rails new test --no-rc' }
assert_equal false, $?.success?
end
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 7ae1b5ccfd..68d96bae94 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -279,7 +279,7 @@ Module.new do
environment = File.expand_path('../../../../load_paths', __FILE__)
require_environment = "-r #{environment}"
- `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails new #{app_template_path} --skip-gemfile`
+ `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails new #{app_template_path} --skip-gemfile --no-rc`
File.open("#{app_template_path}/config/boot.rb", 'w') do |f|
f.puts "require '#{environment}'"
f.puts "require 'rails/all'"