aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock12
-rw-r--r--actionmailer/lib/action_mailer/mail_helper.rb12
-rw-r--r--actionmailer/test/fixtures/base_mailer/email_custom_layout.text.html.erb1
-rw-r--r--actionmailer/test/fixtures/first_mailer/share.erb1
-rw-r--r--actionmailer/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb1
-rw-r--r--actionmailer/test/fixtures/second_mailer/share.erb1
-rw-r--r--actionmailer/test/fixtures/test_mailer/_subtemplate.text.erb1
-rw-r--r--actionmailer/test/fixtures/test_mailer/custom_templating_extension.html.haml6
-rw-r--r--actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.haml6
-rw-r--r--actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb10
-rw-r--r--actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~10
-rw-r--r--actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.ignored.erb1
-rw-r--r--actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak1
-rw-r--r--actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.erb2
-rw-r--r--actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb1
-rw-r--r--actionmailer/test/fixtures/test_mailer/included_subtemplate.text.erb1
-rw-r--r--actionmailer/test/fixtures/test_mailer/multipart_alternative.html.erb1
-rw-r--r--actionmailer/test/fixtures/test_mailer/multipart_alternative.plain.erb1
-rw-r--r--actionmailer/test/fixtures/test_mailer/rxml_template.rxml2
-rw-r--r--actionmailer/test/fixtures/test_mailer/signed_up.html.erb3
-rw-r--r--actionpack/CHANGELOG.md5
-rw-r--r--actionpack/actionpack.gemspec2
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb2
-rw-r--r--actionpack/lib/action_dispatch/journey/router.rb2
-rw-r--r--actionpack/lib/action_dispatch/journey/routes.rb19
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cache_store.rb9
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/polymorphic_routes.rb18
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb30
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb6
-rw-r--r--actionpack/test/abstract_unit.rb4
-rw-r--r--actionpack/test/controller/live_stream_test.rb2
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb4
-rw-r--r--actionpack/test/journey/routes_test.rb22
-rw-r--r--actionview/lib/action_view/routing_url_for.rb6
-rw-r--r--actionview/test/activerecord/polymorphic_routes_test.rb2
-rw-r--r--activemodel/lib/active_model.rb1
-rw-r--r--activemodel/lib/active_model/attribute_assignment.rb11
-rw-r--r--activemodel/lib/active_model/errors.rb11
-rw-r--r--activemodel/test/cases/attribute_assignment_test.rb6
-rw-r--r--activemodel/test/cases/helper.rb9
-rw-r--r--activemodel/test/cases/model_test.rb2
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb6
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb4
-rw-r--r--activerecord/lib/active_record/attribute_assignment.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/transaction.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb4
-rw-r--r--activerecord/lib/active_record/core.rb45
-rw-r--r--activerecord/lib/active_record/errors.rb6
-rw-r--r--activerecord/lib/active_record/fixtures.rb8
-rw-r--r--activerecord/lib/active_record/persistence.rb3
-rw-r--r--activerecord/lib/active_record/transactions.rb38
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb13
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb2
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb6
-rw-r--r--activerecord/test/cases/attributes_test.rb2
-rw-r--r--activerecord/test/cases/fixtures_test.rb2
-rw-r--r--activerecord/test/cases/migration/create_join_table_test.rb2
-rw-r--r--activerecord/test/cases/migrator_test.rb2
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb2
-rw-r--r--activerecord/test/schema/mysql2_specific_schema.rb8
-rw-r--r--activerecord/test/schema/mysql_specific_schema.rb8
-rw-r--r--activesupport/CHANGELOG.md5
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/enumerable.rb11
-rw-r--r--activesupport/lib/active_support/rescuable.rb2
-rw-r--r--activesupport/test/caching_test.rb2
-rw-r--r--activesupport/test/core_ext/array/access_test.rb4
-rw-r--r--activesupport/test/core_ext/enumerable_test.rb7
-rw-r--r--activesupport/test/core_ext/object/duplicable_test.rb3
-rw-r--r--activesupport/test/json/encoding_test.rb2
-rw-r--r--guides/source/4_0_release_notes.md4
-rw-r--r--guides/source/active_support_core_extensions.md11
-rw-r--r--guides/source/association_basics.md2
-rw-r--r--guides/source/debugging_rails_applications.md113
-rw-r--r--guides/source/getting_started.md15
-rw-r--r--guides/source/routing.md2
-rw-r--r--railties/lib/rails/engine.rb2
-rw-r--r--railties/lib/rails/ruby_version_check.rb2
-rw-r--r--railties/lib/rails/tasks/restart.rake2
85 files changed, 371 insertions, 273 deletions
diff --git a/Gemfile b/Gemfile
index 074db1b4eb..25850ff34e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -15,6 +15,7 @@ gem 'jquery-rails', github: 'rails/jquery-rails', branch: 'master'
gem 'coffee-rails', '~> 4.1.0'
gem 'turbolinks'
gem 'arel', github: 'rails/arel', branch: 'master'
+gem 'mail', github: 'mikel/mail'
# require: false so bcrypt is loaded only when has_secure_password is used.
# This is to avoid ActiveModel (and by extension the entire framework)
diff --git a/Gemfile.lock b/Gemfile.lock
index d2ed998160..e34449a7b0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -12,6 +12,13 @@ GIT
redis-namespace
GIT
+ remote: git://github.com/mikel/mail.git
+ revision: b159e0a542962fdd5e292a48cfffa560d7cf412e
+ specs:
+ mail (2.6.3.edge)
+ mime-types (>= 1.16, < 3)
+
+GIT
remote: git://github.com/rails/arel.git
revision: aac9da257f291ad8d2d4f914528881c240848bb2
branch: master
@@ -41,7 +48,7 @@ PATH
actionview (= 5.0.0.alpha)
activesupport (= 5.0.0.alpha)
rack (~> 1.6)
- rack-test (~> 0.6.2)
+ rack-test (~> 0.6.3)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.1)
actionview (5.0.0.alpha)
@@ -123,8 +130,6 @@ GEM
nokogiri
loofah (2.0.1)
nokogiri (>= 1.5.9)
- mail (2.6.3)
- mime-types (>= 1.16, < 3)
metaclass (0.0.4)
mime-types (2.4.3)
mini_portile (0.6.2)
@@ -250,6 +255,7 @@ DEPENDENCIES
jquery-rails!
json
kindlerb (= 0.1.1)
+ mail!
minitest (< 5.3.4)
mocha (~> 0.14)
mysql (>= 2.9.0)
diff --git a/actionmailer/lib/action_mailer/mail_helper.rb b/actionmailer/lib/action_mailer/mail_helper.rb
index 227192f48d..239974e7b1 100644
--- a/actionmailer/lib/action_mailer/mail_helper.rb
+++ b/actionmailer/lib/action_mailer/mail_helper.rb
@@ -4,7 +4,17 @@ module ActionMailer
# attachments list.
module MailHelper
# Take the text and format it, indented two spaces for each line, and
- # wrapped at 72 columns.
+ # wrapped at 72 columns:
+ #
+ # text = <<-TEXT
+ # This is
+ # the paragraph.
+ #
+ # * item1 * item2
+ # TEXT
+ #
+ # block_format text
+ # # => " This is the paragraph.\n\n * item1\n * item2\n"
def block_format(text)
formatted = text.split(/\n\r?\n/).collect { |paragraph|
format_paragraph(paragraph)
diff --git a/actionmailer/test/fixtures/base_mailer/email_custom_layout.text.html.erb b/actionmailer/test/fixtures/base_mailer/email_custom_layout.text.html.erb
deleted file mode 100644
index a2187308b6..0000000000
--- a/actionmailer/test/fixtures/base_mailer/email_custom_layout.text.html.erb
+++ /dev/null
@@ -1 +0,0 @@
-body_text \ No newline at end of file
diff --git a/actionmailer/test/fixtures/first_mailer/share.erb b/actionmailer/test/fixtures/first_mailer/share.erb
deleted file mode 100644
index da43638ceb..0000000000
--- a/actionmailer/test/fixtures/first_mailer/share.erb
+++ /dev/null
@@ -1 +0,0 @@
-first mail
diff --git a/actionmailer/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb b/actionmailer/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb
deleted file mode 100644
index 2d0cd5c124..0000000000
--- a/actionmailer/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb
+++ /dev/null
@@ -1 +0,0 @@
-Have some dots. Enjoy! \ No newline at end of file
diff --git a/actionmailer/test/fixtures/second_mailer/share.erb b/actionmailer/test/fixtures/second_mailer/share.erb
deleted file mode 100644
index 9a54010672..0000000000
--- a/actionmailer/test/fixtures/second_mailer/share.erb
+++ /dev/null
@@ -1 +0,0 @@
-second mail
diff --git a/actionmailer/test/fixtures/test_mailer/_subtemplate.text.erb b/actionmailer/test/fixtures/test_mailer/_subtemplate.text.erb
deleted file mode 100644
index 3b4ba35f20..0000000000
--- a/actionmailer/test/fixtures/test_mailer/_subtemplate.text.erb
+++ /dev/null
@@ -1 +0,0 @@
-let's go! \ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.html.haml b/actionmailer/test/fixtures/test_mailer/custom_templating_extension.html.haml
deleted file mode 100644
index 8dcf9746cc..0000000000
--- a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-%p Hello there,
-
-%p
- Mr.
- = @recipient
- from haml \ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.haml b/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.haml
deleted file mode 100644
index 8dcf9746cc..0000000000
--- a/actionmailer/test/fixtures/test_mailer/custom_templating_extension.text.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-%p Hello there,
-
-%p
- Mr.
- = @recipient
- from haml \ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb
deleted file mode 100644
index 946d99ede5..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
- <body>
- HTML formatted message to <strong><%= @recipient %></strong>.
- </body>
-</html>
-<html>
- <body>
- HTML formatted message to <strong><%= @recipient %></strong>.
- </body>
-</html>
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~ b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~
deleted file mode 100644
index 946d99ede5..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.html.erb~
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
- <body>
- HTML formatted message to <strong><%= @recipient %></strong>.
- </body>
-</html>
-<html>
- <body>
- HTML formatted message to <strong><%= @recipient %></strong>.
- </body>
-</html>
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.ignored.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.ignored.erb
deleted file mode 100644
index 6940419d47..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.ignored.erb
+++ /dev/null
@@ -1 +0,0 @@
-Ignored when searching for implicitly multipart parts.
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak
deleted file mode 100644
index 6940419d47..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak
+++ /dev/null
@@ -1 +0,0 @@
-Ignored when searching for implicitly multipart parts.
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.erb
deleted file mode 100644
index a6c8d54cf9..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-Plain text to <%= @recipient %>.
-Plain text to <%= @recipient %>.
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb
deleted file mode 100644
index c14348c770..0000000000
--- a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.yaml.erb
+++ /dev/null
@@ -1 +0,0 @@
-yaml to: <%= @recipient %> \ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.erb b/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.erb
deleted file mode 100644
index ae3cfa77e7..0000000000
--- a/actionmailer/test/fixtures/test_mailer/included_subtemplate.text.erb
+++ /dev/null
@@ -1 +0,0 @@
-Hey Ho, <%= render partial: "subtemplate" %> \ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/multipart_alternative.html.erb b/actionmailer/test/fixtures/test_mailer/multipart_alternative.html.erb
deleted file mode 100644
index 73ea14f82f..0000000000
--- a/actionmailer/test/fixtures/test_mailer/multipart_alternative.html.erb
+++ /dev/null
@@ -1 +0,0 @@
-<strong>foo</strong> <%= @foo %> \ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/multipart_alternative.plain.erb b/actionmailer/test/fixtures/test_mailer/multipart_alternative.plain.erb
deleted file mode 100644
index 779fe4c1ea..0000000000
--- a/actionmailer/test/fixtures/test_mailer/multipart_alternative.plain.erb
+++ /dev/null
@@ -1 +0,0 @@
-foo: <%= @foo %> \ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/rxml_template.rxml b/actionmailer/test/fixtures/test_mailer/rxml_template.rxml
deleted file mode 100644
index d566bd8d7c..0000000000
--- a/actionmailer/test/fixtures/test_mailer/rxml_template.rxml
+++ /dev/null
@@ -1,2 +0,0 @@
-xml.instruct!
-xml.test \ No newline at end of file
diff --git a/actionmailer/test/fixtures/test_mailer/signed_up.html.erb b/actionmailer/test/fixtures/test_mailer/signed_up.html.erb
deleted file mode 100644
index 7afe1f651c..0000000000
--- a/actionmailer/test/fixtures/test_mailer/signed_up.html.erb
+++ /dev/null
@@ -1,3 +0,0 @@
-Hello there,
-
-Mr. <%= @recipient %> \ No newline at end of file
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 0134bf7cab..8c4ba2a154 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Partitioning of routes is now done when the routes are being drawn. This
+ helps to decrease the time spent filtering the routes during the first request.
+
+ *Guo Xiang Tan*
+
* Fix regression in functional tests. Responses should have default headers
assigned.
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index d9b23ad4a9..d907001bd6 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
s.add_dependency 'activesupport', version
s.add_dependency 'rack', '~> 1.6'
- s.add_dependency 'rack-test', '~> 0.6.2'
+ s.add_dependency 'rack-test', '~> 0.6.3'
s.add_dependency 'rails-html-sanitizer', '~> 1.0', '>= 1.0.1'
s.add_dependency 'rails-dom-testing', '~> 1.0', '>= 1.0.5'
s.add_dependency 'actionview', version
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index a9c3e438fb..819837e767 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -93,6 +93,10 @@ module ActionController
super(args)
end
+ # Return a list of helper names in specific path.
+ #
+ # ActionController::Base.all_helpers_from_path 'app/helpers'
+ # # => ["application", "chart", "rubygems"]
def all_helpers_from_path(path)
helpers = Array(path).flat_map do |_path|
extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 07b3814ca4..732ee67268 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -114,7 +114,7 @@ module ActionDispatch
end
def engine_script_name(_routes) # :nodoc:
- env["ROUTES_#{_routes.object_id}_SCRIPT_NAME"]
+ env[_routes.env_key]
end
def request_method=(request_method) #:nodoc:
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 001b14ec97..7da6301ac4 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -67,7 +67,7 @@ module ActionDispatch
end
def path_for(options)
- path = options[:script_name].to_s.chomp("/")
+ path = options[:script_name].to_s.chomp("/".freeze)
path << options[:path] if options.key?(:path)
add_trailing_slash(path) if options[:trailing_slash]
diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb
index 2b036796ab..cc4bd6105d 100644
--- a/actionpack/lib/action_dispatch/journey/router.rb
+++ b/actionpack/lib/action_dispatch/journey/router.rb
@@ -88,7 +88,7 @@ module ActionDispatch
end
def custom_routes
- partitioned_routes.last
+ routes.custom_routes
end
def filter_routes(path)
diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb
index 80e3818ccd..a6d1980db2 100644
--- a/actionpack/lib/action_dispatch/journey/routes.rb
+++ b/actionpack/lib/action_dispatch/journey/routes.rb
@@ -5,13 +5,14 @@ module ActionDispatch
class Routes # :nodoc:
include Enumerable
- attr_reader :routes, :named_routes
+ attr_reader :routes, :named_routes, :custom_routes, :anchored_routes
def initialize
@routes = []
@named_routes = {}
@ast = nil
- @partitioned_routes = nil
+ @anchored_routes = []
+ @custom_routes = []
@simulator = nil
end
@@ -30,18 +31,22 @@ module ActionDispatch
def clear
routes.clear
+ anchored_routes.clear
+ custom_routes.clear
named_routes.clear
end
- def partitioned_routes
- @partitioned_routes ||= routes.partition do |r|
- r.path.anchored && r.ast.grep(Nodes::Symbol).all?(&:default_regexp?)
+ def partition_route(route)
+ if route.path.anchored && route.ast.grep(Nodes::Symbol).all?(&:default_regexp?)
+ anchored_routes << route
+ else
+ custom_routes << route
end
end
def ast
@ast ||= begin
- asts = partitioned_routes.first.map(&:ast)
+ asts = anchored_routes.map(&:ast)
Nodes::Or.new(asts) unless asts.empty?
end
end
@@ -60,6 +65,7 @@ module ActionDispatch
route.precedence = routes.length
routes << route
named_routes[name] = route if name && !named_routes[name]
+ partition_route(route)
clear_cache!
route
end
@@ -68,7 +74,6 @@ module ActionDispatch
def clear_cache!
@ast = nil
- @partitioned_routes = nil
@simulator = nil
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/cache_store.rb
index 625050dc4b..857e49a682 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cache_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cache_store.rb
@@ -2,12 +2,15 @@ require 'action_dispatch/middleware/session/abstract_store'
module ActionDispatch
module Session
- # Session store that uses an ActiveSupport::Cache::Store to store the sessions. This store is most useful
+ # A session store that uses an ActiveSupport::Cache::Store to store the sessions. This store is most useful
# if you don't store critical data in your sessions and you don't need them to live for extended periods
# of time.
+ #
+ # ==== Options
+ # * <tt>cache</tt> - The cache to use. If it is not specified, <tt>Rails.cache</tt> will be used.
+ # * <tt>expire_after</tt> - The length of time a session will be stored before automatically expiring.
+ # By default, the <tt>:expires_in</tt> option of the cache is used.
class CacheStore < AbstractStore
- # Create a new store. The cache to use can be passed in the <tt>:cache</tt> option. If it is
- # not specified, <tt>Rails.cache</tt> will be used.
def initialize(app, options = {})
@cache = options[:cache] || Rails.cache
options[:expire_after] ||= @cache.options[:expires_in]
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index ed25c67ae5..d8f9614904 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -52,6 +52,16 @@ module ActionDispatch
# JavaScript before upgrading.
#
# Note that changing the secret key will invalidate all existing sessions!
+ #
+ # Because CookieStore extends Rack::Session::Abstract::ID, many of the
+ # options described there can be used to customize the session cookie that
+ # is generated. For example:
+ #
+ # Rails.application.config.session_store :cookie_store, expire_after: 14.days
+ #
+ # would set the session cookie to expire automatically 14 days after creation.
+ # Other useful options include <tt>:key</tt>, <tt>:secure</tt> and
+ # <tt>:httponly</tt>.
class CookieStore < Rack::Session::Abstract::ID
include Compatibility
include StaleSessionCheck
diff --git a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb
index b4d6629c35..cb19786f0b 100644
--- a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb
@@ -8,6 +8,10 @@ end
module ActionDispatch
module Session
+ # A session store that uses MemCache to implement storage.
+ #
+ # ==== Options
+ # * <tt>expire_after</tt> - The length of time a session will be stored before automatically expiring.
class MemCacheStore < Rack::Session::Dalli
include Compatibility
include StaleSessionCheck
diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
index f2ce175cac..9934f5547a 100644
--- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
+++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
@@ -247,14 +247,12 @@ module ActionDispatch
args = []
model = record.to_model
- name = if model.persisted?
- args << model
- model.model_name.singular_route_key
- else
- @key_strategy.call model.model_name
- end
-
- named_route = "#{prefix}#{name}_#{suffix}"
+ named_route = if model.persisted?
+ args << model
+ get_method_for_string model.model_name.singular_route_key
+ else
+ get_method_for_class model
+ end
[named_route, args]
end
@@ -309,11 +307,11 @@ module ActionDispatch
def get_method_for_class(klass)
name = @key_strategy.call klass.model_name
- prefix + "#{name}_#{suffix}"
+ get_method_for_string name
end
def get_method_for_string(str)
- prefix + "#{str}_#{suffix}"
+ "#{prefix}#{str}_#{suffix}"
end
[nil, 'new', 'edit'].each do |action|
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index ce04f0b08a..58b3fff9d7 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -199,12 +199,9 @@ module ActionDispatch
private
def optimized_helper(args)
- params = parameterize_args(args)
- missing_keys = missing_keys(params)
-
- unless missing_keys.empty?
- raise_generation_error(params, missing_keys)
- end
+ params = parameterize_args(args) { |k|
+ raise_generation_error(args)
+ }
@route.format params
end
@@ -215,16 +212,21 @@ module ActionDispatch
def parameterize_args(args)
params = {}
- @required_parts.zip(args.map(&:to_param)) { |k,v| params[k] = v }
+ @arg_size.times { |i|
+ key = @required_parts[i]
+ value = args[i].to_param
+ yield key if value.nil? || value.empty?
+ params[key] = value
+ }
params
end
- def missing_keys(args)
- args.select{ |part, arg| arg.nil? || arg.empty? }.keys
- end
-
- def raise_generation_error(args, missing_keys)
- constraints = Hash[@route.requirements.merge(args).sort]
+ def raise_generation_error(args)
+ missing_keys = []
+ params = parameterize_args(args) { |missing_key|
+ missing_keys << missing_key
+ }
+ constraints = Hash[@route.requirements.merge(params).sort]
message = "No route matches #{constraints.inspect}"
message << " missing required keys: #{missing_keys.sort.inspect}"
@@ -308,6 +310,7 @@ module ActionDispatch
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
attr_accessor :disable_clear_and_finalize, :resources_path_names
attr_accessor :default_url_options, :request_class
+ attr_reader :env_key
alias :routes :set
@@ -325,6 +328,7 @@ module ActionDispatch
@prepend = []
@disable_clear_and_finalize = false
@finalized = false
+ @env_key = "ROUTES_#{object_id}_SCRIPT_NAME".freeze
@set = Journey::Routes.new
@router = Journey::Router.new @set
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index dca86858cc..eb554ec383 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -184,12 +184,6 @@ module ActionDispatch
def _routes_context
self
end
-
- private
-
- def _generate_paths_by_default
- true
- end
end
end
end
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 918589f916..f5dd9d76af 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -95,7 +95,7 @@ end
module ActiveSupport
class TestCase
include ActionDispatch::DrawOnce
- if ActiveSupport::Testing::Isolation.forking_env? && PROCESS_COUNT > 0
+ if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0
parallelize_me!
end
end
@@ -479,7 +479,7 @@ class ForkingExecutor
end
end
-if ActiveSupport::Testing::Isolation.forking_env? && PROCESS_COUNT > 0
+if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0
# Use N processes (N defaults to 4)
Minitest.parallel_executor = ForkingExecutor.new(PROCESS_COUNT)
end
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index 7fd1276e98..0c65270ec1 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -276,6 +276,8 @@ module ActionController
end
def test_async_stream
+ rubinius_skip "https://github.com/rubinius/rubinius/issues/2934"
+
@controller.latch = ActiveSupport::Concurrency::Latch.new
parts = ['hello', 'world']
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index 7921f05688..a867aee7ec 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -305,7 +305,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_response 500
assert_select '#Application-Trace' do
- assert_select 'pre code', /\(eval\):1: syntax error, unexpected/
+ assert_select 'pre code', /syntax error, unexpected/
end
end
@@ -332,7 +332,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_response 500
assert_select '#Application-Trace' do
- assert_select 'pre code', /\(eval\):1: syntax error, unexpected/
+ assert_select 'pre code', /syntax error, unexpected/
end
end
diff --git a/actionpack/test/journey/routes_test.rb b/actionpack/test/journey/routes_test.rb
index a4efc82b8c..b54d961f66 100644
--- a/actionpack/test/journey/routes_test.rb
+++ b/actionpack/test/journey/routes_test.rb
@@ -3,6 +3,10 @@ require 'abstract_unit'
module ActionDispatch
module Journey
class TestRoutes < ActiveSupport::TestCase
+ setup do
+ @routes = Routes.new
+ end
+
def test_clear
routes = Routes.new
exp = Router::Strexp.build '/foo(/:id)', {}, ['/.?']
@@ -36,8 +40,24 @@ module ActionDispatch
assert_not_equal sim, routes.simulator
end
+ def test_partition_route
+ path = Path::Pattern.from_string '/hello'
+
+ anchored_route = @routes.add_route nil, path, {}, {}, {}
+ assert_equal [anchored_route], @routes.anchored_routes
+ assert_equal [], @routes.custom_routes
+
+ strexp = Router::Strexp.build(
+ "/hello/:who", { who: /\d/ }, ['/', '.', '?']
+ )
+ path = Path::Pattern.new strexp
+
+ custom_route = @routes.add_route nil, path, {}, {}, {}
+ assert_equal [custom_route], @routes.custom_routes
+ assert_equal [anchored_route], @routes.anchored_routes
+ end
+
def test_first_name_wins
- #def add_route app, path, conditions, defaults, name = nil
routes = Routes.new
one = Path::Pattern.from_string '/hello'
diff --git a/actionview/lib/action_view/routing_url_for.rb b/actionview/lib/action_view/routing_url_for.rb
index f281333a41..0371db07dc 100644
--- a/actionview/lib/action_view/routing_url_for.rb
+++ b/actionview/lib/action_view/routing_url_for.rb
@@ -130,5 +130,11 @@ module ActionView
controller.optimize_routes_generation? : super
end
protected :optimize_routes_generation?
+
+ private
+
+ def _generate_paths_by_default
+ true
+ end
end
end
diff --git a/actionview/test/activerecord/polymorphic_routes_test.rb b/actionview/test/activerecord/polymorphic_routes_test.rb
index 6b51775cf3..34b2698c7f 100644
--- a/actionview/test/activerecord/polymorphic_routes_test.rb
+++ b/actionview/test/activerecord/polymorphic_routes_test.rb
@@ -208,7 +208,7 @@ class PolymorphicRoutesTest < ActionController::TestCase
@series.save
polymorphic_url([nil, @series])
end
- assert_match(/undefined method `series_url' for/, exception.message)
+ assert_match(/undefined method `series_url'/, exception.message)
end
end
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index 58fe08cc11..8aa1b6f664 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -50,6 +50,7 @@ module ActiveModel
eager_autoload do
autoload :Errors
autoload :StrictValidationFailed, 'active_model/errors'
+ autoload :UnknownAttributeError, 'active_model/errors'
end
module Serializers
diff --git a/activemodel/lib/active_model/attribute_assignment.rb b/activemodel/lib/active_model/attribute_assignment.rb
index 356421476c..087d11f708 100644
--- a/activemodel/lib/active_model/attribute_assignment.rb
+++ b/activemodel/lib/active_model/attribute_assignment.rb
@@ -48,16 +48,5 @@ module ActiveModel
raise UnknownAttributeError.new(self, k)
end
end
-
- # Raised when unknown attributes are supplied via mass assignment.
- class UnknownAttributeError < NoMethodError
- attr_reader :record, :attribute
-
- def initialize(record, attribute)
- @record = record
- @attribute = attribute
- super("unknown attribute '#{attribute}' for #{@record.class}.")
- end
- end
end
end
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 8326853879..f324788979 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -524,4 +524,15 @@ module ActiveModel
# # => ActiveModel::StrictValidationFailed: Name can't be blank
class StrictValidationFailed < StandardError
end
+
+ # Raised when unknown attributes are supplied via mass assignment.
+ class UnknownAttributeError < NoMethodError
+ attr_reader :record, :attribute
+
+ def initialize(record, attribute)
+ @record = record
+ @attribute = attribute
+ super("unknown attribute '#{attribute}' for #{@record.class}.")
+ end
+ end
end
diff --git a/activemodel/test/cases/attribute_assignment_test.rb b/activemodel/test/cases/attribute_assignment_test.rb
index 402caf21f7..3b01644dd1 100644
--- a/activemodel/test/cases/attribute_assignment_test.rb
+++ b/activemodel/test/cases/attribute_assignment_test.rb
@@ -49,7 +49,7 @@ class AttributeAssignmentTest < ActiveModel::TestCase
test "assign non-existing attribute" do
model = Model.new
- error = assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) do
+ error = assert_raises(ActiveModel::UnknownAttributeError) do
model.assign_attributes(hz: 1)
end
@@ -58,8 +58,10 @@ class AttributeAssignmentTest < ActiveModel::TestCase
end
test "assign private attribute" do
+ rubinius_skip "https://github.com/rubinius/rubinius/issues/3328"
+
model = Model.new
- assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) do
+ assert_raises(ActiveModel::UnknownAttributeError) do
model.assign_attributes(metadata: { a: 1 })
end
end
diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb
index 4ce6103593..3276f69f09 100644
--- a/activemodel/test/cases/helper.rb
+++ b/activemodel/test/cases/helper.rb
@@ -14,6 +14,15 @@ require 'active_support/testing/autorun'
require 'mocha/setup' # FIXME: stop using mocha
+# Skips the current run on Rubinius using Minitest::Assertions#skip
+def rubinius_skip(message = '')
+ skip message if RUBY_ENGINE == 'rbx'
+end
+# Skips the current run on JRuby using Minitest::Assertions#skip
+def jruby_skip(message = '')
+ skip message if defined?(JRUBY_VERSION)
+end
+
# FIXME: we have tests that depend on run order, we should fix that and
# remove this method call.
require 'active_support/test_case'
diff --git a/activemodel/test/cases/model_test.rb b/activemodel/test/cases/model_test.rb
index 9a8d873ec9..3017f3541b 100644
--- a/activemodel/test/cases/model_test.rb
+++ b/activemodel/test/cases/model_test.rb
@@ -70,7 +70,7 @@ class ModelTest < ActiveModel::TestCase
end
def test_mixin_initializer_when_args_dont_exist
- assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) do
+ assert_raises(ActiveModel::UnknownAttributeError) do
SimpleModel.new(hello: 'world')
end
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 82a7c27799..0ba03338f6 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -129,11 +129,11 @@ module ActiveRecord
first_nth_or_last(:last, *args)
end
- def take
+ def take(n = nil)
if loaded?
- target.first
+ n ? target.take(n) : target.first
else
- scope.take.tap do |record|
+ scope.take(n).tap do |record|
set_inverse_instance record if record.is_a? ActiveRecord::Base
end
end
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 87e80e88b2..e11c9490b7 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -227,8 +227,8 @@ module ActiveRecord
@association.last(*args)
end
- def take
- @association.take
+ def take(n = nil)
+ @association.take(n)
end
# Returns a new object of the collection type that has been instantiated
diff --git a/activerecord/lib/active_record/attribute_assignment.rb b/activerecord/lib/active_record/attribute_assignment.rb
index 483d4200bd..cc265e2af6 100644
--- a/activerecord/lib/active_record/attribute_assignment.rb
+++ b/activerecord/lib/active_record/attribute_assignment.rb
@@ -29,6 +29,13 @@ module ActiveRecord
assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
end
+ # Re-raise with the ActiveRecord constant in case of an error
+ def _assign_attribute(k, v) # :nodoc:
+ super
+ rescue ActiveModel::UnknownAttributeError
+ raise UnknownAttributeError.new(self, k)
+ end
+
# Assign any deferred nested attributes after the base attributes have been set.
def assign_nested_parameter_attributes(pairs)
pairs.each { |k, v| _assign_attribute(k, v) }
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 0acc815d51..8231f44b4e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -401,7 +401,7 @@ module ActiveRecord
# Adds a reference. Optionally adds a +type+ column, if the
# +:polymorphic+ option is provided. +references+ and +belongs_to+
- # are acceptable. The reference column will be an +integer+ by default,
+ # are interchangeable. The reference column will be an +integer+ by default,
# the +:type+ option can be used to specify a different type. A foreign
# key will be created if the +:foreign_key+ option is passed.
#
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
index 3a1e4a4a88..c74f4e8fa5 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
@@ -1,13 +1,10 @@
module ActiveRecord
module ConnectionAdapters
class TransactionState
- attr_reader :parent
-
VALID_STATES = Set.new([:committed, :rolledback, nil])
def initialize(state = nil)
@state = state
- @parent = nil
end
def finalized?
@@ -27,7 +24,7 @@ module ActiveRecord
end
def set_state(state)
- if !VALID_STATES.include?(state)
+ unless VALID_STATES.include?(state)
raise ArgumentError, "Invalid transaction state: #{state}"
end
@state = state
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 75b9d079bd..eeb141dd1e 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -514,14 +514,14 @@ module ActiveRecord
sql = case type.to_s
when 'binary'
# PostgreSQL doesn't support limits on binary (bytea) columns.
- # The hard limit is 1Gb, because of a 32-bit size field, and TOAST.
+ # The hard limit is 1GB, because of a 32-bit size field, and TOAST.
case limit
when nil, 0..0x3fffffff; super(type)
else raise(ActiveRecordError, "No binary type has byte size #{limit}.")
end
when 'text'
# PostgreSQL doesn't support limits on text columns.
- # The hard limit is 1Gb, according to section 8.3 in the manual.
+ # The hard limit is 1GB, according to section 8.3 in the manual.
case limit
when nil, 0..0x3fffffff; super(type)
else raise(ActiveRecordError, "The limit on text can be at most 1GB - 1byte.")
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index d41872d767..97ce4642aa 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -483,51 +483,6 @@ module ActiveRecord
private
- def set_transaction_state(state) # :nodoc:
- @transaction_state = state
- end
-
- def has_transactional_callbacks? # :nodoc:
- !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
- end
-
- # Updates the attributes on this particular ActiveRecord object so that
- # if it is associated with a transaction, then the state of the AR object
- # will be updated to reflect the current state of the transaction
- #
- # The @transaction_state variable stores the states of the associated
- # transaction. This relies on the fact that a transaction can only be in
- # one rollback or commit (otherwise a list of states would be required)
- # Each AR object inside of a transaction carries that transaction's
- # TransactionState.
- #
- # This method checks to see if the ActiveRecord object's state reflects
- # the TransactionState, and rolls back or commits the ActiveRecord object
- # as appropriate.
- #
- # Since ActiveRecord objects can be inside multiple transactions, this
- # method recursively goes through the parent of the TransactionState and
- # checks if the ActiveRecord object reflects the state of the object.
- def sync_with_transaction_state
- update_attributes_from_transaction_state(@transaction_state, 0)
- end
-
- def update_attributes_from_transaction_state(transaction_state, depth)
- @reflects_state = [false] if depth == 0
-
- if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
- unless @reflects_state[depth]
- restore_transaction_record_state if transaction_state.rolledback?
- clear_transaction_record_state
- @reflects_state[depth] = true
- end
-
- if transaction_state.parent && !@reflects_state[depth+1]
- update_attributes_from_transaction_state(transaction_state.parent, depth+1)
- end
- end
- end
-
# Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
# of the array, and then rescues from the possible NoMethodError. If those elements are
# ActiveRecord::Base's, then this triggers the various method_missing's that we have,
diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb
index d710d96a9a..98aee77557 100644
--- a/activerecord/lib/active_record/errors.rb
+++ b/activerecord/lib/active_record/errors.rb
@@ -178,10 +178,8 @@ module ActiveRecord
class DangerousAttributeError < ActiveRecordError
end
- UnknownAttributeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new( # :nodoc:
- 'ActiveRecord::UnknownAttributeError',
- 'ActiveModel::AttributeAssignment::UnknownAttributeError'
- )
+ # Raised when unknown attributes are supplied via mass assignment.
+ UnknownAttributeError = ActiveModel::UnknownAttributeError
# Raised when an error occurred while doing a mass assignment to an attribute through the
# +attributes=+ method. The exception has an +attribute+ property that is the name of the
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 75b0e1e08d..18775caad2 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -539,12 +539,10 @@ module ActiveRecord
conn.insert_fixture(row, fixture_set_name)
end
end
- end
- # Cap primary key sequences to max(pk).
- if connection.respond_to?(:reset_pk_sequence!)
- fixture_sets.each do |fs|
- connection.reset_pk_sequence!(fs.table_name)
+ # Cap primary key sequences to max(pk).
+ if conn.respond_to?(:reset_pk_sequence!)
+ conn.reset_pk_sequence!(fs.table_name)
end
end
end
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 7c076864a3..a6176dffdb 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -96,7 +96,8 @@ module ActiveRecord
# Returns true if the record is persisted, i.e. it's not a new record and it was
# not destroyed, otherwise returns false.
def persisted?
- !(new_record? || destroyed?)
+ sync_with_transaction_state
+ !(@new_record || @destroyed)
end
# Saves the model.
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 598defce50..ffe7c4ae42 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -442,5 +442,43 @@ module ActiveRecord
end
end
end
+
+ private
+
+ def set_transaction_state(state) # :nodoc:
+ @transaction_state = state
+ end
+
+ def has_transactional_callbacks? # :nodoc:
+ !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
+ end
+
+ # Updates the attributes on this particular ActiveRecord object so that
+ # if it is associated with a transaction, then the state of the AR object
+ # will be updated to reflect the current state of the transaction
+ #
+ # The @transaction_state variable stores the states of the associated
+ # transaction. This relies on the fact that a transaction can only be in
+ # one rollback or commit (otherwise a list of states would be required)
+ # Each AR object inside of a transaction carries that transaction's
+ # TransactionState.
+ #
+ # This method checks to see if the ActiveRecord object's state reflects
+ # the TransactionState, and rolls back or commits the ActiveRecord object
+ # as appropriate.
+ #
+ # Since ActiveRecord objects can be inside multiple transactions, this
+ # method recursively goes through the parent of the TransactionState and
+ # checks if the ActiveRecord object reflects the state of the object.
+ def sync_with_transaction_state
+ update_attributes_from_transaction_state(@transaction_state)
+ end
+
+ def update_attributes_from_transaction_state(transaction_state)
+ if transaction_state && transaction_state.finalized?
+ restore_transaction_record_state if transaction_state.rolledback?
+ clear_transaction_record_state
+ end
+ end
end
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 897c52a49d..675bed9bfa 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -478,6 +478,19 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
end
+ def test_taking_with_a_number
+ # taking from unloaded Relation
+ bob = Author.find(authors(:bob).id)
+ assert_equal [posts(:misc_by_bob)], bob.posts.take(1)
+ bob = Author.find(authors(:bob).id)
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], bob.posts.take(2)
+
+ # taking from loaded Relation
+ bob.posts.to_a
+ assert_equal [posts(:misc_by_bob)], authors(:bob).posts.take(1)
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], authors(:bob).posts.take(2)
+ end
+
def test_taking_with_inverse_of
interests(:woodsmanship).destroy
interests(:survival).destroy
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 3b6a4038cd..7dc9266074 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -276,7 +276,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
def test_create_with_inexistent_foreign_key_failing
firm = Firm.create(name: 'GlobalMegaCorp')
- assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) do
+ assert_raises(ActiveRecord::UnknownAttributeError) do
firm.create_account_with_inexistent_foreign_key
end
end
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index 243c90e945..ea2b94cbf4 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -758,12 +758,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase
def test_bulk_update_respects_access_control
privatize("title=(value)")
- assert_raise(ActiveModel::AttributeAssignment::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
- assert_raise(ActiveModel::AttributeAssignment::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
end
def test_bulk_update_raise_unknown_attribute_error
- error = assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) {
+ error = assert_raises(ActiveRecord::UnknownAttributeError) {
Topic.new(hello: "world")
}
assert_instance_of Topic, error.record
diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb
index e7b76b1cf9..927d7950a5 100644
--- a/activerecord/test/cases/attributes_test.rb
+++ b/activerecord/test/cases/attributes_test.rb
@@ -58,7 +58,7 @@ module ActiveRecord
data = OverloadedType.new(non_existent_decimal: 1)
assert_equal BigDecimal.new(1), data.non_existent_decimal
- assert_raise ActiveModel::AttributeAssignment::UnknownAttributeError do
+ assert_raise ActiveRecord::UnknownAttributeError do
UnoverloadedType.new(non_existent_decimal: 1)
end
end
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 7ef2ebc998..d1add21219 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -327,7 +327,7 @@ if Account.connection.respond_to?(:reset_pk_sequence!)
fixtures :companies
def setup
- @instances = [Account.new(:credit_limit => 50), Company.new(:name => 'RoR Consulting')]
+ @instances = [Account.new(:credit_limit => 50), Company.new(:name => 'RoR Consulting'), Course.new(name: 'Test')]
ActiveRecord::FixtureSet.reset_cache # make sure tables get reinitialized
end
diff --git a/activerecord/test/cases/migration/create_join_table_test.rb b/activerecord/test/cases/migration/create_join_table_test.rb
index bea9d6b2c9..8fd08fe4ce 100644
--- a/activerecord/test/cases/migration/create_join_table_test.rb
+++ b/activerecord/test/cases/migration/create_join_table_test.rb
@@ -140,7 +140,7 @@ module ActiveRecord
tables_after = connection.tables - tables_before
tables_after.each do |table|
- connection.execute "DROP TABLE #{table}"
+ connection.drop_table table
end
end
end
diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb
index c0daa83e9c..1760314099 100644
--- a/activerecord/test/cases/migrator_test.rb
+++ b/activerecord/test/cases/migrator_test.rb
@@ -312,7 +312,7 @@ class MigratorTest < ActiveRecord::TestCase
def test_migrator_db_has_no_schema_migrations_table
_, migrator = migrator_class(3)
- ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
+ ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true
assert_not ActiveRecord::Base.connection.table_exists?('schema_migrations')
migrator.migrate("valid", 1)
assert ActiveRecord::Base.connection.table_exists?('schema_migrations')
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index 198cd6f341..c5f6589c22 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -672,7 +672,7 @@ module NestedAttributesOnACollectionAssociationTests
end
def test_should_not_assign_destroy_key_to_a_record
- assert_nothing_raised ActiveModel::AttributeAssignment::UnknownAttributeError do
+ assert_nothing_raised ActiveRecord::UnknownAttributeError do
@pirate.send(association_setter, { 'foo' => { '_destroy' => '0' }})
end
end
diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb
index a9a6514c9d..d6fd0c4ab0 100644
--- a/activerecord/test/schema/mysql2_specific_schema.rb
+++ b/activerecord/test/schema/mysql2_specific_schema.rb
@@ -35,9 +35,7 @@ BEGIN
END
SQL
- ActiveRecord::Base.connection.execute <<-SQL
-DROP TABLE IF EXISTS collation_tests;
-SQL
+ ActiveRecord::Base.connection.drop_table "collation_tests", if_exists: true
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE collation_tests (
@@ -46,9 +44,7 @@ CREATE TABLE collation_tests (
) CHARACTER SET utf8 COLLATE utf8_general_ci
SQL
- ActiveRecord::Base.connection.execute <<-SQL
-DROP TABLE IF EXISTS enum_tests;
-SQL
+ ActiveRecord::Base.connection.drop_table "enum_tests", if_exists: true
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE enum_tests (
diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb
index f2cffca52c..b5378341b5 100644
--- a/activerecord/test/schema/mysql_specific_schema.rb
+++ b/activerecord/test/schema/mysql_specific_schema.rb
@@ -46,9 +46,7 @@ BEGIN
END
SQL
- ActiveRecord::Base.connection.execute <<-SQL
-DROP TABLE IF EXISTS collation_tests;
-SQL
+ ActiveRecord::Base.connection.drop_table "collation_tests", if_exists: true
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE collation_tests (
@@ -57,9 +55,7 @@ CREATE TABLE collation_tests (
) CHARACTER SET utf8 COLLATE utf8_general_ci
SQL
- ActiveRecord::Base.connection.execute <<-SQL
-DROP TABLE IF EXISTS enum_tests;
-SQL
+ ActiveRecord::Base.connection.drop_table "enum_tests", if_exists: true
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE enum_tests (
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 35be823ea1..43fb87f203 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Added `#without` on `Enumerable` and `Array` to return a copy of an
+ enumerable without the specified elements.
+
+ *Todd Bealmear*
+
* Fixed a problem where String#truncate_words would get stuck with a complex
string.
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index ca66d806ef..3177d8498e 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -27,6 +27,18 @@ class Array
end
end
+ # Returns a copy of the Array without the specified elements.
+ #
+ # people = ["David", "Rafael", "Aaron", "Todd"]
+ # people.without "Aaron", "Todd"
+ # => ["David", "Rafael"]
+ #
+ # Note: This is an optimization of `Enumerable#without` that uses `Array#-`
+ # instead of `Array#reject` for performance reasons.
+ def without(*elements)
+ self - elements
+ end
+
# Equal to <tt>self[1]</tt>.
#
# %w( a b c d e ).second # => "b"
diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb
index 1343beb87a..7a893292b3 100644
--- a/activesupport/lib/active_support/core_ext/enumerable.rb
+++ b/activesupport/lib/active_support/core_ext/enumerable.rb
@@ -60,6 +60,17 @@ module Enumerable
def exclude?(object)
!include?(object)
end
+
+ # Returns a copy of the enumerable without the specified elements.
+ #
+ # ["David", "Rafael", "Aaron", "Todd"].without "Aaron", "Todd"
+ # => ["David", "Rafael"]
+ #
+ # {foo: 1, bar: 2, baz: 3}.without :bar
+ # => {foo: 1, baz: 3}
+ def without(*elements)
+ reject { |element| elements.include?(element) }
+ end
end
class Range #:nodoc:
diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb
index 1a02acd5b1..67aac32742 100644
--- a/activesupport/lib/active_support/rescuable.rb
+++ b/activesupport/lib/active_support/rescuable.rb
@@ -100,7 +100,7 @@ module ActiveSupport
# a string, otherwise a NameError will be raised by the interpreter
# itself when rescue_from CONSTANT is executed.
klass = self.class.const_get(klass_name) rescue nil
- klass ||= klass_name.constantize rescue nil
+ klass ||= (klass_name.constantize rescue nil)
klass === exception if klass
end
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index 095e908907..7f5f8feb0d 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -1028,7 +1028,7 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase
@cache.read_multi('hello', 'world')
- assert_match "Caches multi read:\n- hello\n- world", @buffer.string.tap { |l| p l }
+ assert_match "Caches multi read:\n- hello\n- world", @buffer.string
end
end
diff --git a/activesupport/test/core_ext/array/access_test.rb b/activesupport/test/core_ext/array/access_test.rb
index f14f64421d..3f1e0c4cb4 100644
--- a/activesupport/test/core_ext/array/access_test.rb
+++ b/activesupport/test/core_ext/array/access_test.rb
@@ -27,4 +27,8 @@ class AccessTest < ActiveSupport::TestCase
assert_equal array[4], array.fifth
assert_equal array[41], array.forty_two
end
+
+ def test_without
+ assert_equal [1, 2, 4], [1, 2, 3, 4, 5].without(3, 5)
+ end
end
diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb
index 346dc3d208..e5d8ae7882 100644
--- a/activesupport/test/core_ext/enumerable_test.rb
+++ b/activesupport/test/core_ext/enumerable_test.rb
@@ -103,4 +103,11 @@ class EnumerableTests < ActiveSupport::TestCase
assert_equal true, GenericEnumerable.new([ 1 ]).exclude?(2)
assert_equal false, GenericEnumerable.new([ 1 ]).exclude?(1)
end
+
+ def test_without
+ assert_equal [1, 2, 4], GenericEnumerable.new((1..5).to_a).without(3, 5)
+ assert_equal [1, 2, 4], (1..5).to_a.without(3, 5)
+ assert_equal [1, 2, 4], (1..5).to_set.without(3, 5)
+ assert_equal({foo: 1, baz: 3}, {foo: 1, bar: 2, baz: 3}.without(:bar))
+ end
end
diff --git a/activesupport/test/core_ext/object/duplicable_test.rb b/activesupport/test/core_ext/object/duplicable_test.rb
index d37f4bd0d8..042f5cfb34 100644
--- a/activesupport/test/core_ext/object/duplicable_test.rb
+++ b/activesupport/test/core_ext/object/duplicable_test.rb
@@ -9,6 +9,9 @@ class DuplicableTest < ActiveSupport::TestCase
ALLOW_DUP << BigDecimal.new('4.56')
def test_duplicable
+ rubinius_skip "* Method#dup is allowed at the moment on Rubinius\n" \
+ "* https://github.com/rubinius/rubinius/issues/3089"
+
RAISE_DUP.each do |v|
assert !v.duplicable?
assert_raises(TypeError, v.class.name) { v.dup }
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index 63d921e3b4..2f269a66f0 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -130,6 +130,8 @@ class TestJSONEncoding < ActiveSupport::TestCase
end
def test_process_status
+ rubinius_skip "https://github.com/rubinius/rubinius/issues/3334"
+
# There doesn't seem to be a good way to get a handle on a Process::Status object without actually
# creating a child process, hence this to populate $?
system("not_a_real_program_#{SecureRandom.hex}")
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index 67f4a3c02c..bd35e2d31a 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -73,7 +73,7 @@ Major Features
* **Strong parameters** ([commit](https://github.com/rails/rails/commit/a8f6d5c6450a7fe058348a7f10a908352bb6c7fc)) - Only allow whitelisted parameters to update model objects (`params.permit(:title, :text)`).
* **Routing concerns** ([commit](https://github.com/rails/rails/commit/0dd24728a088fcb4ae616bb5d62734aca5276b1b)) - In the routing DSL, factor out common subroutes (`comments` from `/posts/1/comments` and `/videos/1/comments`).
* **ActionController::Live** ([commit](https://github.com/rails/rails/commit/af0a9f9eefaee3a8120cfd8d05cbc431af376da3)) - Stream JSON with `response.stream`.
- * **Declarative ETags** ([commit](https://github.com/rails/rails/commit/ed5c938fa36995f06d4917d9543ba78ed506bb8d)) - Add controller-level etag additions that will be part of the action etag computation
+ * **Declarative ETags** ([commit](https://github.com/rails/rails/commit/ed5c938fa36995f06d4917d9543ba78ed506bb8d)) - Add controller-level etag additions that will be part of the action etag computation.
* **[Russian doll caching](http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works)** ([commit](https://github.com/rails/rails/commit/4154bf012d2bec2aae79e4a49aa94a70d3e91d49)) - Cache nested fragments of views. Each fragment expires based on a set of dependencies (a cache key). The cache key is usually a template version number and a model object.
* **Turbolinks** ([commit](https://github.com/rails/rails/commit/e35d8b18d0649c0ecc58f6b73df6b3c8d0c6bb74)) - Serve only one initial HTML page. When the user navigates to another page, use pushState to update the URL and use AJAX to update the title and body.
* **Decouple ActionView from ActionController** ([commit](https://github.com/rails/rails/commit/78b0934dd1bb84e8f093fb8ef95ca99b297b51cd)) - ActionView was decoupled from ActionPack and will be moved to a separated gem in Rails 4.1.
@@ -181,7 +181,7 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/4-0-stable/a
* `String#to_date` now raises `ArgumentError: invalid date` instead of `NoMethodError: undefined method 'div' for nil:NilClass`
when given an invalid date. It is now the same as `Date.parse`, and it accepts more invalid dates than 3.x, such as:
- ```
+ ```ruby
# ActiveSupport 3.x
"asdf".to_date # => NoMethodError: undefined method `div' for nil:NilClass
"333".to_date # => NoMethodError: undefined method `div' for nil:NilClass
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 2e7f776319..66626f41d1 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -2182,6 +2182,17 @@ to_visit << node if visited.exclude?(node)
NOTE: Defined in `active_support/core_ext/enumerable.rb`.
+### `without`
+
+The method `without` returns a copy of an enumerable with the specified elements
+removed:
+
+```ruby
+people.without("Aaron", "Todd")
+```
+
+NOTE: Defined in `active_support/core_ext/enumerable.rb`.
+
Extensions to `Array`
---------------------
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index d6b2e75e1e..280c3008e9 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -460,7 +460,7 @@ class CreatePictures < ActiveRecord::Migration
t.timestamps null: false
end
- add_index :pictures, :imageable_id
+ add_index :pictures, [:imageable_type, :imageable_id]
end
end
```
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index 926a048762..9cb2efb9a2 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -242,55 +242,6 @@ The contents of the block, and therefore the string interpolation, is only
evaluated if debug is enabled. This performance savings is only really
noticeable with large amounts of logging, but it's a good practice to employ.
-
-Debugging with the `web-console` gem
--------------------------------------
-
-The web console allows you to start an interactive Ruby session in your browser.
-An interactive console is launched automatically in case of an error but can also
-be launched for debugging purposes by invoking `console` in a view or controller.
-
-For example in a view:
-
-```ruby
-# new.html.erb
-<%= console %>
-```
-
-Or in a controller:
-
-```ruby
-# posts_controller.rb
-class PostsController < ApplicationController
- def new
- console
- @post = Post.new
- end
-end
-```
-
-### config.web_console.whitelisted_ips
-
-By default the web console can only be accessed from localhost.
-`config.web_console.whitelisted_ips` lets you control which IPs have access to
-the console.
-
-For example, to allow access from both localhost and 192.168.0.100, you can put
-inside your configuration file:
-
-```ruby
-config.web_console.whitelisted_ips = %w( 127.0.0.1 192.168.0.100 )
-```
-
-Or to allow access from an entire network:
-
-```ruby
-config.web_console.whitelisted_ips = %w( 127.0.0.1 192.168.0.0/16 )
-```
-
-The web console is a powerful tool so be careful when you give access to an IP.
-
-
Debugging with the `byebug` gem
---------------------------------
@@ -831,10 +782,10 @@ will be stopped and you will have to start it again.
`byebug` has a few available options to tweak its behaviour:
-* `set autoreload`: Reload source code when changed (default: true).
-* `set autolist`: Execute `list` command on every breakpoint (default: true).
+* `set autoreload`: Reload source code when changed (defaults: true).
+* `set autolist`: Execute `list` command on every breakpoint (defaults: true).
* `set listsize _n_`: Set number of source lines to list by default to _n_
-(default: 10)
+(defaults: 10)
* `set forcestep`: Make sure the `next` and `step` commands always move to a new
line.
@@ -849,6 +800,63 @@ set forcestep
set listsize 25
```
+Debugging with the `web-console` gem
+------------------------------------
+
+Web Console is a bit like `byebug`, but it runs in the browser. In any page you
+are developing, you can request a console in the context of a view or a
+controller. The console would be rendered next to your HTML content.
+
+### Console
+
+Inside any controller action or view, you can then invoke the console by
+calling the `console` method.
+
+For example, in a controller:
+
+```ruby
+class PostController < ApplicationController
+ def new
+ console
+ @post = Post.new
+ end
+end
+```
+
+Or in a view:
+
+```html+erb
+<% console %>
+
+<h2>New Post</h2>
+```
+
+This will render a console inside your view. You don't need to care about the
+location of the `console` call; it won't be rendered on the spot of its
+invocation but next to your HTML content.
+
+The console executes pure Ruby code. You can define and instantiate
+custom classes, create new models and inspect variables.
+
+NOTE: Only one console can be rendered per request. Otherwise `web-console`
+will raise an error on the second `console` invocation.
+
+### Inspecting Variables
+
+You can invoke `instance_variables` to list all the instance variables
+available in your context. If you want to list all the local variables, you can
+do that with `local_variables`.
+
+### Settings
+
+* `config.web_console.whitelisted_ips`: Authorized list of IPv4 or IPv6
+addresses and networks (defaults: `127.0.0.1/8, ::1`).
+* `config.web_console.whiny_requests`: Log a message when a console rendering
+is prevented (defaults: `true`).
+
+Since `web-console` evaluates plain Ruby code remotely on the server, don't try
+to use it in production.
+
Debugging Memory Leaks
----------------------
@@ -905,6 +913,7 @@ References
* [ruby-debug Homepage](http://bashdb.sourceforge.net/ruby-debug/home-page.html)
* [debugger Homepage](https://github.com/cldwalker/debugger)
* [byebug Homepage](https://github.com/deivid-rodriguez/byebug)
+* [web-console Homepage](https://github.com/rails/web-console)
* [Article: Debugging a Rails application with ruby-debug](http://www.sitepoint.com/debug-rails-app-ruby-debug/)
* [Ryan Bates' debugging ruby (revised) screencast](http://railscasts.com/episodes/54-debugging-ruby-revised)
* [Ryan Bates' stack trace screencast](http://railscasts.com/episodes/24-the-stack-trace)
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 51b8a2ca5f..66cfb72aaf 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -1479,13 +1479,14 @@ Finally, add a 'Destroy' link to your `index` action template
```
Here we're using `link_to` in a different way. We pass the named route as the
-second argument, and then the options as another argument. The `:method` and
-`:'data-confirm'` options are used as HTML5 attributes so that when the link is
-clicked, Rails will first show a confirm dialog to the user, and then submit the
-link with method `delete`. This is done via the JavaScript file `jquery_ujs`
-which is automatically included into your application's layout
-(`app/views/layouts/application.html.erb`) when you generated the application.
-Without this file, the confirmation dialog box wouldn't appear.
+second argument, and then the options as another argument. The `method: :delete`
+and `data: { confirm: 'Are you sure?' }` options are used as HTML5 attributes so
+that when the link is clicked, Rails will first show a confirm dialog to the
+user, and then submit the link with method `delete`. This is done via the
+JavaScript file `jquery_ujs` which is automatically included in your
+application's layout (`app/views/layouts/application.html.erb`) when you
+generated the application. Without this file, the confirmation dialog box won't
+appear.
![Confirm Dialog](images/getting_started/confirm_dialog.png)
diff --git a/guides/source/routing.md b/guides/source/routing.md
index a689e131ff..b5defc9d20 100644
--- a/guides/source/routing.md
+++ b/guides/source/routing.md
@@ -229,7 +229,7 @@ or, for a single case:
resources :articles, path: '/admin/articles'
```
-In each of these cases, the named routes remain the same as if you did not use `scope`. In the last case, the following paths map to `PostsController`:
+In each of these cases, the named routes remain the same as if you did not use `scope`. In the last case, the following paths map to `ArticlesController`:
| HTTP Verb | Path | Controller#Action | Named Helper |
| --------- | ------------------------ | -------------------- | ---------------------- |
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index e1d5caf790..fd37fd0457 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -513,7 +513,7 @@ module Rails
def call(env)
env.merge!(env_config)
if env['SCRIPT_NAME']
- env["ROUTES_#{routes.object_id}_SCRIPT_NAME"] = env['SCRIPT_NAME'].dup
+ env[routes.env_key] = env['SCRIPT_NAME'].dup
end
app.call(env)
end
diff --git a/railties/lib/rails/ruby_version_check.rb b/railties/lib/rails/ruby_version_check.rb
index aea3d2339c..e2a199ec4d 100644
--- a/railties/lib/rails/ruby_version_check.rb
+++ b/railties/lib/rails/ruby_version_check.rb
@@ -1,4 +1,4 @@
-if RUBY_VERSION < '2.2.0'
+if RUBY_VERSION < '2.2.0' && RUBY_ENGINE == 'ruby'
desc = defined?(RUBY_DESCRIPTION) ? RUBY_DESCRIPTION : "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})"
abort <<-end_message
diff --git a/railties/lib/rails/tasks/restart.rake b/railties/lib/rails/tasks/restart.rake
index 1af0302824..1e8940b675 100644
--- a/railties/lib/rails/tasks/restart.rake
+++ b/railties/lib/rails/tasks/restart.rake
@@ -1,4 +1,4 @@
desc "Restart app by touching tmp/restart.txt"
-task restart: :environment do
+task :restart do
FileUtils.touch('tmp/restart.txt')
end