diff options
Diffstat (limited to 'actionpack/lib/action_view')
56 files changed, 305 insertions, 253 deletions
diff --git a/actionpack/lib/action_view/buffers.rb b/actionpack/lib/action_view/buffers.rb index 2372d3c433..361a0dccbe 100644 --- a/actionpack/lib/action_view/buffers.rb +++ b/actionpack/lib/action_view/buffers.rb @@ -8,9 +8,15 @@ module ActionView end def <<(value) + return self if value.nil? super(value.to_s) end alias :append= :<< + + def safe_concat(value) + return self if value.nil? + super(value.to_s) + end alias :safe_append= :safe_concat end diff --git a/actionpack/lib/action_view/dependency_tracker.rb b/actionpack/lib/action_view/dependency_tracker.rb index a2a555dfcb..b2e8334077 100644 --- a/actionpack/lib/action_view/dependency_tracker.rb +++ b/actionpack/lib/action_view/dependency_tracker.rb @@ -39,7 +39,7 @@ module ActionView render\s* # render, followed by optional whitespace \(? # start an optional parenthesis for the render call (partial:|:partial\s+=>)?\s* # naming the partial, used with collection -- 1st capture - ([@a-z"'][@a-z_\/\."']+) # the template name itself -- 2nd capture + ([@a-z"'][@\w\/\."']+) # the template name itself -- 2nd capture /x def self.call(name, template) @@ -74,7 +74,7 @@ module ActionView # render(@topic) => render("topics/topic") # render(topics) => render("topics/topic") # render(message.topics) => render("topics/topic") - collect { |name| name.sub(/\A@?([a-z]+\.)*([a-z_]+)\z/) { "#{$2.pluralize}/#{$2.singularize}" } }. + collect { |name| name.sub(/\A@?([a-z_]+\.)*([a-z_]+)\z/) { "#{$2.pluralize}/#{$2.singularize}" } }. # render("headline") => render("message/headline") collect { |name| name.include?("/") ? name : "#{directory}/#{name}" }. diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 31e37893c6..2b3a3c6a29 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 @@ -58,7 +56,7 @@ module ActionView sources.uniq.map { |source| tag_options = { "src" => path_to_javascript(source, path_options) - }.merge(options) + }.merge!(options) content_tag(:script, "", tag_options) }.join("\n").html_safe end @@ -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 @@ -98,7 +95,7 @@ module ActionView "rel" => "stylesheet", "media" => "screen", "href" => path_to_stylesheet(source, path_options) - }.merge(options) + }.merge!(options) tag(:link, tag_options) }.join("\n").html_safe end @@ -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) @@ -127,11 +127,7 @@ module ActionView # # => <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 " + - "the :type option key. This behavior is deprecated and will be remove in Rails 4.1. You should pass " + - ":type option explicitly if you want to use other types, for example: " + - "auto_discovery_link_tag(:xml, '/feed.xml', :type => 'application/xml')" - ActiveSupport::Deprecation.warn message + raise ArgumentError.new("You should pass :type tag_option key explicitly, because you have passed #{type} type other than :rss or :atom.") end tag( @@ -148,11 +144,14 @@ 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" /> + # # => <link href="/assets/myicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" /> # # 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. @@ -160,19 +159,19 @@ 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', :type => 'image/vnd.microsoft.icon', :href => path_to_image(source) - }.merge(options.symbolize_keys)) + }.merge!(options.symbolize_keys)) end # Returns an HTML image tag for the +source+. The +source+ can be a full # 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 +249,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/asset_url_helper.rb b/actionpack/lib/action_view/helpers/asset_url_helper.rb index 71b78cf0b5..b5f2df76ab 100644 --- a/actionpack/lib/action_view/helpers/asset_url_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_url_helper.rb @@ -193,7 +193,6 @@ module ActionView request = self.request if respond_to?(:request) host = config.asset_host if defined? config.asset_host host ||= request.base_url if request && options[:protocol] == :request - return unless host if host.respond_to?(:call) arity = host.respond_to?(:arity) ? host.arity : host.method(:call).arity @@ -204,6 +203,8 @@ module ActionView host = host % (Zlib.crc32(source) % 4) end + return unless host + if host =~ URI_REGEXP host else diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index d3953c26b7..8fb5eb1548 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -808,7 +808,7 @@ module ActionView options[:max_years_allowed] = @options[:max_years_allowed] || 1000 if (options[:end] - options[:start]).abs > options[:max_years_allowed] - raise ArgumentError, "There're too many years options to be built. Are you sure you haven't mistyped something? You can provide the :max_years_allowed parameter" + raise ArgumentError, "There are too many years options to be built. Are you sure you haven't mistyped something? You can provide the :max_years_allowed parameter." end build_options_and_select(:year, val, options) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 6b6a7edc1d..36dedf0676 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -655,14 +655,6 @@ module ActionView # ... # <% end %> # - # When projects is already an association on Person you can use - # +accepts_nested_attributes_for+ to define the writer method for you: - # - # class Person < ActiveRecord::Base - # has_many :projects - # accepts_nested_attributes_for :projects - # end - # # If you want to destroy any of the associated models through the # form, you have to enable it first using the <tt>:allow_destroy</tt> # option for +accepts_nested_attributes_for+: @@ -1160,12 +1152,65 @@ module ActionView end end + # A +FormBuilder+ object is associated with a particular model object and + # allows you to generate fields associated with the model object. The + # +FormBuilder+ object is yielded when using +form_for+ or +fields_for+. + # For example: + # + # <%= form_for @person do |person_form| %> + # Name: <%= person_form.text_field :name %> + # Admin: <%= person_form.check_box :admin %> + # <% end %> + # + # In the above block, the a +FormBuilder+ object is yielded as the + # +person_form+ variable. This allows you to generate the +text_field+ + # and +check_box+ fields by specifying their eponymous methods, which + # modify the underlying template and associates the +@person+ model object + # with the form. + # + # The +FormBuilder+ object can be thought of as serving as a proxy for the + # methods in the +FormHelper+ module. This class, however, allows you to + # call methods with the model object you are building the form for. + # + # You can create your own custom FormBuilder templates by subclasses this + # class. For example: + # + # class MyFormBuilder < ActionView::Helpers::FormBuilder + # def div_radio_button(method, tag_value, options = {}) + # @template.content_tag(:div, + # @template.radio_button( + # @object_name, method, tag_value, objectify_options(options) + # ) + # ) + # end + # + # The above code creates a new method +div_radio_button+ which wraps a div + # around the a new radio button. Note that when options are passed in, you + # must called +objectify_options+ in order for the model object to get + # correctly passed to the method. If +objectify_options+ is not called, + # then the newly created helper will not be linked back to the model. + # + # The +div_radio_button+ code from above can now be used as follows: + # + # <%= form_for @person, :builder => MyFormBuilder do |f| %> + # I am a child: <%= f.div_radio_button(:admin, "child") %> + # I am an adult: <%= f.div_radio_button(:admin, "adult") %> + # <% end -%> + # + # The standard set of helper methods for form building are located in the + # +field_helpers+ class attribute. class FormBuilder include ModelNaming # The methods which wrap a form helper call. class_attribute :field_helpers - self.field_helpers = FormHelper.instance_methods - [:form_for, :convert_to_model, :model_name_from_record_or_class] + self.field_helpers = [:fields_for, :label, :text_field, :password_field, + :hidden_field, :file_field, :text_area, :check_box, + :radio_button, :color_field, :search_field, + :telephone_field, :phone_field, :date_field, + :time_field, :datetime_field, :datetime_local_field, + :month_field, :week_field, :url_field, :email_field, + :number_field, :range_field] attr_accessor :object_name, :object, :options @@ -1247,7 +1292,7 @@ module ActionView # Admin? : <%= permission_fields.check_box :admin %> # <% end %> # - # <%= f.submit %> + # <%= person_form.submit %> # <% end %> # # In this case, the checkbox field will be represented by an HTML +input+ @@ -1425,14 +1470,6 @@ module ActionView # ... # <% end %> # - # When projects is already an association on Person you can use - # +accepts_nested_attributes_for+ to define the writer method for you: - # - # class Person < ActiveRecord::Base - # has_many :projects - # accepts_nested_attributes_for :projects - # end - # # If you want to destroy any of the associated models through the # form, you have to enable it first using the <tt>:allow_destroy</tt> # option for +accepts_nested_attributes_for+: diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 377819a80c..ad26505086 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 = { @@ -515,7 +515,6 @@ module ActionView divider = options[:divider] else prompt = options - options = {} message = "Passing the prompt to grouped_options_for_select as an argument is deprecated. " \ "Please use an options hash like `{ prompt: #{prompt.inspect} }`." ActiveSupport::Deprecation.warn message @@ -565,7 +564,7 @@ module ActionView if priority_zones if priority_zones.is_a?(Regexp) - priority_zones = zones.grep(priority_zones) + priority_zones = zones.select { |z| z =~ priority_zones } end zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected) @@ -752,7 +751,7 @@ module ActionView end def prompt_text(prompt) - prompt = prompt.kind_of?(String) ? prompt : I18n.translate('helpers.select.prompt', :default => 'Please select') + prompt.kind_of?(String) ? prompt : I18n.translate('helpers.select.prompt', :default => 'Please select') end end diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 8abd5d6e9c..3fa7696b83 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -81,7 +81,7 @@ module ActionView # ==== Options # * <tt>:multiple</tt> - If set to true the selection will allow multiple choices. # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input. - # * <tt>:include_blank</tt> - If set to true, an empty option will be create + # * <tt>:include_blank</tt> - If set to true, an empty option will be created. # * <tt>:prompt</tt> - Create a prompt option with blank value and the text asking user to select something # * Any other key creates standard HTML attributes for the tag. # @@ -426,22 +426,6 @@ module ActionView def submit_tag(value = "Save changes", options = {}) options = options.stringify_keys - if disable_with = options.delete("disable_with") - message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { disable_with: \'Text\' }' instead." - ActiveSupport::Deprecation.warn message - - options["data-disable-with"] = disable_with - end - - if confirm = options.delete("confirm") - message = ":confirm option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { confirm: \'Text\' }' instead'." - ActiveSupport::Deprecation.warn message - - options["data-confirm"] = confirm - end - tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options) end @@ -488,22 +472,6 @@ module ActionView options ||= {} options = options.stringify_keys - if disable_with = options.delete("disable_with") - message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { disable_with: \'Text\' }' instead." - ActiveSupport::Deprecation.warn message - - options["data-disable-with"] = disable_with - end - - if confirm = options.delete("confirm") - message = ":confirm option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { confirm: \'Text\' }' instead'." - ActiveSupport::Deprecation.warn message - - options["data-confirm"] = confirm - end - options.reverse_merge! 'name' => 'button', 'type' => 'submit' content_tag :button, content_or_options || 'Button', options, &block @@ -541,15 +509,6 @@ module ActionView # # => <input alt="Save" src="/images/save.png" data-confirm="Are you sure?" type="image" /> def image_submit_tag(source, options = {}) options = options.stringify_keys - - if confirm = options.delete("confirm") - message = ":confirm option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { confirm: \'Text\' }' instead'." - ActiveSupport::Deprecation.warn message - - options["data-confirm"] = confirm - end - tag :input, { "alt" => image_alt(source), "type" => "image", "src" => path_to_image(source) }.update(options) end diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index 878d3e0eda..e475d5b018 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -70,48 +70,6 @@ module ActionView def javascript_cdata_section(content) #:nodoc: "\n//#{cdata_section("\n#{content}\n//")}\n".html_safe end - - # Returns a button whose +onclick+ handler triggers the passed JavaScript. - # - # The helper receives a name, JavaScript code, and an optional hash of HTML options. The - # name is used as button label and the JavaScript code goes into its +onclick+ attribute. - # If +html_options+ has an <tt>:onclick</tt>, that one is put before +function+. - # - # button_to_function "Greeting", "alert('Hello world!')", class: "ok" - # # => <input class="ok" onclick="alert('Hello world!');" type="button" value="Greeting" /> - # - def button_to_function(name, function=nil, html_options={}) - message = "button_to_function is deprecated and will be removed from Rails 4.1. We recomend to use Unobtrusive JavaScript instead. " + - "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript" - ActiveSupport::Deprecation.warn message - - onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};" - - tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick)) - end - - # Returns a link whose +onclick+ handler triggers the passed JavaScript. - # - # The helper receives a name, JavaScript code, and an optional hash of HTML options. The - # name is used as the link text and the JavaScript code goes into the +onclick+ attribute. - # If +html_options+ has an <tt>:onclick</tt>, that one is put before +function+. Once all - # the JavaScript is set, the helper appends "; return false;". - # - # The +href+ attribute of the tag is set to "#" unless +html_options+ has one. - # - # link_to_function "Greeting", "alert('Hello world!')", class: "nav_link" - # # => <a class="nav_link" href="#" onclick="alert('Hello world!'); return false;">Greeting</a> - # - def link_to_function(name, function, html_options={}) - message = "link_to_function is deprecated and will be removed from Rails 4.1. We recomend to use Unobtrusive JavaScript instead. " + - "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript" - ActiveSupport::Deprecation.warn message - - onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;" - href = html_options[:href] || '#' - - content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick)) - end end end end 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/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 8c7524e795..3939e4737b 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -148,7 +148,7 @@ module ActionView attrs << tag_option(key, value, escape) end end - " #{attrs.sort * ' '}".html_safe unless attrs.empty? + " #{attrs.sort! * ' '}".html_safe unless attrs.empty? end def data_tag_option(key, value, escape) diff --git a/actionpack/lib/action_view/helpers/tags/base.rb b/actionpack/lib/action_view/helpers/tags/base.rb index aef1572290..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 @@ -73,27 +73,26 @@ module ActionView def add_default_name_and_id(options) if options.has_key?("index") - options["name"] ||= options.fetch("name"){ tag_name_with_index(options["index"]) } + options["name"] ||= options.fetch("name"){ tag_name_with_index(options["index"], options["multiple"]) } options["id"] = options.fetch("id"){ tag_id_with_index(options["index"]) } options.delete("index") elsif defined?(@auto_index) - options["name"] ||= options.fetch("name"){ tag_name_with_index(@auto_index) } + options["name"] ||= options.fetch("name"){ tag_name_with_index(@auto_index, options["multiple"]) } options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) } else - options["name"] ||= options.fetch("name"){ tag_name } + options["name"] ||= options.fetch("name"){ tag_name(options["multiple"]) } options["id"] = options.fetch("id"){ tag_id } end - options["name"] += "[]" if options["multiple"] && !options["name"].ends_with?("[]") options["id"] = [options.delete('namespace'), options["id"]].compact.join("_").presence end - def tag_name - "#{@object_name}[#{sanitized_method_name}]" + def tag_name(multiple = false) + "#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}" end - def tag_name_with_index(index) - "#{@object_name}[#{index}][#{sanitized_method_name}]" + def tag_name_with_index(index, multiple = false) + "#{@object_name}[#{index}][#{sanitized_method_name}]#{"[]" if multiple}" end def tag_id 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/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 775d93ed39..8a83f6f356 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -425,8 +425,8 @@ module ActionView # * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email. # # ==== Obfuscation - # Prior to Rails 4.0, +mail_to+ provided options for encoding the address - # in order to hinder email harvesters. To take advantage of these options, + # Prior to Rails 4.0, +mail_to+ provided options for encoding the address + # in order to hinder email harvesters. To take advantage of these options, # install the +actionview-encoded_mail_to+ gem. # # ==== Examples @@ -439,18 +439,30 @@ module ActionView # mail_to "me@domain.com", "My email", cc: "ccaddress@domain.com", # subject: "This is an example email" # # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a> - def mail_to(email_address, name = nil, html_options = {}) + # + # You can use a block as well if your link target is hard to fit into the name parameter. ERB example: + # + # <%= mail_to "me@domain.com" do %> + # <strong>Email me:</strong> <span>me@domain.com</span> + # <% end %> + # # => <a href="mailto:me@domain.com"> + # <strong>Email me:</strong> <span>me@domain.com</span> + # </a> + def mail_to(email_address, name = nil, html_options = {}, &block) email_address = ERB::Util.html_escape(email_address) - html_options.stringify_keys! + html_options, name = name, nil if block_given? + html_options = (html_options || {}).stringify_keys extras = %w{ cc bcc body subject }.map { |item| option = html_options.delete(item) || next "#{item}=#{Rack::Utils.escape_path(option)}" }.compact extras = extras.empty? ? '' : '?' + ERB::Util.html_escape(extras.join('&')) - - content_tag "a", name || email_address.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe) + + html_options["href"] = "mailto:#{email_address}#{extras}".html_safe + + content_tag(:a, name || email_address.html_safe, html_options, &block) end # True if the current request URI was generated by the given +options+. @@ -536,28 +548,10 @@ module ActionView html_options = html_options.stringify_keys html_options['data-remote'] = 'true' if link_to_remote_options?(options) || link_to_remote_options?(html_options) - disable_with = html_options.delete("disable_with") - confirm = html_options.delete('confirm') method = html_options.delete('method') - if confirm - message = ":confirm option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { confirm: \'Text\' }' instead." - ActiveSupport::Deprecation.warn message - - html_options["data-confirm"] = confirm - end - add_method_to_attributes!(html_options, method) if method - if disable_with - message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { disable_with: \'Text\' }' instead." - ActiveSupport::Deprecation.warn message - - html_options["data-disable-with"] = disable_with - end - html_options else link_to_remote_options?(options) ? {'data-remote' => 'true'} : {} diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index d61cc0f304..f9d5b97fe3 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -1,5 +1,6 @@ require 'thread_safe' require 'active_support/core_ext/module/remove_method' +require 'active_support/core_ext/module/attribute_accessors' module ActionView # = Action View Lookup Context diff --git a/actionpack/lib/action_view/path_set.rb b/actionpack/lib/action_view/path_set.rb index d9c76366f8..91ee2ea8f5 100644 --- a/actionpack/lib/action_view/path_set.rb +++ b/actionpack/lib/action_view/path_set.rb @@ -1,5 +1,11 @@ module ActionView #:nodoc: # = Action View PathSet + # + # This class is used to store and access paths in Action View. A number of + # operations are defined so that you can search among the paths in this + # set and also perform operations on other +PathSet+ objects. + # + # A +LookupContext+ will use a +PathSet+ to store the paths in its context. class PathSet #:nodoc: include Enumerable diff --git a/actionpack/lib/action_view/renderer/abstract_renderer.rb b/actionpack/lib/action_view/renderer/abstract_renderer.rb index 6fb8cbb46c..73c19a0ae2 100644 --- a/actionpack/lib/action_view/renderer/abstract_renderer.rb +++ b/actionpack/lib/action_view/renderer/abstract_renderer.rb @@ -1,4 +1,19 @@ module ActionView + # This class defines the interface for a renderer. Each class that + # subclasses +AbstractRenderer+ is used by the base +Renderer+ class to + # render a specific type of object. + # + # The base +Renderer+ class uses its +render+ method to delegate to the + # renderers. These currently consist of + # + # PartialRenderer - Used for rendering partials + # TemplateRenderer - Used for rendering other types of templates + # StreamingTemplateRenderer - Used for streaming + # + # Whenever the +render+ method is called on the base +Renderer+ class, a new + # renderer object of the correct type is created, and the +render+ method on + # that new object is called in turn. This abstracts the setup and rendering + # into a separate classes for partials and templates. class AbstractRenderer #:nodoc: delegate :find_template, :template_exists?, :with_fallbacks, :with_layout_format, :formats, :to => :@lookup_context diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb index 43a88b0623..821026268a 100644 --- a/actionpack/lib/action_view/renderer/partial_renderer.rb +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -313,6 +313,13 @@ module ActionView private + # Sets up instance variables needed for rendering a partial. This method + # finds the options and details and extracts them. The method also contains + # logic that handles the type of object passed in as the partial. + # + # If +options[:partial]+ is a string, then the +@path+ instance variable is + # set to that string. Otherwise, the +options[:partial]+ object must + # respond to +to_partial_path+ in order to setup the path. def setup(context, options, block) @view = context partial = options[:partial] @@ -413,6 +420,13 @@ module ActionView end end + # Obtains the path to where the object's partial is located. If the object + # responds to +to_partial_path+, then +to_partial_path+ will be called and + # will provide the path. If the object does not respond to +to_partial_path+, + # then an +ArgumentError+ is raised. + # + # If +prefix_partial_path_with_controller_namespace+ is true, then this + # method will prefix the partial paths with a namespace. def partial_path(object = @object) object = object.to_model if object.respond_to?(:to_model) diff --git a/actionpack/lib/action_view/renderer/renderer.rb b/actionpack/lib/action_view/renderer/renderer.rb index 30a0c4be70..964b18337e 100644 --- a/actionpack/lib/action_view/renderer/renderer.rb +++ b/actionpack/lib/action_view/renderer/renderer.rb @@ -2,6 +2,12 @@ module ActionView # This is the main entry point for rendering. It basically delegates # to other objects like TemplateRenderer and PartialRenderer which # actually renders the template. + # + # The Renderer will parse the options from the +render+ or +render_body+ + # method and render a partial or a template based on the options. The + # +TemplateRenderer+ and +PartialRenderer+ objects are wrappers which do all + # the setup and logic necessary to render a view and a new object is created + # each time +render+ is called. class Renderer attr_accessor :lookup_context diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 946db1df79..e2c50fec47 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -138,7 +138,7 @@ module ActionView # we use a bang in this instrumentation because you don't want to # consume this in production. This is only slow if it's being listened to. def render(view, locals, buffer=nil, &block) - ActiveSupport::Notifications.instrument("!render_template.action_view", virtual_path: @virtual_path, identifier: @identifier) do + instrument("!render_template") do compile!(view) view.send(method_name, locals, buffer, &block) end @@ -146,12 +146,6 @@ module ActionView handle_render_error(view, e) end - def mime_type - message = 'Template#mime_type is deprecated and will be removed in Rails 4.1. Please use type method instead.' - ActiveSupport::Deprecation.warn message - @mime_type ||= Mime::Type.lookup_by_extension(@formats.first.to_s) if @formats.first - end - def type @type ||= Types[@formats.first] if @formats.first end @@ -245,7 +239,9 @@ module ActionView mod = view.singleton_class end - compile(view, mod) + instrument("!compile_template") do + compile(view, mod) + end # Just discard the source if we have a virtual path. This # means we can get the template back. @@ -271,7 +267,7 @@ module ActionView method_name = self.method_name code = @handler.call(self) - # Make sure that the resulting String to be evalled is in the + # Make sure that the resulting String to be eval'd is in the # encoding of the code source = <<-end_src def #{method_name}(local_assigns, output_buffer) @@ -335,5 +331,10 @@ module ActionView def identifier_method_name #:nodoc: inspect.gsub(/[^a-z_]/, '_') end + + def instrument(action, &block) + payload = { virtual_path: @virtual_path, identifier: @identifier } + ActiveSupport::Notifications.instrument("#{action}.action_view", payload, &block) + end end end diff --git a/actionpack/lib/action_view/template/handlers/erb.rb b/actionpack/lib/action_view/template/handlers/erb.rb index 5aaafc15c1..7d7a7af51d 100644 --- a/actionpack/lib/action_view/template/handlers/erb.rb +++ b/actionpack/lib/action_view/template/handlers/erb.rb @@ -6,12 +6,23 @@ module ActionView module Handlers class Erubis < ::Erubis::Eruby def add_preamble(src) + @newline_pending = 0 src << "@output_buffer = output_buffer || ActionView::OutputBuffer.new;" end def add_text(src, text) return if text.empty? - src << "@output_buffer.safe_concat('" << escape_text(text) << "');" + + if text == "\n" + @newline_pending += 1 + else + src << "@output_buffer.safe_append='" + src << "\n" * @newline_pending if @newline_pending > 0 + src << escape_text(text) + src << "';" + + @newline_pending = 0 + end end # Erubis toggles <%= and <%== behavior when escaping is enabled. @@ -28,24 +39,39 @@ module ActionView BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/ def add_expr_literal(src, code) + flush_newline_if_pending(src) if code =~ BLOCK_EXPR src << '@output_buffer.append= ' << code else - src << '@output_buffer.append= (' << code << ');' + src << '@output_buffer.append=(' << code << ');' end end def add_expr_escaped(src, code) + flush_newline_if_pending(src) if code =~ BLOCK_EXPR src << "@output_buffer.safe_append= " << code else - src << "@output_buffer.safe_concat((" << code << ").to_s);" + src << "@output_buffer.safe_append=(" << code << ");" end end + def add_stmt(src, code) + flush_newline_if_pending(src) + super + end + def add_postamble(src) + flush_newline_if_pending(src) src << '@output_buffer.to_s' end + + def flush_newline_if_pending(src) + if @newline_pending > 0 + src << "@output_buffer.safe_append='#{"\n" * @newline_pending}';" + @newline_pending = 0 + end + end end class ERB diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 47bd011d5e..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 @@ -255,7 +255,7 @@ module ActionView # # FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}") # - # This one allows you to keep files with different formats in seperated subdirectories, + # This one allows you to keep files with different formats in separate subdirectories, # eg. `users/new.html` will be loaded from `users/html/new.erb` or `users/new.html.erb`, # `users/new.js` from `users/js/new.erb` or `users/new.js.erb`, etc. # diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 10b487f37a..3145446114 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -211,7 +211,9 @@ module ActionView alias_method :_view, :view INTERNAL_IVARS = [ - :@__name__, + :@NAME, + :@failures, + :@assertions, :@__io__, :@_assertion_wrapped, :@_assertions, diff --git a/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb b/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb index 60b6783b19..7f8609c408 100644 --- a/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb +++ b/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb @@ -537,7 +537,7 @@ module HTML # Get identifier, class, attribute name, pseudo or negation. while true # Element identifier. - next if statement.sub!(/^#(\?|[\w\-]+)/) do |match| + next if statement.sub!(/^#(\?|[\w\-]+)/) do id = $1 if id == "?" id = values.shift @@ -549,7 +549,7 @@ module HTML end # Class name. - next if statement.sub!(/^\.([\w\-]+)/) do |match| + next if statement.sub!(/^\.([\w\-]+)/) do class_name = $1 @source << ".#{class_name}" class_name = Regexp.new("(^|\s)#{Regexp.escape(class_name)}($|\s)") unless class_name.is_a?(Regexp) @@ -558,7 +558,7 @@ module HTML end # Attribute value. - next if statement.sub!(/^\[\s*([[:alpha:]][\w\-:]*)\s*((?:[~|^$*])?=)?\s*('[^']*'|"[^*]"|[^\]]*)\s*\]/) do |match| + next if statement.sub!(/^\[\s*([[:alpha:]][\w\-:]*)\s*((?:[~|^$*])?=)?\s*('[^']*'|"[^*]"|[^\]]*)\s*\]/) do name, equality, value = $1, $2, $3 if value == "?" value = values.shift @@ -575,7 +575,7 @@ module HTML end # Root element only. - next if statement.sub!(/^:root/) do |match| + next if statement.sub!(/^:root/) do pseudo << lambda do |element| element.parent.nil? || !element.parent.tag? end @@ -611,7 +611,7 @@ module HTML "" # Remove end # First/last child (of type). - next if statement.sub!(/^:(first|last)-(child|of-type)/) do |match| + next if statement.sub!(/^:(first|last)-(child|of-type)/) do reverse = $1 == "last" of_type = $2 == "of-type" pseudo << nth_child(0, 1, of_type, reverse) @@ -619,7 +619,7 @@ module HTML "" # Remove end # Only child (of type). - next if statement.sub!(/^:only-(child|of-type)/) do |match| + next if statement.sub!(/^:only-(child|of-type)/) do of_type = $1 == "of-type" pseudo << only_child(of_type) @source << ":only-#{$1}" @@ -628,7 +628,7 @@ module HTML # Empty: no child elements or meaningful content (whitespaces # are ignored). - next if statement.sub!(/^:empty/) do |match| + next if statement.sub!(/^:empty/) do pseudo << lambda do |element| empty = true for child in element.children @@ -644,7 +644,7 @@ module HTML end # Content: match the text content of the element, stripping # leading and trailing spaces. - next if statement.sub!(/^:content\(\s*(\?|'[^']*'|"[^"]*"|[^)]*)\s*\)/) do |match| + next if statement.sub!(/^:content\(\s*(\?|'[^']*'|"[^"]*"|[^)]*)\s*\)/) do content = $1 if content == "?" content = values.shift |