aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/url_for.rb6
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb29
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb5
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb21
-rw-r--r--actionpack/lib/action_controller/test_case.rb7
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb26
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb56
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb51
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb9
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb8
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/selector.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/test_process.rb2
-rw-r--r--actionpack/lib/action_view.rb1
-rw-r--r--actionpack/lib/action_view/base.rb10
-rw-r--r--actionpack/lib/action_view/helpers/atom_feed_helper.rb8
-rw-r--r--actionpack/lib/action_view/helpers/cache_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb8
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb143
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb62
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb12
-rw-r--r--actionpack/lib/action_view/helpers/translation_helper.rb8
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb2
-rw-r--r--actionpack/lib/action_view/path_set.rb2
-rw-r--r--actionpack/lib/action_view/template.rb10
-rw-r--r--actionpack/lib/action_view/template/error.rb2
-rw-r--r--actionpack/lib/action_view/template/resolver.rb62
-rw-r--r--actionpack/lib/sprockets/railtie.rb6
30 files changed, 331 insertions, 241 deletions
diff --git a/actionpack/lib/abstract_controller/url_for.rb b/actionpack/lib/abstract_controller/url_for.rb
index e5d5bef6b4..e4261068d8 100644
--- a/actionpack/lib/abstract_controller/url_for.rb
+++ b/actionpack/lib/abstract_controller/url_for.rb
@@ -1,3 +1,9 @@
+# Includes +url_for+ into the host class (e.g. an abstract controller or mailer). The class
+# has to provide a +RouteSet+ by implementing the <tt>_routes</tt> methods. Otherwise, an
+# exception will be raised.
+#
+# Note that this module is completely decoupled from HTTP - the only requirement is a valid
+# <tt>_routes</tt> implementation.
module AbstractController
module UrlFor
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 881af74147..93241fc056 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -2,6 +2,7 @@ require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/array/wrap'
+require 'active_support/core_ext/module/anonymous'
require 'action_dispatch/http/mime_types'
module ActionController
@@ -136,15 +137,25 @@ module ActionController
# this could be done by trying to find the defined model that has the
# same singularize name as the controller. For example, +UsersController+
# will try to find if the +User+ model exists.
- def _default_wrap_model
+ #
+ # This method also does namespace lookup. Foo::Bar::UsersController will
+ # try to find Foo::Bar::User, Foo::User and finally User.
+ def _default_wrap_model #:nodoc:
+ return nil if self.anonymous?
+
model_name = self.name.sub(/Controller$/, '').singularize
begin
model_klass = model_name.constantize
- rescue NameError => e
- unscoped_model_name = model_name.split("::", 2).last
- break if unscoped_model_name == model_name
- model_name = unscoped_model_name
+ rescue NameError, ArgumentError => e
+ if e.message =~ /is not missing constant|uninitialized constant #{model_name}/
+ namespaces = model_name.split("::")
+ namespaces.delete_at(-2)
+ break if namespaces.last == model_name
+ model_name = namespaces.join("::")
+ else
+ raise
+ end
end until model_klass
model_klass
@@ -155,12 +166,12 @@ module ActionController
unless options[:only] || options[:except]
model ||= _default_wrap_model
- if model.respond_to?(:column_names)
- options[:only] = model.column_names
+ if model.respond_to?(:attribute_names) && model.attribute_names.present?
+ options[:only] = model.attribute_names
end
end
- unless options[:name]
+ unless options[:name] || self.anonymous?
model ||= _default_wrap_model
options[:name] = model ? model.to_s.demodulize.underscore :
controller_name.singularize
@@ -218,7 +229,7 @@ module ActionController
# Checks if we should perform parameters wrapping.
def _wrapper_enabled?
ref = request.content_mime_type.try(:ref)
- _wrapper_formats.include?(ref) && !request.request_parameters[_wrapper_key]
+ _wrapper_formats.include?(ref) && _wrapper_key && !request.request_parameters[_wrapper_key]
end
end
end
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 1cd93a188c..13044a7450 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -73,7 +73,10 @@ module ActionController #:nodoc:
protected
# The actual before_filter that is used. Modify this to change how you handle unverified requests.
def verify_authenticity_token
- verified_request? || handle_unverified_request
+ unless verified_request?
+ logger.debug "WARNING: Can't verify CSRF token authenticity" if logger
+ handle_unverified_request
+ end
end
def handle_unverified_request
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 6fc0cf1fb8..08132b1900 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -1,3 +1,24 @@
+# Includes +url_for+ into the host class. The class has to provide a +RouteSet+ by implementing
+# the <tt>_routes</tt> method. Otherwise, an exception will be raised.
+#
+# In addition to <tt>AbstractController::UrlFor</tt>, this module accesses the HTTP layer to define
+# url options like the +host+. In order to do so, this module requires the host class
+# to implement +env+ and +request+, which need to be a Rack-compatible.
+#
+# Example:
+#
+# class RootUrl
+# include ActionController::UrlFor
+# include Rails.application.routes.url_helpers
+#
+# delegate :env, :request, :to => :controller
+#
+# def initialize(controller)
+# @controller = controller
+# @url = root_path # named route from the application.
+# end
+# end
+# =>
module ActionController
module UrlFor
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 0085f542aa..89ff5ba174 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -2,6 +2,7 @@ require 'rack/session/abstract/id'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/object/to_query'
require 'active_support/core_ext/class/attribute'
+require 'active_support/core_ext/module/anonymous'
module ActionController
module TemplateAssertions
@@ -413,7 +414,11 @@ module ActionController
@request.env['REQUEST_METHOD'] = http_method
parameters ||= {}
- @request.assign_parameters(@routes, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters)
+ controller_class_name = @controller.class.anonymous? ?
+ "anonymous_controller" :
+ @controller.class.name.underscore.sub(/_controller$/, '')
+
+ @request.assign_parameters(@routes, controller_class_name, action.to_s, parameters)
@request.session = ActionController::TestSession.new(session) if session
@request.session["flash"] = @request.flash.update(flash || {})
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index 4f4cb96a74..aaed0d750f 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -42,20 +42,6 @@ module ActionDispatch
attr_reader :cache_control, :etag
alias :etag? :etag
- def initialize(*)
- super
-
- @cache_control = {}
- @etag = self["ETag"]
-
- if cache_control = self["Cache-Control"]
- cache_control.split(/,\s*/).each do |segment|
- first, last = segment.split("=")
- @cache_control[first.to_sym] = last || true
- end
- end
- end
-
def last_modified
if last = headers['Last-Modified']
Time.httpdate(last)
@@ -77,6 +63,18 @@ module ActionDispatch
private
+ def prepare_cache_control!
+ @cache_control = {}
+ @etag = self["ETag"]
+
+ if cache_control = self["Cache-Control"]
+ cache_control.split(/,\s*/).each do |segment|
+ first, last = segment.split("=")
+ @cache_control[first.to_sym] = last || true
+ end
+ end
+ end
+
def handle_conditional_get!
if etag? || last_modified? || !@cache_control.empty?
set_conditional_cache_control!
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 1f4f3ac0da..3a6b1da4fd 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -56,26 +56,25 @@ module ActionDispatch # :nodoc:
cattr_accessor(:default_charset) { "utf-8" }
- module Setup
- def initialize(status = 200, header = {}, body = [])
- self.body, self.header, self.status = body, header, status
+ include Rack::Response::Helpers
+ include ActionDispatch::Http::Cache::Response
- @sending_file = false
- @blank = false
+ def initialize(status = 200, header = {}, body = [])
+ self.body, self.header, self.status = body, header, status
- if content_type = self["Content-Type"]
- type, charset = content_type.split(/;\s*charset=/)
- @content_type = Mime::Type.lookup(type)
- @charset = charset || "UTF-8"
- end
+ @sending_file = false
+ @blank = false
- yield self if block_given?
+ if content_type = self["Content-Type"]
+ type, charset = content_type.split(/;\s*charset=/)
+ @content_type = Mime::Type.lookup(type)
+ @charset = charset || "UTF-8"
end
- end
- include Rack::Response::Helpers
- include Setup
- include ActionDispatch::Http::Cache::Response
+ prepare_cache_control!
+
+ yield self if block_given?
+ end
def status=(status)
@status = Rack::Utils.status_code(status)
@@ -116,9 +115,32 @@ module ActionDispatch # :nodoc:
EMPTY = " "
+ class BodyBuster #:nodoc:
+ def initialize(response)
+ @response = response
+ @body = ""
+ end
+
+ def bust(body)
+ body.call(@response, self)
+ body.close if body.respond_to?(:close)
+ @body
+ end
+
+ def write(string)
+ @body << string.to_s
+ end
+ end
+
def body=(body)
@blank = true if body == EMPTY
+ if body.respond_to?(:call)
+ ActiveSupport::Deprecation.warn "Setting a Proc or an object that responds to call " \
+ "in response_body is no longer supported", caller
+ body = BodyBuster.new(self).bust(body)
+ end
+
# Explicitly check for strings. This is *wrong* theoretically
# but if we don't check this, the performance on string bodies
# is bad on Ruby 1.8 (because strings responds to each then).
@@ -150,6 +172,10 @@ module ActionDispatch # :nodoc:
headers['Location'] = url
end
+ def close
+ @body.close if @body.respond_to?(:close)
+ end
+
def to_a
assign_default_content_type_and_charset!
handle_conditional_get!
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index d9c07d6ca3..8487b0fc8c 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -162,7 +162,7 @@ module ActionDispatch
# Returns all the \subdomains as a string, so <tt>"dev.www"</tt> would be
# returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
- # such as 2 to catch <tt>["www"]</tt> instead of <tt>"www.rubyonrails"</tt>
+ # such as 2 to catch <tt>"www"</tt> instead of <tt>"www.rubyonrails"</tt>
# in "www.rubyonrails.co.uk".
def subdomain(tld_length = @@tld_length)
subdomains(tld_length).join(".")
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 43fd93adf6..74c090f260 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -49,8 +49,8 @@ module ActionDispatch
# You may wish to organize groups of controllers under a namespace. Most
# commonly, you might group a number of administrative controllers under
# an +admin+ namespace. You would place these controllers under the
- # app/controllers/admin directory, and you can group them together in your
- # router:
+ # <tt>app/controllers/admin</tt> directory, and you can group them together
+ # in your router:
#
# namespace "admin" do
# resources :posts, :comments
@@ -152,7 +152,7 @@ module ActionDispatch
# }
# end
#
- # Using the multiline match modifier will raise an ArgumentError.
+ # Using the multiline match modifier will raise an +ArgumentError+.
# Encoding regular expression modifiers are silently ignored. The
# match will always use the default encoding or ASCII.
#
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index a65f6e1fce..3ba6094fbb 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -335,7 +335,7 @@ module ActionDispatch
#
# [:on]
# Shorthand for wrapping routes in a specific RESTful context. Valid
- # values are :member, :collection, and :new. Only use within
+ # values are +:member+, +:collection+, and +:new+. Only use within
# <tt>resource(s)</tt> block. For example:
#
# resource :bar do
@@ -352,7 +352,7 @@ module ActionDispatch
#
# [:constraints]
# Constrains parameters with a hash of regular expressions or an
- # object that responds to #matches?
+ # object that responds to <tt>matches?</tt>
#
# match 'path/:id', :constraints => { :id => /[A-Z]\d{5}/ }
#
@@ -373,7 +373,7 @@ module ActionDispatch
# See <tt>Scoping#defaults</tt> for its scope equivalent.
#
# [:anchor]
- # Boolean to anchor a #match pattern. Default is true. When set to
+ # Boolean to anchor a <tt>match</tt> pattern. Default is true. When set to
# false, the pattern matches any request prefixed with the given path.
#
# # Matches any request starting with 'path'
@@ -517,15 +517,15 @@ module ActionDispatch
# You may wish to organize groups of controllers under a namespace.
# Most commonly, you might group a number of administrative controllers
# under an +admin+ namespace. You would place these controllers under
- # the app/controllers/admin directory, and you can group them together
- # in your router:
+ # the <tt>app/controllers/admin</tt> directory, and you can group them
+ # together in your router:
#
# namespace "admin" do
# resources :posts, :comments
# end
#
# This will create a number of routes for each of the posts and comments
- # controller. For Admin::PostsController, Rails will create:
+ # controller. For <tt>Admin::PostsController</tt>, Rails will create:
#
# GET /admin/posts
# GET /admin/posts/new
@@ -536,7 +536,7 @@ module ActionDispatch
# DELETE /admin/posts/1
#
# If you want to route /posts (without the prefix /admin) to
- # Admin::PostsController, you could use
+ # <tt>Admin::PostsController</tt>, you could use
#
# scope :module => "admin" do
# resources :posts
@@ -546,7 +546,7 @@ module ActionDispatch
#
# resources :posts, :module => "admin"
#
- # If you want to route /admin/posts to PostsController
+ # If you want to route /admin/posts to +PostsController+
# (without the Admin:: module prefix), you could use
#
# scope "/admin" do
@@ -555,11 +555,11 @@ module ActionDispatch
#
# or, for a single case
#
- # resources :posts, :path => "/admin"
+ # resources :posts, :path => "/admin/posts"
#
# 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:
+ # +PostsController+:
#
# GET /admin/posts
# GET /admin/posts/new
@@ -587,7 +587,7 @@ module ActionDispatch
#
# === Examples
#
- # # route /posts (without the prefix /admin) to Admin::PostsController
+ # # route /posts (without the prefix /admin) to <tt>Admin::PostsController</tt>
# scope :module => "admin" do
# resources :posts
# end
@@ -597,7 +597,7 @@ module ActionDispatch
# resources :posts
# end
#
- # # prefix the routing helper name: sekret_posts_path instead of posts_path
+ # # prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
# scope :as => "sekret" do
# resources :posts
# end
@@ -679,12 +679,12 @@ module ActionDispatch
# resources :posts
# end
#
- # # maps to Sekret::PostsController rather than Admin::PostsController
+ # # maps to <tt>Sekret::PostsController</tt> rather than <tt>Admin::PostsController</tt>
# namespace :admin, :module => "sekret" do
# resources :posts
# end
#
- # # generates sekret_posts_path rather than admin_posts_path
+ # # generates +sekret_posts_path+ rather than +admin_posts_path+
# namespace :admin, :as => "sekret" do
# resources :posts
# end
@@ -712,6 +712,7 @@ module ActionDispatch
# constraints(:post_id => /\d+\.\d+) do
# resources :comments
# end
+ # end
#
# === Restricting based on IP
#
@@ -846,20 +847,20 @@ module ActionDispatch
# You may wish to organize groups of controllers under a namespace. Most
# commonly, you might group a number of administrative controllers under
# an +admin+ namespace. You would place these controllers under the
- # app/controllers/admin directory, and you can group them together in your
- # router:
+ # <tt>app/controllers/admin</tt> directory, and you can group them together
+ # in your router:
#
# namespace "admin" do
# resources :posts, :comments
# end
#
- # By default the :id parameter doesn't accept dots. If you need to
- # use dots as part of the :id parameter add a constraint which
+ # By default the +:id+ parameter doesn't accept dots. If you need to
+ # use dots as part of the +:id+ parameter add a constraint which
# overrides this restriction, e.g:
#
# resources :articles, :id => /[^\/]+/
#
- # This allows any character other than a slash as part of your :id.
+ # This allows any character other than a slash as part of your +:id+.
#
module Resources
# CANONICAL_ACTIONS holds all actions that does not need a prefix or
@@ -975,7 +976,7 @@ module ActionDispatch
# resource :geocoder
#
# creates six different routes in your application, all mapping to
- # the GeoCoders controller (note that the controller is named after
+ # the +GeoCoders+ controller (note that the controller is named after
# the plural):
#
# GET /geocoder/new
@@ -1024,7 +1025,7 @@ module ActionDispatch
# resources :photos
#
# creates seven different routes in your application, all mapping to
- # the Photos controller:
+ # the +Photos+ controller:
#
# GET /photos/new
# POST /photos
@@ -1107,11 +1108,11 @@ module ActionDispatch
#
# === Examples
#
- # # routes call Admin::PostsController
+ # # routes call <tt>Admin::PostsController</tt>
# resources :posts, :module => "admin"
#
# # resource actions are at /admin/posts.
- # resources :posts, :path => "admin"
+ # resources :posts, :path => "admin/posts"
def resources(*resources, &block)
options = resources.extract_options!
@@ -1151,7 +1152,7 @@ module ActionDispatch
# end
#
# This will enable Rails to recognize paths such as <tt>/photos/search</tt>
- # with GET, and route to the search action of PhotosController. It will also
+ # with GET, and route to the search action of +PhotosController+. It will also
# create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
# route helpers.
def collection
@@ -1175,7 +1176,7 @@ module ActionDispatch
# end
#
# This will recognize <tt>/photos/1/preview</tt> with GET, and route to the
- # preview action of PhotosController. It will also create the
+ # preview action of +PhotosController+. It will also create the
# <tt>preview_photo_url</tt> and <tt>preview_photo_path</tt> helpers.
def member
unless resource_scope?
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 97e8ccc9a5..5097f6732d 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -224,6 +224,7 @@ module ActionDispatch
self.valid_conditions.push(:controller, :action)
@append = []
+ @prepend = []
@disable_clear_and_finalize = false
clear!
end
@@ -232,7 +233,6 @@ module ActionDispatch
clear! unless @disable_clear_and_finalize
eval_block(block)
finalize! unless @disable_clear_and_finalize
-
nil
end
@@ -240,6 +240,10 @@ module ActionDispatch
@append << block
end
+ def prepend(&block)
+ @prepend << block
+ end
+
def eval_block(block)
if block.arity == 1
raise "You are using the old router DSL which has been removed in Rails 3.1. " <<
@@ -262,8 +266,6 @@ module ActionDispatch
end
def clear!
- # Clear the controller cache so we may discover new ones
- @controller_constraints = nil
@finalized = false
routes.clear
named_routes.clear
@@ -271,6 +273,7 @@ module ActionDispatch
:parameters_key => PARAMETERS_KEY,
:request_class => request_class
)
+ @prepend.each { |blk| eval_block(blk) }
end
def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false)
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index d4db78a25a..5893f86798 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -131,10 +131,10 @@ module ActionDispatch
#
# Examples:
#
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :port=>'8080' # => 'http://somehost.org:8080/tasks/testing'
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok'
- # url_for :controller => 'tasks', :action => 'testing', :trailing_slash=>true # => 'http://somehost.org/tasks/testing/'
- # url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33'
+ # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :port => '8080' # => 'http://somehost.org:8080/tasks/testing'
+ # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok'
+ # url_for :controller => 'tasks', :action => 'testing', :trailing_slash => true # => 'http://somehost.org/tasks/testing/'
+ # url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33'
def url_for(options = nil)
case options
when String
diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
index c67a0664dc..5fa91d1a76 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb
@@ -169,7 +169,7 @@ module ActionDispatch
# assert_select "title", "Welcome"
#
# # Page title is "Welcome" and there is only one title element
- # assert_select "title", {:count=>1, :text=>"Welcome"},
+ # assert_select "title", {:count => 1, :text => "Welcome"},
# "Wrong title or more than one title element"
#
# # Page contains no forms
diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb
index d430691429..397bda41d5 100644
--- a/actionpack/lib/action_dispatch/testing/test_process.rb
+++ b/actionpack/lib/action_dispatch/testing/test_process.rb
@@ -29,7 +29,7 @@ module ActionDispatch
@response.redirect_url
end
- # Shortcut for <tt>ARack::Test::UploadedFile.new(ActionController::TestCase.fixture_path + path, type)</tt>:
+ # Shortcut for <tt>Rack::Test::UploadedFile.new(ActionController::TestCase.fixture_path + path, type)</tt>:
#
# post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png')
#
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index 92b6f7c770..a67b61c1ef 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -50,6 +50,7 @@ module ActionView
autoload :Resolver
autoload :PathResolver
autoload :FileSystemResolver
+ autoload :OptimizedFileSystemResolver
autoload :FallbackFileSystemResolver
end
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index c98110353f..fd2970b8e2 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -85,11 +85,11 @@ module ActionView #:nodoc:
#
# Here are some basic examples:
#
- # xml.em("emphasized") # => <em>emphasized</em>
- # xml.em { xml.b("emph & bold") } # => <em><b>emph &amp; bold</b></em>
- # xml.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A Link</a>
- # xml.target("name"=>"compile", "option"=>"fast") # => <target option="fast" name="compile"\>
- # # NOTE: order of attributes is not specified.
+ # xml.em("emphasized") # => <em>emphasized</em>
+ # xml.em { xml.b("emph & bold") } # => <em><b>emph &amp; bold</b></em>
+ # xml.a("A Link", "href" => "http://onestepback.org") # => <a href="http://onestepback.org">A Link</a>
+ # xml.target("name" => "compile", "option" => "fast") # => <target option="fast" name="compile"\>
+ # # NOTE: order of attributes is not specified.
#
# Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following:
#
diff --git a/actionpack/lib/action_view/helpers/atom_feed_helper.rb b/actionpack/lib/action_view/helpers/atom_feed_helper.rb
index 96e5722252..889ea8a763 100644
--- a/actionpack/lib/action_view/helpers/atom_feed_helper.rb
+++ b/actionpack/lib/action_view/helpers/atom_feed_helper.rb
@@ -81,8 +81,8 @@ module ActionView
#
# The Atom spec defines five elements (content rights title subtitle
# summary) which may directly contain xhtml content if :type => 'xhtml'
- # is specified as an attribute. If so, this helper will take care of
- # the enclosing div and xhtml namespace declaration. Example usage:
+ # is specified as an attribute. If so, this helper will take care of
+ # the enclosing div and xhtml namespace declaration. Example usage:
#
# entry.summary :type => 'xhtml' do |xhtml|
# xhtml.p pluralize(order.line_items.count, "line item")
@@ -91,8 +91,8 @@ module ActionView
# end
#
#
- # atom_feed yields an AtomFeedBuilder instance. Nested elements yield
- # an AtomBuilder instance.
+ # <tt>atom_feed</tt> yields an +AtomFeedBuilder+ instance. Nested elements yield
+ # an +AtomBuilder+ instance.
def atom_feed(options = {}, &block)
if options[:schema_date]
options[:schema_date] = options[:schema_date].strftime("%Y-%m-%d") if options[:schema_date].respond_to?(:strftime)
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb
index 385378ea29..e81d03b537 100644
--- a/actionpack/lib/action_view/helpers/cache_helper.rb
+++ b/actionpack/lib/action_view/helpers/cache_helper.rb
@@ -3,7 +3,7 @@ module ActionView
module Helpers
module CacheHelper
# This helper exposes a method for caching fragments of a view
- # rather than an entire action or page. This technique is useful
+ # rather than an entire action or page. This technique is useful
# caching pieces like menus, lists of newstopics, static HTML
# fragments, and so on. This method takes a block that contains
# the content you wish to cache.
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index ead7feb091..3b5f4e694f 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -135,8 +135,12 @@ module ActionView
# for elements that will be fragment cached.
def content_for(name, content = nil, &block)
content = capture(&block) if block_given?
- result = @view_flow.append(name, content) if content
- result unless content
+ if content
+ @view_flow.append(name, content)
+ nil
+ else
+ @view_flow.get(name)
+ end
end
# The same as +content_for+ but when used with streaming flushes
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index d2ddaafcb3..c78c03a5eb 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -12,14 +12,14 @@ module ActionView
# select-type methods share a number of common options that are as follows:
#
# * <tt>:prefix</tt> - overwrites the default prefix of "date" used for the select names. So specifying "birthday"
- # would give birthday[month] instead of date[month] if passed to the select_month method.
+ # would give birthday[month] instead of date[month] if passed to the <tt>select_month</tt> method.
# * <tt>:include_blank</tt> - set to true if it should be possible to set an empty date.
# * <tt>:discard_type</tt> - set to true if you want to discard the type part of the select name. If set to true,
- # the select_month method would use simply "date" (which can be overwritten using <tt>:prefix</tt>) instead of
- # "date[month]".
+ # the <tt>select_month</tt> method would use simply "date" (which can be overwritten using <tt>:prefix</tt>) instead
+ # of "date[month]".
module DateHelper
# Reports the approximate distance in time between two Time or Date objects or integers as seconds.
- # Set <tt>include_seconds</tt> to true if you want more detailed approximations when distance < 1 min, 29 secs
+ # Set <tt>include_seconds</tt> to true if you want more detailed approximations when distance < 1 min, 29 secs.
# Distances are reported based on the following table:
#
# 0 <-> 29 secs # => less than a minute
@@ -119,7 +119,7 @@ module ActionView
end
end
- # Like distance_of_time_in_words, but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>.
+ # Like <tt>distance_of_time_in_words</tt>, but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>.
#
# ==== Examples
# time_ago_in_words(3.minutes.from_now) # => 3 minutes
@@ -176,7 +176,7 @@ module ActionView
# NOTE: Discarded selects will default to 1. So if no month select is available, January will be assumed.
#
# ==== Examples
- # # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute
+ # # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute.
# date_select("post", "written_on")
#
# # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute,
@@ -197,7 +197,7 @@ module ActionView
# # lacking a year field.
# date_select("user", "birthday", :order => [:month, :day])
#
- # # Generates a date select that when POSTed is stored in the user variable, in the birthday attribute
+ # # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute
# # which is initially set to the date 3 days from the current date
# date_select("post", "written_on", :default => 3.days.from_now)
#
@@ -205,7 +205,7 @@ module ActionView
# # that will have a default day of 20.
# date_select("credit_card", "bill_due", :default => { :day => 20 })
#
- # # Generates a date select with custom prompts
+ # # Generates a date select with custom prompts.
# date_select("post", "written_on", :prompt => { :day => 'Select day', :month => 'Select month', :year => 'Select year' })
#
# The selects are prepared for multi-parameter assignment to an Active Record object.
@@ -222,22 +222,23 @@ module ActionView
# with <tt>:ampm</tt> option.
#
# This method will also generate 3 input hidden tags, for the actual year, month and day unless the option
- # <tt>:ignore_date</tt> is set to +true+.
+ # <tt>:ignore_date</tt> is set to +true+. If you set the <tt>:ignore_date</tt> to +true+, you must have a
+ # +date_select+ on the same method within the form otherwise an exception will be raised.
#
# If anything is passed in the html_options hash it will be applied to every select tag in the set.
#
# ==== Examples
- # # Creates a time select tag that, when POSTed, will be stored in the post variable in the sunrise attribute
+ # # Creates a time select tag that, when POSTed, will be stored in the post variable in the sunrise attribute.
# time_select("post", "sunrise")
#
# # Creates a time select tag with a seconds field that, when POSTed, will be stored in the post variables in
# # the sunrise attribute.
# time_select("post", "start_time", :include_seconds => true)
#
- # # You can set the :minute_step to 15 which will give you: 00, 15, 30 and 45.
+ # # You can set the <tt>:minute_step</tt> to 15 which will give you: 00, 15, 30 and 45.
# time_select 'game', 'game_time', {:minute_step => 15}
#
- # # Creates a time select tag with a custom prompt. Use :prompt => true for generic prompts.
+ # # Creates a time select tag with a custom prompt. Use <tt>:prompt => true</tt> for generic prompts.
# time_select("post", "written_on", :prompt => {:hour => 'Choose hour', :minute => 'Choose minute', :second => 'Choose seconds'})
# time_select("post", "written_on", :prompt => {:hour => true}) # generic prompt for hours
# time_select("post", "written_on", :prompt => true) # generic prompts for all
@@ -261,7 +262,7 @@ module ActionView
#
# ==== Examples
# # Generates a datetime select that, when POSTed, will be stored in the post variable in the written_on
- # # attribute
+ # # attribute.
# datetime_select("post", "written_on")
#
# # Generates a datetime select with a year select that starts at 1995 that, when POSTed, will be stored in the
@@ -279,7 +280,7 @@ module ActionView
# # as the written_on attribute.
# datetime_select("post", "written_on", :discard_type => true)
#
- # # Generates a datetime select with a custom prompt. Use :prompt=>true for generic prompts.
+ # # Generates a datetime select with a custom prompt. Use <tt>:prompt => true</tt> for generic prompts.
# datetime_select("post", "written_on", :prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year'})
# datetime_select("post", "written_on", :prompt => {:hour => true}) # generic prompt for hours
# datetime_select("post", "written_on", :prompt => true) # generic prompts for all
@@ -301,7 +302,7 @@ module ActionView
# ==== Examples
# my_date_time = Time.now + 4.days
#
- # # Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+ # # Generates a datetime select that defaults to the datetime in my_date_time (four days after today).
# select_datetime(my_date_time)
#
# # Generates a datetime select that defaults to today (no specified datetime)
@@ -331,7 +332,7 @@ module ActionView
# # prefixed with 'payday' rather than 'date'
# select_datetime(my_date_time, :prefix => 'payday')
#
- # # Generates a datetime select with a custom prompt. Use :prompt=>true for generic prompts.
+ # # Generates a datetime select with a custom prompt. Use <tt>:prompt => true</tt> for generic prompts.
# select_datetime(my_date_time, :prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year'})
# select_datetime(my_date_time, :prompt => {:hour => true}) # generic prompt for hours
# select_datetime(my_date_time, :prompt => true) # generic prompts for all
@@ -350,10 +351,10 @@ module ActionView
# ==== Examples
# my_date = Time.today + 6.days
#
- # # Generates a date select that defaults to the date in my_date (six days after today)
+ # # Generates a date select that defaults to the date in my_date (six days afteri today).
# select_date(my_date)
#
- # # Generates a date select that defaults to today (no specified date)
+ # # Generates a date select that defaults to today (no specified date).
# select_date()
#
# # Generates a date select that defaults to the date in my_date (six days after today)
@@ -361,18 +362,18 @@ module ActionView
# select_date(my_date, :order => [:year, :month, :day])
#
# # Generates a date select that discards the type of the field and defaults to the date in
- # # my_date (six days after today)
+ # # my_date (six days after today).
# select_date(my_date, :discard_type => true)
#
# # Generates a date select that defaults to the date in my_date,
- # # which has fields separated by '/'
+ # # which has fields separated by '/'.
# select_date(my_date, :date_separator => '/')
#
# # Generates a date select that defaults to the datetime in my_date (six days after today)
- # # prefixed with 'payday' rather than 'date'
+ # # prefixed with 'payday' rather than 'date'.
# select_date(my_date, :prefix => 'payday')
#
- # # Generates a date select with a custom prompt. Use :prompt=>true for generic prompts.
+ # # Generates a date select with a custom prompt. Use <tt>:prompt => true</tt> for generic prompts.
# select_date(my_date, :prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year'})
# select_date(my_date, :prompt => {:hour => true}) # generic prompt for hours
# select_date(my_date, :prompt => true) # generic prompts for all
@@ -381,7 +382,7 @@ module ActionView
DateTimeSelector.new(date, options, html_options).select_date
end
- # Returns a set of html select-tags (one for hour and minute)
+ # Returns a set of html select-tags (one for hour and minute).
# You can set <tt>:time_separator</tt> key to format the output, and
# the <tt>:include_seconds</tt> option to include an input for seconds.
#
@@ -390,28 +391,28 @@ module ActionView
# ==== Examples
# my_time = Time.now + 5.days + 7.hours + 3.minutes + 14.seconds
#
- # # Generates a time select that defaults to the time in my_time
+ # # Generates a time select that defaults to the time in my_time.
# select_time(my_time)
#
- # # Generates a time select that defaults to the current time (no specified time)
+ # # Generates a time select that defaults to the current time (no specified time).
# select_time()
#
# # Generates a time select that defaults to the time in my_time,
- # # which has fields separated by ':'
+ # # which has fields separated by ':'.
# select_time(my_time, :time_separator => ':')
#
# # Generates a time select that defaults to the time in my_time,
- # # that also includes an input for seconds
+ # # that also includes an input for seconds.
# select_time(my_time, :include_seconds => true)
#
# # Generates a time select that defaults to the time in my_time, that has fields
- # # separated by ':' and includes an input for seconds
+ # # separated by ':' and includes an input for seconds.
# select_time(my_time, :time_separator => ':', :include_seconds => true)
#
# # Generate a time select field with hours in the AM/PM format
# select_time(my_time, :ampm => true)
#
- # # Generates a time select with a custom prompt. Use :prompt=>true for generic prompts.
+ # # Generates a time select with a custom prompt. Use <tt>:prompt</tt> to true for generic prompts.
# select_time(my_time, :prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year'})
# select_time(my_time, :prompt => {:hour => true}) # generic prompt for hours
# select_time(my_time, :prompt => true) # generic prompts for all
@@ -427,17 +428,17 @@ module ActionView
# ==== Examples
# my_time = Time.now + 16.minutes
#
- # # Generates a select field for seconds that defaults to the seconds for the time in my_time
+ # # Generates a select field for seconds that defaults to the seconds for the time in my_time.
# select_second(my_time)
#
- # # Generates a select field for seconds that defaults to the number given
+ # # Generates a select field for seconds that defaults to the number given.
# select_second(33)
#
# # Generates a select field for seconds that defaults to the seconds for the time in my_time
- # # that is named 'interval' rather than 'second'
+ # # that is named 'interval' rather than 'second'.
# select_second(my_time, :field_name => 'interval')
#
- # # Generates a select field for seconds with a custom prompt. Use :prompt=>true for a
+ # # Generates a select field for seconds with a custom prompt. Use <tt>:prompt => true</tt> for a
# # generic prompt.
# select_minute(14, :prompt => 'Choose seconds')
#
@@ -453,17 +454,17 @@ module ActionView
# ==== Examples
# my_time = Time.now + 6.hours
#
- # # Generates a select field for minutes that defaults to the minutes for the time in my_time
+ # # Generates a select field for minutes that defaults to the minutes for the time in my_tiime.
# select_minute(my_time)
#
- # # Generates a select field for minutes that defaults to the number given
+ # # Generates a select field for minutes that defaults to the number given.
# select_minute(14)
#
# # Generates a select field for minutes that defaults to the minutes for the time in my_time
- # # that is named 'stride' rather than 'second'
+ # # that is named 'stride' rather than 'second'.
# select_minute(my_time, :field_name => 'stride')
#
- # # Generates a select field for minutes with a custom prompt. Use :prompt=>true for a
+ # # Generates a select field for minutes with a custom prompt. Use <tt>:prompt => true</tt> for a
# # generic prompt.
# select_minute(14, :prompt => 'Choose minutes')
#
@@ -478,17 +479,17 @@ module ActionView
# ==== Examples
# my_time = Time.now + 6.hours
#
- # # Generates a select field for hours that defaults to the hour for the time in my_time
+ # # Generates a select field for hours that defaults to the hour for the time in my_time.
# select_hour(my_time)
#
- # # Generates a select field for hours that defaults to the number given
+ # # Generates a select field for hours that defaults to the number given.
# select_hour(13)
#
# # Generates a select field for hours that defaults to the minutes for the time in my_time
- # # that is named 'stride' rather than 'second'
+ # # that is named 'stride' rather than 'second'.
# select_hour(my_time, :field_name => 'stride')
#
- # # Generates a select field for hours with a custom prompt. Use :prompt => true for a
+ # # Generates a select field for hours with a custom prompt. Use <tt>:prompt => true</tt> for a
# # generic prompt.
# select_hour(13, :prompt => 'Choose hour')
#
@@ -506,17 +507,17 @@ module ActionView
# ==== Examples
# my_date = Time.today + 2.days
#
- # # Generates a select field for days that defaults to the day for the date in my_date
+ # # Generates a select field for days that defaults to the day for the date in my_date.
# select_day(my_time)
#
- # # Generates a select field for days that defaults to the number given
+ # # Generates a select field for days that defaults to the number given.
# select_day(5)
#
# # Generates a select field for days that defaults to the day for the date in my_date
- # # that is named 'due' rather than 'day'
+ # # that is named 'due' rather than 'day'.
# select_day(my_time, :field_name => 'due')
#
- # # Generates a select field for days with a custom prompt. Use :prompt => true for a
+ # # Generates a select field for days with a custom prompt. Use <tt>:prompt => true</tt> for a
# # generic prompt.
# select_day(5, :prompt => 'Choose day')
#
@@ -539,7 +540,7 @@ module ActionView
# select_month(Date.today)
#
# # Generates a select field for months that defaults to the current month that
- # # is named "start" rather than "month"
+ # # is named "start" rather than "month".
# select_month(Date.today, :field_name => 'start')
#
# # Generates a select field for months that defaults to the current month that
@@ -558,7 +559,7 @@ module ActionView
# # will use keys like "Januar", "Marts."
# select_month(Date.today, :use_month_names => %w(Januar Februar Marts ...))
#
- # # Generates a select field for months with a custom prompt. Use :prompt => true for a
+ # # Generates a select field for months with a custom prompt. Use <tt>:prompt => true</tt> for a
# # generic prompt.
# select_month(14, :prompt => 'Choose month')
#
@@ -574,22 +575,22 @@ module ActionView
#
# ==== Examples
# # Generates a select field for years that defaults to the current year that
- # # has ascending year values
+ # # has ascending year values.
# select_year(Date.today, :start_year => 1992, :end_year => 2007)
#
# # Generates a select field for years that defaults to the current year that
- # # is named 'birth' rather than 'year'
+ # # is named 'birth' rather than 'year'.
# select_year(Date.today, :field_name => 'birth')
#
# # Generates a select field for years that defaults to the current year that
- # # has descending year values
+ # # has descending year values.
# select_year(Date.today, :start_year => 2005, :end_year => 1900)
#
# # Generates a select field for years that defaults to the year 2006 that
- # # has ascending year values
+ # # has ascending year values.
# select_year(2006, :start_year => 2000, :end_year => 2010)
#
- # # Generates a select field for years with a custom prompt. Use :prompt => true for a
+ # # Generates a select field for years with a custom prompt. Use <tt>:prompt => true</tt> for a
# # generic prompt.
# select_year(14, :prompt => 'Choose year')
#
@@ -783,7 +784,7 @@ module ActionView
end
# Returns translated month names, but also ensures that a custom month
- # name array has a leading nil element
+ # name array has a leading nil element.
def month_names
month_names = @options[:use_month_names] || translated_month_names
month_names.unshift(nil) if month_names.size < 13
@@ -791,13 +792,13 @@ module ActionView
end
memoize :month_names
- # Returns translated month names
+ # Returns translated month names.
# => [nil, "January", "February", "March",
# "April", "May", "June", "July",
# "August", "September", "October",
# "November", "December"]
#
- # If :use_short_month option is set
+ # If <tt>:use_short_month</tt> option is set
# => [nil, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
# "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
def translated_month_names
@@ -805,13 +806,13 @@ module ActionView
I18n.translate(key, :locale => @options[:locale])
end
- # Lookup month name for number
+ # Lookup month name for number.
# month_name(1) => "January"
#
- # If :use_month_numbers option is passed
+ # If <tt>:use_month_numbers</tt> option is passed
# month_name(1) => 1
#
- # If :add_month_numbers option is passed
+ # If <tt>:add_month_numbers</tt> option is passed
# month_name(1) => "1 - January"
def month_name(number)
if @options[:use_month_numbers]
@@ -832,16 +833,22 @@ module ActionView
I18n.translate(:'date.order', :locale => @options[:locale]) || []
end
- # Build full select tag from date type and options
+ # Build full select tag from date type and options.
def build_options_and_select(type, selected, options = {})
build_select(type, build_options(selected, options))
end
- # Build select option html from date value and options
+ # Build select option html from date value and options.
# build_options(15, :start => 1, :end => 31)
# => "<option value="1">1</option>
- # <option value=\"2\">2</option>
- # <option value=\"3\">3</option>..."
+ # <option value="2">2</option>
+ # <option value="3">3</option>..."
+ #
+ # If <tt>:step</tt> options is passed
+ # build_options(15, :start => 1, :end => 31, :step => 2)
+ # => "<option value="1">1</option>
+ # <option value="3">3</option>
+ # <option value="5">5</option>..."
def build_options(selected, options = {})
start = options.delete(:start) || 0
stop = options.delete(:end) || 59
@@ -860,7 +867,7 @@ module ActionView
(select_options.join("\n") + "\n").html_safe
end
- # Builds select tag from date type and html select options
+ # Builds select tag from date type and html select options.
# build_select(:month, "<option value="1">January</option>...")
# => "<select id="post_written_on_2i" name="post[written_on(2i)]">
# <option value="1">January</option>...
@@ -880,7 +887,7 @@ module ActionView
(content_tag(:select, select_html.html_safe, select_options) + "\n").html_safe
end
- # Builds a prompt option tag with supplied options or from default options
+ # Builds a prompt option tag with supplied options or from default options.
# prompt_option_tag(:month, :prompt => 'Select month')
# => "<option value="">Select month</option>"
def prompt_option_tag(type, options)
@@ -897,7 +904,7 @@ module ActionView
prompt ? content_tag(:option, prompt, :value => '') : ''
end
- # Builds hidden input tag for date part and value
+ # Builds hidden input tag for date part and value.
# build_hidden(:year, 2008)
# => "<input id="post_written_on_1i" name="post[written_on(1i)]" type="hidden" value="2008" />"
def build_hidden(type, value)
@@ -909,7 +916,7 @@ module ActionView
}.merge(@html_options.slice(:disabled))) + "\n").html_safe
end
- # Returns the name attribute for the input tag
+ # Returns the name attribute for the input tag.
# => post[written_on(1i)]
def input_name_from_type(type)
prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
@@ -923,7 +930,7 @@ module ActionView
@options[:discard_type] ? prefix : "#{prefix}[#{field_name}]"
end
- # Returns the id attribute for the input tag
+ # Returns the id attribute for the input tag.
# => "post_written_on_1i"
def input_id_from_type(type)
input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '')
@@ -940,7 +947,7 @@ module ActionView
select.html_safe
end
- # Returns the separator for a given datetime component
+ # Returns the separator for a given datetime component.
def separator(type)
case type
when :year
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index b6bb90a3ce..07e2c8d341 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -243,7 +243,7 @@ module ActionView
#
# === Setting the method
#
- # You can force the form to use the full array of HTTP verbs by setting
+ # You can force the form to use the full array of HTTP verbs by setting
#
# :method => (:get|:post|:put|:delete)
#
@@ -584,8 +584,8 @@ module ActionView
# <% end %>
# ...
# <% end %>
- def fields_for(record, record_object = nil, options = {}, &block)
- builder = instantiate_builder(record, record_object, options, &block)
+ def fields_for(record_name, record_object = nil, options = {}, &block)
+ builder = instantiate_builder(record_name, record_object, options, &block)
output = capture(builder, &block)
output.concat builder.hidden_field(:id) if output && options[:hidden_field_id] && !builder.emitted_hidden_id?
output
@@ -898,16 +898,13 @@ module ActionView
private
- def instantiate_builder(record, *args, &block)
- options = args.extract_options!
- record_object = args.shift
-
- case record
+ def instantiate_builder(record_name, record_object, options, &block)
+ case record_name
when String, Symbol
object = record_object
- object_name = record
+ object_name = record_name
else
- object = record
+ object = record_name
object_name = ActiveModel::Naming.param_key(object)
end
@@ -1219,35 +1216,30 @@ module ActionView
RUBY_EVAL
end
- def fields_for(record_or_name_or_array, *args, &block)
- if options.has_key?(:index)
- index = "[#{options[:index]}]"
- elsif defined?(@auto_index)
- self.object_name = @object_name.to_s.sub(/\[\]$/,"")
- index = "[#{@auto_index}]"
- else
- index = ""
- end
-
- args << {} unless args.last.is_a?(Hash)
- args.last[:builder] ||= options[:builder]
- args.last[:parent_builder] = self
+ def fields_for(record_name, record_object = nil, fields_options = {}, &block)
+ fields_options, record_object = record_object, nil if record_object.is_a?(Hash)
+ fields_options[:builder] ||= options[:builder]
+ fields_options[:parent_builder] = self
- case record_or_name_or_array
+ case record_name
when String, Symbol
- if nested_attributes_association?(record_or_name_or_array)
- return fields_for_with_nested_attributes(record_or_name_or_array, args, block)
- else
- name = record_or_name_or_array
+ if nested_attributes_association?(record_name)
+ return fields_for_with_nested_attributes(record_name, record_object, fields_options, block)
end
else
- object = record_or_name_or_array.is_a?(Array) ? record_or_name_or_array.last : record_or_name_or_array
- name = ActiveModel::Naming.param_key(object)
- args.unshift(object)
+ record_object = record_name.is_a?(Array) ? record_name.last : record_name
+ record_name = ActiveModel::Naming.param_key(record_object)
+ end
+
+ index = if options.has_key?(:index)
+ "[#{options[:index]}]"
+ elsif defined?(@auto_index)
+ self.object_name = @object_name.to_s.sub(/\[\]$/,"")
+ "[#{@auto_index}]"
end
- name = "#{object_name}#{index}[#{name}]"
+ record_name = "#{object_name}#{index}[#{record_name}]"
- @template.fields_for(name, *args, &block)
+ @template.fields_for(record_name, record_object, fields_options, &block)
end
def label(method, text = nil, options = {}, &block)
@@ -1336,10 +1328,8 @@ module ActionView
@object.respond_to?("#{association_name}_attributes=")
end
- def fields_for_with_nested_attributes(association_name, args, block)
+ def fields_for_with_nested_attributes(association_name, association, options, block)
name = "#{object_name}[#{association_name}_attributes]"
- options = args.extract_options!
- association = args.shift
association = convert_to_model(association)
if association.respond_to?(:persisted?)
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index 7698602022..0aaa690129 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -274,10 +274,10 @@ module ActionView
# You can optionally provide html attributes as the last element of the array.
#
# Examples:
- # options_for_select([ "Denmark", ["USA", {:class=>'bold'}], "Sweden" ], ["USA", "Sweden"])
+ # options_for_select([ "Denmark", ["USA", {:class => 'bold'}], "Sweden" ], ["USA", "Sweden"])
# <option value="Denmark">Denmark</option>\n<option value="USA" class="bold" selected="selected">USA</option>\n<option value="Sweden" selected="selected">Sweden</option>
#
- # options_for_select([["Dollar", "$", {:class=>"bold"}], ["Kroner", "DKK", {:onclick => "alert('HI');"}]])
+ # options_for_select([["Dollar", "$", {:class => "bold"}], ["Kroner", "DKK", {:onclick => "alert('HI');"}]])
# <option value="$" class="bold">Dollar</option>\n<option value="DKK" onclick="alert('HI');">Kroner</option>
#
# If you wish to specify disabled option tags, set +selected+ to be a hash, with <tt>:disabled</tt> being either a value
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 9e0f8f32b7..65a98fb27a 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -82,22 +82,22 @@ module ActionView
# select_tag "people", options_from_collection_for_select(@people, "id", "name")
# # <select id="people" name="people"><option value="1">David</option></select>
#
- # select_tag "people", "<option>David</option>"
+ # select_tag "people", "<option>David</option>".html_safe
# # => <select id="people" name="people"><option>David</option></select>
#
- # select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>"
+ # select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>".html_safe
# # => <select id="count" name="count"><option>1</option><option>2</option>
# # <option>3</option><option>4</option></select>
#
- # select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>", :multiple => true
+ # select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>".html_safe, :multiple => true
# # => <select id="colors" multiple="multiple" name="colors[]"><option>Red</option>
# # <option>Green</option><option>Blue</option></select>
#
- # select_tag "locations", "<option>Home</option><option selected="selected">Work</option><option>Out</option>"
+ # select_tag "locations", "<option>Home</option><option selected="selected">Work</option><option>Out</option>".html_safe
# # => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
# # <option>Out</option></select>
#
- # select_tag "access", "<option>Read</option><option>Write</option>", :multiple => true, :class => 'form_input'
+ # select_tag "access", "<option>Read</option><option>Write</option>".html_safe, :multiple => true, :class => 'form_input'
# # => <select class="form_input" id="access" multiple="multiple" name="access[]"><option>Read</option>
# # <option>Write</option></select>
#
@@ -107,7 +107,7 @@ module ActionView
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), :prompt => "Select something"
# # => <select id="people" name="people"><option value="">Select something</option><option value="1">David</option></select>
#
- # select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>", :disabled => true
+ # select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>".html_safe, :disabled => true
# # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
# # <option>Paris</option><option>Rome</option></select>
def select_tag(name, option_tags = nil, options = {})
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
index ec9bdd5320..fd8fe417d0 100644
--- a/actionpack/lib/action_view/helpers/translation_helper.rb
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -15,10 +15,10 @@ module ActionView
# = Action View Translation Helpers
module Helpers
module TranslationHelper
- # Delegates to I18n#translate but also performs three additional functions.
+ # Delegates to <tt>I18n#translate</tt> but also performs three additional functions.
#
- # First, it'll pass the :rescue_format => :html option to I18n so that any
- # thrown MissingTranslation messages will be turned into inline spans that
+ # First, it'll pass the <tt>:rescue_format => :html</tt> option to I18n so that any
+ # thrown +MissingTranslation+ messages will be turned into inline spans that
#
# * have a "translation-missing" class set,
# * contain the missing key as a title attribute and
@@ -54,7 +54,7 @@ module ActionView
end
alias :t :translate
- # Delegates to I18n.localize with no additional functionality.
+ # Delegates to <tt>I18n.localize</tt> with no additional functionality.
def localize(*args)
I18n.localize(*args)
end
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index ffa9a5bb0b..5488c752cc 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -420,7 +420,7 @@ module ActionView
end
# Creates a link tag of the given +name+ using a URL created by the set of
- # +options+ if +condition+ is true, in which case only the name is
+ # +options+ if +condition+ is true, otherwise only the name is
# returned. To specialize the default behavior, you can pass a block that
# accepts the name or the full argument list for +link_to_unless+ (see the examples
# in +link_to_unless+).
diff --git a/actionpack/lib/action_view/path_set.rb b/actionpack/lib/action_view/path_set.rb
index 8b840a6463..e0cb5d6a70 100644
--- a/actionpack/lib/action_view/path_set.rb
+++ b/actionpack/lib/action_view/path_set.rb
@@ -35,7 +35,7 @@ module ActionView #:nodoc:
each_with_index do |path, i|
path = path.to_s if path.is_a?(Pathname)
next unless path.is_a?(String)
- self[i] = FileSystemResolver.new(path)
+ self[i] = OptimizedFileSystemResolver.new(path)
end
end
end
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 98ecd15aa0..b99d24d281 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -79,9 +79,9 @@ module ActionView
# you are handling out-of-band metadata, you are
# also responsible for alerting the user to any
# problems with converting the user's data to
- # the default_internal.
+ # the <tt>default_internal</tt>.
#
- # To do so, simply raise the raise WrongEncodingError
+ # To do so, simply raise the raise +WrongEncodingError+
# as follows:
#
# raise WrongEncodingError.new(
@@ -198,7 +198,7 @@ module ActionView
# Among other things, this method is responsible for properly setting
# the encoding of the source. Until this point, we assume that the
# source is BINARY data. If no additional information is supplied,
- # we assume the encoding is the same as Encoding.default_external.
+ # we assume the encoding is the same as <tt>Encoding.default_external</tt>.
#
# The user can also specify the encoding via a comment on the first
# line of the template (# encoding: NAME-OF-ENCODING). This will work
@@ -212,8 +212,8 @@ module ActionView
# specifying the encoding. For instance, ERB supports <%# encoding: %>
#
# Otherwise, after we figure out the correct encoding, we then
- # encode the source into Encoding.default_internal. In general,
- # this means that templates will be UTF-8 inside of Rails,
+ # encode the source into <tt>Encoding.default_internal</tt>.
+ # In general, this means that templates will be UTF-8 inside of Rails,
# regardless of the original source encoding.
def compile(view, mod) #:nodoc:
method_name = self.method_name
diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb
index e246646963..d4448a7b33 100644
--- a/actionpack/lib/action_view/template/error.rb
+++ b/actionpack/lib/action_view/template/error.rb
@@ -1,3 +1,4 @@
+require "active_support/core_ext/array/wrap"
require "active_support/core_ext/enumerable"
module ActionView
@@ -29,6 +30,7 @@ module ActionView
def initialize(paths, path, prefixes, partial, details, *)
@path = path
+ prefixes = Array.wrap(prefixes)
display_paths = paths.compact.map{ |p| p.to_s.inspect }.join(", ")
template_type = if partial
"partial"
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb
index 870897958a..2b9427ace5 100644
--- a/actionpack/lib/action_view/template/resolver.rb
+++ b/actionpack/lib/action_view/template/resolver.rb
@@ -10,17 +10,16 @@ module ActionView
attr_reader :name, :prefix, :partial, :virtual
alias_method :partial?, :partial
- def initialize(name, prefix, partial)
- @name, @prefix, @partial = name, prefix, partial
- rebuild(@name, @prefix, @partial)
+ def self.build(name, prefix, partial)
+ virtual = ""
+ virtual << "#{prefix}/" unless prefix.empty?
+ virtual << (partial ? "_#{name}" : name)
+ new name, prefix, partial, virtual
end
- def rebuild(name, prefix, partial)
- @virtual = ""
- @virtual << "#{prefix}/" unless prefix.empty?
- @virtual << (partial ? "_#{name}" : name)
-
- self.replace(@virtual)
+ def initialize(name, prefix, partial, virtual)
+ @name, @prefix, @partial = name, prefix, partial
+ super(virtual)
end
end
@@ -60,7 +59,7 @@ module ActionView
# Helpers that builds a path. Useful for building virtual paths.
def build_path(name, prefix, partial)
- Path.new(name, prefix, partial)
+ Path.build(name, prefix, partial)
end
# Handles templates caching. If a key is given and caching is on
@@ -112,7 +111,8 @@ module ActionView
end
end
- class PathResolver < Resolver
+ # An abstract class that implements a Resolver with path semantics.
+ class PathResolver < Resolver #:nodoc:
EXTENSIONS = [:locale, :formats, :handlers]
DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}"
@@ -124,13 +124,12 @@ module ActionView
private
def find_templates(name, prefix, partial, details)
- path = build_path(name, prefix, partial)
- extensions = Hash[EXTENSIONS.map { |ext| [ext, details[ext]] }.flatten(0)]
- query(path, extensions, details[:formats])
+ path = Path.build(name, prefix, partial)
+ query(path, details, details[:formats])
end
- def query(path, exts, formats)
- query = build_query(path, exts)
+ def query(path, details, formats)
+ query = build_query(path, details)
templates = []
sanitizer = Hash.new { |h,k| h[k] = Dir["#{File.dirname(k)}/*"] }
@@ -138,7 +137,7 @@ module ActionView
next if File.directory?(p) || !sanitizer[p].include?(p)
handler, format = extract_handler_and_format(p, formats)
- contents = File.open(p, "rb") {|io| io.read }
+ contents = File.open(p, "rb") { |io| io.read }
templates << Template.new(contents, File.expand_path(p), handler,
:virtual_path => path.virtual, :format => format, :updated_at => mtime(p))
@@ -147,18 +146,15 @@ module ActionView
templates
end
- # Helper for building query glob string based on resolver's pattern.
- def build_query(path, exts)
+ # Helper for building query glob string based on resolver's pattern.
+ def build_query(path, details)
query = @pattern.dup
query.gsub!(/\:prefix(\/)?/, path.prefix.empty? ? "" : "#{path.prefix}\\1") # prefix can be empty...
query.gsub!(/\:action/, path.partial? ? "_#{path.name}" : path.name)
- exts.each { |ext, variants|
+ details.each do |ext, variants|
query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
- }
-
- query.gsub!('.{html,', '.{html,text.html,')
- query.gsub!('.{text,', '.{text,text.plain,')
+ end
File.expand_path(query, @path)
end
@@ -235,9 +231,25 @@ module ActionView
alias :== :eql?
end
+ # An Optimized resolver for Rails' most common case.
+ class OptimizedFileSystemResolver < FileSystemResolver #:nodoc:
+ def build_query(path, details)
+ exts = EXTENSIONS.map { |ext| details[ext] }
+ query = File.join(@path, path)
+
+ exts.each do |ext|
+ query << "{"
+ ext.compact.each { |e| query << ".#{e}," }
+ query << "}"
+ end
+
+ query
+ end
+ end
+
# The same as FileSystemResolver but does not allow templates to store
# a virtual path since it is invalid for such resolvers.
- class FallbackFileSystemResolver < FileSystemResolver
+ class FallbackFileSystemResolver < FileSystemResolver #:nodoc:
def self.instances
[new(""), new("/")]
end
diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb
index 9c10decd60..8cee3babe2 100644
--- a/actionpack/lib/sprockets/railtie.rb
+++ b/actionpack/lib/sprockets/railtie.rb
@@ -34,12 +34,12 @@ module Sprockets
app.assets = asset_environment(app)
ActiveSupport.on_load(:action_view) do
- app.assets.context.instance_eval do
+ app.assets.context_class.instance_eval do
include ::ActionView::Helpers::SprocketsHelper
end
end
- app.routes.append do
+ app.routes.prepend do
mount app.assets => assets.prefix
end
@@ -91,7 +91,7 @@ module Sprockets
compressor
when :yui
require 'yui/compressor'
- YUI::JavaScriptCompressor.new(:munge => true)
+ YUI::CssCompressor.new
else
sym
end