aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/base.rb4
-rw-r--r--actionpack/lib/abstract_controller/layouts.rb2
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb4
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb2
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb2
-rw-r--r--actionpack/lib/action_controller/metal/responder.rb15
-rw-r--r--actionpack/lib/action_controller/test_case.rb7
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/callbacks.rb12
-rw-r--r--actionpack/lib/action_dispatch/railtie.rb1
-rw-r--r--actionpack/lib/action_dispatch/routing.rb15
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb125
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb32
-rw-r--r--actionpack/lib/action_dispatch/testing/test_process.rb3
-rw-r--r--actionpack/lib/action_view/base.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb14
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb25
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb7
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb8
-rw-r--r--actionpack/lib/action_view/lookup_context.rb14
-rw-r--r--actionpack/lib/action_view/railtie.rb1
-rw-r--r--actionpack/lib/action_view/renderer/abstract_renderer.rb2
-rw-r--r--actionpack/lib/action_view/renderer/template_renderer.rb3
-rw-r--r--actionpack/lib/action_view/template/handlers.rb1
-rw-r--r--actionpack/lib/action_view/template/handlers/erb.rb4
-rw-r--r--actionpack/lib/sprockets/helpers/rails_helper.rb12
27 files changed, 191 insertions, 134 deletions
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index fd6a46fbec..3d915cf513 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -42,8 +42,8 @@ module AbstractController
controller.public_instance_methods(true)
end
- # The list of hidden actions to an empty array. Defaults to an
- # empty array. This can be modified by other modules or subclasses
+ # The list of hidden actions. Defaults to an empty array.
+ # This can be modified by other modules or subclasses
# to specify particular actions as hidden.
#
# ==== Returns
diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb
index 6a6387632c..aa39e21ba9 100644
--- a/actionpack/lib/abstract_controller/layouts.rb
+++ b/actionpack/lib/abstract_controller/layouts.rb
@@ -322,7 +322,7 @@ module AbstractController
super
if _include_layout?(options)
- layout = options.key?(:layout) ? options.delete(:layout) : :default
+ layout = options.delete(:layout) { :default }
options[:layout] = _layout_for_option(layout)
end
end
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 3d46163b74..b8b43ea9ef 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -279,7 +279,7 @@ module ActionController
#
# An implementation might choose not to accept a previously used nonce or a previously used digest, in order to
# protect against a replay attack. Or, an implementation might choose to use one-time nonces or digests for
- # POST or PUT requests and a time-stamp for GET requests. For more details on the issues involved see Section 4
+ # POST, PUT, or PATCH requests and a time-stamp for GET requests. For more details on the issues involved see Section 4
# of this document.
#
# The nonce is opaque to the client. Composed of Time, and hash of Time with secret
@@ -293,7 +293,7 @@ module ActionController
end
# Might want a shorter timeout depending on whether the request
- # is a PUT or POST, and if client is browser or web service.
+ # is a PATCH, PUT, or POST, and if client is browser or web service.
# Can be much shorter if the Stale directive is implemented. This would
# allow a user to use new nonce without prompting user again for their
# username and password.
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index 80ecc16d53..55de7e7d8e 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -280,7 +280,7 @@ module ActionController #:nodoc:
if format
self.content_type ||= format.to_s
- lookup_context.freeze_formats([format.to_sym])
+ lookup_context.formats = [format.to_sym]
collector
else
head :not_acceptable
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index a677cdf15d..c5e7d4e357 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -14,7 +14,7 @@ module ActionController
def render(*args) #:nodoc:
raise ::AbstractController::DoubleRenderError if response_body
super
- self.content_type ||= Mime[formats.first].to_s
+ self.content_type ||= Mime[lookup_context.rendered_format].to_s
response_body
end
diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb
index 4ad64bff20..ccda01ed44 100644
--- a/actionpack/lib/action_controller/metal/responder.rb
+++ b/actionpack/lib/action_controller/metal/responder.rb
@@ -53,7 +53,7 @@ module ActionController #:nodoc:
# end
# end
#
- # The same happens for PUT and DELETE requests.
+ # The same happens for PATCH/PUT and DELETE requests.
#
# === Nested resources
#
@@ -116,8 +116,9 @@ module ActionController #:nodoc:
class Responder
attr_reader :controller, :request, :format, :resource, :resources, :options
- ACTIONS_FOR_VERBS = {
+ DEFAULT_ACTIONS_FOR_VERBS = {
:post => :new,
+ :patch => :edit,
:put => :edit
}
@@ -132,7 +133,7 @@ module ActionController #:nodoc:
end
delegate :head, :render, :redirect_to, :to => :controller
- delegate :get?, :post?, :put?, :delete?, :to => :request
+ delegate :get?, :post?, :patch?, :put?, :delete?, :to => :request
# Undefine :to_json and :to_yaml since it's defined on Object
undef_method(:to_json) if method_defined?(:to_json)
@@ -259,15 +260,15 @@ module ActionController #:nodoc:
resource.respond_to?(:errors) && !resource.errors.empty?
end
- # By default, render the <code>:edit</code> action for HTML requests with failure, unless
- # the verb is POST.
+ # By default, render the <code>:edit</code> action for HTML requests with errors, unless
+ # the verb was POST.
#
def default_action
- @action ||= ACTIONS_FOR_VERBS[request.request_method_symbol]
+ @action ||= DEFAULT_ACTIONS_FOR_VERBS[request.request_method_symbol]
end
def resource_errors
- respond_to?("#{format}_resource_errors") ? send("#{format}_resource_errors") : resource.errors
+ respond_to?("#{format}_resource_errors", true) ? send("#{format}_resource_errors") : resource.errors
end
def json_resource_errors
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 1e226fc336..3509e74d5e 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -225,7 +225,7 @@ module ActionController
# == Basic example
#
# Functional tests are written as follows:
- # 1. First, one uses the +get+, +post+, +put+, +delete+ or +head+ method to simulate
+ # 1. First, one uses the +get+, +post+, +patch+, +put+, +delete+ or +head+ method to simulate
# an HTTP request.
# 2. Then, one asserts whether the current state is as expected. "State" can be anything:
# the controller's HTTP response, the database contents, etc.
@@ -392,6 +392,11 @@ module ActionController
process(action, "POST", *args)
end
+ # Executes a request simulating PATCH HTTP method and set/volley the response
+ def patch(action, *args)
+ process(action, "PATCH", *args)
+ end
+
# Executes a request simulating PUT HTTP method and set/volley the response
def put(action, *args)
process(action, "PUT", *args)
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 0a0ebe7fad..de014a9c00 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -97,6 +97,12 @@ module ActionDispatch
HTTP_METHOD_LOOKUP[request_method] == :post
end
+ # Is this a PATCH request?
+ # Equivalent to <tt>request.request_method == :patch</tt>.
+ def patch?
+ HTTP_METHOD_LOOKUP[request_method] == :patch
+ end
+
# Is this a PUT request?
# Equivalent to <tt>request.request_method_symbol == :put</tt>.
def put?
diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb
index 8c0f4052ec..338b116940 100644
--- a/actionpack/lib/action_dispatch/middleware/callbacks.rb
+++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb
@@ -5,7 +5,7 @@ module ActionDispatch
class Callbacks
include ActiveSupport::Callbacks
- define_callbacks :call, :rescuable => true
+ define_callbacks :call
class << self
delegate :to_prepare, :to_cleanup, :to => "ActionDispatch::Reloader"
@@ -24,9 +24,15 @@ module ActionDispatch
end
def call(env)
- run_callbacks :call do
- @app.call(env)
+ error = nil
+ result = run_callbacks :call do
+ begin
+ @app.call(env)
+ rescue => error
+ end
end
+ raise error if error
+ result
end
end
end
diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb
index 35f901c575..4135f3c142 100644
--- a/actionpack/lib/action_dispatch/railtie.rb
+++ b/actionpack/lib/action_dispatch/railtie.rb
@@ -23,6 +23,7 @@ module ActionDispatch
ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
+ ActionDispatch::Routing::Mapper.default_method_for_update = app.config.default_method_for_update
ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses)
ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates)
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 107fe80d1f..38a0270151 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -182,10 +182,13 @@ module ActionDispatch
#
# == HTTP Methods
#
- # Using the <tt>:via</tt> option when specifying a route allows you to restrict it to a specific HTTP method.
- # Possible values are <tt>:post</tt>, <tt>:get</tt>, <tt>:put</tt>, <tt>:delete</tt> and <tt>:any</tt>.
- # If your route needs to respond to more than one method you can use an array, e.g. <tt>[ :get, :post ]</tt>.
- # The default value is <tt>:any</tt> which means that the route will respond to any of the HTTP methods.
+ # Using the <tt>:via</tt> option when specifying a route allows you to
+ # restrict it to a specific HTTP method. Possible values are <tt>:post</tt>,
+ # <tt>:get</tt>, <tt>:patch</tt>, <tt>:put</tt>, <tt>:delete</tt> and
+ # <tt>:any</tt>. If your route needs to respond to more than one method you
+ # can use an array, e.g. <tt>[ :get, :post ]</tt>. The default value is
+ # <tt>:any</tt> which means that the route will respond to any of the HTTP
+ # methods.
#
# Examples:
#
@@ -198,7 +201,7 @@ module ActionDispatch
# === HTTP helper methods
#
# An alternative method of specifying which HTTP method a route should respond to is to use the helper
- # methods <tt>get</tt>, <tt>post</tt>, <tt>put</tt> and <tt>delete</tt>.
+ # methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>.
#
# Examples:
#
@@ -283,6 +286,6 @@ module ActionDispatch
autoload :PolymorphicRoutes, 'action_dispatch/routing/polymorphic_routes'
SEPARATORS = %w( / . ? ) #:nodoc:
- HTTP_METHODS = [:get, :head, :post, :put, :delete, :options] #:nodoc:
+ HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options] #:nodoc:
end
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index cf9c0d7b6a..f66d28bf83 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -7,6 +7,8 @@ require 'action_dispatch/routing/redirection'
module ActionDispatch
module Routing
class Mapper
+ cattr_accessor(:default_method_for_update) {:put}
+
class Constraints #:nodoc:
def self.new(app, constraints, request = Rack::Request)
if constraints.any?
@@ -465,7 +467,7 @@ module ActionDispatch
#
# Example:
#
- # get 'bacon', :to => 'food#bacon'
+ # get 'bacon', :to => 'food#bacon'
def get(*args, &block)
map_method(:get, args, &block)
end
@@ -475,17 +477,27 @@ module ActionDispatch
#
# Example:
#
- # post 'bacon', :to => 'food#bacon'
+ # post 'bacon', :to => 'food#bacon'
def post(*args, &block)
map_method(:post, args, &block)
end
+ # Define a route that only recognizes HTTP PATCH.
+ # For supported arguments, see <tt>Base#match</tt>.
+ #
+ # Example:
+ #
+ # patch 'bacon', :to => 'food#bacon'
+ def patch(*args, &block)
+ map_method(:patch, args, &block)
+ end
+
# Define a route that only recognizes HTTP PUT.
# For supported arguments, see <tt>Base#match</tt>.
#
# Example:
#
- # put 'bacon', :to => 'food#bacon'
+ # put 'bacon', :to => 'food#bacon'
def put(*args, &block)
map_method(:put, args, &block)
end
@@ -495,7 +507,7 @@ module ActionDispatch
#
# Example:
#
- # delete 'broccoli', :to => 'food#broccoli'
+ # delete 'broccoli', :to => 'food#broccoli'
def delete(*args, &block)
map_method(:delete, args, &block)
end
@@ -522,13 +534,13 @@ module ActionDispatch
# This will create a number of routes for each of the posts and comments
# controller. For <tt>Admin::PostsController</tt>, Rails will create:
#
- # GET /admin/posts
- # GET /admin/posts/new
- # POST /admin/posts
- # GET /admin/posts/1
- # GET /admin/posts/1/edit
- # PUT /admin/posts/1
- # DELETE /admin/posts/1
+ # GET /admin/posts
+ # GET /admin/posts/new
+ # POST /admin/posts
+ # GET /admin/posts/1
+ # GET /admin/posts/1/edit
+ # PUT/PATCH /admin/posts/1
+ # DELETE /admin/posts/1
#
# If you want to route /posts (without the prefix /admin) to
# <tt>Admin::PostsController</tt>, you could use
@@ -556,13 +568,13 @@ module ActionDispatch
# not use scope. In the last case, the following paths map to
# +PostsController+:
#
- # GET /admin/posts
- # GET /admin/posts/new
- # POST /admin/posts
- # GET /admin/posts/1
- # GET /admin/posts/1/edit
- # PUT /admin/posts/1
- # DELETE /admin/posts/1
+ # GET /admin/posts
+ # GET /admin/posts/new
+ # POST /admin/posts
+ # GET /admin/posts/1
+ # GET /admin/posts/1/edit
+ # PUT/PATCH /admin/posts/1
+ # DELETE /admin/posts/1
module Scoping
# Scopes a set of routes to the given default options.
#
@@ -651,13 +663,13 @@ module ActionDispatch
#
# This generates the following routes:
#
- # admin_posts GET /admin/posts(.:format) admin/posts#index
- # admin_posts POST /admin/posts(.:format) admin/posts#create
- # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
- # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
- # admin_post GET /admin/posts/:id(.:format) admin/posts#show
- # admin_post PUT /admin/posts/:id(.:format) admin/posts#update
- # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
+ # admin_posts GET /admin/posts(.:format) admin/posts#index
+ # admin_posts POST /admin/posts(.:format) admin/posts#create
+ # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
+ # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
+ # admin_post GET /admin/posts/:id(.:format) admin/posts#show
+ # admin_post PUT/PATCH /admin/posts/:id(.:format) admin/posts#update
+ # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
#
# === Options
#
@@ -972,12 +984,12 @@ module ActionDispatch
# the +GeoCoders+ controller (note that the controller is named after
# the plural):
#
- # GET /geocoder/new
- # POST /geocoder
- # GET /geocoder
- # GET /geocoder/edit
- # PUT /geocoder
- # DELETE /geocoder
+ # GET /geocoder/new
+ # POST /geocoder
+ # GET /geocoder
+ # GET /geocoder/edit
+ # PUT/PATCH /geocoder
+ # DELETE /geocoder
#
# === Options
# Takes same options as +resources+.
@@ -1002,7 +1014,9 @@ module ActionDispatch
member do
get :edit if parent_resource.actions.include?(:edit)
get :show if parent_resource.actions.include?(:show)
- put :update if parent_resource.actions.include?(:update)
+ if parent_resource.actions.include?(:update)
+ send default_method_for_update, :update
+ end
delete :destroy if parent_resource.actions.include?(:destroy)
end
end
@@ -1020,13 +1034,13 @@ module ActionDispatch
# creates seven different routes in your application, all mapping to
# the +Photos+ controller:
#
- # GET /photos
- # GET /photos/new
- # POST /photos
- # GET /photos/:id
- # GET /photos/:id/edit
- # PUT /photos/:id
- # DELETE /photos/:id
+ # GET /photos
+ # GET /photos/new
+ # POST /photos
+ # GET /photos/:id
+ # GET /photos/:id/edit
+ # PUT/PATCH /photos/:id
+ # DELETE /photos/:id
#
# Resources can also be nested infinitely by using this block syntax:
#
@@ -1036,13 +1050,13 @@ module ActionDispatch
#
# This generates the following comments routes:
#
- # GET /photos/:photo_id/comments
- # GET /photos/:photo_id/comments/new
- # POST /photos/:photo_id/comments
- # GET /photos/:photo_id/comments/:id
- # GET /photos/:photo_id/comments/:id/edit
- # PUT /photos/:photo_id/comments/:id
- # DELETE /photos/:photo_id/comments/:id
+ # GET /photos/:photo_id/comments
+ # GET /photos/:photo_id/comments/new
+ # POST /photos/:photo_id/comments
+ # GET /photos/:photo_id/comments/:id
+ # GET /photos/:photo_id/comments/:id/edit
+ # PUT/PATCH /photos/:photo_id/comments/:id
+ # DELETE /photos/:photo_id/comments/:id
#
# === Options
# Takes same options as <tt>Base#match</tt> as well as:
@@ -1104,13 +1118,13 @@ module ActionDispatch
#
# The +comments+ resource here will have the following routes generated for it:
#
- # post_comments GET /posts/:post_id/comments(.:format)
- # post_comments POST /posts/:post_id/comments(.:format)
- # new_post_comment GET /posts/:post_id/comments/new(.:format)
- # edit_comment GET /sekret/comments/:id/edit(.:format)
- # comment GET /sekret/comments/:id(.:format)
- # comment PUT /sekret/comments/:id(.:format)
- # comment DELETE /sekret/comments/:id(.:format)
+ # post_comments GET /posts/:post_id/comments(.:format)
+ # post_comments POST /posts/:post_id/comments(.:format)
+ # new_post_comment GET /posts/:post_id/comments/new(.:format)
+ # edit_comment GET /sekret/comments/:id/edit(.:format)
+ # comment GET /sekret/comments/:id(.:format)
+ # comment PUT/PATCH /sekret/comments/:id(.:format)
+ # comment DELETE /sekret/comments/:id(.:format)
#
# === Examples
#
@@ -1138,10 +1152,13 @@ module ActionDispatch
get :new
end if parent_resource.actions.include?(:new)
+ # TODO: Only accept patch or put depending on config
member do
get :edit if parent_resource.actions.include?(:edit)
get :show if parent_resource.actions.include?(:show)
- put :update if parent_resource.actions.include?(:update)
+ if parent_resource.actions.include?(:update)
+ send default_method_for_update, :update
+ end
delete :destroy if parent_resource.actions.include?(:destroy)
end
end
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 08b7ff49c2..62b3a344f8 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -26,8 +26,8 @@ module ActionDispatch
# object's <tt>@response</tt> instance variable will point to the same
# response object.
#
- # You can also perform POST, PUT, DELETE, and HEAD requests with +#post+,
- # +#put+, +#delete+, and +#head+.
+ # You can also perform POST, PATCH, PUT, DELETE, and HEAD requests with
+ # +#post+, +#patch+, +#put+, +#delete+, and +#head+.
def get(path, parameters = nil, headers = nil)
process :get, path, parameters, headers
end
@@ -38,6 +38,12 @@ module ActionDispatch
process :post, path, parameters, headers
end
+ # Performs a PATCH request with the given parameters. See +#get+ for more
+ # details.
+ def patch(path, parameters = nil, headers = nil)
+ process :patch, path, parameters, headers
+ end
+
# Performs a PUT request with the given parameters. See +#get+ for more
# details.
def put(path, parameters = nil, headers = nil)
@@ -56,13 +62,19 @@ module ActionDispatch
process :head, path, parameters, headers
end
+ # Performs a OPTIONS request with the given parameters. See +#get+ for
+ # more details.
+ def options(path, parameters = nil, headers = nil)
+ process :options, path, parameters, headers
+ end
+
# Performs an XMLHttpRequest request with the given parameters, mirroring
# a request from the Prototype library.
#
- # The request_method is +:get+, +:post+, +:put+, +:delete+ or +:head+; the
- # parameters are +nil+, a hash, or a url-encoded or multipart string;
- # the headers are a hash. Keys are automatically upcased and prefixed
- # with 'HTTP_' if not already.
+ # The request_method is +:get+, +:post+, +:patch+, +:put+, +:delete+ or
+ # +:head+; the parameters are +nil+, a hash, or a url-encoded or multipart
+ # string; the headers are a hash. Keys are automatically upcased and
+ # prefixed with 'HTTP_' if not already.
def xml_http_request(request_method, path, parameters = nil, headers = nil)
headers ||= {}
headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
@@ -102,6 +114,12 @@ module ActionDispatch
request_via_redirect(:post, path, parameters, headers)
end
+ # Performs a PATCH request, following any subsequent redirect.
+ # See +request_via_redirect+ for more information.
+ def patch_via_redirect(path, parameters = nil, headers = nil)
+ request_via_redirect(:patch, path, parameters, headers)
+ end
+
# Performs a PUT request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def put_via_redirect(path, parameters = nil, headers = nil)
@@ -312,7 +330,7 @@ module ActionDispatch
@integration_session = Integration::Session.new(app)
end
- %w(get post put head delete cookies assigns
+ %w(get post put patch head delete options cookies assigns
xml_http_request xhr get_via_redirect post_via_redirect).each do |method|
define_method(method) do |*args|
reset! unless integration_session
diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb
index b08ff41950..3a6d081721 100644
--- a/actionpack/lib/action_dispatch/testing/test_process.rb
+++ b/actionpack/lib/action_dispatch/testing/test_process.rb
@@ -5,7 +5,8 @@ require 'active_support/core_ext/hash/indifferent_access'
module ActionDispatch
module TestProcess
def assigns(key = nil)
- assigns = @controller.view_assigns.with_indifferent_access
+ assigns = {}.with_indifferent_access
+ @controller.view_assigns.each {|k, v| assigns.regular_writer(k, v)}
key.nil? ? assigns : assigns[key]
end
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 23329d7f35..4641f10dc8 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -132,6 +132,8 @@ module ActionView #:nodoc:
class Base
include Helpers, ::ERB::Util, Context
+ cattr_accessor(:default_method_for_update) {:put}
+
# Specify the proc used to decorate input tags that refer to attributes with errors.
cattr_accessor :field_error_proc
@@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe }
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 44e24fecd1..33d509d968 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -250,7 +250,7 @@ module ActionView
#
# You can force the form to use the full array of HTTP verbs by setting
#
- # :method => (:get|:post|:put|:delete)
+ # :method => (:get|:post|:patch|:put|:delete)
#
# in the options hash. If the verb is not GET or POST, which are natively supported by HTML forms, the
# form will be set to POST and a hidden input called _method will carry the intended verb for the server
@@ -385,7 +385,7 @@ module ActionView
object = convert_to_model(object)
as = options[:as]
- action, method = object.respond_to?(:persisted?) && object.persisted? ? [:edit, :put] : [:new, :post]
+ action, method = object.respond_to?(:persisted?) && object.persisted? ? [:edit, ActionView::Base.default_method_for_update] : [:new, :post]
options[:html].reverse_merge!(
:class => as ? "#{action}_#{as}" : dom_class(object, action),
:id => as ? "#{action}_#{as}" : [options[:namespace], dom_id(object, action)].compact.join("_").presence,
@@ -1102,14 +1102,14 @@ module ActionView
# <% end %>
#
# In the example above, if @post is a new record, it will use "Create Post" as
- # submit button label, otherwise, it uses "Update Post".
+ # button label, otherwise, it uses "Update Post".
#
- # Those labels can be customized using I18n, under the helpers.submit key and accept
- # the %{model} as translation interpolation:
+ # Those labels can be customized using I18n, under the helpers.submit key
+ # (the same as submit helper) and accept the %{model} as translation interpolation:
#
# en:
# helpers:
- # button:
+ # submit:
# create: "Create a %{model}"
# update: "Confirm changes to %{model}"
#
@@ -1117,7 +1117,7 @@ module ActionView
#
# en:
# helpers:
- # button:
+ # submit:
# post:
# create: "Add %{model}"
#
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index bc03a1cf83..abb548c276 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -330,9 +330,12 @@ module ActionView
container.map do |element|
html_attributes = option_html_attributes(element)
text, value = option_text_and_value(element).map { |item| item.to_s }
- selected_attribute = ' selected="selected"' if option_value_selected?(value, selected)
- disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled)
- %(<option value="#{ERB::Util.html_escape(value)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{ERB::Util.html_escape(text)}</option>)
+
+ html_attributes[:selected] = 'selected' if option_value_selected?(value, selected)
+ html_attributes[:disabled] = 'disabled' if disabled && option_value_selected?(value, disabled)
+ html_attributes[:value] = value
+
+ content_tag(:option, text, html_attributes)
end.join("\n").html_safe
end
@@ -472,16 +475,16 @@ module ActionView
# <b>Note:</b> Only the <tt><optgroup></tt> and <tt><option></tt> tags are returned, so you still have to
# wrap the output in an appropriate <tt><select></tt> tag.
def grouped_options_for_select(grouped_options, selected_key = nil, prompt = nil)
- body = ''
- body << content_tag(:option, prompt, { :value => "" }, true) if prompt
+ body = "".html_safe
+ body.safe_concat content_tag(:option, prompt, :value => "") if prompt
grouped_options = grouped_options.sort if grouped_options.is_a?(Hash)
- grouped_options.each do |group|
- body << content_tag(:optgroup, options_for_select(group[1], selected_key), :label => group[0])
+ grouped_options.each do |label, container|
+ body.safe_concat content_tag(:optgroup, options_for_select(container, selected_key), :label => label)
end
- body.html_safe
+ body
end
# Returns a string of option tags for pretty much any time zone in the
@@ -649,11 +652,9 @@ module ActionView
private
def option_html_attributes(element)
- return "" unless Array === element
+ return {} unless Array === element
- element.select { |e| Hash === e }.reduce({}, :merge).map do |k, v|
- " #{k}=\"#{ERB::Util.html_escape(v.to_s)}\""
- end.join
+ Hash[element.select { |e| Hash === e }.reduce({}, :merge).map { |k, v| [k, ERB::Util.html_escape(v.to_s)] }]
end
def option_text_and_value(option)
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 53fd189c39..2cf1c9055c 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -313,7 +313,7 @@ module ActionView
options["cols"], options["rows"] = size.split("x") if size.respond_to?(:split)
end
- escape = options.key?("escape") ? options.delete("escape") : true
+ escape = options.delete("escape") { true }
content = ERB::Util.html_escape(content) if escape
content_tag :textarea, content.to_s.html_safe, { "name" => name, "id" => sanitize_to_id(name) }.update(options)
diff --git a/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb b/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb
index 507466a57a..507ba8835f 100644
--- a/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb
+++ b/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb
@@ -14,8 +14,13 @@ module ActionView
end
def render
+ option_tags_options = {
+ :selected => @options.fetch(:selected) { value(@object) },
+ :disabled => @options[:disabled]
+ }
+
select_content_tag(
- option_groups_from_collection_for_select(@collection, @group_method, @group_label_method, @option_key_method, @option_value_method, value(@object)), @options, @html_options
+ option_groups_from_collection_for_select(@collection, @group_method, @group_label_method, @option_key_method, @option_value_method, option_tags_options), @options, @html_options
)
end
end
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index b5fc882e31..93f476926c 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -146,12 +146,12 @@ module ActionView
# create an HTML form and immediately submit the form for processing using
# the HTTP verb specified. Useful for having links perform a POST operation
# in dangerous actions like deleting a record (which search bots can follow
- # while spidering your site). Supported verbs are <tt>:post</tt>, <tt>:delete</tt> and <tt>:put</tt>.
+ # while spidering your site). Supported verbs are <tt>:post</tt>, <tt>:delete</tt>, <tt>:patch</tt>, and <tt>:put</tt>.
# Note that if the user has JavaScript disabled, the request will fall back
# to using GET. If <tt>:href => '#'</tt> is used and the user has JavaScript
# disabled clicking the link will have no effect. If you are relying on the
# POST behavior, you should check for it in your controller's action by using
- # the request object's methods for <tt>post?</tt>, <tt>delete?</tt> or <tt>put?</tt>.
+ # the request object's methods for <tt>post?</tt>, <tt>delete?</tt>, <tt>:patch</tt>, or <tt>put?</tt>.
# * <tt>:remote => true</tt> - This will allow the unobtrusive JavaScript
# driver to make an Ajax request to the URL in question instead of following
# the link. The drivers each provide mechanisms for listening for the
@@ -272,7 +272,7 @@ module ActionView
#
# There are a few special +html_options+:
# * <tt>:method</tt> - Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>,
- # <tt>:delete</tt> and <tt>:put</tt>. By default it will be <tt>:post</tt>.
+ # <tt>:delete</tt>, <tt>:patch</tt>, and <tt>:put</tt>. By default it will be <tt>:post</tt>.
# * <tt>:disabled</tt> - If set to true, it will generate a disabled button.
# * <tt>:confirm</tt> - This will use the unobtrusive JavaScript driver to
# prompt with the question specified. If the user accepts, the link is
@@ -329,7 +329,7 @@ module ActionView
remote = html_options.delete('remote')
method = html_options.delete('method').to_s
- method_tag = %w{put delete}.include?(method) ? method_tag(method) : ""
+ method_tag = %w{put patch delete}.include?(method) ? method_tag(method) : ""
form_method = method == 'get' ? 'get' : 'post'
form_options = html_options.delete('form') || {}
diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb
index 90c4a2759a..b7945a23be 100644
--- a/actionpack/lib/action_view/lookup_context.rb
+++ b/actionpack/lib/action_view/lookup_context.rb
@@ -9,7 +9,7 @@ module ActionView
# generate a key, given to view paths, used in the resolver cache lookup. Since
# this key is generated just once during the request, it speeds up all cache accesses.
class LookupContext #:nodoc:
- attr_accessor :prefixes
+ attr_accessor :prefixes, :rendered_format
mattr_accessor :fallbacks
@@fallbacks = FallbackFileSystemResolver.instances
@@ -170,23 +170,15 @@ module ActionView
def initialize(view_paths, details = {}, prefixes = [])
@details, @details_key = {}, nil
- @frozen_formats, @skip_default_locale = false, false
+ @skip_default_locale = false
@cache = true
@prefixes = prefixes
+ @rendered_format = nil
self.view_paths = view_paths
initialize_details(details)
end
- # Freeze the current formats in the lookup context. By freezing them, you
- # that next template lookups are not going to modify the formats. The con
- # use this, to ensure that formats won't be further modified (as it does
- def freeze_formats(formats, unless_frozen=false) #:nodoc:
- return if unless_frozen && @frozen_formats
- self.formats = formats
- @frozen_formats = true
- end
-
# Override formats= to expand ["*/*"] values and automatically
# add :html as fallback to :js.
def formats=(values)
diff --git a/actionpack/lib/action_view/railtie.rb b/actionpack/lib/action_view/railtie.rb
index 43371a1c49..2296db9092 100644
--- a/actionpack/lib/action_view/railtie.rb
+++ b/actionpack/lib/action_view/railtie.rb
@@ -34,6 +34,7 @@ module ActionView
initializer "action_view.set_configs" do |app|
ActiveSupport.on_load(:action_view) do
+ self.default_method_for_update = app.config.default_method_for_update
app.config.action_view.each do |k,v|
send "#{k}=", v
end
diff --git a/actionpack/lib/action_view/renderer/abstract_renderer.rb b/actionpack/lib/action_view/renderer/abstract_renderer.rb
index a588abcee3..52473cd222 100644
--- a/actionpack/lib/action_view/renderer/abstract_renderer.rb
+++ b/actionpack/lib/action_view/renderer/abstract_renderer.rb
@@ -1,7 +1,7 @@
module ActionView
class AbstractRenderer #:nodoc:
delegate :find_template, :template_exists?, :with_fallbacks, :update_details,
- :with_layout_format, :formats, :freeze_formats, :to => :@lookup_context
+ :with_layout_format, :formats, :to => :@lookup_context
def initialize(lookup_context)
@lookup_context = lookup_context
diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb
index f3abc6d533..20f75fba45 100644
--- a/actionpack/lib/action_view/renderer/template_renderer.rb
+++ b/actionpack/lib/action_view/renderer/template_renderer.rb
@@ -6,7 +6,8 @@ module ActionView
@view = context
@details = extract_details(options)
template = determine_template(options)
- freeze_formats(template.formats, true)
+ @lookup_context.rendered_format ||= template.formats.first
+ @lookup_context.formats = template.formats
render_template(template, options[:layout], options[:locals])
end
diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb
index 67978ada7e..4e22bec6cc 100644
--- a/actionpack/lib/action_view/template/handlers.rb
+++ b/actionpack/lib/action_view/template/handlers.rb
@@ -23,6 +23,7 @@ module ActionView #:nodoc:
# and should return the rendered template as a String.
def register_template_handler(extension, handler)
@@template_handlers[extension.to_sym] = handler
+ @@template_extensions = nil
end
def template_handler_extensions
diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb
index 323df67c97..19b9112afd 100644
--- a/actionpack/lib/action_view/template/handlers/erb.rb
+++ b/actionpack/lib/action_view/template/handlers/erb.rb
@@ -44,10 +44,6 @@ module ActionView
class_attribute :erb_trim_mode
self.erb_trim_mode = '-'
- # Default format used by ERB.
- class_attribute :default_format
- self.default_format = Mime::HTML
-
# Default implementation used.
class_attribute :erb_implementation
self.erb_implementation = Erubis
diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb
index 976ae5a76d..839ec7635f 100644
--- a/actionpack/lib/sprockets/helpers/rails_helper.rb
+++ b/actionpack/lib/sprockets/helpers/rails_helper.rb
@@ -19,9 +19,9 @@ module Sprockets
def javascript_include_tag(*sources)
options = sources.extract_options!
- debug = options.key?(:debug) ? options.delete(:debug) : debug_assets?
- body = options.key?(:body) ? options.delete(:body) : false
- digest = options.key?(:digest) ? options.delete(:digest) : digest_assets?
+ debug = options.delete(:debug) { debug_assets? }
+ body = options.delete(:body) { false }
+ digest = options.delete(:digest) { digest_assets? }
sources.collect do |source|
if debug && asset = asset_paths.asset_for(source, 'js')
@@ -36,9 +36,9 @@ module Sprockets
def stylesheet_link_tag(*sources)
options = sources.extract_options!
- debug = options.key?(:debug) ? options.delete(:debug) : debug_assets?
- body = options.key?(:body) ? options.delete(:body) : false
- digest = options.key?(:digest) ? options.delete(:digest) : digest_assets?
+ debug = options.delete(:debug) { debug_assets? }
+ body = options.delete(:body) { false }
+ digest = options.delete(:digest) { digest_assets? }
sources.collect do |source|
if debug && asset = asset_paths.asset_for(source, 'css')