aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/action_controller/base.rb2
-rw-r--r--actionpack/lib/action_controller/metal.rb6
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb6
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb4
-rw-r--r--actionpack/lib/action_controller/railtie.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/rack_cache.rb67
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb20
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/abstract_store.rb5
-rw-r--r--actionpack/lib/action_dispatch/railtie.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb2
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb64
-rw-r--r--actionpack/lib/action_view/helpers/csrf_helper.rb28
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb27
-rw-r--r--actionpack/lib/action_view/render/partials.rb36
-rw-r--r--actionpack/lib/action_view/test_case.rb6
16 files changed, 219 insertions, 72 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index b37bc02127..631a0f2945 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -148,6 +148,8 @@ module ActionController
#
# In this case, after saving our new entry to the database, the user is redirected to the <tt>show</tt> method which is then executed.
#
+ # Learn more about <tt>redirect_to</tt> and what options you have in ActionController::Redirecting.
+ #
# == Calling multiple redirects or renders
#
# An action may contain only a single render or a single redirect. Attempting to try to do either again will result in a DoubleRenderError:
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index def28a0054..96cb5977d5 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -12,7 +12,7 @@ module ActionController
#
class MiddlewareStack < ActionDispatch::MiddlewareStack #:nodoc:
class Middleware < ActionDispatch::MiddlewareStack::Middleware #:nodoc:
- def initialize(klass, *args)
+ def initialize(klass, *args, &block)
options = args.extract_options!
@only = Array(options.delete(:only)).map(&:to_s)
@except = Array(options.delete(:except)).map(&:to_s)
@@ -149,8 +149,8 @@ module ActionController
super
end
- def self.use(*args)
- middleware_stack.use(*args)
+ def self.use(*args, &block)
+ middleware_stack.use(*args, &block)
end
def self.middleware
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index b5f1d23ef0..10d7794b57 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -38,6 +38,9 @@ module ActionController
# redirect_to :action=>'atom', :status => :moved_permanently
# redirect_to post_url(@post), :status => 301
# redirect_to :action=>'atom', :status => 302
+ #
+ # The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an
+ # integer, or a symbol representing the downcased, underscored and symbolized description.
#
# It is also possible to assign a flash message as part of the redirection. There are two special accessors for commonly used the flash names
# +alert+ and +notice+ as well as a general purpose +flash+ bucket.
@@ -48,8 +51,7 @@ module ActionController
# redirect_to post_url(@post), :status => 301, :flash => { :updated_post_id => @post.id }
# redirect_to { :action=>'atom' }, :alert => "Something serious happened"
#
- # When using <tt>redirect_to :back</tt>, if there is no referrer,
- # RedirectBackError will be raised. You may specify some fallback
+ # When using <tt>redirect_to :back</tt>, if there is no referrer, RedirectBackError will be raised. You may specify some fallback
# behavior for this case by rescuing RedirectBackError.
def redirect_to(options = {}, response_status = {}) #:doc:
raise ActionControllerError.new("Cannot redirect to nil!") if options.nil?
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index fc3118671f..02f577647e 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -17,11 +17,11 @@ module ActionController #:nodoc:
# which will check the token and raise an ActionController::InvalidAuthenticityToken
# if it doesn't match what was expected. A call to this method is generated for new
# \Rails applications by default. You can customize the error message by editing
- # public/422.html.
+ # public/422.html.
#
# The token parameter is named <tt>authenticity_token</tt> by default. The name and
# value of this token must be added to every layout that renders forms by including
- # <tt>csrf_meta_tag</tt> in the html +head+.
+ # <tt>csrf_meta_tags</tt> in the html +head+.
#
# Learn more about CSRF attacks and securing your application in the
# {Ruby on Rails Security Guide}[http://guides.rubyonrails.org/security.html].
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index d26b7e2486..aea28d9265 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -27,7 +27,7 @@ module ActionController
options.page_cache_directory ||= paths.public.to_a.first
ActiveSupport.on_load(:action_controller) do
- include app.routes.mounted_helpers(:app)
+ include app.routes.mounted_helpers
extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
extend ::ActionController::Railties::Paths.with(app)
options.each { |k,v| send("#{k}=", v) }
diff --git a/actionpack/lib/action_dispatch/http/rack_cache.rb b/actionpack/lib/action_dispatch/http/rack_cache.rb
new file mode 100644
index 0000000000..e5914abc81
--- /dev/null
+++ b/actionpack/lib/action_dispatch/http/rack_cache.rb
@@ -0,0 +1,67 @@
+require "rack/cache"
+require "rack/cache/context"
+require "active_support/cache"
+
+module ActionDispatch
+ class RailsMetaStore < Rack::Cache::MetaStore
+ def self.resolve(uri)
+ new
+ end
+
+ # TODO: Finally deal with the RAILS_CACHE global
+ def initialize(store = RAILS_CACHE)
+ @store = store
+ end
+
+ def read(key)
+ @store.read(key) || []
+ end
+
+ def write(key, value)
+ @store.write(key, value)
+ end
+
+ def purge(key)
+ @store.delete(key)
+ nil
+ end
+
+ ::Rack::Cache::MetaStore::RAILS = self
+ end
+
+ class RailsEntityStore < Rack::Cache::EntityStore
+ def self.resolve(uri)
+ new
+ end
+
+ def initialize(store = RAILS_CACHE)
+ @store = store
+ end
+
+ def exist?(key)
+ @store.exist?(key)
+ end
+
+ def open(key)
+ @store.read(key)
+ end
+
+ def read(key)
+ body = open(key)
+ body.join if body
+ end
+
+ def write(body)
+ buf = []
+ key, size = slurp(body) { |part| buf << part }
+ @store.write(key, buf)
+ [key, size]
+ end
+
+ def purge(key)
+ @store.delete(key)
+ end
+
+ ::Rack::Cache::EntityStore::RAILS = self
+ end
+end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 5606d6abfe..7a28228817 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -136,11 +136,11 @@ module ActionDispatch
super.to_i
end
- # Returns true if the request's "X-Requested-With" header contains
- # "XMLHttpRequest". (The Prototype Javascript library sends this header with
- # every Ajax request.)
+ # Returns true if the "X-Requested-With" header contains "XMLHttpRequest"
+ # (case-insensitive). All major JavaScript libraries send this header with
+ # every Ajax request.
def xml_http_request?
- !(@env['HTTP_X_REQUESTED_WITH'] !~ /XMLHttpRequest/i)
+ @env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/i
end
alias :xhr? :xml_http_request?
@@ -149,8 +149,16 @@ module ActionDispatch
end
# Which IP addresses are "trusted proxies" that can be stripped from
- # the right-hand-side of X-Forwarded-For
- TRUSTED_PROXIES = /^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i
+ # the right-hand-side of X-Forwarded-For.
+ #
+ # http://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces.
+ TRUSTED_PROXIES = %r{
+ ^127\.0\.0\.1$ | # localhost
+ ^(10 | # private IP 10.x.x.x
+ 172\.(1[6-9]|2[0-9]|3[0-1]) | # private IP in the range 172.16.0.0 .. 172.31.255.255
+ 192\.168 # private IP 192.168.x.x
+ )\.
+ }x
# Determines originating IP address. REMOTE_ADDR is the standard
# but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 38f46fa120..2e39d0dbc2 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -1,7 +1,9 @@
module ActionDispatch
module Http
module URL
- # Returns the complete \URL used for this request.
+ mattr_accessor :tld_length
+
+ # Returns the complete URL used for this request.
def url
protocol + host_with_port + fullpath
end
@@ -85,13 +87,13 @@ module ActionDispatch
# 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>
# in "www.rubyonrails.co.uk".
- def subdomains(tld_length = 1)
+ def subdomains(tld_length = @@tld_length)
return [] unless named_host?(host)
parts = host.split('.')
parts[0..-(tld_length+2)]
end
- def subdomain(tld_length = 1)
+ def subdomain(tld_length = @@tld_length)
subdomains(tld_length).join('.')
end
@@ -102,4 +104,4 @@ module ActionDispatch
end
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
index dd82294644..348a2d1eb2 100644
--- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
@@ -152,6 +152,10 @@ module ActionDispatch
options = env[ENV_SESSION_OPTIONS_KEY]
if !session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after]
+ request = ActionDispatch::Request.new(env)
+
+ return response if (options[:secure] && !request.ssl?)
+
session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded?
sid = options[:id] || generate_sid
@@ -165,7 +169,6 @@ module ActionDispatch
cookie[:expires] = Time.now + options.delete(:expire_after)
end
- request = ActionDispatch::Request.new(env)
set_cookie(request, cookie.merge!(options))
end
diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb
index ed066ad75e..0a3bd5fe40 100644
--- a/actionpack/lib/action_dispatch/railtie.rb
+++ b/actionpack/lib/action_dispatch/railtie.rb
@@ -8,5 +8,11 @@ module ActionDispatch
config.action_dispatch.ip_spoofing_check = true
config.action_dispatch.show_exceptions = true
config.action_dispatch.best_standards_support = true
+ config.action_dispatch.tld_length = 1
+ config.action_dispatch.rack_cache = {:metastore => "rails:/", :entitystore => "rails:/", :verbose => true}
+
+ initializer "action_dispatch.configure" do |app|
+ ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 956bd2e719..835ba03784 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -262,7 +262,7 @@ module ActionDispatch
module MountedHelpers
end
- def mounted_helpers(name = nil)
+ def mounted_helpers(name = :main_app)
define_mounted_helper(name) if name
MountedHelpers
end
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 3329a8b368..fdc40c8f2e 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -257,53 +257,53 @@ module ActionView
end
alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route
- # Returns an html script tag for each of the +sources+ provided. You
- # can pass in the filename (.js extension is optional) of javascript files
- # that exist in your public/javascripts directory for inclusion into the
+ # Returns an HTML script tag for each of the +sources+ provided. You
+ # can pass in the filename (.js extension is optional) of JavaScript files
+ # that exist in your <tt>public/javascripts</tt> directory for inclusion into the
# current page or you can pass the full path relative to your document
- # root. To include the Prototype and Scriptaculous javascript libraries in
+ # root. To include the Prototype and Scriptaculous JavaScript libraries in
# your application, pass <tt>:defaults</tt> as the source. When using
- # <tt>:defaults</tt>, if an application.js file exists in your public
- # javascripts directory, it will be included as well. You can modify the
- # html attributes of the script tag by passing a hash as the last argument.
+ # <tt>:defaults</tt>, if an <tt>application.js</tt> file exists in
+ # <tt>public/javascripts</tt> it will be included as well. You can modify the
+ # HTML attributes of the script tag by passing a hash as the last argument.
#
# ==== Examples
# javascript_include_tag "xmlhr" # =>
- # <script type="text/javascript" src="/javascripts/xmlhr.js"></script>
+ # <script type="text/javascript" src="/javascripts/xmlhr.js?1284139606"></script>
#
# javascript_include_tag "xmlhr.js" # =>
- # <script type="text/javascript" src="/javascripts/xmlhr.js"></script>
+ # <script type="text/javascript" src="/javascripts/xmlhr.js?1284139606"></script>
#
# javascript_include_tag "common.javascript", "/elsewhere/cools" # =>
- # <script type="text/javascript" src="/javascripts/common.javascript"></script>
- # <script type="text/javascript" src="/elsewhere/cools.js"></script>
+ # <script type="text/javascript" src="/javascripts/common.javascript?1284139606"></script>
+ # <script type="text/javascript" src="/elsewhere/cools.js?1423139606"></script>
#
# javascript_include_tag "http://www.railsapplication.com/xmlhr" # =>
- # <script type="text/javascript" src="http://www.railsapplication.com/xmlhr.js"></script>
+ # <script type="text/javascript" src="http://www.railsapplication.com/xmlhr.js?1284139606"></script>
#
# javascript_include_tag "http://www.railsapplication.com/xmlhr.js" # =>
- # <script type="text/javascript" src="http://www.railsapplication.com/xmlhr.js"></script>
+ # <script type="text/javascript" src="http://www.railsapplication.com/xmlhr.js?1284139606"></script>
#
# javascript_include_tag :defaults # =>
- # <script type="text/javascript" src="/javascripts/prototype.js"></script>
- # <script type="text/javascript" src="/javascripts/effects.js"></script>
+ # <script type="text/javascript" src="/javascripts/prototype.js?1284139606"></script>
+ # <script type="text/javascript" src="/javascripts/effects.js?1284139606"></script>
# ...
- # <script type="text/javascript" src="/javascripts/application.js"></script>
+ # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
#
# * = The application.js file is only referenced if it exists
#
# Though it's not really recommended practice, if you need to extend the default JavaScript set for any reason
# (e.g., you're going to be using a certain .js file in every action), then take a look at the register_javascript_include_default method.
#
- # You can also include all javascripts in the javascripts directory using <tt>:all</tt> as the source:
+ # You can also include all javascripts in the +javascripts+ directory using <tt>:all</tt> as the source:
#
# javascript_include_tag :all # =>
- # <script type="text/javascript" src="/javascripts/prototype.js"></script>
- # <script type="text/javascript" src="/javascripts/effects.js"></script>
+ # <script type="text/javascript" src="/javascripts/prototype.js?1284139606"></script>
+ # <script type="text/javascript" src="/javascripts/effects.js?1284139606"></script>
# ...
- # <script type="text/javascript" src="/javascripts/application.js"></script>
- # <script type="text/javascript" src="/javascripts/shop.js"></script>
- # <script type="text/javascript" src="/javascripts/checkout.js"></script>
+ # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
+ # <script type="text/javascript" src="/javascripts/shop.js?1284139606"></script>
+ # <script type="text/javascript" src="/javascripts/checkout.js?1284139606"></script>
#
# Note that the default javascript files will be included first. So Prototype and Scriptaculous are available to
# all subsequently included files.
@@ -321,23 +321,23 @@ module ActionView
#
# ==== Examples
# javascript_include_tag :all, :cache => true # when config.perform_caching is false =>
- # <script type="text/javascript" src="/javascripts/prototype.js"></script>
- # <script type="text/javascript" src="/javascripts/effects.js"></script>
+ # <script type="text/javascript" src="/javascripts/prototype.js?1284139606"></script>
+ # <script type="text/javascript" src="/javascripts/effects.js?1284139606"></script>
# ...
- # <script type="text/javascript" src="/javascripts/application.js"></script>
- # <script type="text/javascript" src="/javascripts/shop.js"></script>
- # <script type="text/javascript" src="/javascripts/checkout.js"></script>
+ # <script type="text/javascript" src="/javascripts/application.js?1284139606"></script>
+ # <script type="text/javascript" src="/javascripts/shop.js?1284139606"></script>
+ # <script type="text/javascript" src="/javascripts/checkout.js?1284139606"></script>
#
# javascript_include_tag :all, :cache => true # when config.perform_caching is true =>
- # <script type="text/javascript" src="/javascripts/all.js"></script>
+ # <script type="text/javascript" src="/javascripts/all.js?1344139789"></script>
#
# javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when config.perform_caching is false =>
- # <script type="text/javascript" src="/javascripts/prototype.js"></script>
- # <script type="text/javascript" src="/javascripts/cart.js"></script>
- # <script type="text/javascript" src="/javascripts/checkout.js"></script>
+ # <script type="text/javascript" src="/javascripts/prototype.js?1284139606"></script>
+ # <script type="text/javascript" src="/javascripts/cart.js?1289139157"></script>
+ # <script type="text/javascript" src="/javascripts/checkout.js?1299139816"></script>
#
# javascript_include_tag "prototype", "cart", "checkout", :cache => "shop" # when config.perform_caching is true =>
- # <script type="text/javascript" src="/javascripts/shop.js"></script>
+ # <script type="text/javascript" src="/javascripts/shop.js?1299139816"></script>
#
# The <tt>:recursive</tt> option is also available for caching:
#
diff --git a/actionpack/lib/action_view/helpers/csrf_helper.rb b/actionpack/lib/action_view/helpers/csrf_helper.rb
index 3d03f6aac6..65c8debc76 100644
--- a/actionpack/lib/action_view/helpers/csrf_helper.rb
+++ b/actionpack/lib/action_view/helpers/csrf_helper.rb
@@ -1,14 +1,30 @@
+require 'active_support/core_ext/string/strip'
+
module ActionView
# = Action View CSRF Helper
module Helpers
module CsrfHelper
- # Returns a meta tag with the cross-site request forgery protection token
- # for forms to use. Place this in your head.
- def csrf_meta_tag
- if protect_against_forgery?
- %(<meta name="csrf-param" content="#{Rack::Utils.escape_html(request_forgery_protection_token)}"/>\n<meta name="csrf-token" content="#{Rack::Utils.escape_html(form_authenticity_token)}"/>).html_safe
- end
+ # Returns meta tags "csrf-param" and "csrf-token" with the name of the cross-site
+ # request forgery protection parameter and token, respectively.
+ #
+ # <head>
+ # <%= csrf_meta_tags %>
+ # </head>
+ #
+ # These are used to generate the dynamic forms that implement non-remote links with
+ # <tt>:method</tt>.
+ #
+ # Note that regular forms generate hidden fields, and that Ajax calls are whitelisted,
+ # so they do not use these tags.
+ def csrf_meta_tags
+ <<-METAS.strip_heredoc.chomp.html_safe if protect_against_forgery?
+ <meta name="csrf-param" content="#{Rack::Utils.escape_html(request_forgery_protection_token)}"/>
+ <meta name="csrf-token" content="#{Rack::Utils.escape_html(form_authenticity_token)}"/>
+ METAS
end
+
+ # For backwards compatibility.
+ alias csrf_meta_tag csrf_meta_tags
end
end
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 43dbedc448..79a9d997dd 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -293,31 +293,32 @@ module ActionView
#
# If you don't need to attach a form to a model instance, then check out
# FormTagHelper#form_tag.
- def form_for(record_or_name_or_array, *args, &proc)
+ def form_for(record, record_object = nil, options = nil, &proc)
raise ArgumentError, "Missing block" unless block_given?
- options = args.extract_options!
+ options, record_object = record_object, nil if record_object.is_a?(Hash)
+ options ||= {}
- case record_or_name_or_array
+ case record
when String, Symbol
- ActiveSupport::Deprecation.warn("Using form_for(:name, @resource) is deprecated. Please use form_for(@resource, :as => :name) instead.", caller) unless args.empty?
- object_name = record_or_name_or_array
+ ActiveSupport::Deprecation.warn("Using form_for(:name, @resource) is deprecated. Please use form_for(@resource, :as => :name) instead.", caller) if record_object
+ object_name = record
+ object = record_object
when Array
- object = record_or_name_or_array.last
+ object = record.last
object_name = options[:as] || ActiveModel::Naming.param_key(object)
- apply_form_for_options!(record_or_name_or_array, options)
- args.unshift object
+ apply_form_for_options!(record, options)
else
- object = record_or_name_or_array
+ object = record
object_name = options[:as] || ActiveModel::Naming.param_key(object)
apply_form_for_options!([object], options)
- args.unshift object
end
- (options[:html] ||= {})[:remote] = true if options.delete(:remote)
+ options[:html] ||= {}
+ options[:html][:remote] = options.delete(:remote)
- output = form_tag(options.delete(:url) || {}, options.delete(:html) || {})
- output << fields_for(object_name, *(args << options), &proc)
+ output = form_tag(options.delete(:url) || {}, options.delete(:html) || {})
+ output << fields_for(object_name, object, options, &proc)
output.safe_concat('</form>')
end
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index 92cdbfb3af..cc9b444837 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -26,6 +26,35 @@ module ActionView
# This would first render "advertiser/_account.erb" with @buyer passed in as the local variable +account+, then
# render "advertiser/_ad.erb" and pass the local variable +ad+ to the template for display.
#
+ # == The :as and :object options
+ #
+ # By default <tt>ActionView::Partials::PartialRenderer</tt> has its object in a local variable with the same
+ # name as the template. So, given
+ #
+ # <%= render :partial => "contract" %>
+ #
+ # within contract we'll get <tt>@contract</tt> in the local variable +contract+, as if we had written
+ #
+ # <%= render :partial => "contract", :locals => { :contract => @contract } %>
+ #
+ # With the <tt>:as</tt> option we can specify a different name for said local variable. For example, if we
+ # wanted it to be +agreement+ instead of +contract+ we'd do:
+ #
+ # <%= render :partial => "contract", :as => :agreement %>
+ #
+ # The <tt>:object</tt> option can be used to directly specify which object is rendered into the partial;
+ # useful when the template's object is elsewhere, in a different ivar or in a local variable for instance.
+ #
+ # Revisiting a previous example we could have written this code:
+ #
+ # <%= render :partial => "account", :object => @buyer %>
+ #
+ # <% for ad in @advertisements %>
+ # <%= render :partial => "ad", :object => ad %>
+ # <% end %>
+ #
+ # The <tt>:object</tt> and <tt>:as</tt> options can be used together.
+ #
# == Rendering a collection of partials
#
# The example of partial use describes a familiar pattern where a template needs to iterate over an array and
@@ -39,6 +68,13 @@ module ActionView
# iteration counter will automatically be made available to the template with a name of the form
# +partial_name_counter+. In the case of the example above, the template would be fed +ad_counter+.
#
+ # The <tt>:as</tt> option may be used when rendering partials.
+ #
+ # You can specify a partial to be rendered between elements via the <tt>:spacer_template</tt> option.
+ # The following example will render <tt>advertiser/_ad_divider.html.erb</tt> between each ad partial:
+ #
+ # <%= render :partial => "ad", :collection => @advertisements, :spacer_template => "ad_divider" %>
+ #
# NOTE: Due to backwards compatibility concerns, the collection can't be one of hashes. Normally you'd also
# just keep domain objects, like Active Records, in there.
#
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index e9d2e0b843..2c2661df26 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -74,6 +74,11 @@ module ActionView
@helper_class ||= determine_default_helper_class(name)
end
+ def new(*)
+ include_helper_modules!
+ super
+ end
+
private
def include_helper_modules!
@@ -89,7 +94,6 @@ module ActionView
@output_buffer = ActiveSupport::SafeBuffer.new
@rendered = ''
- self.class.send(:include_helper_modules!)
make_test_case_available_to_view!
say_no_to_protect_against_forgery!
end