diff options
Diffstat (limited to 'actionpack/lib')
36 files changed, 416 insertions, 387 deletions
diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb index 02ac111392..599fff81c2 100644 --- a/actionpack/lib/abstract_controller/callbacks.rb +++ b/actionpack/lib/abstract_controller/callbacks.rb @@ -40,19 +40,22 @@ module AbstractController end end - # Skip before, after, and around filters matching any of the names + # Skip before, after, and around action callbacks matching any of the names + # Aliased as skip_filter. # # ==== Parameters # * <tt>names</tt> - A list of valid names that could be used for # callbacks. Note that skipping uses Ruby equality, so it's # impossible to skip a callback defined using an anonymous proc # using #skip_filter - def skip_filter(*names) - skip_before_filter(*names) - skip_after_filter(*names) - skip_around_filter(*names) + def skip_action_callback(*names) + skip_before_action(*names) + skip_after_action(*names) + skip_around_action(*names) end + alias_method :skip_filter, :skip_action_callback + # Take callback names and an optional callback proc, normalize them, # then call the block with each callback. This allows us to abstract # the normalization across several methods that use it. @@ -75,119 +78,138 @@ module AbstractController end ## - # :method: before_filter + # :method: before_action # - # :call-seq: before_filter(names, block) + # :call-seq: before_action(names, block) # - # Append a before filter. See _insert_callbacks for parameter details. + # Append a callback before actions. See _insert_callbacks for parameter details. + # Aliased as before_filter. ## - # :method: prepend_before_filter + # :method: prepend_before_action # - # :call-seq: prepend_before_filter(names, block) + # :call-seq: prepend_before_action(names, block) # - # Prepend a before filter. See _insert_callbacks for parameter details. + # Prepend a callback before actions. See _insert_callbacks for parameter details. + # Aliased as prepend_before_filter. ## - # :method: skip_before_filter + # :method: skip_before_action # - # :call-seq: skip_before_filter(names) + # :call-seq: skip_before_action(names) # - # Skip a before filter. See _insert_callbacks for parameter details. + # Skip a callback before actions. See _insert_callbacks for parameter details. + # Aliased as skip_before_filter. ## - # :method: append_before_filter + # :method: append_before_action # - # :call-seq: append_before_filter(names, block) + # :call-seq: append_before_action(names, block) # - # Append a before filter. See _insert_callbacks for parameter details. + # Append a callback before actions. See _insert_callbacks for parameter details. + # Aliased as append_before_filter. ## - # :method: after_filter + # :method: after_action # - # :call-seq: after_filter(names, block) + # :call-seq: after_action(names, block) # - # Append an after filter. See _insert_callbacks for parameter details. + # Append a callback after actions. See _insert_callbacks for parameter details. + # Aliased as after_filter. ## - # :method: prepend_after_filter + # :method: prepend_after_action # - # :call-seq: prepend_after_filter(names, block) + # :call-seq: prepend_after_action(names, block) # - # Prepend an after filter. See _insert_callbacks for parameter details. + # Prepend a callback after actions. See _insert_callbacks for parameter details. + # Aliased as prepend_after_filter. ## - # :method: skip_after_filter + # :method: skip_after_action # - # :call-seq: skip_after_filter(names) + # :call-seq: skip_after_action(names) # - # Skip an after filter. See _insert_callbacks for parameter details. + # Skip a callback after actions. See _insert_callbacks for parameter details. + # Aliased as skip_after_filter. ## - # :method: append_after_filter + # :method: append_after_action # - # :call-seq: append_after_filter(names, block) + # :call-seq: append_after_action(names, block) # - # Append an after filter. See _insert_callbacks for parameter details. + # Append a callback after actions. See _insert_callbacks for parameter details. + # Aliased as append_after_filter. ## - # :method: around_filter + # :method: around_action # - # :call-seq: around_filter(names, block) + # :call-seq: around_action(names, block) # - # Append an around filter. See _insert_callbacks for parameter details. + # Append a callback around actions. See _insert_callbacks for parameter details. + # Aliased as around_filter. ## - # :method: prepend_around_filter + # :method: prepend_around_action # - # :call-seq: prepend_around_filter(names, block) + # :call-seq: prepend_around_action(names, block) # - # Prepend an around filter. See _insert_callbacks for parameter details. + # Prepend a callback around actions. See _insert_callbacks for parameter details. + # Aliased as prepend_around_filter. ## - # :method: skip_around_filter + # :method: skip_around_action # - # :call-seq: skip_around_filter(names) + # :call-seq: skip_around_action(names) # - # Skip an around filter. See _insert_callbacks for parameter details. + # Skip a callback around actions. See _insert_callbacks for parameter details. + # Aliased as skip_around_filter. ## - # :method: append_around_filter + # :method: append_around_action # - # :call-seq: append_around_filter(names, block) + # :call-seq: append_around_action(names, block) # - # Append an around filter. See _insert_callbacks for parameter details. + # Append a callback around actions. See _insert_callbacks for parameter details. + # Aliased as append_around_filter. - # set up before_filter, prepend_before_filter, skip_before_filter, etc. + # set up before_action, prepend_before_action, skip_before_action, etc. # for each of before, after, and around. - [:before, :after, :around].each do |filter| + [:before, :after, :around].each do |callback| class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 - # Append a before, after or around filter. See _insert_callbacks + # Append a before, after or around callback. See _insert_callbacks # for details on the allowed parameters. - def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk) - _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| - set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before, name, options) - end # end - end # end + def #{callback}_action(*names, &blk) # def before_action(*names, &blk) + _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| + set_callback(:process_action, :#{callback}, name, options) # set_callback(:process_action, :before, name, options) + end # end + end # end + + alias_method :#{callback}_filter, :#{callback}_action - # Prepend a before, after or around filter. See _insert_callbacks + # Prepend a before, after or around callback. See _insert_callbacks # for details on the allowed parameters. - def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk) - _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| - set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true)) - end # end - end # end + def prepend_#{callback}_action(*names, &blk) # def prepend_before_action(*names, &blk) + _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| + set_callback(:process_action, :#{callback}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true)) + end # end + end # end + + alias_method :prepend_#{callback}_filter, :prepend_#{callback}_action - # Skip a before, after or around filter. See _insert_callbacks + # Skip a before, after or around callback. See _insert_callbacks # for details on the allowed parameters. - def skip_#{filter}_filter(*names) # def skip_before_filter(*names) - _insert_callbacks(names) do |name, options| # _insert_callbacks(names) do |name, options| - skip_callback(:process_action, :#{filter}, name, options) # skip_callback(:process_action, :before, name, options) - end # end - end # end - - # *_filter is the same as append_*_filter - alias_method :append_#{filter}_filter, :#{filter}_filter # alias_method :append_before_filter, :before_filter + def skip_#{callback}_action(*names) # def skip_before_action(*names) + _insert_callbacks(names) do |name, options| # _insert_callbacks(names) do |name, options| + skip_callback(:process_action, :#{callback}, name, options) # skip_callback(:process_action, :before, name, options) + end # end + end # end + + alias_method :skip_#{callback}_filter, :skip_#{callback}_action + + # *_action is the same as append_*_action + alias_method :append_#{callback}_action, :#{callback}_action # alias_method :append_before_action, :before_action + alias_method :append_#{callback}_filter, :#{callback}_action # alias_method :append_before_filter, :before_action RUBY_EVAL end end diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb index d3929b685c..d4e73bf257 100644 --- a/actionpack/lib/abstract_controller/helpers.rb +++ b/actionpack/lib/abstract_controller/helpers.rb @@ -58,11 +58,10 @@ module AbstractController # The +helper+ class method can take a series of helper module names, a block, or both. # - # ==== Parameters + # ==== Options # * <tt>*args</tt> - Module, Symbol, String, :all # * <tt>block</tt> - A block defining helper methods # - # ==== Examples # When the argument is a module it will be included directly in the template class. # helper FooHelper # => includes FooHelper # diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index 177da1c8a0..2892e093af 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -6,8 +6,7 @@ module ActionController # \Caching is a cheap way of speeding up slow applications by keeping the result of # calculations, renderings, and database calls around for subsequent requests. # - # You can read more about each approach and the by clicking the - # modules below. + # You can read more about each approach by clicking the modules below. # # Note: To turn off all caching, set # config.action_controller.perform_caching = false. diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index 426adfe675..3f9b382a11 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -42,7 +42,7 @@ module ActionController # * <tt>:public</tt> By default the Cache-Control header is private, set this to # +true+ if you want your application to be cachable by other devices (proxy caches). # - # === Example: + # === Example: # # def show # @article = Article.find(params[:id]) diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb index c38d8ccef3..f1e8714a86 100644 --- a/actionpack/lib/action_controller/metal/force_ssl.rb +++ b/actionpack/lib/action_controller/metal/force_ssl.rb @@ -32,14 +32,14 @@ module ActionController # ==== Options # * <tt>host</tt> - Redirect to a different host name # * <tt>only</tt> - The callback should be run only for this action - # * <tt>except</tt> - The callback should be run for all actions except this action + # * <tt>except</tt> - The callback should be run for all actions except this action # * <tt>if</tt> - A symbol naming an instance method or a proc; the callback # will be called only when it returns a true value. # * <tt>unless</tt> - A symbol naming an instance method or a proc; the callback # will be called only when it returns a false value. def force_ssl(options = {}) host = options.delete(:host) - before_filter(options) do + before_action(options) do force_ssl_redirect(host) end end diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index d3b5bafee1..283f6413ec 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -25,7 +25,7 @@ module ActionController # the regular HTML interface is protected by a session approach: # # class ApplicationController < ActionController::Base - # before_filter :set_account, :authenticate + # before_action :set_account, :authenticate # # protected # def set_account @@ -68,7 +68,7 @@ module ActionController module ClassMethods def http_basic_authenticate_with(options = {}) - before_filter(options.except(:name, :password, :realm)) do + before_action(options.except(:name, :password, :realm)) do authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password| name == options[:name] && password == options[:password] end @@ -124,7 +124,7 @@ module ActionController # USERS = {"dhh" => "secret", #plain text password # "dap" => Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":"))} #ha1 digest password # - # before_filter :authenticate, except: [:index] + # before_action :authenticate, except: [:index] # # def index # render text: "Everyone can see me!" @@ -317,7 +317,7 @@ module ActionController # class PostsController < ApplicationController # TOKEN = "secret" # - # before_filter :authenticate, except: [ :index ] + # before_action :authenticate, except: [ :index ] # # def index # render text: "Everyone can see me!" @@ -340,7 +340,7 @@ module ActionController # the regular HTML interface is protected by a session approach: # # class ApplicationController < ActionController::Base - # before_filter :set_account, :authenticate + # before_action :set_account, :authenticate # # protected # def set_account diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb index ca4ae532ca..d3aa8f90c5 100644 --- a/actionpack/lib/action_controller/metal/instrumentation.rb +++ b/actionpack/lib/action_controller/metal/instrumentation.rb @@ -60,7 +60,7 @@ module ActionController ActiveSupport::Notifications.instrument("redirect_to.action_controller") do |payload| result = super payload[:status] = response.status - payload[:location] = response.location + payload[:location] = response.filtered_location result end end diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 265ce5d6f3..c5db0cb0d4 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -19,7 +19,7 @@ module ActionController #:nodoc: # # class ApplicationController < ActionController::Base # protect_from_forgery - # skip_before_filter :verify_authenticity_token, if: :json_request? + # skip_before_action :verify_authenticity_token, if: :json_request? # # protected # @@ -66,15 +66,15 @@ module ActionController #:nodoc: # # You can disable csrf protection on controller-by-controller basis: # - # skip_before_filter :verify_authenticity_token + # skip_before_action :verify_authenticity_token # # It can also be disabled for specific controller actions: # - # skip_before_filter :verify_authenticity_token, except: [:create] + # skip_before_action :verify_authenticity_token, except: [:create] # # Valid Options: # - # * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call. Set which actions are verified. + # * <tt>:only/:except</tt> - Passed to the <tt>before_action</tt> call. Set which actions are verified. # * <tt>:with</tt> - Set the method to handle unverified request. # # Valid unverified request handling methods are: @@ -84,7 +84,7 @@ module ActionController #:nodoc: def protect_from_forgery(options = {}) include protection_method_module(options[:with] || :null_session) self.request_forgery_protection_token ||= :authenticity_token - prepend_before_filter :verify_authenticity_token, options + prepend_before_action :verify_authenticity_token, options end private @@ -152,7 +152,7 @@ module ActionController #:nodoc: end protected - # The actual before_filter that is used. Modify this to change how you handle unverified requests. + # The actual before_action that is used. Modify this to change how you handle unverified requests. def verify_authenticity_token unless verified_request? logger.warn "Can't verify CSRF token authenticity" if logger diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb index 4eb582648e..0b3c438ec2 100644 --- a/actionpack/lib/action_controller/metal/streaming.rb +++ b/actionpack/lib/action_controller/metal/streaming.rb @@ -21,8 +21,6 @@ module ActionController #:nodoc: # supports fibers (fibers are supported since version 1.9.2 of the main # Ruby implementation). # - # == Examples - # # Streaming can be added to a given template easily, all you need to do is # to pass the :stream option. # diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb index 386075bd30..25e72adbe0 100644 --- a/actionpack/lib/action_controller/metal/strong_parameters.rb +++ b/actionpack/lib/action_controller/metal/strong_parameters.rb @@ -163,7 +163,7 @@ module ActionController # } # }) # - # permitted = params.permit(person: [ :name, { pets: :name } ]) + # permitted = params.permit(person: [ :name, { pets: :name } ]) # permitted.permitted? # => true # permitted[:person][:name] # => "Francesco" # permitted[:person][:age] # => nil @@ -228,7 +228,7 @@ module ActionController # Returns a parameter for the given +key+. If not found, # returns +nil+. # - # params = ActionController::Parameters.new(person: { name: 'Francesco' }) + # params = ActionController::Parameters.new(person: { name: 'Francesco' }) # params[:person] # => {"name"=>"Francesco"} # params[:none] # => nil def [](key) diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 1d716a3248..d002babee3 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -75,6 +75,7 @@ module ActionDispatch autoload :Parameters autoload :ParameterFilter autoload :FilterParameters + autoload :FilterRedirect autoload :Upload autoload :UploadedFile, 'action_dispatch/http/upload' autoload :URL diff --git a/actionpack/lib/action_dispatch/http/filter_redirect.rb b/actionpack/lib/action_dispatch/http/filter_redirect.rb new file mode 100644 index 0000000000..900ce1c646 --- /dev/null +++ b/actionpack/lib/action_dispatch/http/filter_redirect.rb @@ -0,0 +1,37 @@ +module ActionDispatch + module Http + module FilterRedirect + + FILTERED = '[FILTERED]'.freeze # :nodoc: + + def filtered_location + if !location_filter.empty? && location_filter_match? + FILTERED + else + location + end + end + + private + + def location_filter + if request.present? + request.env['action_dispatch.redirect_filter'] || [] + else + [] + end + end + + def location_filter_match? + location_filter.any? do |filter| + if String === filter + location.include?(filter) + elsif Regexp === filter + location.match(filter) + end + end + end + + end + end +end diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index 0f98e84788..57660e93c4 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -68,7 +68,7 @@ module ActionDispatch # that are not controlled by the extension. # # class ApplicationController < ActionController::Base - # before_filter :adjust_format_for_iphone + # before_action :adjust_format_for_iphone # # private # def adjust_format_for_iphone @@ -87,7 +87,7 @@ module ActionDispatch # to the :html format. # # class ApplicationController < ActionController::Base - # before_filter :adjust_format_for_iphone_with_html_fallback + # before_action :adjust_format_for_iphone_with_html_fallback # # private # def adjust_format_for_iphone_with_html_fallback diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 11b7534ea4..0f808ac9cf 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -61,6 +61,7 @@ module ActionDispatch # :nodoc: cattr_accessor(:default_headers) include Rack::Response::Helpers + include ActionDispatch::Http::FilterRedirect include ActionDispatch::Http::Cache::Response include MonitorMixin diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb index 7b18c57420..f24e9b8e18 100644 --- a/actionpack/lib/action_dispatch/middleware/flash.rb +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -105,7 +105,7 @@ module ActionDispatch super end - def []=(k, v) #:nodoc: + def []=(k, v) @discard.delete k @flashes[k] = v end diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 98c87d9b2d..5a835ae439 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -1,7 +1,7 @@ require "action_dispatch" module ActionDispatch - class Railtie < Rails::Railtie + class Railtie < Rails::Railtie # :nodoc: config.action_dispatch = ActiveSupport::OrderedOptions.new config.action_dispatch.x_sendfile_header = nil config.action_dispatch.ip_spoofing_check = true diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index 4417cb841a..d55eb8109a 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -191,8 +191,6 @@ module ActionDispatch # <tt>:any</tt> which means that the route will respond to any of the HTTP # methods. # - # Examples: - # # match 'post/:id' => 'posts#show', via: :get # match 'post/:id' => 'posts#create_comment', via: :post # @@ -204,8 +202,6 @@ module ActionDispatch # An alternative method of specifying which HTTP method a route should respond to is to use the helper # methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>. # - # Examples: - # # get 'post/:id' => 'posts#show' # post 'post/:id' => 'posts#create_comment' # diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 0c19b493ab..3c99932e72 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -158,7 +158,7 @@ module ActionDispatch def requirements @requirements ||= (@options[:constraints].is_a?(Hash) ? @options[:constraints] : {}).tap do |requirements| requirements.reverse_merge!(@scope[:constraints]) if @scope[:constraints] - @options.each { |k, v| requirements[k] = v if v.is_a?(Regexp) } + @options.each { |k, v| requirements[k] ||= v if v.is_a?(Regexp) } end end @@ -624,8 +624,6 @@ module ActionDispatch # # Takes same options as <tt>Base#match</tt> and <tt>Resources#resources</tt>. # - # === Examples - # # # route /posts (without the prefix /admin) to <tt>Admin::PostsController</tt> # scope module: "admin" do # resources :posts @@ -706,8 +704,6 @@ module ActionDispatch # For options, see <tt>Base#match</tt>. For +:shallow_path+ option, see # <tt>Resources#resources</tt>. # - # === Examples - # # # accessible through /sekret/posts rather than /admin/posts # namespace :admin, path: "sekret" do # resources :posts @@ -1052,15 +1048,7 @@ module ActionDispatch get :new end if parent_resource.actions.include?(:new) - member do - get :edit if parent_resource.actions.include?(:edit) - get :show if parent_resource.actions.include?(:show) - if parent_resource.actions.include?(:update) - patch :update - put :update - end - delete :destroy if parent_resource.actions.include?(:destroy) - end + set_member_mappings_for_resource end self @@ -1219,15 +1207,7 @@ module ActionDispatch get :new end if parent_resource.actions.include?(:new) - member do - get :edit if parent_resource.actions.include?(:edit) - get :show if parent_resource.actions.include?(:show) - if parent_resource.actions.include?(:update) - patch :update - put :update - end - delete :destroy if parent_resource.actions.include?(:destroy) - end + set_member_mappings_for_resource end self @@ -1578,6 +1558,18 @@ module ActionDispatch end end end + + def set_member_mappings_for_resource + member do + get :edit if parent_resource.actions.include?(:edit) + get :show if parent_resource.actions.include?(:show) + if parent_resource.actions.include?(:update) + patch :update + put :update + end + delete :destroy if parent_resource.actions.include?(:destroy) + end + end end # Routing Concerns allow you to declare common routes that can be reused diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 497ac3d545..6d3f8da932 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -74,8 +74,6 @@ module ActionDispatch # * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>. # Default is <tt>:url</tt>. # - # ==== Examples - # # # an Article record # polymorphic_url(record) # same as article_url(record) # diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index 2207a43afc..e481f3b245 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -155,8 +155,6 @@ module ActionDispatch # If the method is called with a block, once all equality tests are # evaluated the block is called with an array of all matched elements. # - # ==== Examples - # # # At least one form element # assert_select "form" # diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 29a5ccedc1..cf2a117966 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -32,6 +32,9 @@ module ActionView # You can modify the HTML attributes of the script tag by passing a hash as the # last argument. # + # When the Asset Pipeline is enabled, you can pass the name of your manifest as + # source, and include other JavaScript or CoffeeScript files inside the manifest. + # # javascript_include_tag "xmlhr" # # => <script src="/assets/xmlhr.js?1284139606"></script> # @@ -106,19 +109,18 @@ module ActionView # * <tt>:type</tt> - Override the auto-generated mime type # * <tt>:title</tt> - Specify the title of the link, defaults to the +type+ # - # ==== Examples - # auto_discovery_link_tag - # # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/action" /> - # auto_discovery_link_tag(:atom) - # # => <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.currenthost.com/controller/action" /> - # auto_discovery_link_tag(:rss, {action: "feed"}) - # # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/feed" /> - # auto_discovery_link_tag(:rss, {action: "feed"}, {title: "My RSS"}) - # # => <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.currenthost.com/controller/feed" /> - # auto_discovery_link_tag(:rss, {controller: "news", action: "feed"}) - # # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/news/feed" /> - # auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {title: "Example RSS"}) - # # => <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed" /> + # auto_discovery_link_tag + # # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/action" /> + # auto_discovery_link_tag(:atom) + # # => <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.currenthost.com/controller/action" /> + # auto_discovery_link_tag(:rss, {action: "feed"}) + # # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/feed" /> + # auto_discovery_link_tag(:rss, {action: "feed"}, {title: "My RSS"}) + # # => <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.currenthost.com/controller/feed" /> + # auto_discovery_link_tag(:rss, {controller: "news", action: "feed"}) + # # => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/news/feed" /> + # auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {title: "Example RSS"}) + # # => <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed" /> def auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {}) if !(type == :rss || type == :atom) && tag_options[:type].blank? message = "You have passed type other than :rss or :atom to auto_discovery_link_tag and haven't supplied " + @@ -137,27 +139,24 @@ module ActionView ) end - # <%= favicon_link_tag %> - # - # generates - # - # <link href="/assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" /> - # - # You may specify a different file in the first argument: + # Returns a link loading a favicon file. You may specify a different file + # in the first argument. The helper accepts an additional options hash where + # you can override "rel" and "type". # - # <%= favicon_link_tag '/myicon.ico' %> - # - # That's passed to +path_to_image+ as is, so it gives - # - # <link href="/myicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" /> + # ==== Options + # * <tt>:rel</tt> - Specify the relation of this link, defaults to 'shortcut icon' + # * <tt>:type</tt> - Override the auto-generated mime type, defaults to 'image/vnd.microsoft.icon' # - # The helper accepts an additional options hash where you can override "rel" and "type". + # favicon_link_tag '/myicon.ico' + # # => <link href="/assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" /> # - # For example, Mobile Safari looks for a different LINK tag, pointing to an image that + # Mobile Safari looks for a different <link> tag, pointing to an image that # will be used if you add the page to the home screen of an iPod Touch, iPhone, or iPad. # The following call would generate such a tag: # - # <%= favicon_link_tag 'mb-icon.png', rel: 'apple-touch-icon', type: 'image/png' %> + # favicon_link_tag '/mb-icon.png', rel: 'apple-touch-icon', type: 'image/png' + # # => <link href="/assets/mb-icon.png" rel="apple-touch-icon" type="image/png" /> + # def favicon_link_tag(source='favicon.ico', options={}) tag('link', { :rel => 'shortcut icon', @@ -166,7 +165,7 @@ module ActionView }.merge(options.symbolize_keys)) end - # Returns an html image tag for the +source+. The +source+ can be a full + # Returns an HTML image tag for the +source+. The +source+ can be a full # path or a file. # # ==== Options @@ -179,18 +178,18 @@ module ActionView # width="30" and height="45", and "50" becomes width="50" and height="50". # <tt>:size</tt> will be ignored if the value is not in the correct format. # - # image_tag("icon") - # # => <img alt="Icon" src="/assets/icon" /> - # image_tag("icon.png") - # # => <img alt="Icon" src="/assets/icon.png" /> - # image_tag("icon.png", size: "16x10", alt: "Edit Entry") - # # => <img src="/assets/icon.png" width="16" height="10" alt="Edit Entry" /> - # image_tag("/icons/icon.gif", size: "16") - # # => <img src="/icons/icon.gif" width="16" height="16" alt="Icon" /> - # image_tag("/icons/icon.gif", height: '32', width: '32') - # # => <img alt="Icon" height="32" src="/icons/icon.gif" width="32" /> - # image_tag("/icons/icon.gif", class: "menu_icon") - # # => <img alt="Icon" class="menu_icon" src="/icons/icon.gif" /> + # image_tag("icon") + # # => <img alt="Icon" src="/assets/icon" /> + # image_tag("icon.png") + # # => <img alt="Icon" src="/assets/icon.png" /> + # image_tag("icon.png", size: "16x10", alt: "Edit Entry") + # # => <img src="/assets/icon.png" width="16" height="10" alt="Edit Entry" /> + # image_tag("/icons/icon.gif", size: "16") + # # => <img src="/icons/icon.gif" width="16" height="16" alt="Icon" /> + # image_tag("/icons/icon.gif", height: '32', width: '32') + # # => <img alt="Icon" height="32" src="/icons/icon.gif" width="32" /> + # image_tag("/icons/icon.gif", class: "menu_icon") + # # => <img alt="Icon" class="menu_icon" src="/icons/icon.gif" /> def image_tag(source, options={}) options = options.symbolize_keys @@ -208,6 +207,9 @@ module ActionView tag("img", options) end + # Returns a string suitable for an html image tag alt attribute. + # +src+ is meant to be an image file path. + # It removes the basename of the file path and the digest, if any. def image_alt(src) File.basename(src, '.*').sub(/-[[:xdigit:]]{32}\z/, '').capitalize end @@ -228,24 +230,24 @@ module ActionView # width="30" and height="45". <tt>:size</tt> will be ignored if the # value is not in the correct format. # - # video_tag("trailer") - # # => <video src="/videos/trailer" /> - # video_tag("trailer.ogg") - # # => <video src="/videos/trailer.ogg" /> - # video_tag("trailer.ogg", controls: true, autobuffer: true) - # # => <video autobuffer="autobuffer" controls="controls" src="/videos/trailer.ogg" /> - # video_tag("trailer.m4v", size: "16x10", poster: "screenshot.png") - # # => <video src="/videos/trailer.m4v" width="16" height="10" poster="/assets/screenshot.png" /> - # video_tag("/trailers/hd.avi", size: "16x16") - # # => <video src="/trailers/hd.avi" width="16" height="16" /> - # video_tag("/trailers/hd.avi", height: '32', width: '32') - # # => <video height="32" src="/trailers/hd.avi" width="32" /> - # video_tag("trailer.ogg", "trailer.flv") - # # => <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video> - # video_tag(["trailer.ogg", "trailer.flv"]) - # # => <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video> - # video_tag(["trailer.ogg", "trailer.flv"], size: "160x120") - # # => <video height="120" width="160"><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video> + # video_tag("trailer") + # # => <video src="/videos/trailer" /> + # video_tag("trailer.ogg") + # # => <video src="/videos/trailer.ogg" /> + # video_tag("trailer.ogg", controls: true, autobuffer: true) + # # => <video autobuffer="autobuffer" controls="controls" src="/videos/trailer.ogg" /> + # video_tag("trailer.m4v", size: "16x10", poster: "screenshot.png") + # # => <video src="/videos/trailer.m4v" width="16" height="10" poster="/assets/screenshot.png" /> + # video_tag("/trailers/hd.avi", size: "16x16") + # # => <video src="/trailers/hd.avi" width="16" height="16" /> + # video_tag("/trailers/hd.avi", height: '32', width: '32') + # # => <video height="32" src="/trailers/hd.avi" width="32" /> + # video_tag("trailer.ogg", "trailer.flv") + # # => <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video> + # video_tag(["trailer.ogg", "trailer.flv"]) + # # => <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video> + # video_tag(["trailer.ogg", "trailer.flv"], size: "160x120") + # # => <video height="120" width="160"><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video> def video_tag(*sources) multiple_sources_tag('video', sources) do |options| options[:poster] = path_to_image(options[:poster]) if options[:poster] @@ -256,18 +258,18 @@ module ActionView end end - # Returns an html audio tag for the +source+. + # Returns an HTML audio tag for the +source+. # The +source+ can be full path or file that exists in # your public audios directory. # - # audio_tag("sound") # => - # <audio src="/audios/sound" /> - # audio_tag("sound.wav") # => - # <audio src="/audios/sound.wav" /> - # audio_tag("sound.wav", autoplay: true, controls: true) # => - # <audio autoplay="autoplay" controls="controls" src="/audios/sound.wav" /> - # audio_tag("sound.wav", "sound.mid") # => - # <audio><source src="/audios/sound.wav" /><source src="/audios/sound.mid" /></audio> + # audio_tag("sound") + # # => <audio src="/audios/sound" /> + # audio_tag("sound.wav") + # # => <audio src="/audios/sound.wav" /> + # audio_tag("sound.wav", autoplay: true, controls: true) + # # => <audio autoplay="autoplay" controls="controls" src="/audios/sound.wav" /> + # audio_tag("sound.wav", "sound.mid") + # # => <audio><source src="/audios/sound.wav" /><source src="/audios/sound.mid" /></audio> def audio_tag(*sources) multiple_sources_tag('audio', sources) end diff --git a/actionpack/lib/action_view/helpers/asset_url_helper.rb b/actionpack/lib/action_view/helpers/asset_url_helper.rb index 0bb5e739bb..0affac41e8 100644 --- a/actionpack/lib/action_view/helpers/asset_url_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_url_helper.rb @@ -2,7 +2,7 @@ require 'zlib' module ActionView # = Action View Asset URL Helpers - module Helpers #:nodoc: + module Helpers # This module provides methods for generating asset paths and # urls. # diff --git a/actionpack/lib/action_view/helpers/atom_feed_helper.rb b/actionpack/lib/action_view/helpers/atom_feed_helper.rb index f5ac455208..42b1dd8933 100644 --- a/actionpack/lib/action_view/helpers/atom_feed_helper.rb +++ b/actionpack/lib/action_view/helpers/atom_feed_helper.rb @@ -2,7 +2,7 @@ require 'set' module ActionView # = Action View Atom Feed Helpers - module Helpers #:nodoc: + module Helpers 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). @@ -124,7 +124,7 @@ module ActionView end end - class AtomBuilder + class AtomBuilder #:nodoc: XHTML_TAG_NAMES = %w(content rights title subtitle summary).to_set def initialize(xml) @@ -158,7 +158,7 @@ module ActionView end end - class AtomFeedBuilder < AtomBuilder + class AtomFeedBuilder < AtomBuilder #:nodoc: def initialize(xml, view, feed_options = {}) @xml, @view, @feed_options = xml, view, feed_options end diff --git a/actionpack/lib/action_view/helpers/benchmark_helper.rb b/actionpack/lib/action_view/helpers/benchmark_helper.rb index dfdd5a786d..87fbf8f1a8 100644 --- a/actionpack/lib/action_view/helpers/benchmark_helper.rb +++ b/actionpack/lib/action_view/helpers/benchmark_helper.rb @@ -2,7 +2,7 @@ require 'active_support/benchmarkable' module ActionView module Helpers - module BenchmarkHelper + module BenchmarkHelper #:nodoc: include ActiveSupport::Benchmarkable def benchmark(*) diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb index db920ae7a4..8693f4f0e4 100644 --- a/actionpack/lib/action_view/helpers/cache_helper.rb +++ b/actionpack/lib/action_view/helpers/cache_helper.rb @@ -110,8 +110,15 @@ module ActionView # <%= some_helper_method(person) %> # # Now all you'll have to do is change that timestamp when the helper method changes. + # + # ==== Conditional caching + # + # You can pass :if and :unless options, to conditionally perform or skip the cache. + # + # <%= cache @model, if: some_condition(@model) do %> + # def cache(name = {}, options = nil, &block) - if controller.perform_caching + if controller.perform_caching && conditions_match?(options) safe_concat(fragment_for(cache_fragment_name(name, options), options, &block)) else yield @@ -136,6 +143,11 @@ module ActionView end private + + def conditions_match?(options) + !(options && (!options.fetch(:if, true) || options.fetch(:unless, false))) + end + def fragment_name_with_digest(name) #:nodoc: if @virtual_path [ diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index 85e398e559..4ec860d69a 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -42,14 +42,12 @@ module ActionView end # Calling content_for stores a block of markup in an identifier for later use. - # You can make subsequent calls to the stored content in other templates, helper modules - # or the layout by passing the identifier as an argument to <tt>content_for</tt>. + # In order to access this stored content in other templates, helper modules + # or the layout, you would pass the identifier as an argument to <tt>content_for</tt>. # # Note: <tt>yield</tt> can still be used to retrieve the stored content, but calling # <tt>yield</tt> doesn't work in helper modules, while <tt>content_for</tt> does. # - # ==== Examples - # # <% content_for :not_authorized do %> # alert('You are not authorized to do that!') # <% end %> @@ -74,7 +72,8 @@ module ActionView # # <%= stored_content %> # - # You can use the <tt>yield</tt> syntax alongside an existing call to <tt>yield</tt> in a layout. For example: + # You can also use the <tt>yield</tt> syntax alongside an existing call to + # <tt>yield</tt> in a layout. For example: # # <%# This is the layout %> # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> @@ -115,7 +114,7 @@ module ActionView # <li><%= link_to 'Home', action: 'index' %></li> # <% end %> # - # <%# Add some other content, or use a different template: %> + # And in other place: # # <% content_for :navigation do %> # <li><%= link_to 'Login', action: 'login' %></li> @@ -145,8 +144,7 @@ module ActionView # # <% content_for :script, javascript_include_tag(:defaults) %> # - # WARNING: content_for is ignored in caches. So you shouldn't use it - # for elements that will be fragment cached. + # WARNING: content_for is ignored in caches. So you shouldn't use it for elements that will be fragment cached. def content_for(name, content = nil, options = {}, &block) if content || block_given? if block_given? @@ -173,13 +171,9 @@ module ActionView result unless content end - # content_for? simply checks whether any content has been captured yet using content_for + # content_for? checks whether any content has been captured yet using `content_for`. # Useful to render parts of your layout differently based on what is in your views. # - # ==== Examples - # - # Perhaps you will use different css in you layout if no content_for :right_column - # # <%# This is the layout %> # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> # <head> diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 6e51ba66a5..1fbf61a5a9 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -45,7 +45,6 @@ module ActionView # 40-59 secs # => less than a minute # 60-89 secs # => 1 minute # - # ==== Examples # from_time = Time.now # distance_of_time_in_words(from_time, from_time + 50.minutes) # => about 1 hour # distance_of_time_in_words(from_time, 50.minutes.from_now) # => about 1 hour @@ -166,7 +165,6 @@ module ActionView # Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based # attribute (identified by +method+) on an object assigned to the template (identified by +object+). # - # # ==== Options # * <tt>:use_month_numbers</tt> - Set to true if you want to use month numbers rather than month names (e.g. # "2" instead of "February"). diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index c79d30ea88..17386a57b8 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -460,8 +460,6 @@ module ActionView # doesn't create the form tags themselves. This makes fields_for suitable # for specifying additional model objects in the same form. # - # === Generic Examples - # # Although the usage and purpose of +field_for+ is similar to +form_for+'s, # its method signature is slightly different. Like +form_for+, it yields # a FormBuilder object associated with a particular model object to a block, diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 9310a90f0f..c0e7ee1f8d 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -7,13 +7,11 @@ 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 + # # The <tt>collection_select</tt>, <tt>select</tt> and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter, a hash: # # * <tt>:include_blank</tt> - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element. # - # For example, - # # select("post", "category", Post::CATEGORIES, {include_blank: true}) # # could become: @@ -24,7 +22,7 @@ module ActionView # <option>poem</option> # </select> # - # Another common case is a select tag for an <tt>belongs_to</tt>-associated object. + # Another common case is a select tag for a <tt>belongs_to</tt>-associated object. # # Example with @post.person_id => 2: # @@ -41,8 +39,6 @@ module ActionView # # * <tt>:prompt</tt> - 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. # - # Example: - # # select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {prompt: 'Select Person'}) # # could become: @@ -57,8 +53,6 @@ module ActionView # Like the other form helpers, +select+ can accept an <tt>:index</tt> option to manually set the ID used in the resulting output. Unlike other helpers, +select+ expects this # option to be in the +html_options+ parameter. # - # Example: - # # select("album[]", "genre", %w[rap rock country], {}, { index: nil }) # # becomes: @@ -71,8 +65,6 @@ module ActionView # # * <tt>:disabled</tt> - can be a single value or an array of values that will be disabled options in the final output. # - # Example: - # # select("post", "category", Post::CATEGORIES, {disabled: 'restricted'}) # # could become: @@ -86,8 +78,6 @@ module ActionView # # When used with the <tt>collection_select</tt> helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled. # - # Example: - # # collection_select(:post, :category_id, Category.all, :id, :name, {disabled: lambda{|category| category.archived? }}) # # If the categories "2008 stuff" and "Christmas" return true when the method <tt>archived?</tt> is called, this would return: @@ -152,7 +142,8 @@ module ActionView # form, and parameters extraction gets the last occurrence of any repeated # key in the query string, that works for ordinary forms. # - # In case if you don't want the helper to generate this hidden field you can specify <tt>include_hidden: false</tt> option. + # In case if you don't want the helper to generate this hidden field you can specify + # <tt>include_hidden: false</tt> option. # def select(object, method, choices, options = {}, html_options = {}) Tags::Select.new(object, method, self, choices, options, html_options).render @@ -170,9 +161,11 @@ module ActionView # retrieve the value/text. # # Example object structure for use with this method: + # # class Post < ActiveRecord::Base # belongs_to :author # end + # # class Author < ActiveRecord::Base # has_many :posts # def name_with_initial @@ -181,6 +174,7 @@ module ActionView # end # # Sample usage (selecting the associated Author for an instance of Post, <tt>@post</tt>): + # # collection_select(:post, :author_id, Author.all, :id, :name_with_initial, prompt: true) # # If <tt>@post.author_id</tt> is already <tt>1</tt>, this would return: @@ -213,23 +207,28 @@ module ActionView # +collection+, returns a value to be used as the contents of its <tt><option></tt> tag. # # Example object structure for use with this method: + # # class Continent < ActiveRecord::Base # has_many :countries # # attribs: id, name # end + # # class Country < ActiveRecord::Base # belongs_to :continent # # attribs: id, name, continent_id # end + # # class City < ActiveRecord::Base # belongs_to :country # # attribs: id, name, country_id # end # # Sample usage: + # # grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name) # # Possible output: + # # <select name="city[country_id]"> # <optgroup label="Africa"> # <option value="1">South Africa</option> @@ -284,57 +283,54 @@ module ActionView # become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag. +selected+ # may also be an array of values to be selected when using a multiple select. # - # Examples (call, result): # options_for_select([["Dollar", "$"], ["Kroner", "DKK"]]) - # # <option value="$">Dollar</option> - # # <option value="DKK">Kroner</option> + # # => <option value="$">Dollar</option> + # # => <option value="DKK">Kroner</option> # # options_for_select([ "VISA", "MasterCard" ], "MasterCard") - # # <option>VISA</option> - # # <option selected="selected">MasterCard</option> + # # => <option>VISA</option> + # # => <option selected="selected">MasterCard</option> # # options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40") - # # <option value="$20">Basic</option> - # # <option value="$40" selected="selected">Plus</option> + # # => <option value="$20">Basic</option> + # # => <option value="$40" selected="selected">Plus</option> # # options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"]) - # # <option selected="selected">VISA</option> - # # <option>MasterCard</option> - # # <option selected="selected">Discover</option> + # # => <option selected="selected">VISA</option> + # # => <option>MasterCard</option> + # # => <option selected="selected">Discover</option> # # You can optionally provide html attributes as the last element of the array. # - # Examples: # options_for_select([ "Denmark", ["USA", {class: 'bold'}], "Sweden" ], ["USA", "Sweden"]) - # # <option value="Denmark">Denmark</option> - # # <option value="USA" class="bold" selected="selected">USA</option> - # # <option value="Sweden" selected="selected">Sweden</option> + # # => <option value="Denmark">Denmark</option> + # # => <option value="USA" class="bold" selected="selected">USA</option> + # # => <option value="Sweden" selected="selected">Sweden</option> # # options_for_select([["Dollar", "$", {class: "bold"}], ["Kroner", "DKK", {onclick: "alert('HI');"}]]) - # # <option value="$" class="bold">Dollar</option> - # # <option value="DKK" onclick="alert('HI');">Kroner</option> + # # => <option value="$" class="bold">Dollar</option> + # # => <option value="DKK" onclick="alert('HI');">Kroner</option> # # If you wish to specify disabled option tags, set +selected+ to be a hash, with <tt>:disabled</tt> being either a value # or array of values to be disabled. In this case, you can use <tt>:selected</tt> to specify selected option tags. # - # Examples: # options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], disabled: "Super Platinum") - # # <option value="Free">Free</option> - # # <option value="Basic">Basic</option> - # # <option value="Advanced">Advanced</option> - # # <option value="Super Platinum" disabled="disabled">Super Platinum</option> + # # => <option value="Free">Free</option> + # # => <option value="Basic">Basic</option> + # # => <option value="Advanced">Advanced</option> + # # => <option value="Super Platinum" disabled="disabled">Super Platinum</option> # # options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], disabled: ["Advanced", "Super Platinum"]) - # # <option value="Free">Free</option> - # # <option value="Basic">Basic</option> - # # <option value="Advanced" disabled="disabled">Advanced</option> - # # <option value="Super Platinum" disabled="disabled">Super Platinum</option> + # # => <option value="Free">Free</option> + # # => <option value="Basic">Basic</option> + # # => <option value="Advanced" disabled="disabled">Advanced</option> + # # => <option value="Super Platinum" disabled="disabled">Super Platinum</option> # # options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], selected: "Free", disabled: "Super Platinum") - # # <option value="Free" selected="selected">Free</option> - # # <option value="Basic">Basic</option> - # # <option value="Advanced">Advanced</option> - # # <option value="Super Platinum" disabled="disabled">Super Platinum</option> + # # => <option value="Free" selected="selected">Free</option> + # # => <option value="Basic">Basic</option> + # # => <option value="Advanced">Advanced</option> + # # => <option value="Super Platinum" disabled="disabled">Super Platinum</option> # # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag. def options_for_select(container, selected = nil) @@ -358,12 +354,12 @@ module ActionView # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning # the result of a call to the +value_method+ as the option value and the +text_method+ as the option text. - # Example: + # # options_from_collection_for_select(@people, 'id', 'name') - # This will output the same HTML as if you did this: - # <option value="#{person.id}">#{person.name}</option> + # # => <option value="#{person.id}">#{person.name}</option> # # This is more often than not used inside a #select_tag like this example: + # # select_tag 'person', options_from_collection_for_select(@people, 'id', 'name') # # If +selected+ is specified as a value or array of values, the element(s) returning a match on +value_method+ @@ -412,10 +408,12 @@ module ActionView # to be specified. # # Example object structure for use with this method: + # # class Continent < ActiveRecord::Base # has_many :countries # # attribs: id, name # end + # # class Country < ActiveRecord::Base # belongs_to :continent # # attribs: id, name, continent_id @@ -465,7 +463,6 @@ module ActionView # prepends an option with a generic prompt - "Please select" - or the given prompt string. # * <tt>:divider</tt> - the divider for the options groups. # - # Sample usage (Array): # grouped_options = [ # ['North America', # [['United States','US'],'Canada']], @@ -474,7 +471,6 @@ module ActionView # ] # grouped_options_for_select(grouped_options) # - # Sample usage (Hash): # grouped_options = { # 'North America' => [['United States','US'], 'Canada'], # 'Europe' => ['Denmark','Germany','France'] @@ -492,7 +488,6 @@ module ActionView # <option value="France">France</option> # </optgroup> # - # Sample usage (divider): # grouped_options = [ # [['United States','US'], 'Canada'], # ['Denmark','Germany','France'] diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 1a99fc7091..cfdd7c77d8 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -18,7 +18,8 @@ module ActionView # Escapes carriage returns and single and double quotes for JavaScript segments. # - # Also available through the alias j(). This is particularly helpful in JavaScript responses, like: + # Also available through the alias j(). This is particularly helpful in JavaScript + # responses, like: # # $('some_element').replaceWith('<%=j render 'some/element_template' %>'); def escape_javascript(javascript) @@ -43,12 +44,14 @@ module ActionView # </script> # # +html_options+ may be a hash of attributes for the <tt>\<script></tt> - # tag. Example: + # tag. + # # javascript_tag "alert('All is good')", defer: 'defer' # # => <script defer="defer">alert('All is good')</script> # # Instead of passing the content as an argument, you can also use a block # in which case, you pass your +html_options+ as the first parameter. + # # <%= javascript_tag defer: 'defer' do -%> # alert('All is good') # <% end -%> diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 82340171af..9e1be65b1a 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -28,8 +28,6 @@ module ActionView # Formats a +number+ into a US phone number (e.g., (555) # 123-9876). You can customize the format in the +options+ hash. # - # ==== Options - # # * <tt>:area_code</tt> - Adds parentheses around the area code. # * <tt>:delimiter</tt> - Specifies the delimiter to use # (defaults to "-"). @@ -40,21 +38,18 @@ module ActionView # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when # the argument is invalid. # - # ==== Examples - # - # number_to_phone(5551234) # => 555-1234 - # number_to_phone("5551234") # => 555-1234 - # number_to_phone(1235551234) # => 123-555-1234 - # number_to_phone(1235551234, area_code: true) # => (123) 555-1234 - # number_to_phone(1235551234, delimiter: " ") # => 123 555 1234 - # number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555 - # number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234 - # number_to_phone("123a456") # => 123a456 - # - # number_to_phone("1234a567", raise: true) # => InvalidNumberError - # - # number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: ".") - # # => +1.123.555.1234 x 1343 + # number_to_phone(5551234) # => 555-1234 + # number_to_phone("5551234") # => 555-1234 + # number_to_phone(1235551234) # => 123-555-1234 + # number_to_phone(1235551234, area_code: true) # => (123) 555-1234 + # number_to_phone(1235551234, delimiter: " ") # => 123 555 1234 + # number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555 + # number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234 + # number_to_phone("123a456") # => 123a456 + # number_to_phone("1234a567", raise: true) # => InvalidNumberError + # + # number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: ".") + # # => +1.123.555.1234 x 1343 def number_to_phone(number, options = {}) return unless number options = options.symbolize_keys @@ -66,8 +61,6 @@ module ActionView # Formats a +number+ into a currency string (e.g., $13.65). You # can customize the format in the +options+ hash. # - # ==== Options - # # * <tt>:locale</tt> - Sets the locale to be used for formatting # (defaults to current locale). # * <tt>:precision</tt> - Sets the level of precision (defaults @@ -89,22 +82,20 @@ module ActionView # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when # the argument is invalid. # - # ==== Examples - # - # number_to_currency(1234567890.50) # => $1,234,567,890.50 - # number_to_currency(1234567890.506) # => $1,234,567,890.51 - # number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506 - # number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 € - # number_to_currency("123a456") # => $123a456 + # number_to_currency(1234567890.50) # => $1,234,567,890.50 + # number_to_currency(1234567890.506) # => $1,234,567,890.51 + # number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506 + # number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 € + # number_to_currency("123a456") # => $123a456 # - # number_to_currency("123a456", raise: true) # => InvalidNumberError + # number_to_currency("123a456", raise: true) # => InvalidNumberError # - # number_to_currency(-1234567890.50, negative_format: "(%u%n)") - # # => ($1,234,567,890.50) - # number_to_currency(1234567890.50, unit: "£", separator: ",", delimiter: "") - # # => £1234567890,50 - # number_to_currency(1234567890.50, unit: "£", separator: ",", delimiter: "", format: "%n %u") - # # => 1234567890,50 £ + # number_to_currency(-1234567890.50, negative_format: "(%u%n)") + # # => ($1,234,567,890.50) + # number_to_currency(1234567890.50, unit: "£", separator: ",", delimiter: "") + # # => £1234567890,50 + # number_to_currency(1234567890.50, unit: "£", separator: ",", delimiter: "", format: "%n %u") + # # => 1234567890,50 £ def number_to_currency(number, options = {}) return unless number options = escape_unsafe_delimiters_and_separators(options.symbolize_keys) @@ -117,7 +108,6 @@ module ActionView # Formats a +number+ as a percentage string (e.g., 65%). You can # customize the format in the +options+ hash. # - # ==== Options # # * <tt>:locale</tt> - Sets the locale to be used for formatting # (defaults to current locale). @@ -138,18 +128,16 @@ module ActionView # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when # the argument is invalid. # - # ==== Examples + # number_to_percentage(100) # => 100.000% + # number_to_percentage("98") # => 98.000% + # number_to_percentage(100, precision: 0) # => 100% + # number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000% + # number_to_percentage(302.24398923423, precision: 5) # => 302.24399% + # number_to_percentage(1000, locale: :fr) # => 1 000,000% + # number_to_percentage("98a") # => 98a% + # number_to_percentage(100, format: "%n %") # => 100 % # - # number_to_percentage(100) # => 100.000% - # number_to_percentage("98") # => 98.000% - # number_to_percentage(100, precision: 0) # => 100% - # number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000% - # number_to_percentage(302.24398923423, precision: 5) # => 302.24399% - # number_to_percentage(1000, locale: :fr) # => 1 000,000% - # number_to_percentage("98a") # => 98a% - # number_to_percentage(100, format: "%n %") # => 100 % - # - # number_to_percentage("98a", raise: true) # => InvalidNumberError + # number_to_percentage("98a", raise: true) # => InvalidNumberError def number_to_percentage(number, options = {}) return unless number options = escape_unsafe_delimiters_and_separators(options.symbolize_keys) @@ -163,8 +151,6 @@ module ActionView # (e.g., 12,324). You can customize the format in the +options+ # hash. # - # ==== Options - # # * <tt>:locale</tt> - Sets the locale to be used for formatting # (defaults to current locale). # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults @@ -174,20 +160,18 @@ module ActionView # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when # the argument is invalid. # - # ==== Examples - # - # number_with_delimiter(12345678) # => 12,345,678 - # number_with_delimiter("123456") # => 123,456 - # number_with_delimiter(12345678.05) # => 12,345,678.05 - # number_with_delimiter(12345678, delimiter: ".") # => 12.345.678 - # number_with_delimiter(12345678, delimiter: ",") # => 12,345,678 - # number_with_delimiter(12345678.05, separator: " ") # => 12,345,678 05 - # number_with_delimiter(12345678.05, locale: :fr) # => 12 345 678,05 - # number_with_delimiter("112a") # => 112a - # number_with_delimiter(98765432.98, delimiter: " ", separator: ",") - # # => 98 765 432,98 - # - # number_with_delimiter("112a", raise: true) # => raise InvalidNumberError + # number_with_delimiter(12345678) # => 12,345,678 + # number_with_delimiter("123456") # => 123,456 + # number_with_delimiter(12345678.05) # => 12,345,678.05 + # number_with_delimiter(12345678, delimiter: ".") # => 12.345.678 + # number_with_delimiter(12345678, delimiter: ",") # => 12,345,678 + # number_with_delimiter(12345678.05, separator: " ") # => 12,345,678 05 + # number_with_delimiter(12345678.05, locale: :fr) # => 12 345 678,05 + # number_with_delimiter("112a") # => 112a + # number_with_delimiter(98765432.98, delimiter: " ", separator: ",") + # # => 98 765 432,98 + # + # number_with_delimiter("112a", raise: true) # => raise InvalidNumberError def number_with_delimiter(number, options = {}) options = escape_unsafe_delimiters_and_separators(options.symbolize_keys) @@ -201,8 +185,6 @@ module ActionView # +:significant+ is +false+, and 5 if +:significant+ is +true+). # You can customize the format in the +options+ hash. # - # ==== Options - # # * <tt>:locale</tt> - Sets the locale to be used for formatting # (defaults to current locale). # * <tt>:precision</tt> - Sets the precision of the number @@ -220,23 +202,21 @@ module ActionView # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when # the argument is invalid. # - # ==== Examples - # - # number_with_precision(111.2345) # => 111.235 - # number_with_precision(111.2345, precision: 2) # => 111.23 - # number_with_precision(13, precision: 5) # => 13.00000 - # number_with_precision(389.32314, precision: 0) # => 389 - # number_with_precision(111.2345, significant: true) # => 111 - # number_with_precision(111.2345, precision: 1, significant: true) # => 100 - # number_with_precision(13, precision: 5, significant: true) # => 13.000 - # number_with_precision(111.234, locale: :fr) # => 111,234 - # - # number_with_precision(13, precision: 5, significant: true, strip_insignificant_zeros: true) - # # => 13 - # - # number_with_precision(389.32314, precision: 4, significant: true) # => 389.3 - # number_with_precision(1111.2345, precision: 2, separator: ',', delimiter: '.') - # # => 1.111,23 + # number_with_precision(111.2345) # => 111.235 + # number_with_precision(111.2345, precision: 2) # => 111.23 + # number_with_precision(13, precision: 5) # => 13.00000 + # number_with_precision(389.32314, precision: 0) # => 389 + # number_with_precision(111.2345, significant: true) # => 111 + # number_with_precision(111.2345, precision: 1, significant: true) # => 100 + # number_with_precision(13, precision: 5, significant: true) # => 13.000 + # number_with_precision(111.234, locale: :fr) # => 111,234 + # + # number_with_precision(13, precision: 5, significant: true, strip_insignificant_zeros: true) + # # => 13 + # + # number_with_precision(389.32314, precision: 4, significant: true) # => 389.3 + # number_with_precision(1111.2345, precision: 2, separator: ',', delimiter: '.') + # # => 1.111,23 def number_with_precision(number, options = {}) options = escape_unsafe_delimiters_and_separators(options.symbolize_keys) @@ -245,7 +225,6 @@ module ActionView } end - # Formats the bytes in +number+ into a more understandable # representation (e.g., giving it 1500 yields 1.5 KB). This # method is useful for reporting file sizes to users. You can @@ -254,8 +233,6 @@ module ActionView # See <tt>number_to_human</tt> if you want to pretty-print a # generic number. # - # ==== Options - # # * <tt>:locale</tt> - Sets the locale to be used for formatting # (defaults to current locale). # * <tt>:precision</tt> - Sets the precision of the number @@ -275,24 +252,23 @@ module ActionView # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when # the argument is invalid. # - # ==== Examples - # - # number_to_human_size(123) # => 123 Bytes - # number_to_human_size(1234) # => 1.21 KB - # number_to_human_size(12345) # => 12.1 KB - # number_to_human_size(1234567) # => 1.18 MB - # number_to_human_size(1234567890) # => 1.15 GB - # number_to_human_size(1234567890123) # => 1.12 TB - # number_to_human_size(1234567, precision: 2) # => 1.2 MB - # number_to_human_size(483989, precision: 2) # => 470 KB - # number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB + # number_to_human_size(123) # => 123 Bytes + # number_to_human_size(1234) # => 1.21 KB + # number_to_human_size(12345) # => 12.1 KB + # number_to_human_size(1234567) # => 1.18 MB + # number_to_human_size(1234567890) # => 1.15 GB + # number_to_human_size(1234567890123) # => 1.12 TB + # number_to_human_size(1234567, precision: 2) # => 1.2 MB + # number_to_human_size(483989, precision: 2) # => 470 KB + # number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB # # 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" + # + # number_to_human_size(1234567890123, precision: 5) # => "1.1229 TB" + # number_to_human_size(524288000, precision: 5) # => "500 MB" def number_to_human_size(number, options = {}) options = escape_unsafe_delimiters_and_separators(options.symbolize_keys) @@ -348,29 +324,27 @@ module ActionView # * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when # the argument is invalid. # - # ==== Examples - # - # number_to_human(123) # => "123" - # number_to_human(1234) # => "1.23 Thousand" - # number_to_human(12345) # => "12.3 Thousand" - # number_to_human(1234567) # => "1.23 Million" - # number_to_human(1234567890) # => "1.23 Billion" - # number_to_human(1234567890123) # => "1.23 Trillion" - # number_to_human(1234567890123456) # => "1.23 Quadrillion" - # number_to_human(1234567890123456789) # => "1230 Quadrillion" - # number_to_human(489939, precision: 2) # => "490 Thousand" - # number_to_human(489939, precision: 4) # => "489.9 Thousand" - # number_to_human(1234567, precision: 4, - # significant: false) # => "1.2346 Million" - # number_to_human(1234567, precision: 1, + # number_to_human(123) # => "123" + # number_to_human(1234) # => "1.23 Thousand" + # number_to_human(12345) # => "12.3 Thousand" + # number_to_human(1234567) # => "1.23 Million" + # number_to_human(1234567890) # => "1.23 Billion" + # number_to_human(1234567890123) # => "1.23 Trillion" + # number_to_human(1234567890123456) # => "1.23 Quadrillion" + # number_to_human(1234567890123456789) # => "1230 Quadrillion" + # number_to_human(489939, precision: 2) # => "490 Thousand" + # number_to_human(489939, precision: 4) # => "489.9 Thousand" + # number_to_human(1234567, precision: 4, + # significant: false) # => "1.2346 Million" + # number_to_human(1234567, precision: 1, # separator: ',', - # significant: false) # => "1,2 Million" + # significant: false) # => "1,2 Million" # # Non-significant zeros after the decimal separator are stripped # out by default (set <tt>:strip_insignificant_zeros</tt> to # +false+ to change that): - # number_to_human(12345012345, significant_digits: 6) # => "12.345 Billion" - # number_to_human(500000000, precision: 5) # => "500 Million" + # number_to_human(12345012345, significant_digits: 6) # => "12.345 Billion" + # number_to_human(500000000, precision: 5) # => "500 Million" # # ==== Custom Unit Quantifiers # @@ -392,12 +366,12 @@ module ActionView # # Then you could do: # - # number_to_human(543934, units: :distance) # => "544 kilometers" - # number_to_human(54393498, units: :distance) # => "54400 kilometers" - # number_to_human(54393498000, units: :distance) # => "54.4 gazillion-distance" - # number_to_human(343, units: :distance, precision: 1) # => "300 meters" - # number_to_human(1, units: :distance) # => "1 meter" - # number_to_human(0.34, units: :distance) # => "34 centimeters" + # number_to_human(543934, units: :distance) # => "544 kilometers" + # number_to_human(54393498, units: :distance) # => "54400 kilometers" + # number_to_human(54393498000, units: :distance) # => "54.4 gazillion-distance" + # number_to_human(343, units: :distance, precision: 1) # => "300 meters" + # number_to_human(1, units: :distance) # => "1 meter" + # number_to_human(0.34, units: :distance) # => "34 centimeters" # def number_to_human(number, options = {}) options = escape_unsafe_delimiters_and_separators(options.symbolize_keys) diff --git a/actionpack/lib/action_view/helpers/output_safety_helper.rb b/actionpack/lib/action_view/helpers/output_safety_helper.rb index 2e7e9dc50c..60a4478c26 100644 --- a/actionpack/lib/action_view/helpers/output_safety_helper.rb +++ b/actionpack/lib/action_view/helpers/output_safety_helper.rb @@ -11,7 +11,8 @@ module ActionView #:nodoc: # # For example: # - # <%=raw @user.name %> + # raw @user.name + # # => 'Jimmy <alert>Tables</alert>' def raw(stringish) stringish.to_s.html_safe end diff --git a/actionpack/lib/action_view/helpers/sanitize_helper.rb b/actionpack/lib/action_view/helpers/sanitize_helper.rb index e6f61d269c..e5cb843670 100644 --- a/actionpack/lib/action_view/helpers/sanitize_helper.rb +++ b/actionpack/lib/action_view/helpers/sanitize_helper.rb @@ -3,7 +3,7 @@ require 'action_view/vendor/html-scanner' module ActionView # = Action View Sanitize Helpers - module Helpers #:nodoc: + module Helpers # 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 diff --git a/actionpack/lib/action_view/railtie.rb b/actionpack/lib/action_view/railtie.rb index 3875d88a9f..e80e0ed9b0 100644 --- a/actionpack/lib/action_view/railtie.rb +++ b/actionpack/lib/action_view/railtie.rb @@ -3,7 +3,7 @@ require "rails" module ActionView # = Action View Railtie - class Railtie < Rails::Railtie + class Railtie < Rails::Railtie # :nodoc: config.action_view = ActiveSupport::OrderedOptions.new config.action_view.embed_authenticity_token_in_remote_forms = false diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb index f5fdf766ad..8fb9b6ff18 100644 --- a/actionpack/lib/action_view/renderer/partial_renderer.rb +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -293,7 +293,7 @@ module ActionView object, as = @object, @variable if !block && (layout = @options[:layout]) - layout = find_template(layout, @template_keys) + layout = find_template(layout.to_s, @template_keys) end object ||= locals[as] diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index 731d8f9dab..afbbece90f 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -14,6 +14,17 @@ module ActionView src << "@output_buffer.safe_concat('" << escape_text(text) << "');" end + # Erubis toggles <%= and <%== behavior when escaping is enabled. + # We override to always treat <%== as escaped. + def add_expr(src, code, indicator) + case indicator + when '==' + add_expr_escaped(src, code) + else + super + end + end + BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/ def add_expr_literal(src, code) |