diff options
Diffstat (limited to 'actionpack')
63 files changed, 406 insertions, 129 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 913edbd8df..cbf5b66003 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,20 @@ ## Rails 4.0.0 (unreleased) ## +* Add support for extracting the port from the `:host` option passed to `url_for`. + + *Andrew White* + +* Add support for removing the subdomain from a url by passing `nil`, `false` or `''`. + Fixes #10180. + + *Derek Watson + Andrew White* + +* Element of the collection for `options_from_collection_for_select` helper can + optionally contain html attributes as the last element of the array as + `options_for_select` helper. + + *Vasiliy Ermolovich* + * Fix explicit names on multiple file fields. If a file field tag has the multiple option, it is turned into an array field (appending `[]`), but if an explicit name is passed to `file_field` the `[]` is not @@ -64,7 +79,7 @@ *Brad Dunbar* * Include I18n locale fallbacks in view lookup. - Fixes GH#3512. + Fixes #3512. *Juan Barreneche* diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index bac994496e..8e7bdf620e 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -309,6 +309,7 @@ module AbstractController RUBY when Proc define_method :_layout_from_proc, &_layout + protected :_layout_from_proc <<-RUBY result = _layout_from_proc(#{_layout.arity == 0 ? '' : 'self'}) return #{default_behavior} if result.nil? diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 143b3e0cbd..c7cb88e64f 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -57,7 +57,7 @@ module ActionController # And then to route requests to your metal controller, you would add # something like this to <tt>config/routes.rb</tt>: # - # match 'hello', to: HelloController.action(:index) + # get 'hello', to: HelloController.action(:index) # # The +action+ method returns a valid Rack application for the \Rails # router to dispatch to. diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index fb664a69dd..8092fd639f 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -34,6 +34,7 @@ module ActionController module Live class Buffer < ActionDispatch::Response::Buffer #:nodoc: def initialize(response) + @error_callback = nil super(response, SizedQueue.new(10)) end @@ -56,6 +57,14 @@ module ActionController super @buf.push nil end + + def on_error(&block) + @error_callback = block + end + + def call_on_error + @error_callback.call + end end class Response < ActionDispatch::Response #:nodoc: all @@ -121,6 +130,16 @@ module ActionController begin super(name) + rescue => e + begin + @_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html + @_response.stream.call_on_error + rescue => exception + log_error(exception) + ensure + log_error(e) + @_response.stream.close + end ensure @_response.commit! end @@ -129,6 +148,16 @@ module ActionController @_response.await_commit end + def log_error(exception) + logger = ActionController::Base.logger + return unless logger + + message = "\n#{exception.class} (#{exception.message}):\n" + message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code) + message << " " << exception.backtrace.join("\n ") + logger.fatal("#{message}\n\n") + end + def response_body=(body) super response.stream.close if response diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index c5e7d4e357..bea6b88f91 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -6,7 +6,7 @@ module ActionController # Before processing, set the request formats in current controller formats. def process_action(*) #:nodoc: - self.formats = request.formats.map { |x| x.ref } + self.formats = request.formats.map(&:ref).compact super end diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 912da741b7..f29ad359ac 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -223,8 +223,8 @@ module Mime Mime.instance_eval { remove_const(symbol) } SET.delete_if { |v| v.eql?(mime) } - LOOKUP.delete_if { |k,v| v.eql?(mime) } - EXTENSION_LOOKUP.delete_if { |k,v| v.eql?(mime) } + LOOKUP.delete_if { |_,v| v.eql?(mime) } + EXTENSION_LOOKUP.delete_if { |_,v| v.eql?(mime) } end end @@ -306,12 +306,20 @@ module Mime method.to_s.ends_with? '?' end end - + class NullType def nil? true end + def ref + nil + end + + def respond_to_missing?(method, include_private = false) + method.to_s.ends_with? '?' + end + private def method_missing(method, *args) false if method.to_s.ends_with? '?' diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index ab5399c8ea..6f5a52c568 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -4,7 +4,9 @@ require 'active_support/core_ext/hash/slice' module ActionDispatch module Http module URL - IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ + IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ + HOST_REGEXP = /(^.*:\/\/)?([^:]+)(?::(\d+$))?/ + PROTOCOL_REGEXP = /^([^:]+)(:)?(\/\/)?$/ mattr_accessor :tld_length self.tld_length = 1 @@ -28,6 +30,7 @@ module ActionDispatch end def url_for(options = {}) + options = options.dup path = options.delete(:script_name).to_s.chomp("/") path << options.delete(:path).to_s @@ -59,15 +62,20 @@ module ActionDispatch result = "" unless options[:only_path] - protocol = extract_protocol(options) - unless options[:protocol] == false - result << protocol - result << ":" unless result.match(%r{:|//}) + if match = options[:host].match(HOST_REGEXP) + options[:protocol] ||= match[1] unless options[:protocol] == false + options[:host] = match[2] + options[:port] = match[3] unless options.key?(:port) end - result << "//" unless result.match("//") + + options[:protocol] = normalize_protocol(options) + options[:host] = normalize_host(options) + options[:port] = normalize_port(options) + + result << options[:protocol] result << rewrite_authentication(options) - result << host_or_subdomain_and_domain(options) - result << ":#{options.delete(:port)}" if options[:port] + result << options[:host] + result << ":#{options[:port]}" if options[:port] end result end @@ -76,6 +84,10 @@ module ActionDispatch host && IP_HOST_REGEXP !~ host end + def same_host?(options) + (options[:subdomain] == true || !options.key?(:subdomain)) && options[:domain].nil? + end + def rewrite_authentication(options) if options[:user] && options[:password] "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@" @@ -84,29 +96,47 @@ module ActionDispatch end end - # Extracts protocol http:// or https:// from options[:host] - # needs to be called whether the :protocol is being used or not - def extract_protocol(options) - if options[:host] && match = options[:host].match(/(^.*:\/\/)(.*)/) - options[:protocol] ||= match[1] - options[:host] = match[2] + def normalize_protocol(options) + case options[:protocol] + when nil + "http://" + when false, "//" + "//" + when PROTOCOL_REGEXP + "#{$1}://" + else + raise ArgumentError, "Invalid :protocol option: #{options[:protocol].inspect}" end - options[:protocol] || "http" end - def host_or_subdomain_and_domain(options) - return options[:host] if !named_host?(options[:host]) || (options[:subdomain].nil? && options[:domain].nil?) + def normalize_host(options) + return options[:host] if !named_host?(options[:host]) || same_host?(options) tld_length = options[:tld_length] || @@tld_length host = "" - unless options[:subdomain] == false - host << (options[:subdomain] || extract_subdomain(options[:host], tld_length)).to_param - host << "." + if options[:subdomain] == true || !options.key?(:subdomain) + host << extract_subdomain(options[:host], tld_length).to_param + elsif options[:subdomain].present? + host << options[:subdomain].to_param end + host << "." unless host.empty? host << (options[:domain] || extract_domain(options[:host], tld_length)) host end + + def normalize_port(options) + return nil if options[:port].nil? || options[:port] == false + + case options[:protocol] + when "//" + nil + when "https://" + options[:port].to_i == 443 ? nil : options[:port] + else + options[:port].to_i == 80 ? nil : options[:port] + end + end end def initialize(env) diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb index 82c55660ea..a732e570f2 100644 --- a/actionpack/lib/action_dispatch/journey/formatter.rb +++ b/actionpack/lib/action_dispatch/journey/formatter.rb @@ -58,7 +58,7 @@ module ActionDispatch end end - parameterized_parts.keep_if { |_, v| v } + parameterized_parts.keep_if { |_, v| v } parameterized_parts end diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb index 6fda085681..50e1853094 100644 --- a/actionpack/lib/action_dispatch/journey/route.rb +++ b/actionpack/lib/action_dispatch/journey/route.rb @@ -102,6 +102,10 @@ module ActionDispatch value === request.send(method).to_s when Array value.include?(request.send(method)) + when TrueClass + request.send(method).present? + when FalseClass + request.send(method).blank? else value === request.send(method) end diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb index 31868b1814..419e665d12 100644 --- a/actionpack/lib/action_dispatch/journey/router.rb +++ b/actionpack/lib/action_dispatch/journey/router.rb @@ -38,7 +38,9 @@ module ActionDispatch env['REMOTE_ADDR'] end - def [](k); env[k]; end + def [](k) + env[k] + end end attr_reader :request_class, :formatter diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb index 44290445d4..5d1740d0d4 100644 --- a/actionpack/lib/action_dispatch/middleware/request_id.rb +++ b/actionpack/lib/action_dispatch/middleware/request_id.rb @@ -18,7 +18,7 @@ module ActionDispatch def call(env) env["action_dispatch.request_id"] = external_request_id(env) || internal_request_id - @app.call(env).tap { |status, headers, body| headers["X-Request-Id"] = env["action_dispatch.request_id"] } + @app.call(env).tap { |_status, headers, _body| headers["X-Request-Id"] = env["action_dispatch.request_id"] } end private diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb index 550f4dbd0d..db219c8fa9 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb @@ -13,7 +13,7 @@ request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n") def debug_hash(object) - object.to_hash.sort_by { |k, v| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n") + object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n") end unless self.class.method_defined?(:debug_hash) %> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb index 9d947aea40..b181909bff 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb @@ -1,10 +1,8 @@ <% - traces = [ - ["Application Trace", @application_trace], - ["Framework Trace", @framework_trace], - ["Full Trace", @full_trace] - ] - names = traces.collect {|name, trace| name} + traces = { "Application Trace" => @application_trace, + "Framework Trace" => @framework_trace, + "Full Trace" => @full_trace } + names = traces.keys %> <p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p> diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb index 63216ef7c5..31f46ee340 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb @@ -2,7 +2,7 @@ <header> <h1> <%= @exception.original_exception.class.to_s %> in - <%= @request.parameters["controller"].capitalize if @request.parameters["controller"]%>#<%= @request.parameters["action"] %> + <%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %> </h1> </header> diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 8c095d605a..80054c8a40 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -489,7 +489,7 @@ module ActionDispatch end options = app - app, path = options.find { |k, v| k.respond_to?(:call) } + app, path = options.find { |k, _| k.respond_to?(:call) } options.delete(app) if app end @@ -1361,7 +1361,7 @@ module ActionDispatch def match(path, *rest) if rest.empty? && Hash === path options = path - path, to = options.find { |name, value| name.is_a?(String) } + path, to = options.find { |name, _value| name.is_a?(String) } options[:to] = to options.delete(path) paths = [path] diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 07203428d4..342b6ec23d 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -170,9 +170,10 @@ module ActionDispatch def call(t, args) if args.size == arg_size && !args.last.is_a?(Hash) && optimize_routes_generation?(t) - @options.merge!(t.url_options) if t.respond_to?(:url_options) - @options[:path] = optimized_helper(args) - ActionDispatch::Http::URL.url_for(@options) + options = @options.dup + options.merge!(t.url_options) if t.respond_to?(:url_options) + options[:path] = optimized_helper(args) + ActionDispatch::Http::URL.url_for(options) else super end @@ -665,7 +666,7 @@ module ActionDispatch end req = @request_class.new(env) - @router.recognize(req) do |route, matches, params| + @router.recognize(req) do |route, _matches, params| params.merge!(extras) params.each do |key, value| if value.is_a?(String) diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 9210bffd1d..496682e8bd 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -81,7 +81,7 @@ module ActionDispatch # Load routes.rb if it hasn't been loaded. generated_path, extra_keys = @routes.generate_extras(options, defaults) - found_extras = options.reject {|k, v| ! extra_keys.include? k} + found_extras = options.reject { |k, _| ! extra_keys.include? k } msg = message || sprintf("found extras <%s>, not <%s>", found_extras, extras) assert_equal(extras, found_extras, msg) @@ -120,7 +120,7 @@ module ActionDispatch options[:controller] = "/#{controller}" end - generate_options = options.dup.delete_if{ |k,v| defaults.key?(k) } + generate_options = options.dup.delete_if{ |k, _| defaults.key?(k) } assert_generates(path.is_a?(Hash) ? path[:path] : path, generate_options, defaults, extras, message) end diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index e481f3b245..3253a3d424 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -377,8 +377,8 @@ module ActionDispatch node.content.gsub(/<!\[CDATA\[(.*)(\]\]>)?/m) { Rack::Utils.escapeHTML($1) } end - selected = elements.map do |_element| - text = _element.children.select{ |c| not c.tag? }.map{ |c| fix_content[c] }.join + selected = elements.map do |elem| + text = elem.children.select{ |c| not c.tag? }.map{ |c| fix_content[c] }.join root = HTML::Document.new(CGI.unescapeHTML("<encoded>#{text}</encoded>")).root css_select(root, "encoded:root", &block)[0] end diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb index e657283cec..630e6a9b78 100644 --- a/actionpack/lib/action_dispatch/testing/test_process.rb +++ b/actionpack/lib/action_dispatch/testing/test_process.rb @@ -6,7 +6,7 @@ module ActionDispatch module TestProcess def assigns(key = nil) assigns = {}.with_indifferent_access - @controller.view_assigns.each {|k, v| assigns.regular_writer(k, v)} + @controller.view_assigns.each { |k, v| assigns.regular_writer(k, v) } key.nil? ? assigns : assigns[key] end diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 521eaf25d2..693b6bdfcc 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -14,7 +14,6 @@ module ActionView # # => <img alt="Rails" src="/assets/rails.png" /> # stylesheet_link_tag("application") # # => <link href="/assets/application.css?body=1" media="screen" rel="stylesheet" /> - # module AssetTagHelper extend ActiveSupport::Concern @@ -50,7 +49,6 @@ module ActionView # # javascript_include_tag "http://www.example.com/xmlhr.js" # # => <script src="http://www.example.com/xmlhr.js"></script> - # def javascript_include_tag(*sources) options = sources.extract_options!.stringify_keys path_options = options.extract!('protocol').symbolize_keys @@ -67,7 +65,7 @@ module ActionView # you don't specify an extension, <tt>.css</tt> will be appended automatically. # You can modify the link attributes by passing a hash as the last argument. # For historical reasons, the 'media' attribute will always be present and defaults - # to "screen", so you must explicitely set it to "all" for the stylesheet(s) to + # to "screen", so you must explicitly set it to "all" for the stylesheet(s) to # apply to all media types. # # stylesheet_link_tag "style" @@ -88,7 +86,6 @@ module ActionView # stylesheet_link_tag "random.styles", "/css/stylish" # # => <link href="/assets/random.styles" media="screen" rel="stylesheet" /> # # <link href="/css/stylish.css" media="screen" rel="stylesheet" /> - # def stylesheet_link_tag(*sources) options = sources.extract_options!.stringify_keys path_options = options.extract!('protocol').symbolize_keys @@ -109,10 +106,13 @@ module ActionView # +url_options+. You can modify the LINK tag itself in +tag_options+. # # ==== Options + # # * <tt>:rel</tt> - Specify the relation of this link, defaults to "alternate" # * <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) @@ -148,9 +148,12 @@ module ActionView # you can override "rel" and "type". # # ==== 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' # + # ==== Examples + # # favicon_link_tag '/myicon.ico' # # => <link href="/assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" /> # @@ -160,7 +163,6 @@ module ActionView # # 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', @@ -173,6 +175,7 @@ module ActionView # path or a file. # # ==== Options + # # You can add HTML attributes using the +options+. The +options+ supports # three additional keys for convenience and conformance: # @@ -250,6 +253,8 @@ module ActionView # width="30" and height="45". <tt>:size</tt> will be ignored if the # value is not in the correct format. # + # ==== Examples + # # video_tag("trailer") # # => <video src="/videos/trailer" /> # video_tag("trailer.ogg") diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 7e65ebb4e4..719c9c09b5 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -380,7 +380,7 @@ module ActionView # should produce the desired results. def options_from_collection_for_select(collection, value_method, text_method, selected = nil) options = collection.map do |element| - [value_for_collection(element, text_method), value_for_collection(element, value_method)] + [value_for_collection(element, text_method), value_for_collection(element, value_method), option_html_attributes(element)] end selected, disabled = extract_selected_and_disabled(selected) select_deselect = { diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 9e1be65b1a..fda7038a5d 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -28,6 +28,8 @@ 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 "-"). @@ -38,6 +40,8 @@ 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 @@ -61,6 +65,8 @@ 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 @@ -82,6 +88,8 @@ 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 @@ -108,6 +116,7 @@ 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). @@ -128,6 +137,8 @@ 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% @@ -151,6 +162,8 @@ 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 @@ -160,6 +173,8 @@ 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 @@ -185,6 +200,8 @@ 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 @@ -202,6 +219,8 @@ 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 @@ -233,6 +252,8 @@ 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 @@ -252,6 +273,8 @@ 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 @@ -324,6 +347,8 @@ 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" diff --git a/actionpack/lib/action_view/helpers/tags/base.rb b/actionpack/lib/action_view/helpers/tags/base.rb index 10dec66b4f..3fe3f4e9df 100644 --- a/actionpack/lib/action_view/helpers/tags/base.rb +++ b/actionpack/lib/action_view/helpers/tags/base.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class Base #:nodoc: + module Tags # :nodoc: + class Base # :nodoc: include Helpers::ActiveModelInstanceTag, Helpers::TagHelper, Helpers::FormTagHelper include FormOptionsHelper diff --git a/actionpack/lib/action_view/helpers/tags/check_box.rb b/actionpack/lib/action_view/helpers/tags/check_box.rb index e21cc07746..6d51f2629a 100644 --- a/actionpack/lib/action_view/helpers/tags/check_box.rb +++ b/actionpack/lib/action_view/helpers/tags/check_box.rb @@ -2,7 +2,7 @@ require 'action_view/helpers/tags/checkable' module ActionView module Helpers - module Tags + module Tags # :nodoc: class CheckBox < Base #:nodoc: include Checkable diff --git a/actionpack/lib/action_view/helpers/tags/checkable.rb b/actionpack/lib/action_view/helpers/tags/checkable.rb index b97c0c68d7..052e9df662 100644 --- a/actionpack/lib/action_view/helpers/tags/checkable.rb +++ b/actionpack/lib/action_view/helpers/tags/checkable.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - module Checkable + module Tags # :nodoc: + module Checkable # :nodoc: def input_checked?(object, options) if options.has_key?("checked") checked = options.delete "checked" diff --git a/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb b/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb index 9655008fe2..52006d856b 100644 --- a/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb +++ b/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb @@ -2,11 +2,11 @@ require 'action_view/helpers/tags/collection_helpers' module ActionView module Helpers - module Tags - class CollectionCheckBoxes < Base + module Tags # :nodoc: + class CollectionCheckBoxes < Base # :nodoc: include CollectionHelpers - class CheckBoxBuilder < Builder + class CheckBoxBuilder < Builder # :nodoc: def check_box(extra_html_options={}) html_options = extra_html_options.merge(@input_html_options) @template_object.check_box(@object_name, @method_name, html_options, @value, nil) diff --git a/actionpack/lib/action_view/helpers/tags/collection_helpers.rb b/actionpack/lib/action_view/helpers/tags/collection_helpers.rb index e92a318c73..cd12ddaf65 100644 --- a/actionpack/lib/action_view/helpers/tags/collection_helpers.rb +++ b/actionpack/lib/action_view/helpers/tags/collection_helpers.rb @@ -1,8 +1,8 @@ module ActionView module Helpers - module Tags - module CollectionHelpers - class Builder + module Tags # :nodoc: + module CollectionHelpers # :nodoc: + class Builder # :nodoc: attr_reader :object, :text, :value def initialize(template_object, object_name, method_name, object, diff --git a/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb b/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb index 893f4411e7..20be34c1f2 100644 --- a/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb +++ b/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb @@ -2,11 +2,11 @@ require 'action_view/helpers/tags/collection_helpers' module ActionView module Helpers - module Tags - class CollectionRadioButtons < Base + module Tags # :nodoc: + class CollectionRadioButtons < Base # :nodoc: include CollectionHelpers - class RadioButtonBuilder < Builder + class RadioButtonBuilder < Builder # :nodoc: def radio_button(extra_html_options={}) html_options = extra_html_options.merge(@input_html_options) @template_object.radio_button(@object_name, @method_name, @value, html_options) diff --git a/actionpack/lib/action_view/helpers/tags/collection_select.rb b/actionpack/lib/action_view/helpers/tags/collection_select.rb index ec78e6e5f9..6cb2b2e0d3 100644 --- a/actionpack/lib/action_view/helpers/tags/collection_select.rb +++ b/actionpack/lib/action_view/helpers/tags/collection_select.rb @@ -1,6 +1,6 @@ module ActionView module Helpers - module Tags + module Tags # :nodoc: class CollectionSelect < Base #:nodoc: def initialize(object_name, method_name, template_object, collection, value_method, text_method, options, html_options) @collection = collection diff --git a/actionpack/lib/action_view/helpers/tags/color_field.rb b/actionpack/lib/action_view/helpers/tags/color_field.rb index 6f08f8483a..d8fc797035 100644 --- a/actionpack/lib/action_view/helpers/tags/color_field.rb +++ b/actionpack/lib/action_view/helpers/tags/color_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class ColorField < TextField #:nodoc: + module Tags # :nodoc: + class ColorField < TextField # :nodoc: def render options = @options.stringify_keys options["value"] = @options.fetch("value") { validate_color_string(value(object)) } diff --git a/actionpack/lib/action_view/helpers/tags/date_field.rb b/actionpack/lib/action_view/helpers/tags/date_field.rb index 64c29dea3d..c22be0db29 100644 --- a/actionpack/lib/action_view/helpers/tags/date_field.rb +++ b/actionpack/lib/action_view/helpers/tags/date_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class DateField < DatetimeField #:nodoc: + module Tags # :nodoc: + class DateField < DatetimeField # :nodoc: private def format_date(value) diff --git a/actionpack/lib/action_view/helpers/tags/date_select.rb b/actionpack/lib/action_view/helpers/tags/date_select.rb index 734591394b..0c4ac40070 100644 --- a/actionpack/lib/action_view/helpers/tags/date_select.rb +++ b/actionpack/lib/action_view/helpers/tags/date_select.rb @@ -2,8 +2,8 @@ require 'active_support/core_ext/time/calculations' module ActionView module Helpers - module Tags - class DateSelect < Base #:nodoc: + module Tags # :nodoc: + class DateSelect < Base # :nodoc: def initialize(object_name, method_name, template_object, options, html_options) @html_options = html_options diff --git a/actionpack/lib/action_view/helpers/tags/datetime_field.rb b/actionpack/lib/action_view/helpers/tags/datetime_field.rb index e407146e96..9a2279c611 100644 --- a/actionpack/lib/action_view/helpers/tags/datetime_field.rb +++ b/actionpack/lib/action_view/helpers/tags/datetime_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class DatetimeField < TextField #:nodoc: + module Tags # :nodoc: + class DatetimeField < TextField # :nodoc: def render options = @options.stringify_keys options["value"] = @options.fetch("value") { format_date(value(object)) } diff --git a/actionpack/lib/action_view/helpers/tags/datetime_local_field.rb b/actionpack/lib/action_view/helpers/tags/datetime_local_field.rb index 6668d6d718..b4a74185d1 100644 --- a/actionpack/lib/action_view/helpers/tags/datetime_local_field.rb +++ b/actionpack/lib/action_view/helpers/tags/datetime_local_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class DatetimeLocalField < DatetimeField #:nodoc: + module Tags # :nodoc: + class DatetimeLocalField < DatetimeField # :nodoc: class << self def field_type @field_type ||= "datetime-local" diff --git a/actionpack/lib/action_view/helpers/tags/datetime_select.rb b/actionpack/lib/action_view/helpers/tags/datetime_select.rb index a32c840bce..563de1840e 100644 --- a/actionpack/lib/action_view/helpers/tags/datetime_select.rb +++ b/actionpack/lib/action_view/helpers/tags/datetime_select.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class DatetimeSelect < DateSelect #:nodoc: + module Tags # :nodoc: + class DatetimeSelect < DateSelect # :nodoc: end end end diff --git a/actionpack/lib/action_view/helpers/tags/email_field.rb b/actionpack/lib/action_view/helpers/tags/email_field.rb index 45cde507d7..7ce3ccb9bf 100644 --- a/actionpack/lib/action_view/helpers/tags/email_field.rb +++ b/actionpack/lib/action_view/helpers/tags/email_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class EmailField < TextField #:nodoc: + module Tags # :nodoc: + class EmailField < TextField # :nodoc: end end end diff --git a/actionpack/lib/action_view/helpers/tags/file_field.rb b/actionpack/lib/action_view/helpers/tags/file_field.rb index 59f2ff71b4..476b820d84 100644 --- a/actionpack/lib/action_view/helpers/tags/file_field.rb +++ b/actionpack/lib/action_view/helpers/tags/file_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class FileField < TextField #:nodoc: + module Tags # :nodoc: + class FileField < TextField # :nodoc: end end end diff --git a/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb b/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb index 507ba8835f..2ed4712dac 100644 --- a/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb +++ b/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class GroupedCollectionSelect < Base #:nodoc: + module Tags # :nodoc: + class GroupedCollectionSelect < Base # :nodoc: def initialize(object_name, method_name, template_object, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options) @collection = collection @group_method = group_method diff --git a/actionpack/lib/action_view/helpers/tags/hidden_field.rb b/actionpack/lib/action_view/helpers/tags/hidden_field.rb index a8d13dc1b1..c3757c2461 100644 --- a/actionpack/lib/action_view/helpers/tags/hidden_field.rb +++ b/actionpack/lib/action_view/helpers/tags/hidden_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class HiddenField < TextField #:nodoc: + module Tags # :nodoc: + class HiddenField < TextField # :nodoc: end end end diff --git a/actionpack/lib/action_view/helpers/tags/label.rb b/actionpack/lib/action_view/helpers/tags/label.rb index 16135fcd5a..35d3ba8434 100644 --- a/actionpack/lib/action_view/helpers/tags/label.rb +++ b/actionpack/lib/action_view/helpers/tags/label.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class Label < Base #:nodoc: + module Tags # :nodoc: + class Label < Base # :nodoc: def initialize(object_name, method_name, template_object, content_or_options = nil, options = nil) options ||= {} diff --git a/actionpack/lib/action_view/helpers/tags/month_field.rb b/actionpack/lib/action_view/helpers/tags/month_field.rb index 3d3c32d847..4c0fb846ee 100644 --- a/actionpack/lib/action_view/helpers/tags/month_field.rb +++ b/actionpack/lib/action_view/helpers/tags/month_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class MonthField < DatetimeField #:nodoc: + module Tags # :nodoc: + class MonthField < DatetimeField # :nodoc: private def format_date(value) diff --git a/actionpack/lib/action_view/helpers/tags/number_field.rb b/actionpack/lib/action_view/helpers/tags/number_field.rb index 9cd04434f0..4f95b1b4de 100644 --- a/actionpack/lib/action_view/helpers/tags/number_field.rb +++ b/actionpack/lib/action_view/helpers/tags/number_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class NumberField < TextField #:nodoc: + module Tags # :nodoc: + class NumberField < TextField # :nodoc: def render options = @options.stringify_keys diff --git a/actionpack/lib/action_view/helpers/tags/password_field.rb b/actionpack/lib/action_view/helpers/tags/password_field.rb index 6e7a4d3c36..6099fa6f19 100644 --- a/actionpack/lib/action_view/helpers/tags/password_field.rb +++ b/actionpack/lib/action_view/helpers/tags/password_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class PasswordField < TextField #:nodoc: + module Tags # :nodoc: + class PasswordField < TextField # :nodoc: def render @options = {:value => nil}.merge!(@options) super diff --git a/actionpack/lib/action_view/helpers/tags/radio_button.rb b/actionpack/lib/action_view/helpers/tags/radio_button.rb index 8a0421f061..4849c537a5 100644 --- a/actionpack/lib/action_view/helpers/tags/radio_button.rb +++ b/actionpack/lib/action_view/helpers/tags/radio_button.rb @@ -2,8 +2,8 @@ require 'action_view/helpers/tags/checkable' module ActionView module Helpers - module Tags - class RadioButton < Base #:nodoc: + module Tags # :nodoc: + class RadioButton < Base # :nodoc: include Checkable def initialize(object_name, method_name, template_object, tag_value, options) diff --git a/actionpack/lib/action_view/helpers/tags/range_field.rb b/actionpack/lib/action_view/helpers/tags/range_field.rb index 47db4680e7..f98ae88043 100644 --- a/actionpack/lib/action_view/helpers/tags/range_field.rb +++ b/actionpack/lib/action_view/helpers/tags/range_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class RangeField < NumberField #:nodoc: + module Tags # :nodoc: + class RangeField < NumberField # :nodoc: end end end diff --git a/actionpack/lib/action_view/helpers/tags/search_field.rb b/actionpack/lib/action_view/helpers/tags/search_field.rb index 818fd4b887..c09e2f1be7 100644 --- a/actionpack/lib/action_view/helpers/tags/search_field.rb +++ b/actionpack/lib/action_view/helpers/tags/search_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class SearchField < TextField #:nodoc: + module Tags # :nodoc: + class SearchField < TextField # :nodoc: def render options = @options.stringify_keys diff --git a/actionpack/lib/action_view/helpers/tags/select.rb b/actionpack/lib/action_view/helpers/tags/select.rb index 53a108b7e6..d64e2f68ef 100644 --- a/actionpack/lib/action_view/helpers/tags/select.rb +++ b/actionpack/lib/action_view/helpers/tags/select.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class Select < Base #:nodoc: + module Tags # :nodoc: + class Select < Base # :nodoc: def initialize(object_name, method_name, template_object, choices, options, html_options) @choices = choices @choices = @choices.to_a if @choices.is_a?(Range) @@ -31,7 +31,6 @@ module ActionView # # [nil, []] # { nil => [] } - # def grouped_choices? !@choices.empty? && @choices.first.respond_to?(:last) && Array === @choices.first.last end diff --git a/actionpack/lib/action_view/helpers/tags/tel_field.rb b/actionpack/lib/action_view/helpers/tags/tel_field.rb index 87c1f6b6b6..987bb9e67a 100644 --- a/actionpack/lib/action_view/helpers/tags/tel_field.rb +++ b/actionpack/lib/action_view/helpers/tags/tel_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class TelField < TextField #:nodoc: + module Tags # :nodoc: + class TelField < TextField # :nodoc: end end end diff --git a/actionpack/lib/action_view/helpers/tags/text_area.rb b/actionpack/lib/action_view/helpers/tags/text_area.rb index f74652c5e7..c81156c0c8 100644 --- a/actionpack/lib/action_view/helpers/tags/text_area.rb +++ b/actionpack/lib/action_view/helpers/tags/text_area.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class TextArea < Base #:nodoc: + module Tags # :nodoc: + class TextArea < Base # :nodoc: def render options = @options.stringify_keys add_default_name_and_id(options) diff --git a/actionpack/lib/action_view/helpers/tags/text_field.rb b/actionpack/lib/action_view/helpers/tags/text_field.rb index 024a1a8af2..baa5ff768e 100644 --- a/actionpack/lib/action_view/helpers/tags/text_field.rb +++ b/actionpack/lib/action_view/helpers/tags/text_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class TextField < Base #:nodoc: + module Tags # :nodoc: + class TextField < Base # :nodoc: def render options = @options.stringify_keys options["size"] = options["maxlength"] unless options.key?("size") diff --git a/actionpack/lib/action_view/helpers/tags/time_field.rb b/actionpack/lib/action_view/helpers/tags/time_field.rb index a3941860c9..0e90a3aed7 100644 --- a/actionpack/lib/action_view/helpers/tags/time_field.rb +++ b/actionpack/lib/action_view/helpers/tags/time_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class TimeField < DatetimeField #:nodoc: + module Tags # :nodoc: + class TimeField < DatetimeField # :nodoc: private def format_date(value) diff --git a/actionpack/lib/action_view/helpers/tags/time_select.rb b/actionpack/lib/action_view/helpers/tags/time_select.rb index 9e97deb706..0b06311d25 100644 --- a/actionpack/lib/action_view/helpers/tags/time_select.rb +++ b/actionpack/lib/action_view/helpers/tags/time_select.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class TimeSelect < DateSelect #:nodoc: + module Tags # :nodoc: + class TimeSelect < DateSelect # :nodoc: end end end diff --git a/actionpack/lib/action_view/helpers/tags/time_zone_select.rb b/actionpack/lib/action_view/helpers/tags/time_zone_select.rb index 0a176157c3..80d165ec7e 100644 --- a/actionpack/lib/action_view/helpers/tags/time_zone_select.rb +++ b/actionpack/lib/action_view/helpers/tags/time_zone_select.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class TimeZoneSelect < Base #:nodoc: + module Tags # :nodoc: + class TimeZoneSelect < Base # :nodoc: def initialize(object_name, method_name, template_object, priority_zones, options, html_options) @priority_zones = priority_zones @html_options = html_options diff --git a/actionpack/lib/action_view/helpers/tags/url_field.rb b/actionpack/lib/action_view/helpers/tags/url_field.rb index 1ffdfe0b3c..d76340178d 100644 --- a/actionpack/lib/action_view/helpers/tags/url_field.rb +++ b/actionpack/lib/action_view/helpers/tags/url_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class UrlField < TextField #:nodoc: + module Tags # :nodoc: + class UrlField < TextField # :nodoc: end end end diff --git a/actionpack/lib/action_view/helpers/tags/week_field.rb b/actionpack/lib/action_view/helpers/tags/week_field.rb index 1e13939a0a..5b3d0494e9 100644 --- a/actionpack/lib/action_view/helpers/tags/week_field.rb +++ b/actionpack/lib/action_view/helpers/tags/week_field.rb @@ -1,7 +1,7 @@ module ActionView module Helpers - module Tags - class WeekField < DatetimeField #:nodoc: + module Tags # :nodoc: + class WeekField < DatetimeField # :nodoc: private def format_date(value) diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 2e124cf085..147f9fd8ed 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -126,8 +126,8 @@ module ActionView # Extracts an excerpt from +text+ that matches the first instance of +phrase+. # The <tt>:radius</tt> option expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters # defined in <tt>:radius</tt> (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+, - # then the <tt>:omission</tt> option (which defaults to "...") will be prepended/appended accordingly. The - # <tt>:separator</tt> enable to choose the delimation. The resulting string will be stripped in any case. If the +phrase+ + # then the <tt>:omission</tt> option (which defaults to "...") will be prepended/appended accordingly. Use the + # <tt>:separator</tt> option to choose the delimitation. The resulting string will be stripped in any case. If the +phrase+ # isn't found, nil is returned. # # excerpt('This is an example', 'an', radius: 5) @@ -145,7 +145,7 @@ module ActionView # excerpt('This is also an example', 'an', radius: 8, omission: '<chop> ') # # => <chop> is also an example # - # excerpt('This is a very beautiful morning', 'very', separator: ' ', radius: 1) + # excerpt('This is a very beautiful morning', 'very', separator: ' ', radius: 1) # # => ...a very beautiful... def excerpt(text, phrase, options = {}) return unless text && phrase @@ -250,8 +250,11 @@ module ActionView # simple_format("Look ma! A class!", class: 'description') # # => "<p class='description'>Look ma! A class!</p>" # - # simple_format("<span>I'm allowed!</span> It's true.", {}, sanitize: false) - # # => "<p><span>I'm allowed!</span> It's true.</p>" + # simple_format("<blink>Unblinkable.</blink>") + # # => "<p>Unblinkable.</p>" + # + # simple_format("<blink>Blinkable!</blink> It's true.", {}, sanitize: false) + # # => "<p><blink>Blinkable!</span> It's true.</p>" def simple_format(text, html_options = {}, options = {}) wrapper_tag = options.fetch(:wrapper_tag, :p) diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 6b9b0a826b..3304605c1a 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -47,7 +47,7 @@ module ActionView NAME_BLOCK = lambda {|cache, name| cache[name] = SmallCache.new(&PREFIX_BLOCK)} KEY_BLOCK = lambda {|cache, key| cache[key] = SmallCache.new(&NAME_BLOCK)} - # usually a majority of template look ups return nothing, use this canonical preallocated array to safe memory + # usually a majority of template look ups return nothing, use this canonical preallocated array to save memory NO_TEMPLATES = [].freeze def initialize diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index 92baad4523..4a05c00f8b 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -8,6 +8,8 @@ module AbstractControllerTests include AbstractController::Rendering include AbstractController::Layouts + abstract! + self.view_paths = [ActionView::FixtureResolver.new( "layouts/hello.erb" => "With String <%= yield %>", "layouts/hello_override.erb" => "With Override <%= yield %>", @@ -251,6 +253,10 @@ module AbstractControllerTests assert_equal "Hello nil!", controller.response_body end + test "when layout is specified as a proc, do not leak any methods into controller's action_methods" do + assert_equal Set.new(['index']), WithProc.action_methods + end + test "when layout is specified as a proc, call it and use the layout returned" do controller = WithProc.new controller.process(:index) diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb index 5755444a65..34164a19f0 100644 --- a/actionpack/test/controller/live_stream_test.rb +++ b/actionpack/test/controller/live_stream_test.rb @@ -52,6 +52,29 @@ module ActionController def with_stale render :text => 'stale' if stale?(:etag => "123") end + + def exception_in_view + render 'doesntexist' + end + + def exception_with_callback + response.headers['Content-Type'] = 'text/event-stream' + + response.stream.on_error do + response.stream.write %(data: "500 Internal Server Error"\n\n) + response.stream.close + end + + raise 'An exception occurred...' + end + + def exception_in_exception_callback + response.headers['Content-Type'] = 'text/event-stream' + response.stream.on_error do + raise 'We need to go deeper.' + end + response.stream.write params[:widget][:didnt_check_for_nil] + end end tests TestController @@ -66,6 +89,21 @@ module ActionController TestResponse.new end + def assert_stream_closed + assert response.stream.closed?, 'stream should be closed' + end + + def capture_log_output + output = StringIO.new + old_logger, ActionController::Base.logger = ActionController::Base.logger, ActiveSupport::Logger.new(output) + + begin + yield output + ensure + ActionController::Base.logger = old_logger + end + end + def test_set_response! @controller.set_response!(@request) assert_kind_of(Live::Response, @controller.response) @@ -119,7 +157,43 @@ module ActionController def test_render_text get :render_text assert_equal 'zomg', response.body - assert response.stream.closed?, 'stream should be closed' + assert_stream_closed + end + + def test_exception_handling_html + capture_log_output do |output| + get :exception_in_view + assert_match %r((window\.location = "/500\.html"</script></html>)$), response.body + assert_match 'Missing template test/doesntexist', output.rewind && output.read + assert_stream_closed + end + end + + def test_exception_handling_plain_text + capture_log_output do |output| + get :exception_in_view, format: :json + assert_equal '', response.body + assert_match 'Missing template test/doesntexist', output.rewind && output.read + assert_stream_closed + end + end + + def test_exception_callback + capture_log_output do |output| + get :exception_with_callback, format: 'text/event-stream' + assert_equal %(data: "500 Internal Server Error"\n\n), response.body + assert_match 'An exception occurred...', output.rewind && output.read + assert_stream_closed + end + end + + def test_exceptions_raised_handling_exceptions + capture_log_output do |output| + get :exception_in_exception_callback, format: 'text/event-stream' + assert_equal '', response.body + assert_match 'We need to go deeper', output.rewind && output.read + assert_stream_closed + end end def test_stale_without_etag diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index ba24e7fac5..088ad73f2f 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -89,6 +89,13 @@ module AbstractController ) end + def test_subdomain_may_be_removed_with_blank_string + W.default_url_options[:host] = 'api.basecamphq.com' + assert_equal('http://basecamphq.com/c/a/i', + W.new.url_for(:subdomain => '', :controller => 'c', :action => 'a', :id => 'i') + ) + end + def test_multiple_subdomains_may_be_removed W.default_url_options[:host] = 'mobile.www.api.basecamphq.com' assert_equal('http://basecamphq.com/c/a/i', diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 29703dd5b1..afd456e8e5 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -3322,6 +3322,10 @@ class TestUrlConstraints < ActionDispatch::IntegrationTest end get '/' => ok, :as => :alternate_root, :constraints => { :port => 8080 } + + get '/search' => ok, :constraints => { :subdomain => false } + + get '/logs' => ok, :constraints => { :subdomain => true } end end @@ -3348,6 +3352,24 @@ class TestUrlConstraints < ActionDispatch::IntegrationTest get 'http://www.example.com:8080/' assert_response :success end + + test "false constraint expressions check for absence of values" do + get 'http://example.com/search' + assert_response :success + assert_equal 'http://example.com/search', search_url + + get 'http://api.example.com/search' + assert_response :not_found + end + + test "true constraint expressions check for presence of values" do + get 'http://api.example.com/logs' + assert_response :success + assert_equal 'http://api.example.com/logs', logs_url + + get 'http://example.com/logs' + assert_response :not_found + end end class TestInvalidUrls < ActionDispatch::IntegrationTest diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb index 4123529092..f919592d24 100644 --- a/actionpack/test/dispatch/url_generation_test.rb +++ b/actionpack/test/dispatch/url_generation_test.rb @@ -56,6 +56,47 @@ module TestUrlGeneration test "formatting host when protocol is present" do assert_equal "http://www.example.com/foo", foo_url(host: "httpz://www.example.com", protocol: "http://") end + + test "default ports are removed from the host" do + assert_equal "http://www.example.com/foo", foo_url(host: "www.example.com:80", protocol: "http://") + assert_equal "https://www.example.com/foo", foo_url(host: "www.example.com:443", protocol: "https://") + end + + test "port is extracted from the host" do + assert_equal "http://www.example.com:8080/foo", foo_url(host: "www.example.com:8080", protocol: "http://") + end + + test "port option overides the host" do + assert_equal "http://www.example.com:8080/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: 8080) + end + + test "port option disables the host when set to nil" do + assert_equal "http://www.example.com/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: nil) + end + + test "port option disables the host when set to false" do + assert_equal "http://www.example.com/foo", foo_url(host: "www.example.com:8443", protocol: "http://", port: false) + end + + test "keep subdomain when key is true" do + assert_equal "http://www.example.com/foo", foo_url(subdomain: true) + end + + test "keep subdomain when key is missing" do + assert_equal "http://www.example.com/foo", foo_url + end + + test "omit subdomain when key is nil" do + assert_equal "http://example.com/foo", foo_url(subdomain: nil) + end + + test "omit subdomain when key is false" do + assert_equal "http://example.com/foo", foo_url(subdomain: false) + end + + test "omit subdomain when key is blank" do + assert_equal "http://example.com/foo", foo_url(subdomain: "") + end end end diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index 94ae8549f7..1715902927 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -100,6 +100,13 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_collection_options_with_element_attributes + assert_dom_equal( + "<option value=\"USA\" class=\"bold\">USA</option>", + options_from_collection_for_select([[ "USA", "USA", { :class => 'bold' } ]], :first, :second) + ) + end + def test_string_options_for_select options = "<option value=\"Denmark\">Denmark</option><option value=\"USA\">USA</option><option value=\"Sweden\">Sweden</option>" assert_dom_equal( |