aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r--actionpack/lib/action_view/base.rb17
-rw-r--r--actionpack/lib/action_view/context.rb21
-rw-r--r--actionpack/lib/action_view/helpers/active_model_helper.rb19
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb48
-rw-r--r--actionpack/lib/action_view/helpers/atom_feed_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/cache_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/csrf_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb12
-rw-r--r--actionpack/lib/action_view/helpers/debug_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb38
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb7
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb20
-rw-r--r--actionpack/lib/action_view/helpers/javascript_helper.rb1
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/prototype_helper.rb26
-rw-r--r--actionpack/lib/action_view/helpers/raw_output_helper.rb9
-rw-r--r--actionpack/lib/action_view/helpers/record_identification_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/record_tag_helper.rb1
-rw-r--r--actionpack/lib/action_view/helpers/sanitize_helper.rb16
-rw-r--r--actionpack/lib/action_view/helpers/scriptaculous_helper.rb11
-rw-r--r--actionpack/lib/action_view/helpers/tag_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/translation_helper.rb27
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb53
-rw-r--r--actionpack/lib/action_view/log_subscriber.rb28
-rw-r--r--actionpack/lib/action_view/lookup_context.rb2
-rw-r--r--actionpack/lib/action_view/paths.rb1
-rw-r--r--actionpack/lib/action_view/railtie.rb18
-rw-r--r--actionpack/lib/action_view/railties/log_subscriber.rb24
-rw-r--r--actionpack/lib/action_view/render/layouts.rb3
-rw-r--r--actionpack/lib/action_view/render/partials.rb4
-rw-r--r--actionpack/lib/action_view/render/rendering.rb1
-rw-r--r--actionpack/lib/action_view/template.rb20
-rw-r--r--actionpack/lib/action_view/template/error.rb1
-rw-r--r--actionpack/lib/action_view/template/handlers.rb1
-rw-r--r--actionpack/lib/action_view/template/resolver.rb3
-rw-r--r--actionpack/lib/action_view/template/text.rb1
-rw-r--r--actionpack/lib/action_view/test_case.rb50
39 files changed, 311 insertions, 210 deletions
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 4d06ca0d89..956c88a553 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -3,16 +3,19 @@ require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/array/wrap'
require 'active_support/ordered_options'
+require 'action_view/log_subscriber'
module ActionView #:nodoc:
class NonConcattingString < ActiveSupport::SafeBuffer
end
+ # = Action View Base
+ #
# Action View templates can be written in three ways. If the template file has a <tt>.erb</tt> (or <tt>.rhtml</tt>) extension then it uses a mixture of ERb
# (included in Ruby) and HTML. If the template file has a <tt>.builder</tt> (or <tt>.rxml</tt>) extension then Jim Weirich's Builder::XmlMarkup library is used.
# If the template file has a <tt>.rjs</tt> extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.
#
- # = ERb
+ # == ERb
#
# You trigger ERb by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the
# following loop for names:
@@ -32,7 +35,7 @@ module ActionView #:nodoc:
#
# <%- and -%> suppress leading and trailing whitespace, including the trailing newline, and can be used interchangeably with <% and %>.
#
- # == Using sub templates
+ # === Using sub templates
#
# Using sub templates allows you to sidestep tedious replication and extract common display structures in shared templates. The
# classic example is the use of a header and footer (even though the Action Pack-way would be to use Layouts):
@@ -54,7 +57,7 @@ module ActionView #:nodoc:
#
# <title><%= @page_title %></title>
#
- # == Passing local variables to sub templates
+ # === Passing local variables to sub templates
#
# You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values:
#
@@ -74,7 +77,7 @@ module ActionView #:nodoc:
#
# Testing using <tt>defined? headline</tt> will not work. This is an implementation restriction.
#
- # == Template caching
+ # === Template caching
#
# By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will
# check the file's modification time and recompile it.
@@ -202,8 +205,12 @@ module ActionView #:nodoc:
value.dup : ActionView::PathSet.new(Array.wrap(value))
end
+ def assign(new_assigns) # :nodoc:
+ self.assigns = new_assigns.each { |key, value| instance_variable_set("@#{key}", value) }
+ end
+
def initialize(lookup_context = nil, assigns_for_first_render = {}, controller = nil, formats = nil) #:nodoc:
- self.assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) }
+ assign(assigns_for_first_render)
self.helpers = self.class.helpers || Module.new
if @_controller = controller
diff --git a/actionpack/lib/action_view/context.rb b/actionpack/lib/action_view/context.rb
index 88efd4b34f..39d88333e8 100644
--- a/actionpack/lib/action_view/context.rb
+++ b/actionpack/lib/action_view/context.rb
@@ -2,13 +2,12 @@ module ActionView
module CompiledTemplates #:nodoc:
# holds compiled template code
end
-
- # Action View contexts are supplied to Action Controller
- # to render template. The default Action View context
- # is ActionView::Base.
+ # = Action View Context
+ #
+ # Action View contexts are supplied to Action Controller to render template.
+ # The default Action View context is ActionView::Base.
#
- # In order to work with ActionController, a Context
- # must implement:
+ # In order to work with ActionController, a Context must implement:
#
# Context#render_partial[options]
# - responsible for setting options[:_template]
@@ -21,16 +20,14 @@ module ActionView
# options<Hash>:: See _render_template_with_layout in ActionView::Base
# partial<Boolean>:: Whether or not the template to render is a partial
#
- # An Action View context can also mix in Action View's
- # helpers. In order to mix in helpers, a context must
- # implement:
+ # An Action View context can also mix in Action View's helpers. In order to
+ # mix in helpers, a context must implement:
#
# Context#controller
# - Returns an instance of AbstractController
#
- # In any case, a context must mix in ActionView::Context,
- # which stores compiled template and provides the output
- # buffer.
+ # In any case, a context must mix in ActionView::Context, which stores compiled
+ # template and provides the output buffer.
module Context
include CompiledTemplates
attr_accessor :output_buffer
diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb
index 8054de0af6..6bb0875bc3 100644
--- a/actionpack/lib/action_view/helpers/active_model_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_model_helper.rb
@@ -4,6 +4,7 @@ require 'active_support/core_ext/enumerable'
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Active Model Helpers
module Helpers
module ActiveModelHelper
%w(input form error_messages_for error_message_on).each do |method|
@@ -35,12 +36,16 @@ module ActionView
end
end
- %w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth|
+ %w(content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth|
module_eval "def #{meth}(*) error_wrapping(super) end", __FILE__, __LINE__
end
+ def tag(type, options, *)
+ tag_generate_errors?(options) ? error_wrapping(super) : super
+ end
+
def error_wrapping(html_tag)
- if object.respond_to?(:errors) && object.errors.respond_to?(:full_messages) && object.errors[@method_name].any?
+ if object_has_errors?
Base.field_error_proc.call(html_tag, self)
else
html_tag
@@ -50,6 +55,16 @@ module ActionView
def error_message
object.errors[@method_name]
end
+
+ private
+
+ def object_has_errors?
+ object.respond_to?(:errors) && object.errors.respond_to?(:full_messages) && error_message.any?
+ end
+
+ def tag_generate_errors?(options)
+ options['type'] != 'hidden'
+ end
end
class FormBuilder
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 25426a5547..a3c43d3e93 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -6,6 +6,7 @@ require 'active_support/core_ext/file'
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Asset Tag Helpers
module Helpers #:nodoc:
# This module provides methods for generating HTML that links views to assets such
# as images, javascripts, stylesheets, and feeds. These methods do not verify
@@ -193,7 +194,19 @@ module ActionView
# RewriteEngine On
# RewriteRule ^/release-\d+/(images|javascripts|stylesheets)/(.*)$ /$1/$2 [L]
module AssetTagHelper
- JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls', 'rails'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
+ mattr_reader :javascript_expansions
+ @@javascript_expansions = { }
+
+ mattr_reader :stylesheet_expansions
+ @@stylesheet_expansions = {}
+
+ # You can enable or disable the asset tag timestamps cache.
+ # With the cache enabled, the asset tag helper methods will make fewer
+ # expensive file system calls. However this prevents you from modifying
+ # any asset files while the server is running.
+ #
+ # ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
+ mattr_accessor :cache_asset_timestamps
# Returns a link tag that browsers and news readers can use to auto-detect
# an RSS or ATOM feed. The +type+ can either be <tt>:rss</tt> (default) or
@@ -350,8 +363,6 @@ module ActionView
end
end
- @@javascript_expansions = { :defaults => JAVASCRIPT_DEFAULT_SOURCES.dup }
-
# Register one or more javascript files to be included when <tt>symbol</tt>
# is passed to <tt>javascript_include_tag</tt>. This method is typically intended
# to be called from plugin initialization to register javascript files
@@ -367,8 +378,6 @@ module ActionView
@@javascript_expansions.merge!(expansions)
end
- @@stylesheet_expansions = {}
-
# Register one or more stylesheet files to be included when <tt>symbol</tt>
# is passed to <tt>stylesheet_link_tag</tt>. This method is typically intended
# to be called from plugin initialization to register stylesheet files
@@ -384,18 +393,6 @@ module ActionView
@@stylesheet_expansions.merge!(expansions)
end
- # Register one or more additional JavaScript files to be included when
- # <tt>javascript_include_tag :defaults</tt> is called. This method is
- # typically intended to be called from plugin initialization to register additional
- # .js files that the plugin installed in <tt>public/javascripts</tt>.
- def self.register_javascript_include_default(*sources)
- @@javascript_expansions[:defaults].concat(sources)
- end
-
- def self.reset_javascript_include_default #:nodoc:
- @@javascript_expansions[:defaults] = JAVASCRIPT_DEFAULT_SOURCES.dup
- end
-
# Computes the path to a stylesheet asset in the public stylesheets directory.
# If the +source+ filename has no extension, <tt>.css</tt> will be appended (except for explicit URIs).
# Full paths from the document root will be passed through.
@@ -706,23 +703,8 @@ module ActionView
tag("audio", options)
end
- def self.cache_asset_timestamps
- @@cache_asset_timestamps
- end
-
- # You can enable or disable the asset tag timestamps cache.
- # With the cache enabled, the asset tag helper methods will make fewer
- # expensive file system calls. However this prevents you from modifying
- # any asset files while the server is running.
- #
- # ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
- def self.cache_asset_timestamps=(value)
- @@cache_asset_timestamps = value
- end
-
- @@cache_asset_timestamps = true
-
private
+
def rewrite_extension?(source, dir, ext)
source_ext = File.extname(source)[1..-1]
ext && (source_ext.blank? || (ext != source_ext && File.exist?(File.join(config.assets_dir, dir, "#{source}.#{ext}"))))
diff --git a/actionpack/lib/action_view/helpers/atom_feed_helper.rb b/actionpack/lib/action_view/helpers/atom_feed_helper.rb
index 52806f206a..cb5a1404ff 100644
--- a/actionpack/lib/action_view/helpers/atom_feed_helper.rb
+++ b/actionpack/lib/action_view/helpers/atom_feed_helper.rb
@@ -1,10 +1,12 @@
require 'set'
-# Adds easy defaults to writing Atom feeds with the Builder template engine (this does not work on ERb or any other
-# template languages).
module ActionView
+ # = Action View Atom Feed Helpers
module Helpers #:nodoc:
module AtomFeedHelper
+ # Adds easy defaults to writing Atom feeds with the Builder template engine (this does not work on ERb or any other
+ # template languages).
+ #
# Full usage example:
#
# config/routes.rb:
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb
index 8251ed18f4..f544a9d147 100644
--- a/actionpack/lib/action_view/helpers/cache_helper.rb
+++ b/actionpack/lib/action_view/helpers/cache_helper.rb
@@ -1,8 +1,10 @@
module ActionView
+ # = Action View Cache Helper
module Helpers
- # This helper to exposes a method for caching of view fragments.
- # See ActionController::Caching::Fragments for usage instructions.
module CacheHelper
+ # This helper to exposes a method for caching of view fragments.
+ # See ActionController::Caching::Fragments for usage instructions.
+ #
# A method for caching fragments of a view rather than an entire
# action or page. This technique is useful caching pieces like
# menus, lists of news topics, static HTML fragments, and so on.
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index edc6afc622..f9105ca364 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -1,9 +1,11 @@
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Capture Helper
module Helpers
# CaptureHelper exposes methods to let you extract generated markup which
# can be used in other parts of a template or layout file.
+ #
# It provides a method to capture blocks into variables through capture and
# a way to capture a block of markup for use in a layout through content_for.
module CaptureHelper
@@ -176,9 +178,7 @@ module ActionView
def flush_output_buffer #:nodoc:
if output_buffer && !output_buffer.empty?
response.body_parts << output_buffer
- new = ''
- new.force_encoding(output_buffer.encoding) if new.respond_to?(:force_encoding)
- self.output_buffer = new
+ self.output_buffer = output_buffer[0,0]
nil
end
end
diff --git a/actionpack/lib/action_view/helpers/csrf_helper.rb b/actionpack/lib/action_view/helpers/csrf_helper.rb
index 41c6b67f91..3d03f6aac6 100644
--- a/actionpack/lib/action_view/helpers/csrf_helper.rb
+++ b/actionpack/lib/action_view/helpers/csrf_helper.rb
@@ -1,7 +1,9 @@
module ActionView
+ # = Action View CSRF Helper
module Helpers
module CsrfHelper
- # Returns a meta tag with the request forgery protection token for forms to use. Put this in your head.
+ # 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
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 7d846a01dd..f097b9a5a3 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -4,6 +4,8 @@ require 'active_support/core_ext/hash/slice'
module ActionView
module Helpers
+ # = Action View Date Helpers
+ #
# The Date Helper primarily creates select/option tags for different kinds of dates and date elements. All of the
# select-type methods share a number of common options that are as follows:
#
@@ -580,10 +582,10 @@ module ActionView
extend ActiveSupport::Memoizable
include ActionView::Helpers::TagHelper
- DEFAULT_PREFIX = 'date'.freeze unless const_defined?('DEFAULT_PREFIX')
+ DEFAULT_PREFIX = 'date'.freeze
POSITION = {
:year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6
- }.freeze unless const_defined?('POSITION')
+ }.freeze
def initialize(datetime, options = {}, html_options = {})
@options = options.dup
@@ -894,8 +896,10 @@ module ActionView
# Returns the separator for a given datetime component
def separator(type)
case type
- when :month, :day
- @options[:date_separator]
+ when :month
+ @options[:discard_month] ? "" : @options[:date_separator]
+ when :day
+ @options[:discard_day] ? "" : @options[:date_separator]
when :hour
(@options[:discard_year] && @options[:discard_day]) ? "" : @options[:datetime_separator]
when :minute
diff --git a/actionpack/lib/action_view/helpers/debug_helper.rb b/actionpack/lib/action_view/helpers/debug_helper.rb
index e637dc1474..1491cb073f 100644
--- a/actionpack/lib/action_view/helpers/debug_helper.rb
+++ b/actionpack/lib/action_view/helpers/debug_helper.rb
@@ -1,6 +1,8 @@
module ActionView
+ # = Action View Debug Helper
+ #
+ # Provides a set of methods for making it easier to debug Rails objects.
module Helpers
- # Provides a set of methods for making it easier to debug Rails objects.
module DebugHelper
# Returns a YAML representation of +object+ wrapped with <pre> and </pre>.
# If the object cannot be converted to YAML using +to_yaml+, +inspect+ will be called instead.
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index b3db3151d3..d1b10a9281 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -7,6 +7,7 @@ require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Form Helpers
module Helpers
# Form helpers are designed to make working with resources much easier
# compared to using vanilla HTML.
@@ -92,7 +93,7 @@ module ActionView
# # error handling
# end
#
- # That's how you tipically work with resources.
+ # That's how you typically work with resources.
module FormHelper
extend ActiveSupport::Concern
@@ -123,7 +124,6 @@ module ActionView
# model:
#
# <%= form_for :person do |f| %>
- # <%= f.error_messages %>
# First name: <%= f.text_field :first_name %><br />
# Last name : <%= f.text_field :last_name %><br />
# Biography : <%= f.text_area :biography %><br />
@@ -220,15 +220,15 @@ module ActionView
# <% end %>
#
# === Unobtrusive JavaScript
- #
- # Specifying:
- #
+ #
+ # Specifying:
+ #
# :remote => true
#
# in the options hash creates a form that will allow the unobtrusive JavaScript drivers to modify its
- # behaviour. The expected default behaviour is an XMLHttpRequest in the background instead of the regular
+ # behaviour. The expected default behaviour is an XMLHttpRequest in the background instead of the regular
# POST arrangement, but ultimately the behaviour is the choice of the JavaScript driver implementor.
- # Even though it's using JavaScript to serialize the form elements, the form submission will work just like
+ # Even though it's using JavaScript to serialize the form elements, the form submission will work just like
# a regular submission as viewed by the receiving side (all elements available in <tt>params</tt>).
#
# Example:
@@ -269,7 +269,7 @@ module ActionView
# <tt>labelling_form</tt>.
#
# The custom FormBuilder class is automatically merged with the options
- # of a nested fields_for call, unless it's explicitely set.
+ # of a nested fields_for call, unless it's explicitly set.
#
# In many cases you will want to wrap the above in another helper, so you
# could do something like the following:
@@ -302,7 +302,7 @@ module ActionView
args.unshift object
end
- options[:html][:remote] = true if options.delete(:remote)
+ (options[:html] ||= {})[:remote] = true if options.delete(:remote)
output = form_tag(options.delete(:url) || {}, options.delete(:html) || {})
output << fields_for(object_name, *(args << options), &proc)
@@ -717,7 +717,7 @@ module ActionView
#
# To prevent this the helper generates an auxiliary hidden field before
# the very check box. The hidden field has the same name and its
- # attributes mimick an unchecked check box.
+ # attributes mimic an unchecked check box.
#
# This way, the client either sends only the hidden field (representing
# the check box is unchecked), or both fields. Since the HTML specification
@@ -838,9 +838,9 @@ module ActionView
attr_reader :method_name, :object_name
- DEFAULT_FIELD_OPTIONS = { "size" => 30 }.freeze unless const_defined?(:DEFAULT_FIELD_OPTIONS)
- DEFAULT_RADIO_OPTIONS = { }.freeze unless const_defined?(:DEFAULT_RADIO_OPTIONS)
- DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }.freeze unless const_defined?(:DEFAULT_TEXT_AREA_OPTIONS)
+ DEFAULT_FIELD_OPTIONS = { "size" => 30 }.freeze
+ DEFAULT_RADIO_OPTIONS = { }.freeze
+ DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }.freeze
def initialize(object_name, method_name, template_object, object = nil)
@object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup
@@ -897,7 +897,7 @@ module ActionView
options.delete("size")
end
options["type"] ||= field_type
- options["value"] ||= value_before_type_cast(object) unless field_type == "file"
+ options["value"] = options.fetch("value"){ value_before_type_cast(object) } unless field_type == "file"
options["value"] &&= html_escape(options["value"])
add_default_name_and_id(options)
tag("input", options)
@@ -1030,7 +1030,7 @@ module ActionView
private
def add_default_name_and_id_for_value(tag_value, options)
unless tag_value.nil?
- pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/\W/, "").downcase
+ pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase
specified_id = options["id"]
add_default_name_and_id(options)
options["id"] += "_#{pretty_tag_value}" if specified_id.blank? && options["id"].present?
@@ -1042,14 +1042,14 @@ module ActionView
def add_default_name_and_id(options)
if options.has_key?("index")
options["name"] ||= tag_name_with_index(options["index"])
- options["id"] = options.fetch("id", tag_id_with_index(options["index"]))
+ options["id"] = options.fetch("id"){ tag_id_with_index(options["index"]) }
options.delete("index")
elsif defined?(@auto_index)
options["name"] ||= tag_name_with_index(@auto_index)
- options["id"] = options.fetch("id", tag_id_with_index(@auto_index))
+ options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) }
else
options["name"] ||= tag_name + (options.has_key?('multiple') ? '[]' : '')
- options["id"] = options.fetch("id", tag_id)
+ options["id"] = options.fetch("id"){ tag_id }
end
end
@@ -1180,7 +1180,7 @@ module ActionView
# <%= form_for @post do |f| %>
# <%= f.submit %>
# <% end %>
- #
+ #
# In the example above, if @post is a new record, it will use "Create Post" as
# submit button label, otherwise, it uses "Update Post".
#
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index fe71d2cdf7..6f9d14de8b 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -4,6 +4,7 @@ require 'action_view/helpers/form_helper'
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Form Option Helpers
module Helpers
# Provides a number of methods for turning different kinds of containers into a set of option tags.
# == Options
@@ -398,7 +399,7 @@ module ActionView
options_for_select += "<optgroup label=\"#{html_escape(group_label_string)}\">"
options_for_select += options_from_collection_for_select(eval("group.#{group_method}"), option_key_method, option_value_method, selected_key)
options_for_select += '</optgroup>'
- end
+ end.html_safe
end
# Returns a string of <tt><option></tt> tags, like <tt>options_for_select</tt>, but
@@ -412,8 +413,8 @@ module ActionView
# * +selected_key+ - A value equal to the +value+ attribute for one of the <tt><option></tt> tags,
# which will have the +selected+ attribute set. Note: It is possible for this value to match multiple options
# as you might have the same option in multiple groups. Each will then get <tt>selected="selected"</tt>.
- # * +prompt+ - set to true or a prompt string. When the select element doesn’t have a value yet, this
- # prepends an option with a generic prompt — "Please select" — or the given prompt string.
+ # * +prompt+ - set to true or a prompt string. When the select element doesn't have a value yet, this
+ # prepends an option with a generic prompt - "Please select" - or the given prompt string.
#
# Sample usage (Array):
# grouped_options = [
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 796268628a..4c1b751160 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -4,6 +4,7 @@ require 'active_support/core_ext/object/returning'
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Form Tag Helpers
module Helpers
# Provides a number of methods for creating form tags that doesn't rely on an Active Record object assigned to the template like
# FormHelper does. Instead, you provide the names and values manually.
@@ -528,23 +529,34 @@ module ActionView
def html_options_for_form(url_for_options, options, *parameters_for_url)
returning options.stringify_keys do |html_options|
html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart")
+ # The following URL is unescaped, this is just a hash of options, and it is the
+ # responsability of the caller to escape all the values.
html_options["action"] = url_for(url_for_options, *parameters_for_url)
+ html_options["accept-charset"] = "UTF-8"
html_options["data-remote"] = true if html_options.delete("remote")
end
end
def extra_tags_for_form(html_options)
- case method = html_options.delete("method").to_s
- when /^get$/i # must be case-insentive, but can't use downcase as might be nil
+ snowman_tag = tag(:input, :type => "hidden",
+ :name => "_snowman", :value => "&#9731;".html_safe)
+
+ method = html_options.delete("method").to_s
+
+ method_tag = case method
+ when /^get$/i # must be case-insensitive, but can't use downcase as might be nil
html_options["method"] = "get"
''
when /^post$/i, "", nil
html_options["method"] = "post"
- protect_against_forgery? ? content_tag(:div, token_tag, :style => 'margin:0;padding:0;display:inline') : ''
+ token_tag
else
html_options["method"] = "post"
- content_tag(:div, tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag, :style => 'margin:0;padding:0;display:inline')
+ tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag
end
+
+ tags = snowman_tag << method_tag
+ content_tag(:div, tags, :style => 'margin:0;padding:0;display:inline')
end
def form_tag_html(html_options)
diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index b0a7718f22..84f53b842c 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -1,6 +1,7 @@
require 'action_view/helpers/tag_helper'
module ActionView
+ # = Action View JavaScript Helpers
module Helpers
# Provides functionality for working with JavaScript in your views.
#
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 3b0dfb561c..37e5d91d8b 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -3,6 +3,7 @@ require 'active_support/core_ext/float/rounding'
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Number Helpers
module Helpers #:nodoc:
# Provides methods for converting numbers into formatted strings.
@@ -332,7 +333,7 @@ module ActionView
# number_to_human_size(483989, :precision => 2) # => 470 KB
# number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,2 MB
#
- # Unsignificant zeros after the fractional separator are stripped out by default (set
+ # Non-significant zeros after the fractional separator are stripped out by default (set
# <tt>:strip_insignificant_zeros</tt> to +false+ to change that):
# number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB"
# number_to_human_size(524288000, :precision=>5) # => "500 MB"
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index a798c3eaef..5c0ff5d59c 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -1,9 +1,9 @@
require 'set'
require 'active_support/json'
-require 'active_support/core_ext/object/returning'
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Prototype Helpers
module Helpers
# Prototype[http://www.prototypejs.org/] is a JavaScript library that provides
# DOM[http://en.wikipedia.org/wiki/Document_Object_Model] manipulation,
@@ -94,14 +94,12 @@ module ActionView
# See JavaScriptGenerator for information on updating multiple elements
# on the page in an Ajax response.
module PrototypeHelper
- unless const_defined? :CALLBACKS
- CALLBACKS = Set.new([ :create, :uninitialized, :loading, :loaded,
- :interactive, :complete, :failure, :success ] +
- (100..599).to_a)
- AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url,
- :asynchronous, :method, :insertion, :position,
- :form, :with, :update, :script, :type ]).merge(CALLBACKS)
- end
+ CALLBACKS = Set.new([ :create, :uninitialized, :loading, :loaded,
+ :interactive, :complete, :failure, :success ] +
+ (100..599).to_a)
+ AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url,
+ :asynchronous, :method, :insertion, :position,
+ :form, :with, :update, :script, :type ]).merge(CALLBACKS)
# Returns the JavaScript needed for a remote function.
# Takes the same arguments as link_to_remote.
@@ -133,7 +131,7 @@ module ActionView
url_options = options[:url]
url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
- function << "'#{escape_javascript(url_for(url_options))}'"
+ function << "'#{html_escape(escape_javascript(url_for(url_options)))}'"
function << ", #{javascript_options})"
function = "#{options[:before]}; #{function}" if options[:before]
@@ -229,7 +227,7 @@ module ActionView
# <script> tag.
module GeneratorMethods
def to_s #:nodoc:
- returning javascript = @lines * $/ do
+ (@lines * $/).tap do |javascript|
if ActionView::Base.debug_rjs
source = javascript.dup
javascript.replace "try {\n#{source}\n} catch (e) "
@@ -531,9 +529,9 @@ module ActionView
end
def record(line)
- returning line = "#{line.to_s.chomp.gsub(/\;\z/, '')};" do
- self << line
- end
+ line = "#{line.to_s.chomp.gsub(/\;\z/, '')};"
+ self << line
+ line
end
def render(*options)
diff --git a/actionpack/lib/action_view/helpers/raw_output_helper.rb b/actionpack/lib/action_view/helpers/raw_output_helper.rb
index 8c7f41177d..da7599fa8f 100644
--- a/actionpack/lib/action_view/helpers/raw_output_helper.rb
+++ b/actionpack/lib/action_view/helpers/raw_output_helper.rb
@@ -1,6 +1,15 @@
module ActionView #:nodoc:
+ # = Action View Raw Output Helper
module Helpers #:nodoc:
module RawOutputHelper
+ # This method outputs without escaping a string. Since escaping tags is
+ # now default, this can be used when you don't want Rails to automatically
+ # escape tags. This is not recommended if the data is coming from the user's
+ # input.
+ #
+ # For example:
+ #
+ # <%=raw @user.name %>
def raw(stringish)
stringish.to_s.html_safe
end
diff --git a/actionpack/lib/action_view/helpers/record_identification_helper.rb b/actionpack/lib/action_view/helpers/record_identification_helper.rb
index 6c235bff3d..372f1cb8aa 100644
--- a/actionpack/lib/action_view/helpers/record_identification_helper.rb
+++ b/actionpack/lib/action_view/helpers/record_identification_helper.rb
@@ -1,4 +1,7 @@
module ActionView
+ # = Action View Record Identification Helpers
+ #
+ # See ActionController::RecordIdentifier for documentation on these methods.
module Helpers
module RecordIdentificationHelper
# See ActionController::RecordIdentifier.partial_path -- this is just a delegate to that for convenient access in the view.
diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb
index a9cf15f418..7433f08777 100644
--- a/actionpack/lib/action_view/helpers/record_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb
@@ -1,4 +1,5 @@
module ActionView
+ # = Action View Record Tag Helpers
module Helpers
module RecordTagHelper
# Produces a wrapper DIV element with id and class parameters that
diff --git a/actionpack/lib/action_view/helpers/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb
index f173523f6a..b47818a22a 100644
--- a/actionpack/lib/action_view/helpers/sanitize_helper.rb
+++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb
@@ -2,19 +2,25 @@ require 'action_controller/vendor/html-scanner'
require 'action_view/helpers/tag_helper'
module ActionView
+ # = Action View Sanitize Helpers
module Helpers #:nodoc:
# The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements.
# These helper methods extend Action View making them callable within your template files.
module SanitizeHelper
- # This +sanitize+ helper will html encode all tags and strip all attributes that aren't specifically allowed.
- # It also strips href/src tags with invalid protocols, like javascript: especially. It does its best to counter any
- # tricks that hackers may use, like throwing in unicode/ascii/hex values to get past the javascript: filters. Check out
+ # This +sanitize+ helper will html encode all tags and strip all attributes that
+ # aren't specifically allowed.
+ #
+ # It also strips href/src tags with invalid protocols, like javascript: especially.
+ # It does its best to counter any tricks that hackers may use, like throwing in
+ # unicode/ascii/hex values to get past the javascript: filters. Check out
# the extensive test suite.
#
# <%= sanitize @article.body %>
#
- # You can add or remove tags/attributes if you want to customize it a bit. See ActionView::Base for full docs on the
- # available options. You can add tags/attributes for single uses of +sanitize+ by passing either the <tt>:attributes</tt> or <tt>:tags</tt> options:
+ # You can add or remove tags/attributes if you want to customize it a bit.
+ # See ActionView::Base for full docs on the available options. You can add
+ # tags/attributes for single uses of +sanitize+ by passing either the
+ # <tt>:attributes</tt> or <tt>:tags</tt> options:
#
# Normal Use
#
diff --git a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
index 37319cca1b..8610c2469e 100644
--- a/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
+++ b/actionpack/lib/action_view/helpers/scriptaculous_helper.rb
@@ -2,9 +2,11 @@ require 'action_view/helpers/javascript_helper'
require 'active_support/json'
module ActionView
+ # = Action View Scriptaculous Helpers
module Helpers
- # Provides a set of helpers for calling Scriptaculous JavaScript
- # functions, including those which create Ajax controls and visual effects.
+ # Provides a set of helpers for calling Scriptaculous[http://script.aculo.us/]
+ # JavaScript functions, including those which create Ajax controls and visual
+ # effects.
#
# To be able to use these helpers, you must include the Prototype
# JavaScript framework and the Scriptaculous JavaScript library in your
@@ -12,12 +14,11 @@ module ActionView
# for more information on including the necessary JavaScript.
#
# The Scriptaculous helpers' behavior can be tweaked with various options.
+ #
# See the documentation at http://script.aculo.us for more information on
# using these helpers in your application.
module ScriptaculousHelper
- unless const_defined? :TOGGLE_EFFECTS
- TOGGLE_EFFECTS = [:toggle_appear, :toggle_slide, :toggle_blind]
- end
+ TOGGLE_EFFECTS = [:toggle_appear, :toggle_slide, :toggle_blind]
# Returns a JavaScript snippet to be used on the Ajax callbacks for
# starting visual effects.
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb
index 66277f79fe..5d032b32a7 100644
--- a/actionpack/lib/action_view/helpers/tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/tag_helper.rb
@@ -2,6 +2,7 @@ require 'active_support/core_ext/object/blank'
require 'set'
module ActionView
+ # = Action View Tag Helpers
module Helpers #:nodoc:
# Provides methods to generate HTML tags programmatically when you can't use
# a Builder. By default, they output XHTML compliant tags.
@@ -121,7 +122,7 @@ module ActionView
attrs << %(#{key}="#{key}") if value
elsif !value.nil?
final_value = value.is_a?(Array) ? value.join(" ") : value
- final_value = escape_once(final_value) if escape
+ final_value = html_escape(final_value) if escape
attrs << %(#{key}="#{final_value}")
end
end
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index c7f96597b9..0be8a2c36e 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -3,6 +3,7 @@ require 'active_support/core_ext/string/filters'
require 'action_view/helpers/tag_helper'
module ActionView
+ # = Action View Text Helpers
module Helpers #:nodoc:
# The TextHelper module provides a set of methods for filtering, formatting
# and transforming strings, which can reduce the amount of inline Ruby code in
@@ -52,7 +53,7 @@ module ActionView
# truncate("Once upon a time in a world far far away", :length => 17)
# # => "Once upon a ti..."
#
- # truncate("Once upon a time in a world far far away", :lenght => 17, :separator => ' ')
+ # truncate("Once upon a time in a world far far away", :length => 17, :separator => ' ')
# # => "Once upon a..."
#
# truncate("And they found that many people were sleeping better.", :length => 25, :omission => '... (continued)')
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
index 0d2b2aa7b1..dac9c28ab7 100644
--- a/actionpack/lib/action_view/helpers/translation_helper.rb
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -1,21 +1,28 @@
require 'action_view/helpers/tag_helper'
module ActionView
+ # = Action View Translation Helpers
module Helpers
module TranslationHelper
- # Delegates to I18n#translate but also performs three additional functions. First, it'll catch MissingTranslationData exceptions
- # and turn them into inline spans that contains the missing key, such that you can see in a view what is missing where.
+ # Delegates to I18n#translate but also performs three additional functions.
+ # First, it'll catch MissingTranslationData exceptions and turn them into
+ # inline spans that contains the missing key, such that you can see in a
+ # view what is missing where.
#
- # Second, it'll scope the key by the current partial if the key starts with a period. So if you call translate(".foo") from the
- # people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo"). This makes it less repetitive
- # to translate many keys within the same partials and gives you a simple framework for scoping them consistently. If you don't
- # prepend the key with a period, nothing is converted.
+ # Second, it'll scope the key by the current partial if the key starts
+ # with a period. So if you call <tt>translate(".foo")</tt> from the
+ # <tt>people/index.html.erb</tt> template, you'll actually be calling
+ # <tt>I18n.translate("people.index.foo")</tt>. This makes it less repetitive
+ # to translate many keys within the same partials and gives you a simple framework
+ # for scoping them consistently. If you don't prepend the key with a period,
+ # nothing is converted.
#
- # Third, it’ll mark the translation as safe HTML if the key has the suffix "_html" or the last element of the key is the word
- # "html". For example, calling translate("footer_html") or translate("footer.html") will return a safe HTML string that won’t
- # be escaped by other HTML helper methods. This naming convention helps to identify translations that include HTML tags so that
+ # Third, it'll mark the translation as safe HTML if the key has the suffix
+ # "_html" or the last element of the key is the word "html". For example,
+ # calling translate("footer_html") or translate("footer.html") will return
+ # a safe HTML string that won't be escaped by other HTML helper methods. This
+ # naming convention helps to identify translations that include HTML tags so that
# you know what kind of output to expect when you call translate in a template.
-
def translate(key, options = {})
translation = I18n.translate(scope_key_by_partial(key), options.merge!(:raise => true))
if html_safe_translation_key?(key) && translation.respond_to?(:html_safe)
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 210f148c02..b8d6dc22f2 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -4,6 +4,7 @@ require 'active_support/core_ext/hash/keys'
require 'action_dispatch'
module ActionView
+ # = Action View URL Helpers
module Helpers #:nodoc:
# Provides a set of methods for making links and getting URLs that
# depend on the routing subsystem (see ActionDispatch::Routing).
@@ -12,7 +13,7 @@ module ActionView
module UrlHelper
# This helper may be included in any class that includes the
# URL helpers of a router (router.url_helpers). Some methods
- # provided here will only work in the context of a request
+ # provided here will only work in the4 context of a request
# (link_to_unless_current, for instance), which must be provided
# as a method called #request on the context.
@@ -37,9 +38,6 @@ module ActionView
# <tt>:only_path</tt> is <tt>true</tt> so you'll get the relative "/controller/action"
# instead of the fully qualified URL like "http://example.com/controller/action".
#
- # When called from a view, +url_for+ returns an HTML escaped url. If you
- # need an unescaped url, pass <tt>:escape => false</tt> in the +options+.
- #
# ==== Options
# * <tt>:anchor</tt> - Specifies the anchor name to be appended to the path.
# * <tt>:only_path</tt> - If true, returns the relative URL (omitting the protocol, host name, and port) (<tt>true</tt> by default unless <tt>:host</tt> is specified).
@@ -49,7 +47,6 @@ module ActionView
# * <tt>:protocol</tt> - Overrides the default (current) protocol if provided.
# * <tt>:user</tt> - Inline HTTP authentication (only plucked out if <tt>:password</tt> is also present).
# * <tt>:password</tt> - Inline HTTP authentication (only plucked out if <tt>:user</tt> is also present).
- # * <tt>:escape</tt> - Determines whether the returned URL will be HTML escaped or not (<tt>true</tt> by default).
#
# ==== Relying on named routes
#
@@ -71,10 +68,7 @@ module ActionView
# <%= url_for(:action => 'play', :anchor => 'player') %>
# # => /messages/play/#player
#
- # <%= url_for(:action => 'checkout', :anchor => 'tax&ship') %>
- # # => /testing/jump/#tax&amp;ship
- #
- # <%= url_for(:action => 'checkout', :anchor => 'tax&ship', :escape => false) %>
+ # <%= url_for(:action => 'jump', :anchor => 'tax&ship') %>
# # => /testing/jump/#tax&ship
#
# <%= url_for(Workshop.new) %>
@@ -99,21 +93,17 @@ module ActionView
options ||= {}
url = case options
when String
- escape = true
options
when Hash
options = { :only_path => options[:host].nil? }.update(options.symbolize_keys)
- escape = options.key?(:escape) ? options.delete(:escape) : false
super
when :back
- escape = false
controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
else
- escape = false
polymorphic_path(options)
end
- escape ? escape_once(url).html_safe : url
+ url
end
# Creates a link tag of the given +name+ using a URL created by the set
@@ -253,8 +243,8 @@ module ActionView
tag_options = nil
end
- href_attr = "href=\"#{url}\"" unless href
- "<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe
+ href_attr = "href=\"#{html_escape(url)}\"" unless href
+ "<a #{href_attr}#{tag_options}>#{html_escape(name || url)}</a>".html_safe
end
end
@@ -338,7 +328,7 @@ module ActionView
html_options.merge!("type" => "submit", "value" => name)
- ("<form method=\"#{form_method}\" action=\"#{escape_once url}\" #{"data-remote=\"true\"" if remote} class=\"button_to\"><div>" +
+ ("<form method=\"#{form_method}\" action=\"#{html_escape(url)}\" #{"data-remote=\"true\"" if remote} class=\"button_to\"><div>" +
method_tag + tag("input", html_options) + request_token_tag + "</div></form>").html_safe
end
@@ -484,24 +474,27 @@ module ActionView
# :subject => "This is an example email"
# # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a>
def mail_to(email_address, name = nil, html_options = {})
+ email_address = html_escape(email_address)
+
html_options = html_options.stringify_keys
encode = html_options.delete("encode").to_s
cc, bcc, subject, body = html_options.delete("cc"), html_options.delete("bcc"), html_options.delete("subject"), html_options.delete("body")
- string = ''
- extras = ''
- extras << "cc=#{Rack::Utils.escape(cc).gsub("+", "%20")}&" unless cc.nil?
- extras << "bcc=#{Rack::Utils.escape(bcc).gsub("+", "%20")}&" unless bcc.nil?
- extras << "body=#{Rack::Utils.escape(body).gsub("+", "%20")}&" unless body.nil?
- extras << "subject=#{Rack::Utils.escape(subject).gsub("+", "%20")}&" unless subject.nil?
- extras = "?" << extras.gsub!(/&?$/,"") unless extras.empty?
-
- email_address_obfuscated = html_escape(email_address)
+ extras = []
+ extras << "cc=#{Rack::Utils.escape(cc).gsub("+", "%20")}" unless cc.nil?
+ extras << "bcc=#{Rack::Utils.escape(bcc).gsub("+", "%20")}" unless bcc.nil?
+ extras << "body=#{Rack::Utils.escape(body).gsub("+", "%20")}" unless body.nil?
+ extras << "subject=#{Rack::Utils.escape(subject).gsub("+", "%20")}" unless subject.nil?
+ extras = extras.empty? ? '' : '?' + html_escape(extras.join('&'))
+
+ email_address_obfuscated = email_address.dup
email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.has_key?("replace_at")
email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot")
+ string = ''
+
if encode == "javascript"
- "document.write('#{content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge({ "href" => "mailto:"+email_address+extras }))}');".each_byte do |c|
+ "document.write('#{content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe))}');".each_byte do |c|
string << sprintf("%%%x", c)
end
"<script type=\"#{Mime::JS}\">eval(decodeURIComponent('#{string}'))</script>".html_safe
@@ -518,9 +511,9 @@ module ActionView
char = c.chr
string << (char =~ /\w/ ? sprintf("%%%x", c) : char)
end
- content_tag "a", name || email_address_encoded.html_safe, html_options.merge({ "href" => "#{string}#{extras}" })
+ content_tag "a", name || email_address_encoded.html_safe, html_options.merge("href" => "#{string}#{extras}".html_safe)
else
- content_tag "a", name || email_address_obfuscated.html_safe, html_options.merge({ "href" => "mailto:#{email_address}#{extras}" })
+ content_tag "a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe)
end
end
@@ -573,7 +566,7 @@ module ActionView
"in a #request method"
end
- url_string = CGI.unescapeHTML(url_for(options))
+ url_string = url_for(options)
# We ignore any extra parameters in the request_uri if the
# submitted url doesn't have any either. This lets the function
diff --git a/actionpack/lib/action_view/log_subscriber.rb b/actionpack/lib/action_view/log_subscriber.rb
new file mode 100644
index 0000000000..443a0eafd1
--- /dev/null
+++ b/actionpack/lib/action_view/log_subscriber.rb
@@ -0,0 +1,28 @@
+module ActionView
+ # = Action View Log Subscriber
+ #
+ # Provides functionality so that Rails can output logs from Action View.
+ class LogSubscriber < ActiveSupport::LogSubscriber
+ def render_template(event)
+ message = "Rendered #{from_rails_root(event.payload[:identifier])}"
+ message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
+ message << (" (%.1fms)" % event.duration)
+ info(message)
+ end
+ alias :render_partial :render_template
+ alias :render_collection :render_template
+
+ # TODO: Ideally, ActionView should have its own logger so it does not depend on AC.logger
+ def logger
+ ActionController::Base.logger if defined?(ActionController::Base)
+ end
+
+ protected
+
+ def from_rails_root(string)
+ string.sub("#{Rails.root}/", "").sub(/^app\/views\//, "")
+ end
+ end
+end
+
+ActionView::LogSubscriber.attach_to :action_view
diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb
index 823226cb9c..3ea8b86af1 100644
--- a/actionpack/lib/action_view/lookup_context.rb
+++ b/actionpack/lib/action_view/lookup_context.rb
@@ -2,6 +2,8 @@ require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Lookup Context
+ #
# LookupContext is the object responsible to hold all information required to lookup
# templates, i.e. view paths and details. The LookupContext is also responsible to
# generate a key, given to view paths, used in the resolver cache lookup. Since
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index 7f5e5d11b8..9857d688d2 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -1,4 +1,5 @@
module ActionView #:nodoc:
+ # = Action View PathSet
class PathSet < Array #:nodoc:
%w(initialize << concat insert push unshift).each do |method|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
diff --git a/actionpack/lib/action_view/railtie.rb b/actionpack/lib/action_view/railtie.rb
index c606a71e18..33dfcbb803 100644
--- a/actionpack/lib/action_view/railtie.rb
+++ b/actionpack/lib/action_view/railtie.rb
@@ -2,11 +2,11 @@ require "action_view"
require "rails"
module ActionView
+ # = Action View Railtie
class Railtie < Rails::Railtie
config.action_view = ActiveSupport::OrderedOptions.new
-
- require "action_view/railties/log_subscriber"
- log_subscriber :action_view, ActionView::Railties::LogSubscriber.new
+ config.action_view.stylesheet_expansions = {}
+ config.action_view.javascript_expansions = { :defaults => ['prototype', 'effects', 'dragdrop', 'controls', 'rails'] }
initializer "action_view.cache_asset_timestamps" do |app|
unless app.config.cache_classes
@@ -16,6 +16,18 @@ module ActionView
end
end
+ initializer "action_view.javascript_expansions" do |app|
+ ActiveSupport.on_load(:action_view) do
+ ActionView::Helpers::AssetTagHelper.register_javascript_expansion(
+ app.config.action_view.delete(:javascript_expansions)
+ )
+
+ ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion(
+ app.config.action_view.delete(:stylesheet_expansions)
+ )
+ end
+ end
+
initializer "action_view.set_configs" do |app|
ActiveSupport.on_load(:action_view) do
app.config.action_view.each do |k,v|
diff --git a/actionpack/lib/action_view/railties/log_subscriber.rb b/actionpack/lib/action_view/railties/log_subscriber.rb
deleted file mode 100644
index 9487a10706..0000000000
--- a/actionpack/lib/action_view/railties/log_subscriber.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-module ActionView
- module Railties
- class LogSubscriber < Rails::LogSubscriber
- def render_template(event)
- message = "Rendered #{from_rails_root(event.payload[:identifier])}"
- message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
- message << (" (%.1fms)" % event.duration)
- info(message)
- end
- alias :render_partial :render_template
- alias :render_collection :render_template
-
- def logger
- ActionController::Base.logger
- end
-
- protected
-
- def from_rails_root(string)
- string.sub("#{Rails.root}/", "").sub(/^app\/views\//, "")
- end
- end
- end
-end \ No newline at end of file
diff --git a/actionpack/lib/action_view/render/layouts.rb b/actionpack/lib/action_view/render/layouts.rb
index a9dfc0cced..a474783a20 100644
--- a/actionpack/lib/action_view/render/layouts.rb
+++ b/actionpack/lib/action_view/render/layouts.rb
@@ -1,4 +1,5 @@
module ActionView
+ # = Action View Layouts
module Layouts
# Returns the contents that are yielded to a layout, given a name or a block.
#
@@ -55,7 +56,7 @@ module ActionView
end
# This is the method which actually finds the layout using details in the lookup
- # context object. If no layout is found, it checkes if at least a layout with
+ # context object. If no layout is found, it checks if at least a layout with
# the given name exists across all details before raising the error.
def find_layout(layout)
begin
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index 85f67d4f14..459aae94a2 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -1,6 +1,8 @@
require 'active_support/core_ext/object/blank'
module ActionView
+ # = Action View Partials
+ #
# There's also a convenience method for rendering sub templates within the current controller that depends on a
# single object (we call this kind of sub templates for partials). It relies on the fact that partials should
# follow the naming convention of being prefixed with an underscore -- as to separate them from regular
@@ -316,7 +318,7 @@ module ActionView
object.class.model_name.partial_path.dup.tap do |partial|
path = @view.controller_path
- partial.insert(0, "#{File.dirname(path)}/") if path.include?(?/)
+ partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/)
end
end
end
diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb
index 4d35296932..5320245173 100644
--- a/actionpack/lib/action_view/render/rendering.rb
+++ b/actionpack/lib/action_view/render/rendering.rb
@@ -1,6 +1,7 @@
require 'active_support/core_ext/object/try'
module ActionView
+ # = Action View Rendering
module Rendering
# Returns the result of a render that's dictated by the options hash. The primary options are:
#
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 53ad24fdc6..40ff1f2182 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -3,6 +3,7 @@ require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/kernel/singleton_class'
module ActionView
+ # = Action View Template
class Template
extend ActiveSupport::Autoload
@@ -155,11 +156,12 @@ module ActionView
end
def inspect
- if defined?(Rails.root)
- identifier.sub("#{Rails.root}/", '')
- else
- identifier
- end
+ @inspect ||=
+ if defined?(Rails.root)
+ identifier.sub("#{Rails.root}/", '')
+ else
+ identifier
+ end
end
private
@@ -266,9 +268,11 @@ module ActionView
end
def build_method_name(locals)
- # TODO: is locals.keys.hash reliably the same?
- @method_names[locals.keys.hash] ||=
- "_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_")
+ @method_names[locals.keys.hash] ||= "_#{identifier_method_name}__#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_")
+ end
+
+ def identifier_method_name
+ @identifier_method_name ||= inspect.gsub(/[^a-z_]/, '_')
end
end
end
diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb
index e50de7e5af..b1839b65e5 100644
--- a/actionpack/lib/action_view/template/error.rb
+++ b/actionpack/lib/action_view/template/error.rb
@@ -1,6 +1,7 @@
require "active_support/core_ext/enumerable"
module ActionView
+ # = Action View Errors
class ActionViewError < StandardError #:nodoc:
end
diff --git a/actionpack/lib/action_view/template/handlers.rb b/actionpack/lib/action_view/template/handlers.rb
index 6228d7ac39..84d6474dd1 100644
--- a/actionpack/lib/action_view/template/handlers.rb
+++ b/actionpack/lib/action_view/template/handlers.rb
@@ -1,4 +1,5 @@
module ActionView #:nodoc:
+ # = Action View Template Handlers
class Template
module Handlers #:nodoc:
autoload :ERB, 'action_view/template/handlers/erb'
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb
index ef44925951..c9e20ca14e 100644
--- a/actionpack/lib/action_view/template/resolver.rb
+++ b/actionpack/lib/action_view/template/resolver.rb
@@ -3,6 +3,7 @@ require "active_support/core_ext/class"
require "action_view/template"
module ActionView
+ # = Action View Resolver
class Resolver
def initialize
@cached = Hash.new { |h1,k1| h1[k1] =
@@ -98,7 +99,7 @@ module ActionView
def initialize(path)
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
super()
- @path = Pathname.new(path).expand_path
+ @path = File.expand_path(path)
end
def eql?(resolver)
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index 269340514c..51be831dfb 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -1,4 +1,5 @@
module ActionView #:nodoc:
+ # = Action View Text Template
class Template
class Text < String #:nodoc:
attr_accessor :mime_type
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 15d424be74..e5614c9e3b 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -4,6 +4,7 @@ require 'action_controller/test_case'
require 'action_view'
module ActionView
+ # = Action View Test Case
class TestCase < ActiveSupport::TestCase
class TestController < ActionController::Base
include ActionDispatch::TestProcess
@@ -84,6 +85,7 @@ module ActionView
def setup_with_controller
@controller = ActionView::TestCase::TestController.new
+ @request = @controller.request
@output_buffer = ActiveSupport::SafeBuffer.new
@rendered = ''
@@ -97,10 +99,15 @@ module ActionView
end
def render(options = {}, local_assigns = {}, &block)
- @rendered << output = _view.render(options, local_assigns, &block)
+ view.assign(_assigns)
+ @rendered << output = view.render(options, local_assigns, &block)
output
end
+ def locals
+ @locals ||= {}
+ end
+
included do
setup :setup_with_controller
end
@@ -130,36 +137,51 @@ module ActionView
end
end
- def _view
- @_view ||= begin
- view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller)
+ module Locals
+ attr_accessor :locals
+
+ def _render_partial(options)
+ locals[options[:partial]] = options[:locals]
+ super(options)
+ end
+ end
+
+ # The instance of ActionView::Base that is used by +render+.
+ def view
+ @view ||= begin
+ view = ActionView::Base.new(ActionController::Base.view_paths, {}, @controller)
view.singleton_class.send :include, _helpers
view.singleton_class.send :include, @controller._router.url_helpers
view.singleton_class.send :delegate, :alert, :notice, :to => "request.flash"
+ view.extend(Locals)
+ view.locals = self.locals
view.output_buffer = self.output_buffer
view
end
end
+ alias_method :_view, :view
+
EXCLUDE_IVARS = %w{
+ @_assertion_wrapped
@_result
+ @controller
+ @layouts
+ @locals
+ @method_name
@output_buffer
+ @partials
@rendered
+ @request
+ @routes
@templates
- @view_context_class
- @layouts
- @partials
- @controller
-
- @method_name
- @fixture_cache
- @loaded_fixtures
@test_passed
+ @view
+ @view_context_class
}
def _instance_variables
- instance_variables - EXCLUDE_IVARS
- instance_variables
+ instance_variables.map(&:to_s) - EXCLUDE_IVARS
end
def _assigns