aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2008-05-15 21:54:46 +0100
committerPratik Naik <pratiknaik@gmail.com>2008-05-15 21:54:46 +0100
commit879493c35fd8d9e12e5cf3e56cd67ff07c3345c5 (patch)
tree9615859e1d9a52f71da444b0b7359817bb6acc50 /actionpack/lib
parentd6ecce66f4e125531875006eea8022b73fe135b5 (diff)
parentfc02eabf296d6edb74a95174c7322293a54c9492 (diff)
downloadrails-879493c35fd8d9e12e5cf3e56cd67ff07c3345c5.tar.gz
rails-879493c35fd8d9e12e5cf3e56cd67ff07c3345c5.tar.bz2
rails-879493c35fd8d9e12e5cf3e56cd67ff07c3345c5.zip
Merge commit 'mainstream/master'
Conflicts: actionmailer/lib/action_mailer/base.rb
Diffstat (limited to 'actionpack/lib')
-rwxr-xr-xactionpack/lib/action_controller.rb2
-rwxr-xr-xactionpack/lib/action_controller/base.rb51
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb37
-rw-r--r--actionpack/lib/action_controller/caching/sweeping.rb6
-rw-r--r--actionpack/lib/action_controller/cgi_ext/cookie.rb2
-rw-r--r--actionpack/lib/action_controller/mime_type.rb19
-rw-r--r--actionpack/lib/action_controller/mime_types.rb2
-rw-r--r--actionpack/lib/action_controller/request_forgery_protection.rb2
-rw-r--r--actionpack/lib/action_controller/rescue.rb6
-rw-r--r--actionpack/lib/action_controller/session/cookie_store.rb9
-rw-r--r--actionpack/lib/action_pack.rb2
-rw-r--r--actionpack/lib/action_pack/version.rb2
-rw-r--r--actionpack/lib/action_view.rb2
-rw-r--r--actionpack/lib/action_view/helpers/javascripts/controls.js2
-rw-r--r--actionpack/lib/action_view/helpers/javascripts/dragdrop.js2
-rw-r--r--actionpack/lib/action_view/helpers/javascripts/effects.js2
-rw-r--r--actionpack/lib/action_view/helpers/prototype_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb127
18 files changed, 142 insertions, 135 deletions
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index 919fbc6c6a..810a5fb9b5 100755
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2007 David Heinemeier Hansson
+# Copyright (c) 2004-2008 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index e1bf005f39..ea55fe42ce 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -259,12 +259,12 @@ module ActionController #:nodoc:
DEFAULT_RENDER_STATUS_CODE = "200 OK"
include StatusCodes
-
+
# Controller specific instance variables which will not be accessible inside views.
@@protected_view_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller
@action_name @before_filter_chain_aborted @action_cache_path @_session @_cookies @_headers @_params
@_flash @_response)
-
+
# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
# and images to a dedicated asset server away from the main web server. Example:
# ActionController::Base.asset_host = "http://assets.example.com"
@@ -325,7 +325,7 @@ module ActionController #:nodoc:
# Controls the default charset for all renders.
@@default_charset = "utf-8"
cattr_accessor :default_charset
-
+
# The logger is used for generating information on the action run-time (including benchmarking) if available.
# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
cattr_accessor :logger
@@ -333,7 +333,7 @@ module ActionController #:nodoc:
# Controls the resource action separator
@@resource_action_separator = "/"
cattr_accessor :resource_action_separator
-
+
# Allow to override path names for default resources' actions
@@resources_path_names = { :new => 'new', :edit => 'edit' }
cattr_accessor :resources_path_names
@@ -433,7 +433,7 @@ module ActionController #:nodoc:
end
# Adds a view_path to the front of the view_paths array.
- # If the current class has no view paths, copy them from
+ # If the current class has no view paths, copy them from
# the superclass. This change will be visible for all future requests.
#
# ArticleController.prepend_view_path("views/default")
@@ -444,9 +444,9 @@ module ActionController #:nodoc:
view_paths.unshift(*path)
ActionView::TemplateFinder.process_view_paths(path)
end
-
+
# Adds a view_path to the end of the view_paths array.
- # If the current class has no view paths, copy them from
+ # If the current class has no view paths, copy them from
# the superclass. This change will be visible for all future requests.
#
# ArticleController.append_view_path("views/default")
@@ -457,7 +457,7 @@ module ActionController #:nodoc:
view_paths.push(*path)
ActionView::TemplateFinder.process_view_paths(path)
end
-
+
# Replace sensitive parameter data from the request log.
# Filters parameters that have any of the arguments as a substring.
# Looks in all subhashes of the param hash for keys to filter.
@@ -504,6 +504,7 @@ module ActionController #:nodoc:
filtered_parameters
end
+ protected :filter_parameters
end
# Don't render layouts for templates with the given extensions.
@@ -643,12 +644,12 @@ module ActionController #:nodoc:
end
self.view_paths = []
-
+
# View load paths for controller.
def view_paths
@template.finder.view_paths
end
-
+
def view_paths=(value)
@template.finder.view_paths = value # Mutex needed
end
@@ -662,7 +663,7 @@ module ActionController #:nodoc:
def prepend_view_path(path)
@template.finder.prepend_view_path(path) # Mutex needed
end
-
+
# Adds a view_path to the end of the view_paths array.
# This change affects the current request only.
#
@@ -874,10 +875,10 @@ module ActionController #:nodoc:
elsif action_name = options[:action]
template = default_template_name(action_name.to_s)
if options[:layout] && !template_exempt_from_layout?(template)
- render_with_a_layout(:file => template, :status => options[:status], :use_full_path => true, :layout => true)
+ render_with_a_layout(:file => template, :status => options[:status], :use_full_path => true, :layout => true)
else
render_with_no_layout(:file => template, :status => options[:status], :use_full_path => true)
- end
+ end
elsif xml = options[:xml]
response.content_type ||= Mime::XML
@@ -895,12 +896,12 @@ module ActionController #:nodoc:
if collection = options[:collection]
render_for_text(
- @template.send!(:render_partial_collection, partial, collection,
+ @template.send!(:render_partial_collection, partial, collection,
options[:spacer_template], options[:locals]), options[:status]
)
else
render_for_text(
- @template.send!(:render_partial, partial,
+ @template.send!(:render_partial, partial,
ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]), options[:status]
)
end
@@ -1024,7 +1025,7 @@ module ActionController #:nodoc:
# redirect_to articles_url
# redirect_to :back
#
- # The redirection happens as a "302 Moved" header unless otherwise specified.
+ # The redirection happens as a "302 Moved" header unless otherwise specified.
#
# Examples:
# redirect_to post_url(@post), :status=>:found
@@ -1035,17 +1036,17 @@ module ActionController #:nodoc:
# 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:
+ def redirect_to(options = {}, response_status = {}) #:doc:
raise ActionControllerError.new("Cannot redirect to nil!") if options.nil?
- if options.is_a?(Hash) && options[:status]
- status = options.delete(:status)
- elsif response_status[:status]
- status = response_status[:status]
- else
- status = 302
+ if options.is_a?(Hash) && options[:status]
+ status = options.delete(:status)
+ elsif response_status[:status]
+ status = response_status[:status]
+ else
+ status = 302
end
-
+
case options
when %r{^\w+://.*}
raise DoubleRenderError if performed?
@@ -1119,7 +1120,7 @@ module ActionController #:nodoc:
response.body = text.is_a?(Proc) ? text : text.to_s
end
end
-
+
def initialize_template_class(response)
response.template = ActionView::Base.new(self.class.view_paths, {}, self)
response.template.extend self.class.master_helper_module
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index 7b0551c664..1ef9e60a21 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -9,7 +9,7 @@ module ActionController #:nodoc:
# class ListsController < ApplicationController
# before_filter :authenticate, :except => :public
# caches_page :public
- # caches_action :show, :feed
+ # caches_action :index, :show, :feed
# end
#
# In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the
@@ -27,15 +27,19 @@ module ActionController #:nodoc:
# You can set modify the default action cache path by passing a :cache_path option. This will be passed directly to ActionCachePath.path_for. This is handy
# for actions with multiple possible routes that should be cached differently. If a block is given, it is called with the current controller instance.
#
+ # And you can also use :if to pass a Proc that specifies when the action should be cached.
+ #
# class ListsController < ApplicationController
# before_filter :authenticate, :except => :public
# caches_page :public
+ # caches_action :index, :if => Proc.new { |c| !c.request.format.json? } # cache if is not a JSON request
# caches_action :show, :cache_path => { :project => 1 }
- # caches_action :show, :cache_path => Proc.new { |controller|
- # controller.params[:user_id] ?
+ # caches_action :feed, :cache_path => Proc.new { |controller|
+ # controller.params[:user_id] ?
# controller.send(:user_list_url, c.params[:user_id], c.params[:id]) :
# controller.send(:list_url, c.params[:id]) }
# end
+ #
module Actions
def self.included(base) #:nodoc:
base.extend(ClassMethods)
@@ -49,7 +53,8 @@ module ActionController #:nodoc:
# See ActionController::Caching::Actions for details.
def caches_action(*actions)
return unless cache_configured?
- around_filter(ActionCacheFilter.new(*actions))
+ options = actions.extract_options!
+ around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path)), {:only => actions}.merge(options))
end
end
@@ -67,16 +72,12 @@ module ActionController #:nodoc:
end
class ActionCacheFilter #:nodoc:
- def initialize(*actions, &block)
- @options = actions.extract_options!
- @actions = Set.new(actions)
+ def initialize(options, &block)
+ @options = options
end
def before(controller)
- return unless @actions.include?(controller.action_name.intern)
-
cache_path = ActionCachePath.new(controller, path_options_for(controller, @options))
-
if cache = controller.read_fragment(cache_path.path)
controller.rendered_action_cache = true
set_content_type!(controller, cache_path.extension)
@@ -88,7 +89,7 @@ module ActionController #:nodoc:
end
def after(controller)
- return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache || !caching_allowed(controller)
+ return if controller.rendered_action_cache || !caching_allowed(controller)
controller.write_fragment(controller.action_cache_path.path, controller.response.body)
end
@@ -105,16 +106,16 @@ module ActionController #:nodoc:
controller.request.get? && controller.response.headers['Status'].to_i == 200
end
end
-
+
class ActionCachePath
attr_reader :path, :extension
-
+
class << self
def path_for(controller, options)
new(controller, options).path
end
end
-
+
def initialize(controller, options = {})
@extension = extract_extension(controller.request.path)
path = controller.url_for(options).split('://').last
@@ -122,16 +123,16 @@ module ActionController #:nodoc:
add_extension!(path, @extension)
@path = URI.unescape(path)
end
-
+
private
def normalize!(path)
path << 'index' if path[-1] == ?/
end
-
+
def add_extension!(path, extension)
path << ".#{extension}" if extension
end
-
+
def extract_extension(file_path)
# Don't want just what comes after the last '.' to accommodate multi part extensions
# such as tar.gz.
@@ -140,4 +141,4 @@ module ActionController #:nodoc:
end
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/caching/sweeping.rb b/actionpack/lib/action_controller/caching/sweeping.rb
index 3164e14f6f..61559e9ec7 100644
--- a/actionpack/lib/action_controller/caching/sweeping.rb
+++ b/actionpack/lib/action_controller/caching/sweeping.rb
@@ -28,7 +28,7 @@ module ActionController #:nodoc:
# class ListsController < ApplicationController
# caches_action :index, :show, :public, :feed
# cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ]
- # end
+ # end
module Sweeping
def self.included(base) #:nodoc:
base.extend(ClassMethods)
@@ -40,7 +40,7 @@ module ActionController #:nodoc:
sweepers.each do |sweeper|
ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base)
- sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(Inflector.classify(sweeper)) : sweeper).instance
+ sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(sweeper.to_s.classify) : sweeper).instance
if sweeper_instance.is_a?(Sweeper)
around_filter(sweeper_instance, :only => configuration[:only])
@@ -94,4 +94,4 @@ module ActionController #:nodoc:
end
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/cgi_ext/cookie.rb b/actionpack/lib/action_controller/cgi_ext/cookie.rb
index 3dd374f126..a244e2a39a 100644
--- a/actionpack/lib/action_controller/cgi_ext/cookie.rb
+++ b/actionpack/lib/action_controller/cgi_ext/cookie.rb
@@ -37,7 +37,7 @@ class CGI #:nodoc:
@path = nil
else
@name = name['name']
- @value = Array(name['value'])
+ @value = (name['value'].kind_of?(String) ? [name['value']] : Array(name['value'])).delete_if(&:blank?)
@domain = name['domain']
@expires = name['expires']
@secure = name['secure'] || false
diff --git a/actionpack/lib/action_controller/mime_type.rb b/actionpack/lib/action_controller/mime_type.rb
index 8c02f20521..f43e2ba06d 100644
--- a/actionpack/lib/action_controller/mime_type.rb
+++ b/actionpack/lib/action_controller/mime_type.rb
@@ -17,6 +17,10 @@ module Mime
# end
# end
class Type
+ @@html_types = Set.new [:html, :all]
+ @@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
+ cattr_reader :html_types, :unverifiable_types
+
# A simple helper class used in parsing the accept header
class AcceptItem #:nodoc:
attr_accessor :order, :name, :q
@@ -153,12 +157,21 @@ module Mime
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
end
end
-
+
+ # Returns true if ActionPack should check requests using this Mime Type for possible request forgery. See
+ # ActionController::RequestForgerProtection.
+ def verify_request?
+ !@@unverifiable_types.include?(to_sym)
+ end
+
+ def html?
+ @@html_types.include?(to_sym) || @string =~ /html/
+ end
+
private
def method_missing(method, *args)
if method.to_s =~ /(\w+)\?$/
- mime_type = $1.downcase.to_sym
- mime_type == @symbol || (mime_type == :html && @symbol == :all)
+ $1.downcase.to_sym == to_sym
else
super
end
diff --git a/actionpack/lib/action_controller/mime_types.rb b/actionpack/lib/action_controller/mime_types.rb
index 71706b4c41..01a266d3fe 100644
--- a/actionpack/lib/action_controller/mime_types.rb
+++ b/actionpack/lib/action_controller/mime_types.rb
@@ -17,4 +17,4 @@ Mime::Type.register "multipart/form-data", :multipart_form
Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
# http://www.ietf.org/rfc/rfc4627.txt
-Mime::Type.register "application/json", :json, %w( text/x-json )
+Mime::Type.register "application/json", :json, %w( text/x-json ) \ No newline at end of file
diff --git a/actionpack/lib/action_controller/request_forgery_protection.rb b/actionpack/lib/action_controller/request_forgery_protection.rb
index 139e91ecf9..02c9d59d07 100644
--- a/actionpack/lib/action_controller/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/request_forgery_protection.rb
@@ -99,7 +99,7 @@ module ActionController #:nodoc:
end
def verifiable_request_format?
- request.format.html? || request.format.js?
+ request.content_type.nil? || request.content_type.verify_request?
end
# Sets the token value for the current session. Pass a <tt>:secret</tt> option
diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb
index 5022c9a815..40ef4ea044 100644
--- a/actionpack/lib/action_controller/rescue.rb
+++ b/actionpack/lib/action_controller/rescue.rb
@@ -199,10 +199,8 @@ module ActionController #:nodoc:
private
def perform_action_with_rescue #:nodoc:
perform_action_without_rescue
- rescue Exception => exception # errors from action performed
- return if rescue_action_with_handler(exception)
-
- rescue_action(exception)
+ rescue Exception => exception
+ rescue_action_with_handler(exception) || rescue_action(exception)
end
def rescues_path(template_name)
diff --git a/actionpack/lib/action_controller/session/cookie_store.rb b/actionpack/lib/action_controller/session/cookie_store.rb
index 560491f996..ada1862c3e 100644
--- a/actionpack/lib/action_controller/session/cookie_store.rb
+++ b/actionpack/lib/action_controller/session/cookie_store.rb
@@ -130,17 +130,20 @@ class CGI::Session::CookieStore
# Marshal a session hash into safe cookie data. Include an integrity hash.
def marshal(session)
data = ActiveSupport::Base64.encode64(Marshal.dump(session)).chop
- CGI.escape "#{data}--#{generate_digest(data)}"
+ "#{data}--#{generate_digest(data)}"
end
# Unmarshal cookie data to a hash and verify its integrity.
def unmarshal(cookie)
if cookie
- data, digest = CGI.unescape(cookie).split('--')
- unless digest == generate_digest(data)
+ data, digest = cookie.split('--')
+
+ # Do two checks to transparently support old double-escaped data.
+ unless digest == generate_digest(data) || digest == generate_digest(data = CGI.unescape(data))
delete
raise TamperedWithCookie
end
+
Marshal.load(ActiveSupport::Base64.decode64(data))
end
end
diff --git a/actionpack/lib/action_pack.rb b/actionpack/lib/action_pack.rb
index 006c83dbc8..c7fd3092e7 100644
--- a/actionpack/lib/action_pack.rb
+++ b/actionpack/lib/action_pack.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2007 David Heinemeier Hansson
+# Copyright (c) 2004-2008 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb
index 7aa6a5db96..70fc1ced8c 100644
--- a/actionpack/lib/action_pack/version.rb
+++ b/actionpack/lib/action_pack/version.rb
@@ -2,7 +2,7 @@ module ActionPack #:nodoc:
module VERSION #:nodoc:
MAJOR = 2
MINOR = 0
- TINY = 2
+ TINY = 991
STRING = [MAJOR, MINOR, TINY].join('.')
end
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index 609334d52d..5f4126e4e9 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2007 David Heinemeier Hansson
+# Copyright (c) 2004-2008 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_view/helpers/javascripts/controls.js b/actionpack/lib/action_view/helpers/javascripts/controls.js
index fbc4418b83..5aaf0bb2b7 100644
--- a/actionpack/lib/action_view/helpers/javascripts/controls.js
+++ b/actionpack/lib/action_view/helpers/javascripts/controls.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
// Contributors:
diff --git a/actionpack/lib/action_view/helpers/javascripts/dragdrop.js b/actionpack/lib/action_view/helpers/javascripts/dragdrop.js
index ccf4a1e45c..bf5cfea66c 100644
--- a/actionpack/lib/action_view/helpers/javascripts/dragdrop.js
+++ b/actionpack/lib/action_view/helpers/javascripts/dragdrop.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
diff --git a/actionpack/lib/action_view/helpers/javascripts/effects.js b/actionpack/lib/action_view/helpers/javascripts/effects.js
index 65aed23957..f030b5dbe9 100644
--- a/actionpack/lib/action_view/helpers/javascripts/effects.js
+++ b/actionpack/lib/action_view/helpers/javascripts/effects.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 1b12aa8058..1a0e660d52 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -458,7 +458,7 @@ module ActionView
url_options = options[:url]
url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
- function << "'#{url_for(url_options)}'"
+ function << "'#{escape_javascript(url_for(url_options))}'"
function << ", #{javascript_options})"
function = "#{options[:before]}; #{function}" if options[:before]
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index f8c3b67474..9d220c546a 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -3,19 +3,19 @@ require 'html/document'
module ActionView
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
- # your views. These helper methods extend ActionView making them callable
+ # The TextHelper module provides a set of methods for filtering, formatting
+ # and transforming strings, which can reduce the amount of inline Ruby code in
+ # your views. These helper methods extend ActionView making them callable
# within your template files.
- module TextHelper
- # The preferred method of outputting text in your views is to use the
- # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods
- # do not operate as expected in an eRuby code block. If you absolutely must
+ module TextHelper
+ # The preferred method of outputting text in your views is to use the
+ # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods
+ # do not operate as expected in an eRuby code block. If you absolutely must
# output text within a non-output code block (i.e., <% %>), you can use the concat method.
#
# ==== Examples
- # <%
- # concat "hello", binding
+ # <%
+ # concat "hello", binding
# # is the equivalent of <%= "hello" %>
#
# if (logged_in == true):
@@ -30,15 +30,15 @@ module ActionView
end
if RUBY_VERSION < '1.9'
- # If +text+ is longer than +length+, +text+ will be truncated to the length of
+ # If +text+ is longer than +length+, +text+ will be truncated to the length of
# +length+ (defaults to 30) and the last characters will be replaced with the +truncate_string+
# (defaults to "...").
#
# ==== Examples
- # truncate("Once upon a time in a world far far away", 14)
+ # truncate("Once upon a time in a world far far away", 14)
# # => Once upon a...
#
- # truncate("Once upon a time in a world far far away")
+ # truncate("Once upon a time in a world far far away")
# # => Once upon a time in a world f...
#
# truncate("And they found that many people were sleeping better.", 25, "(clipped)")
@@ -63,20 +63,20 @@ module ActionView
end
# Highlights one or more +phrases+ everywhere in +text+ by inserting it into
- # a +highlighter+ string. The highlighter can be specialized by passing +highlighter+
+ # a +highlighter+ string. The highlighter can be specialized by passing +highlighter+
# as a single-quoted string with \1 where the phrase is to be inserted (defaults to
# '<strong class="highlight">\1</strong>')
#
# ==== Examples
- # highlight('You searched for: rails', 'rails')
+ # highlight('You searched for: rails', 'rails')
# # => You searched for: <strong class="highlight">rails</strong>
#
# highlight('You searched for: ruby, rails, dhh', 'actionpack')
- # # => You searched for: ruby, rails, dhh
+ # # => You searched for: ruby, rails, dhh
#
- # highlight('You searched for: rails', ['for', 'rails'], '<em>\1</em>')
+ # highlight('You searched for: rails', ['for', 'rails'], '<em>\1</em>')
# # => You searched <em>for</em>: <em>rails</em>
- #
+ #
# highlight('You searched for: rails', 'rails', "<a href='search?q=\1'>\1</a>")
# # => You searched for: <a href='search?q=rails>rails</a>
def highlight(text, phrases, highlighter = '<strong class="highlight">\1</strong>')
@@ -89,23 +89,23 @@ module ActionView
end
if RUBY_VERSION < '1.9'
- # Extracts an excerpt from +text+ that matches the first instance of +phrase+.
+ # Extracts an excerpt from +text+ that matches the first instance of +phrase+.
# The +radius+ expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters
# defined in +radius+ (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+,
# then the +excerpt_string+ will be prepended/appended accordingly. The resulting string will be stripped in any case.
# If the +phrase+ isn't found, nil is returned.
#
# ==== Examples
- # excerpt('This is an example', 'an', 5)
+ # excerpt('This is an example', 'an', 5)
# # => "...s is an exam..."
#
- # excerpt('This is an example', 'is', 5)
+ # excerpt('This is an example', 'is', 5)
# # => "This is a..."
#
- # excerpt('This is an example', 'is')
+ # excerpt('This is an example', 'is')
# # => "This is an example"
#
- # excerpt('This next thing is an example', 'ex', 2)
+ # excerpt('This next thing is an example', 'ex', 2)
# # => "...next..."
#
# excerpt('This is also an example', 'an', 8, '<chop> ')
@@ -147,33 +147,24 @@ module ActionView
end
end
- # Attempts to pluralize the +singular+ word unless +count+ is 1. If +plural+
- # is supplied, it will use that when count is > 1, if the ActiveSupport Inflector
- # is loaded, it will use the Inflector to determine the plural form, otherwise
- # it will just add an 's' to the +singular+ word.
+ # Attempts to pluralize the +singular+ word unless +count+ is 1. If
+ # +plural+ is supplied, it will use that when count is > 1, otherwise
+ # it will use the Inflector to determine the plural form
#
# ==== Examples
- # pluralize(1, 'person')
+ # pluralize(1, 'person')
# # => 1 person
#
- # pluralize(2, 'person')
+ # pluralize(2, 'person')
# # => 2 people
#
- # pluralize(3, 'person', 'users')
+ # pluralize(3, 'person', 'users')
# # => 3 users
#
# pluralize(0, 'person')
# # => 0 people
def pluralize(count, singular, plural = nil)
- "#{count || 0} " + if count == 1 || count == '1'
- singular
- elsif plural
- plural
- elsif Object.const_defined?("Inflector")
- Inflector.pluralize(singular)
- else
- singular + "s"
- end
+ "#{count || 0} " + ((count == 1 || count == '1') ? singular : (plural || singular.pluralize))
end
# Wraps the +text+ into lines no longer than +line_width+ width. This method
@@ -229,7 +220,7 @@ module ActionView
end
end
- # Returns the text with all the Textile codes turned into HTML tags,
+ # Returns the text with all the Textile codes turned into HTML tags,
# but without the bounding <p> tag that RedCloth adds.
#
# You can learn more about Textile's syntax at its website[http://www.textism.com/tools/textile].
@@ -273,25 +264,25 @@ module ActionView
# # => "<p>We like to <em>write</em> <code>code</code>, not just <em>read</em> it!</p>"
#
# markdown("The [Markdown website](http://daringfireball.net/projects/markdown/) has more information.")
- # # => "<p>The <a href="http://daringfireball.net/projects/markdown/">Markdown website</a>
+ # # => "<p>The <a href="http://daringfireball.net/projects/markdown/">Markdown website</a>
# # has more information.</p>"
#
# markdown('![The ROR logo](http://rubyonrails.com/images/rails.png "Ruby on Rails")')
- # # => '<p><img src="http://rubyonrails.com/images/rails.png" alt="The ROR logo" title="Ruby on Rails" /></p>'
+ # # => '<p><img src="http://rubyonrails.com/images/rails.png" alt="The ROR logo" title="Ruby on Rails" /></p>'
def markdown(text)
text.blank? ? "" : BlueCloth.new(text).to_html
end
rescue LoadError
# We can't really help what's not there
end
-
+
# Returns +text+ transformed into HTML using simple formatting rules.
- # Two or more consecutive newlines(<tt>\n\n</tt>) are considered as a
+ # Two or more consecutive newlines(<tt>\n\n</tt>) are considered as a
# paragraph and wrapped in <tt><p></tt> tags. One newline (<tt>\n</tt>) is
# considered as a linebreak and a <tt><br /></tt> tag is appended. This
- # method does not remove the newlines from the +text+.
+ # method does not remove the newlines from the +text+.
#
- # You can pass any HTML attributes into <tt>html_options</tt>. These
+ # You can pass any HTML attributes into <tt>html_options</tt>. These
# will be added to all created paragraphs.
# ==== Examples
# my_text = "Here is some basic text...\n...with a line break."
@@ -316,19 +307,19 @@ module ActionView
text << "</p>"
end
- # Turns all URLs and e-mail addresses into clickable links. The +link+ parameter
+ # Turns all URLs and e-mail addresses into clickable links. The +link+ parameter
# will limit what should be linked. You can add HTML attributes to the links using
- # +href_options+. Options for +link+ are <tt>:all</tt> (default),
- # <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
+ # +href_options+. Options for +link+ are <tt>:all</tt> (default),
+ # <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
# e-mail address is yielded and the result is used as the link text.
#
# ==== Examples
- # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com")
+ # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com")
# # => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
# # say hello to <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
#
# auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :urls)
- # # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
+ # # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
# # or e-mail david@loudthinking.com"
#
# auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :email_addresses)
@@ -338,9 +329,9 @@ module ActionView
# auto_link(post_body, :all, :target => '_blank') do |text|
# truncate(text, 15)
# end
- # # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
+ # # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
# Please e-mail me at <a href=\"mailto:me@email.com\">me@email.com</a>."
- #
+ #
def auto_link(text, link = :all, href_options = {}, &block)
return '' if text.blank?
case link
@@ -349,15 +340,15 @@ module ActionView
when :urls then auto_link_urls(text, href_options, &block)
end
end
-
+
# Creates a Cycle object whose _to_s_ method cycles through elements of an
- # array every time it is called. This can be used for example, to alternate
- # classes for table rows. You can use named cycles to allow nesting in loops.
- # Passing a Hash as the last parameter with a <tt>:name</tt> key will create a
- # named cycle. You can manually reset a cycle by calling reset_cycle and passing the
+ # array every time it is called. This can be used for example, to alternate
+ # classes for table rows. You can use named cycles to allow nesting in loops.
+ # Passing a Hash as the last parameter with a <tt>:name</tt> key will create a
+ # named cycle. You can manually reset a cycle by calling reset_cycle and passing the
# name of the cycle.
#
- # ==== Examples
+ # ==== Examples
# # Alternate CSS classes for even and odd numbers...
# @items = [1,2,3,4]
# <table>
@@ -370,8 +361,8 @@ module ActionView
#
#
# # Cycle CSS classes for rows, and text colors for values within each row
- # @items = x = [{:first => 'Robert', :middle => 'Daniel', :last => 'James'},
- # {:first => 'Emily', :middle => 'Shannon', :maiden => 'Pike', :last => 'Hicks'},
+ # @items = x = [{:first => 'Robert', :middle => 'Daniel', :last => 'James'},
+ # {:first => 'Emily', :middle => 'Shannon', :maiden => 'Pike', :last => 'Hicks'},
# {:first => 'June', :middle => 'Dae', :last => 'Jones'}]
# <% @items.each do |item| %>
# <tr class="<%= cycle("even", "odd", :name => "row_class") -%>">
@@ -401,8 +392,8 @@ module ActionView
end
return cycle.to_s
end
-
- # Resets a cycle so that it starts from the first element the next time
+
+ # Resets a cycle so that it starts from the first element the next time
# it is called. Pass in +name+ to reset a named cycle.
#
# ==== Example
@@ -428,12 +419,12 @@ module ActionView
class Cycle #:nodoc:
attr_reader :values
-
+
def initialize(first_value, *values)
@values = values.unshift(first_value)
reset
end
-
+
def reset
@index = 0
end
@@ -453,7 +444,7 @@ module ActionView
@_cycles = Hash.new unless defined?(@_cycles)
return @_cycles[name]
end
-
+
def set_cycle(name, cycle_object)
@_cycles = Hash.new unless defined?(@_cycles)
@_cycles[name] = cycle_object
@@ -462,13 +453,13 @@ module ActionView
AUTO_LINK_RE = %r{
( # leading text
<\w+.*?>| # leading HTML tag, or
- [^=!:'"/]| # leading punctuation, or
+ [^=!:'"/]| # leading punctuation, or
^ # beginning of line
)
(
(?:https?://)| # protocol spec, or
(?:www\.) # www.*
- )
+ )
(
[-\w]+ # subdomain or domain
(?:\.[-\w]+)* # remaining subdomains or domain
@@ -502,7 +493,7 @@ module ActionView
body = text.dup
text.gsub(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
text = $1
-
+
if body.match(/<a\b[^>]*>(.*)(#{Regexp.escape(text)})(.*)<\/a>/)
text
else