diff options
Diffstat (limited to 'actionpack')
46 files changed, 329 insertions, 196 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 3f8188b1f7..2d133ca0b2 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,12 @@ *Rails 3.1.0 (unreleased)* +* Added a convenience idiom to generate HTML5 data-* attributes in tag helpers from a :data hash of options: + + tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)}) + # => <div data-name="Stephen" data-city-state="["Chicago","IL"]" /> + + Keys are dasherized. Values are JSON-encoded, except for strings and symbols. [Stephen Celis] + * Added render :once. You can pass either a string or an array of strings and Rails will ensure they each of them are rendered just once. [José Valim] * Deprecate old template handler API. The new API simply requires a template handler to respond to call. [José Valim] @@ -16,6 +23,10 @@ * Add Rack::Cache to the default stack. Create a Rails store that delegates to the Rails cache, so by default, whatever caching layer you are using will be used for HTTP caching. Note that Rack::Cache will be used if you use #expires_in, #fresh_when or #stale with :public => true. Otherwise, the caching rules will apply to the browser only. [Yehuda Katz, Carl Lerche] +*Rails 3.0.1 (October 15, 2010)* + +* No Changes, just a version bump. + *Rails 3.0.0 (August 29, 2010)* * password_field renders with nil value by default making the use of passwords secure by default, if you want to render you should do for instance f.password_field(:password, :value => @user.password) [Santiago Pastorino] diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb index df4d500069..104157d0b1 100644 --- a/actionpack/lib/action_controller/caching/pages.rb +++ b/actionpack/lib/action_controller/caching/pages.rb @@ -134,7 +134,7 @@ module ActionController #:nodoc: # If no options are provided, the requested url is used. Example: # cache_page "I'm the cached content", :controller => "lists", :action => "show" def cache_page(content = nil, options = nil) - return unless self.class.perform_caching && caching_allowed + return unless self.class.perform_caching && caching_allowed? path = case options when Hash @@ -148,10 +148,6 @@ module ActionController #:nodoc: self.class.cache_page(content || response.body, path) end - private - def caching_allowed - request.get? && response.status.to_i == 200 - end end end end diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 547cec7081..39c804d707 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -407,7 +407,7 @@ module ActionController # Returns nil if no token is found. def authenticate(controller, &login_procedure) token, options = token_and_options(controller.request) - if !token.blank? + unless token.blank? login_procedure.call(token, options) end end diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb index 851925e1b7..38d32211cc 100644 --- a/actionpack/lib/action_controller/metal/responder.rb +++ b/actionpack/lib/action_controller/metal/responder.rb @@ -161,6 +161,8 @@ module ActionController #:nodoc: display resource.errors, :status => :unprocessable_entity elsif post? display resource, :status => :created, :location => api_location + elsif has_empty_resource_definition? + display empty_resource, :status => :ok else head :ok end @@ -221,5 +223,23 @@ module ActionController #:nodoc: def default_action @action ||= ACTIONS_FOR_VERBS[request.request_method_symbol] end + + # Check whether resource needs a specific definition of empty resource to be valid + # + def has_empty_resource_definition? + respond_to?("empty_#{format}_resource") + end + + # Delegate to proper empty resource method + # + def empty_resource + send("empty_#{format}_resource") + end + + # Return a valid empty JSON resource + # + def empty_json_resource + "{}" + end end end diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 6061945622..0c26071379 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -40,6 +40,13 @@ module ActionController ActiveSupport::Notifications.unsubscribe("!render_template.action_view") end + def process(*args) + @partials = Hash.new(0) + @templates = Hash.new(0) + @layouts = Hash.new(0) + super + end + # Asserts that the request was rendered with the appropriate template file or partials. # # ==== Examples diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index 4061222d11..1d2f7e4f19 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -39,7 +39,8 @@ module ActionDispatch end module Response - attr_reader :cache_control + attr_reader :cache_control, :etag + alias :etag? :etag def initialize(*) status, header, body = super @@ -69,14 +70,6 @@ module ActionDispatch headers['Last-Modified'] = utc_time.httpdate end - def etag - @etag - end - - def etag? - @etag - end - def etag=(etag) key = ActiveSupport::Cache.expand_cache_key(etag) @etag = self["ETag"] = %("#{Digest::MD5.hexdigest(key)}") @@ -99,7 +92,7 @@ module ActionDispatch if control.empty? headers["Cache-Control"] = DEFAULT_CACHE_CONTROL - elsif @cache_control[:no_cache] + elsif control[:no_cache] headers["Cache-Control"] = "no-cache" else extras = control[:extras] diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index bbcdefb190..55a3166f6d 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -214,13 +214,13 @@ module ActionDispatch # Override Rack's GET method to support indifferent access def GET - @env["action_dispatch.request.query_parameters"] ||= normalize_parameters(super) + @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {}) end alias :query_parameters :GET # Override Rack's POST method to support indifferent access def POST - @env["action_dispatch.request.request_parameters"] ||= normalize_parameters(super) + @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {}) end alias :request_parameters :POST diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 72871e328a..8e03a7879f 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -44,8 +44,8 @@ module ActionDispatch # :nodoc: @block = nil @length = 0 - @status, @header = status, header - self.body = body + @header = header + self.body, self.status = body, status @cookie = [] @sending_file = false diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index ef0c9c51f5..71e736ce9f 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -62,6 +62,7 @@ module ActionDispatch private def render_exception(env, exception) log_error(exception) + exception = original_exception(exception) request = Request.new(env) if @consider_all_requests_local || request.local? @@ -154,5 +155,17 @@ module ActionDispatch def logger defined?(Rails.logger) ? Rails.logger : Logger.new($stderr) end + + def original_exception(exception) + if registered_original_exception?(exception) + exception.original_exception + else + exception + end + end + + def registered_original_exception?(exception) + exception.respond_to?(:original_exception) && @@rescue_responses.has_key?(exception.original_exception.class.name) + end end end diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb index 0f9d35d062..dada64a86f 100644 --- a/actionpack/lib/action_view.rb +++ b/actionpack/lib/action_view.rb @@ -21,9 +21,6 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) -$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) - require 'active_support/ruby/shim' require 'active_support/core_ext/class/attribute_accessors' @@ -33,14 +30,15 @@ module ActionView extend ActiveSupport::Autoload eager_autoload do + autoload :Base autoload :Context - autoload :Template autoload :Helpers - autoload :Base autoload :LookupContext - autoload :Render - autoload :PathSet, "action_view/paths" - autoload :TestCase, "action_view/test_case" + autoload :Partials + autoload :PathSet + autoload :Rendering + autoload :Template + autoload :TestCase autoload_under "renderer" do autoload :AbstractRenderer @@ -48,11 +46,6 @@ module ActionView autoload :TemplateRenderer end - autoload_under "render" do - autoload :Partials - autoload :Rendering - end - autoload_at "action_view/template/resolver" do autoload :Resolver autoload :PathResolver diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index a7a6bbd3a4..1beae37af3 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -224,6 +224,10 @@ module ActionView #:nodoc: @controller_path ||= controller && controller.controller_path end + def controller_prefix + @controller_prefix ||= controller && controller._prefix + end + ActiveSupport.run_load_hooks(:action_view, self) end end diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index d0f91f6b71..a728fde748 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -4,6 +4,7 @@ require 'action_view/helpers/url_helper' require 'action_view/helpers/tag_helper' require 'active_support/core_ext/file' require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/output_safety' module ActionView # = Action View Asset Tag Helpers @@ -819,7 +820,7 @@ module ActionView end def stylesheet_tag(source, options) - tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => html_escape(path_to_stylesheet(source)) }.merge(options), false, false) + tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_stylesheet(source)) }.merge(options), false, false) end def compute_javascript_paths(*args) diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index b34a74788e..d6e175c7e8 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -5,6 +5,7 @@ require 'action_view/helpers/form_tag_helper' require 'active_support/core_ext/class/inheritable_attributes' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/output_safety' module ActionView # = Action View Form Helpers @@ -907,7 +908,7 @@ module ActionView end options["type"] ||= field_type options["value"] = options.fetch("value"){ value_before_type_cast(object) } unless field_type == "file" - options["value"] &&= html_escape(options["value"]) + options["value"] &&= ERB::Util.html_escape(options["value"]) add_default_name_and_id(options) tag("input", options) end @@ -943,7 +944,7 @@ module ActionView options["cols"], options["rows"] = size.split("x") if size.respond_to?(:split) end - content_tag("textarea", html_escape(options.delete('value') || value_before_type_cast(object)), options) + content_tag("textarea", ERB::Util.html_escape(options.delete('value') || value_before_type_cast(object)), options) end def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0") diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 7d6aca0470..6ac8577785 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -2,6 +2,7 @@ require 'cgi' require 'erb' require 'action_view/helpers/form_helper' require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/output_safety' module ActionView # = Action View Form Option Helpers @@ -100,7 +101,6 @@ module ActionView # module FormOptionsHelper # ERB::Util can mask some helpers like textilize. Make sure to include them. - include ERB::Util include TextHelper # Create a select tag and a series of contained option tags for the provided object and method. @@ -247,7 +247,7 @@ module ActionView # # time_zone_select( "user", 'time_zone', /Australia/) # - # time_zone_select( "user", "time_zone", ActiveSupport::Timezone.all.sort, :model => ActiveSupport::Timezone) + # time_zone_select( "user", "time_zone", ActiveSupport::TimeZone.all.sort, :model => ActiveSupport::TimeZone) def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) InstanceTag.new(object, method, self, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options) end @@ -306,7 +306,7 @@ module ActionView text, value = option_text_and_value(element).map(&:to_s) selected_attribute = ' selected="selected"' if option_value_selected?(value, selected) disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled) - %(<option value="#{html_escape(value)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{html_escape(text)}</option>) + %(<option value="#{ERB::Util.html_escape(value)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{ERB::Util.html_escape(text)}</option>) end.join("\n").html_safe end @@ -396,7 +396,7 @@ module ActionView def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil) collection.map do |group| group_label_string = eval("group.#{group_label_method}") - "<optgroup label=\"#{html_escape(group_label_string)}\">" + + "<optgroup label=\"#{ERB::Util.html_escape(group_label_string)}\">" + options_from_collection_for_select(eval("group.#{group_method}"), option_key_method, option_value_method, selected_key) + '</optgroup>' end.join.html_safe @@ -501,7 +501,7 @@ module ActionView return "" unless Array === element html_attributes = [] element.select { |e| Hash === e }.reduce({}, :merge).each do |k, v| - html_attributes << " #{k}=\"#{html_escape(v.to_s)}\"" + html_attributes << " #{k}=\"#{ERB::Util.html_escape(v.to_s)}\"" end html_attributes.join end @@ -595,11 +595,11 @@ module ActionView private def add_options(option_tags, options, value = nil) if options[:include_blank] - option_tags = "<option value=\"\">#{html_escape(options[:include_blank]) if options[:include_blank].kind_of?(String)}</option>\n" + option_tags + option_tags = "<option value=\"\">#{ERB::Util.html_escape(options[:include_blank]) if options[:include_blank].kind_of?(String)}</option>\n" + option_tags end if value.blank? && options[:prompt] prompt = options[:prompt].kind_of?(String) ? options[:prompt] : I18n.translate('helpers.select.prompt', :default => 'Please select') - option_tags = "<option value=\"\">#{html_escape(prompt)}</option>\n" + option_tags + option_tags = "<option value=\"\">#{ERB::Util.html_escape(prompt)}</option>\n" + option_tags end option_tags.html_safe end diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 298db46177..92645f5cf9 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -1,6 +1,7 @@ require 'cgi' require 'action_view/helpers/tag_helper' require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/output_safety' module ActionView # = Action View Form Tag Helpers @@ -287,7 +288,7 @@ module ActionView end escape = options.key?("escape") ? options.delete("escape") : true - content = html_escape(content) if escape + content = ERB::Util.html_escape(content) if escape content_tag :textarea, content.to_s.html_safe, { "name" => name, "id" => sanitize_to_id(name) }.update(options) end @@ -390,7 +391,7 @@ module ActionView end if confirm = options.delete("confirm") - add_confirm_to_attributes!(options, confirm) + options["data-confirm"] = confirm end tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys) @@ -423,7 +424,7 @@ module ActionView options.stringify_keys! if confirm = options.delete("confirm") - add_confirm_to_attributes!(options, confirm) + options["data-confirm"] = confirm end tag :input, { "type" => "image", "src" => path_to_image(source) }.update(options.stringify_keys) diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index d1c8064c1b..1488e72c6e 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/big_decimal/conversions' require 'active_support/core_ext/float/rounding' require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/output_safety' module ActionView # = Action View Number Helpers @@ -47,36 +48,33 @@ module ActionView # number_to_phone(1235551234, :country_code => 1, :extension => 1343, :delimiter => ".") # => +1.123.555.1234 x 1343 def number_to_phone(number, options = {}) - return nil if number.nil? + return unless number begin Float(number) - is_number_html_safe = true rescue ArgumentError, TypeError - if options[:raise] - raise InvalidNumberError, number - else - is_number_html_safe = number.to_s.html_safe? - end - end + raise InvalidNumberError, number + end if options[:raise] number = number.to_s.strip options = options.symbolize_keys - area_code = options[:area_code] || nil + area_code = options[:area_code] delimiter = options[:delimiter] || "-" - extension = options[:extension].to_s.strip || nil - country_code = options[:country_code] || nil + extension = options[:extension] + country_code = options[:country_code] - str = "" - str << "+#{country_code}#{delimiter}" unless country_code.blank? - str << if area_code - number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4}$)/,"(\\1) \\2#{delimiter}\\3") + if area_code + number.gsub!(/(\d{1,3})(\d{3})(\d{4}$)/,"(\\1) \\2#{delimiter}\\3") else - number.gsub!(/([0-9]{0,3})([0-9]{3})([0-9]{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3") - number.starts_with?('-') ? number.slice!(1..-1) : number + number.gsub!(/(\d{0,3})(\d{3})(\d{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3") + number.slice!(0, 1) if number.starts_with?('-') end + + str = [] + str << "+#{country_code}#{delimiter}" unless country_code.blank? + str << number str << " x #{extension}" unless extension.blank? - is_number_html_safe ? str.html_safe : str + ERB::Util.html_escape(str.join) end # Formats a +number+ into a currency string (e.g., $13.65). You can customize the format @@ -104,7 +102,7 @@ module ActionView # number_to_currency(1234567890.50, :unit => "£", :separator => ",", :delimiter => "", :format => "%n %u") # # => 1234567890,50 £ def number_to_currency(number, options = {}) - return nil if number.nil? + return unless number options.symbolize_keys! @@ -149,7 +147,7 @@ module ActionView # number_to_percentage(302.24398923423, :precision => 5) # => 302.24399% # number_to_percentage(1000, :locale => :fr) # => 1 000,000% def number_to_percentage(number, options = {}) - return nil if number.nil? + return unless number options.symbolize_keys! @@ -263,7 +261,7 @@ module ActionView digits = (Math.log10(number.abs) + 1).floor rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision) end - precision = precision - digits + precision -= digits precision = precision > 0 ? precision : 0 #don't let it be negative else rounded_number = BigDecimal.new((number * (10 ** precision)).to_s).round.to_f / 10 ** precision @@ -447,6 +445,8 @@ module ActionView #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros) + inverted_du = DECIMAL_UNITS.invert + units = options.delete :units unit_exponents = case units when Hash @@ -457,7 +457,7 @@ module ActionView I18n.translate(:"number.human.decimal_units.units", :locale => options[:locale], :raise => true) else raise ArgumentError, ":units must be a Hash or String translation scope." - end.keys.map{|e_name| DECIMAL_UNITS.invert[e_name] }.sort_by{|e| -e} + end.keys.map{|e_name| inverted_du[e_name] }.sort_by{|e| -e} number_exponent = number != 0 ? Math.log10(number.abs).floor : 0 display_exponent = unit_exponents.find{|e| number_exponent >= e } diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index 41cd8d5171..f3a429fcce 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -1,6 +1,7 @@ require 'set' require 'active_support/json' require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/output_safety' module ActionView # = Action View Prototype Helpers @@ -131,7 +132,7 @@ module ActionView url_options = options[:url] url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash) - function << "'#{html_escape(escape_javascript(url_for(url_options)))}'" + function << "'#{ERB::Util.html_escape(escape_javascript(url_for(url_options)))}'" function << ", #{javascript_options})" function = "#{options[:before]}; #{function}" if options[:before] diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 1b9e152b4d..ee51617a2b 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/object/blank' +require 'active_support/core_ext/string/output_safety' require 'set' module ActionView @@ -7,8 +8,6 @@ module ActionView # Provides methods to generate HTML tags programmatically when you can't use # a Builder. By default, they output XHTML compliant tags. module TagHelper - include ERB::Util - extend ActiveSupport::Concern include CaptureHelper @@ -25,9 +24,21 @@ module ActionView # escaping. # # ==== Options - # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and - # <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use - # symbols or strings for the attribute names. + # You can use symbols or strings for the attribute names. + # + # Use +true+ with boolean attributes that can render with no value, like + # +disabled+ and +readonly+. + # + # HTML5 <tt>data-*</tt> attributes can be set with a single +data+ key + # pointing to a hash of sub-attributes. + # + # To play nicely with JavaScript conventions sub-attributes are dasherized. + # For example, a key +user_id+ would render as <tt>data-user-id</tt> and + # thus accessed as <tt>dataset.userId</tt>. + # + # Values are encoded to JSON, with the exception of strings and symbols. + # This may come in handy when using jQuery's HTML5-aware <tt>.data()<tt> + # from 1.4.3. # # ==== Examples # tag("br") @@ -36,14 +47,17 @@ module ActionView # tag("br", nil, true) # # => <br> # - # tag("input", { :type => 'text', :disabled => true }) + # tag("input", :type => 'text', :disabled => true) # # => <input type="text" disabled="disabled" /> # - # tag("img", { :src => "open & shut.png" }) + # tag("img", :src => "open & shut.png") # # => <img src="open & shut.png" /> # - # tag("img", { :src => "open & shut.png" }, false, false) + # tag("img", {:src => "open & shut.png"}, false, false) # # => <img src="open & shut.png" /> + # + # tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)}) + # # => <div data-name="Stephen" data-city-state="["Chicago","IL"]" /> def tag(name, options = nil, open = false, escape = true) "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe end @@ -118,11 +132,19 @@ module ActionView unless options.blank? attrs = [] options.each_pair do |key, value| - if BOOLEAN_ATTRIBUTES.include?(key) + if key.to_s == 'data' && value.is_a?(Hash) + value.each do |k, v| + if !v.is_a?(String) && !v.is_a?(Symbol) + v = v.to_json + end + v = ERB::Util.html_escape(v) if escape + attrs << %(data-#{k.to_s.dasherize}="#{v}") + end + elsif BOOLEAN_ATTRIBUTES.include?(key) attrs << %(#{key}="#{key}") if value elsif !value.nil? final_value = value.is_a?(Array) ? value.join(" ") : value - final_value = html_escape(final_value) if escape + final_value = ERB::Util.html_escape(final_value) if escape attrs << %(#{key}="#{final_value}") end end diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 94348cf9fa..7c877a0f57 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -134,6 +134,8 @@ module ActionView # excerpt('This is an example', 'an', 5) # => ...s is an exam... # excerpt('This is also an example', 'an', 8, '<chop> ') # => <chop> is also an example def excerpt(text, phrase, *args) + return unless text && phrase + options = args.extract_options! unless args.empty? options[:radius] = args[0] || 100 @@ -141,21 +143,16 @@ module ActionView end options.reverse_merge!(:radius => 100, :omission => "...") - if text && phrase - phrase = Regexp.escape(phrase) + phrase = Regexp.escape(phrase) + return unless found_pos = text.mb_chars =~ /(#{phrase})/i - if found_pos = text.mb_chars =~ /(#{phrase})/i - start_pos = [ found_pos - options[:radius], 0 ].max - end_pos = [ [ found_pos + phrase.mb_chars.length + options[:radius] - 1, 0].max, text.mb_chars.length ].min + start_pos = [ found_pos - options[:radius], 0 ].max + end_pos = [ [ found_pos + phrase.mb_chars.length + options[:radius] - 1, 0].max, text.mb_chars.length ].min - prefix = start_pos > 0 ? options[:omission] : "" - postfix = end_pos < text.mb_chars.length - 1 ? options[:omission] : "" + prefix = start_pos > 0 ? options[:omission] : "" + postfix = end_pos < text.mb_chars.length - 1 ? options[:omission] : "" - prefix + text.mb_chars[start_pos..end_pos].strip + postfix - else - nil - end - end + prefix + text.mb_chars[start_pos..end_pos].strip + postfix end # Attempts to pluralize the +singular+ word unless +count+ is 1. If @@ -345,10 +342,10 @@ module ActionView values.unshift(first_value) cycle = get_cycle(name) - if (cycle.nil? || cycle.values != values) + unless cycle && cycle.values == values cycle = set_cycle(name, Cycle.new(*values)) end - return cycle.to_s + cycle.to_s end # Returns the current cycle string after a cycle has been started. Useful @@ -389,7 +386,7 @@ module ActionView # </table> def reset_cycle(name = "default") cycle = get_cycle(name) - cycle.reset unless cycle.nil? + cycle.reset if cycle end class Cycle #:nodoc: diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index da42d94318..c23315b344 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -1,6 +1,7 @@ require 'action_view/helpers/javascript_helper' require 'active_support/core_ext/array/access' require 'active_support/core_ext/hash/keys' +require 'active_support/core_ext/string/output_safety' require 'action_dispatch' module ActionView @@ -240,8 +241,8 @@ module ActionView href = html_options['href'] tag_options = tag_options(html_options) - href_attr = "href=\"#{html_escape(url)}\"" unless href - "<a #{href_attr}#{tag_options}>#{html_escape(name || url)}</a>".html_safe + href_attr = "href=\"#{ERB::Util.html_escape(url)}\"" unless href + "<a #{href_attr}#{tag_options}>#{ERB::Util.html_escape(name || url)}</a>".html_safe end end @@ -326,7 +327,7 @@ module ActionView html_options.merge!("type" => "submit", "value" => name) - ("<form method=\"#{form_method}\" action=\"#{html_escape(url)}\" #{"data-remote=\"true\"" if remote} class=\"button_to\"><div>" + + ("<form method=\"#{form_method}\" action=\"#{ERB::Util.html_escape(url)}\" #{"data-remote=\"true\"" if remote} class=\"button_to\"><div>" + method_tag + tag("input", html_options) + request_token_tag + "</div></form>").html_safe end @@ -472,7 +473,7 @@ module ActionView # :subject => "This is an example email" # # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a> def mail_to(email_address, name = nil, html_options = {}) - email_address = html_escape(email_address) + email_address = ERB::Util.html_escape(email_address) html_options = html_options.stringify_keys encode = html_options.delete("encode").to_s @@ -481,7 +482,7 @@ module ActionView option = html_options.delete(item) || next "#{item}=#{Rack::Utils.escape(option).gsub("+", "%20")}" }.compact - extras = extras.empty? ? '' : '?' + html_escape(extras.join('&')) + extras = extras.empty? ? '' : '?' + ERB::Util.html_escape(extras.join('&')) email_address_obfuscated = email_address.dup email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.key?("replace_at") @@ -587,10 +588,12 @@ 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') - add_confirm_to_attributes!(html_options, confirm) if confirm + html_options["data-disable-with"] = disable_with if disable_with + html_options["data-confirm"] = confirm if confirm add_method_to_attributes!(html_options, method) if method html_options @@ -601,13 +604,9 @@ module ActionView options.is_a?(Hash) && options.key?('remote') && options.delete('remote') end - def add_confirm_to_attributes!(html_options, confirm) - html_options["data-confirm"] = confirm if confirm - end - def add_method_to_attributes!(html_options, method) - html_options["rel"] = "nofollow" if method && method.to_s.downcase != "get" - html_options["data-method"] = method if method + html_options["rel"] = "nofollow" if method.to_s.downcase != "get" + html_options["data-method"] = method end def options_for_javascript(options) diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 80451798b1..27f94a73a6 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -61,7 +61,7 @@ module ActionView def initialize(view_paths, details = {}) @details, @details_key = { :handlers => default_handlers }, nil @frozen_formats, @skip_default_locale = false, false - @cache = details.key?(:cache) ? details.delete(:cache) : true + @cache = true self.view_paths = view_paths self.registered_detail_setters.each do |key, setter| diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/partials.rb index 844c3e9572..844c3e9572 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/partials.rb diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/path_set.rb index dc26d75ff3..dc26d75ff3 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/path_set.rb diff --git a/actionpack/lib/action_view/renderer/abstract_renderer.rb b/actionpack/lib/action_view/renderer/abstract_renderer.rb index 77cfa51dff..4a52b3172e 100644 --- a/actionpack/lib/action_view/renderer/abstract_renderer.rb +++ b/actionpack/lib/action_view/renderer/abstract_renderer.rb @@ -1,9 +1,7 @@ module ActionView class AbstractRenderer #:nodoc: - attr_reader :vew, :lookup_context - delegate :find_template, :template_exists?, :with_fallbacks, :update_details, - :with_layout_format, :formats, :to => :lookup_context + :with_layout_format, :formats, :freeze_formats, :to => :@lookup_context def initialize(view) @view = view @@ -18,19 +16,22 @@ module ActionView # the lookup context to take this new format into account. def wrap_formats(value) return yield unless value.is_a?(String) - @@formats_regexp ||= /\.(#{Mime::SET.symbols.join('|')})$/ - if value.sub!(@@formats_regexp, "") + if value.sub!(formats_regexp, "") update_details(:formats => [$1.to_sym]){ yield } else yield end end + def formats_regexp + @@formats_regexp ||= /\.(#{Mime::SET.symbols.join('|')})$/ + end + protected def instrument(name, options={}) ActiveSupport::Notifications.instrument("render_#{name}.action_view", options){ yield } end end -end
\ No newline at end of file +end diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb index eff425687b..c580397cad 100644 --- a/actionpack/lib/action_view/renderer/partial_renderer.rb +++ b/actionpack/lib/action_view/renderer/partial_renderer.rb @@ -110,7 +110,7 @@ module ActionView end def find_template(path=@path, locals=@locals.keys) - prefix = @view.controller_path unless path.include?(?/) + prefix = @view.controller_prefix unless path.include?(?/) @lookup_context.find_template(path, prefix, true, locals) end @@ -151,7 +151,7 @@ module ActionView object = object.to_model if object.respond_to?(:to_model) object.class.model_name.partial_path.dup.tap do |partial| - path = @view.controller_path + path = @view.controller_prefix partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/) end end diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb index a9076760c5..6912acee31 100644 --- a/actionpack/lib/action_view/renderer/template_renderer.rb +++ b/actionpack/lib/action_view/renderer/template_renderer.rb @@ -21,7 +21,8 @@ module ActionView def render_once(options) paths, locals = options[:once], options[:locals] || {} - layout, keys, prefix = options[:layout], locals.keys, options[:prefix] + layout, keys = options[:layout], locals.keys + prefix = options.fetch(:prefix, @view.controller_prefix) raise "render :once expects a String or an Array to be given" unless paths @@ -45,7 +46,7 @@ module ActionView with_fallbacks { find_template(options[:file], options[:prefix], false, keys) } elsif options.key?(:inline) handler = Template.handler_class_for_extension(options[:type] || "erb") - Template::Inline.new(options[:inline], handler, :locals => keys) + Template.new(options[:inline], "inline template", handler, :locals => keys) elsif options.key?(:template) options[:template].respond_to?(:render) ? options[:template] : find_template(options[:template], options[:prefix], false, keys) @@ -55,7 +56,7 @@ module ActionView # Renders the given template. An string representing the layout can be # supplied as well. def render_template(template, layout_name = nil, locals = {}) #:nodoc: - lookup_context.freeze_formats(template.formats, true) + freeze_formats(template.formats, true) view, locals = @view, locals || {} render_with_layout(layout_name, locals) do |layout| @@ -94,4 +95,4 @@ module ActionView end end end -end
\ No newline at end of file +end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/rendering.rb index baa5d2c3fd..baa5d2c3fd 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/rendering.rb diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 3ba18cbfae..dbb1532cd4 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -93,7 +93,6 @@ module ActionView autoload :Error autoload :Handler autoload :Handlers - autoload :Inline autoload :Text end @@ -164,7 +163,7 @@ module ActionView name = pieces.pop partial = !!name.sub!(/^_/, "") lookup.disable_cache do - lookup.find_template(name, pieces.join, partial, @locals) + lookup.find_template(name, pieces.join('/'), partial, @locals) end end @@ -185,14 +184,6 @@ module ActionView end end - def hash - identifier.hash - end - - def eql?(other) - other.is_a?(Template) && other.identifier == identifier - end - def inspect @inspect ||= if defined?(Rails.root) diff --git a/actionpack/lib/action_view/template/handler.rb b/actionpack/lib/action_view/template/handler.rb index 0a9d299807..636f3ebbad 100644 --- a/actionpack/lib/action_view/template/handler.rb +++ b/actionpack/lib/action_view/template/handler.rb @@ -8,7 +8,7 @@ module ActionView module Compilable def self.included(base) ActiveSupport::Deprecation.warn "Including Compilable in your template handler is deprecated. " << - "All the API your template handler needs to implement is to respond to #call." + "Since Rails 3, all the API your template handler needs to implement is to respond to #call." base.extend(ClassMethods) end @@ -30,7 +30,7 @@ module ActionView def self.inherited(base) ActiveSupport::Deprecation.warn "Inheriting from ActionView::Template::Handler is deprecated. " << - "All the API your template handler needs to implement is to respond to #call." + "Since Rails 3, all the API your template handler needs to implement is to respond to #call." super end diff --git a/actionpack/lib/action_view/template/inline.rb b/actionpack/lib/action_view/template/inline.rb deleted file mode 100644 index be08065b6b..0000000000 --- a/actionpack/lib/action_view/template/inline.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'digest/md5' - -module ActionView - class Template - class Inline < ::ActionView::Template - def initialize(source, handler, options={}) - super(source, "inline template", handler, options) - end - - def md5_source - @md5_source ||= Digest::MD5.hexdigest(source) - end - - def eql?(other) - other.is_a?(Inline) && other.md5_source == md5_source - end - end - end -end -
\ No newline at end of file diff --git a/actionpack/test/activerecord/controller_runtime_test.rb b/actionpack/test/activerecord/controller_runtime_test.rb index 16fc901760..7931da3741 100644 --- a/actionpack/test/activerecord/controller_runtime_test.rb +++ b/actionpack/test/activerecord/controller_runtime_test.rb @@ -37,6 +37,6 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase wait assert_equal 2, @logger.logged(:info).size - assert_match(/\(Views: [\d\.]+ms | ActiveRecord: [\d\.]+ms\)/, @logger.logged(:info)[1]) + assert_match(/\(Views: [\d.]+ms | ActiveRecord: [\d.]+ms\)/, @logger.logged(:info)[1]) end end diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 5a8b763717..5a210aa9ec 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -465,6 +465,14 @@ class AssertTemplateTest < ActionController::TestCase assert_template :hello_planet end end + + def test_assert_template_reset_between_requests + get :hello_world + assert_template 'test/hello_world' + + get :nothing + assert_template nil + end end class ActionPackHeaderTest < ActionController::TestCase diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index 90c944d890..e6fe0b1f04 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -93,7 +93,7 @@ class ACLogSubscriberTest < ActionController::TestCase def test_process_action_with_view_runtime get :show wait - assert_match(/\(Views: [\d\.]+ms\)/, logs[1]) + assert_match(/\(Views: [\d.]+ms\)/, logs[1]) end def test_process_action_with_filter_parameters diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index adccfa028f..a898ef76e5 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -709,6 +709,15 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal " ", @response.body end + def test_using_resource_for_put_with_json_yields_ok_on_success + Customer.any_instance.stubs(:to_json).returns('{"name": "David"}') + @request.accept = "application/json" + put :using_resource + assert_equal "application/json", @response.content_type + assert_equal 200, @response.status + assert_equal "{}", @response.body + end + def test_using_resource_for_put_with_xml_yields_unprocessable_entity_on_failure @request.accept = "application/xml" errors = { :name => :invalid } @@ -739,6 +748,16 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal " ", @response.body end + def test_using_resource_for_delete_with_json_yields_ok_on_success + Customer.any_instance.stubs(:to_json).returns('{"name": "David"}') + Customer.any_instance.stubs(:destroyed?).returns(true) + @request.accept = "application/json" + delete :using_resource + assert_equal "application/json", @response.content_type + assert_equal 200, @response.status + assert_equal "{}", @response.body + end + def test_using_resource_for_delete_with_html_redirects_on_failure with_test_route_set do errors = { :name => :invalid } diff --git a/actionpack/test/controller/new_base/render_once_test.rb b/actionpack/test/controller/new_base/render_once_test.rb index 63de25be52..3035ed4ff2 100644 --- a/actionpack/test/controller/new_base/render_once_test.rb +++ b/actionpack/test/controller/new_base/render_once_test.rb @@ -8,29 +8,42 @@ module RenderTemplate "test/a.html.erb" => "a", "test/b.html.erb" => "<>", "test/c.html.erb" => "c", - "test/one.html.erb" => "<%= render :once => 'test/result' %>", - "test/two.html.erb" => "<%= render :once => 'test/result' %>", - "test/three.html.erb" => "<%= render :once => 'test/result' %>", + "test/one.html.erb" => "<%= render :once => 'result' %>", + "test/two.html.erb" => "<%= render :once => 'result' %>", + "test/three.html.erb" => "<%= render :once => 'result' %>", "test/result.html.erb" => "YES!", + "other/result.html.erb" => "NO!", "layouts/test.html.erb" => "l<%= yield %>l" ) self.view_paths = [RESOLVER] + def _prefix + "test" + end + def multiple - render :once => %w(test/a test/b test/c) + render :once => %w(a b c) end def once - render :once => %w(test/one test/two test/three) + render :once => %w(one two three) end def duplicate - render :once => %w(test/a test/a test/a) + render :once => %w(a a a) end def with_layout - render :once => %w(test/a test/b test/c), :layout => "test" + render :once => %w(a b c), :layout => "test" + end + + def with_prefix + render :once => "result", :prefix => "other" + end + + def with_nil_prefix + render :once => "test/result", :prefix => nil end end @@ -54,19 +67,20 @@ module RenderTemplate get :with_layout assert_response "la\n<>\ncl" end - end - class TestWithResolverCache < Rack::TestCase - testing RenderTemplate::RenderOnceController - include Tests + def test_with_prefix_option + get :with_prefix + assert_response "NO!" + end + + def test_with_nil_prefix_option + get :with_nil_prefix + assert_response "YES!" + end end - class TestWithoutResolverCache < Rack::TestCase + class TestRenderOnce < Rack::TestCase testing RenderTemplate::RenderOnceController include Tests - - def setup - RenderTemplate::RenderOnceController::RESOLVER.stubs(:caching?).returns(false) - end end end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 3efed8bef6..04709e5346 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -385,6 +385,18 @@ class RequestTest < ActiveSupport::TestCase assert_equal({"bar" => 2}, request.query_parameters) end + test "parameters still accessible after rack parse error" do + mock_rack_env = { "QUERY_STRING" => "x[y]=1&x[y][][w]=2", "rack.input" => "foo" } + request = nil + begin + request = stub_request(mock_rack_env) + request.parameters + rescue TypeError => e + # rack will raise a TypeError when parsing this query string + end + assert_equal({}, request.parameters) + end + test "formats with accept header" do request = stub_request 'HTTP_ACCEPT' => 'text/html' request.expects(:parameters).at_least_once.returns({}) diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index be6398fead..ab26d1a645 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -18,6 +18,10 @@ class ResponseTest < ActiveSupport::TestCase body.each { |part| parts << part } assert_equal ["Hello, World!"], parts end + + test "status handled properly in initialize" do + assert_equal 200, ActionDispatch::Response.new('200 OK').status + end test "utf8 output" do @response.body = [1090, 1077, 1089, 1090].pack("U*") diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb index ce6c397e32..2a478c214f 100644 --- a/actionpack/test/dispatch/show_exceptions_test.rb +++ b/actionpack/test/dispatch/show_exceptions_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' class ShowExceptionsTest < ActionDispatch::IntegrationTest + Boomer = lambda do |env| req = ActionDispatch::Request.new(env) case req.path @@ -12,6 +13,8 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest raise ActionController::NotImplemented when "/unprocessable_entity" raise ActionController::InvalidAuthenticityToken + when "/not_found_original_exception" + raise ActionView::Template::Error.new('template', {}, AbstractController::ActionNotFound.new) else raise "puke!" end @@ -101,4 +104,21 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest assert_response 500 assert_match(""foo"=>"[FILTERED]"", body) end + + test "show registered original exception for wrapped exceptions when consider_all_requests_local is false" do + @app = ProductionApp + self.remote_addr = '208.77.188.166' + + get "/not_found_original_exception", {}, {'action_dispatch.show_exceptions' => true} + assert_response 404 + assert_match(/404 error/, body) + end + + test "show registered original exception for wrapped exceptions when consider_all_requests_local is true" do + @app = DevelopmentApp + + get "/not_found_original_exception", {}, {'action_dispatch.show_exceptions' => true} + assert_response 404 + assert_match(/AbstractController::ActionNotFound/, body) + end end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 0bfdbeebd1..acb6e7aa64 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -735,11 +735,11 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_search_field # Test case for bug which would emit an "object" attribute # when used with form_for using a search_field form helper - form_for(Post.new, :url => "/search", :html => { :id => 'search-post' }) do |f| + form_for(Post.new, :url => "/search", :html => { :id => 'search-post', :method => :get}) do |f| concat f.search_field(:title) end - expected = whole_form("/search", "search-post", "new_post") do + expected = whole_form("/search", "search-post", "new_post", "get") do "<input name='post[title]' size='30' type='search' id='post_title' />" end @@ -1528,17 +1528,20 @@ class FormHelperTest < ActionView::TestCase def snowman(method = nil) txt = %{<div style="margin:0;padding:0;display:inline">} txt << %{<input name="utf8" type="hidden" value="✓" />} - txt << %{<input name="_method" type="hidden" value="#{method}" />} if method + if (method && !['get','post'].include?(method.to_s)) + txt << %{<input name="_method" type="hidden" value="#{method}" />} + end txt << %{</div>} end - def form_text(action = "/", id = nil, html_class = nil, remote = nil, multipart = nil) + def form_text(action = "/", id = nil, html_class = nil, remote = nil, multipart = nil, method = nil) txt = %{<form accept-charset="UTF-8" action="#{action}"} txt << %{ enctype="multipart/form-data"} if multipart txt << %{ data-remote="true"} if remote txt << %{ class="#{html_class}"} if html_class txt << %{ id="#{id}"} if id - txt << %{ method="post">} + method = method.to_s == "get" ? "get" : "post" + txt << %{ method="#{method}">} end def whole_form(action = "/", id = nil, html_class = nil, options = nil) @@ -1550,7 +1553,7 @@ class FormHelperTest < ActionView::TestCase method = options end - form_text(action, id, html_class, remote, multipart) + snowman(method) + contents + "</form>" + form_text(action, id, html_class, remote, multipart, method) + snowman(method) + contents + "</form>" end def test_default_form_builder diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 8c8e87ae9f..f3933a25b9 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -13,19 +13,23 @@ class FormTagHelperTest < ActionView::TestCase txt = %{<div style="margin:0;padding:0;display:inline">} txt << %{<input name="utf8" type="hidden" value="✓" />} - txt << %{<input name="_method" type="hidden" value="#{method}" />} if method + if (method && !['get','post'].include?(method.to_s)) + txt << %{<input name="_method" type="hidden" value="#{method}" />} + end txt << %{</div>} end def form_text(action = "http://www.example.com", options = {}) - remote, enctype, html_class, id = options.values_at(:remote, :enctype, :html_class, :id) + remote, enctype, html_class, id, method = options.values_at(:remote, :enctype, :html_class, :id, :method) + + method = method.to_s == "get" ? "get" : "post" txt = %{<form accept-charset="UTF-8" action="#{action}"} txt << %{ enctype="multipart/form-data"} if enctype txt << %{ data-remote="true"} if remote txt << %{ class="#{html_class}"} if html_class txt << %{ id="#{id}"} if id - txt << %{ method="post">} + txt << %{ method="#{method}">} end def whole_form(action = "http://www.example.com", options = {}) diff --git a/actionpack/test/template/log_subscriber_test.rb b/actionpack/test/template/log_subscriber_test.rb index 6fb8d39818..435936b19f 100644 --- a/actionpack/test/template/log_subscriber_test.rb +++ b/actionpack/test/template/log_subscriber_test.rb @@ -57,7 +57,7 @@ class AVLogSubscriberTest < ActiveSupport::TestCase end def test_render_partial_with_implicit_path - @view.stubs(:controller_path).returns("test") + @view.stubs(:controller_prefix).returns("test") @view.render(Customer.new("david"), :greeting => "hi") wait @@ -74,7 +74,7 @@ class AVLogSubscriberTest < ActiveSupport::TestCase end def test_render_collection_with_implicit_path - @view.stubs(:controller_path).returns("test") + @view.stubs(:controller_prefix).returns("test") @view.render([ Customer.new("david"), Customer.new("mary") ], :greeting => "hi") wait @@ -83,7 +83,7 @@ class AVLogSubscriberTest < ActiveSupport::TestCase end def test_render_collection_template_without_path - @view.stubs(:controller_path).returns("test") + @view.stubs(:controller_prefix).returns("test") @view.render([ GoodCustomer.new("david"), Customer.new("mary") ], :greeting => "hi") wait diff --git a/actionpack/test/template/lookup_context_test.rb b/actionpack/test/template/lookup_context_test.rb index 850589b13b..6d3b26e131 100644 --- a/actionpack/test/template/lookup_context_test.rb +++ b/actionpack/test/template/lookup_context_test.rb @@ -180,10 +180,6 @@ class LookupContextTest < ActiveSupport::TestCase assert_not_equal template, old_template end - - test "can have cache disabled on initialization" do - assert !ActionView::LookupContext.new(FIXTURE_LOAD_PATH, :cache => false).cache - end end class LookupContextWithFalseCaching < ActiveSupport::TestCase diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index c14dfb250f..dcdf28ddd5 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -289,7 +289,8 @@ class NumberHelperTest < ActionView::TestCase assert number_to_percentage("asdf".html_safe).html_safe? assert number_to_phone(1).html_safe? - assert !number_to_phone("<script></script>").html_safe? + assert_equal "<script></script>", number_to_phone("<script></script>") + assert number_to_phone("<script></script>").html_safe? assert number_to_phone("asdf".html_safe).html_safe? assert number_with_delimiter(1).html_safe? diff --git a/actionpack/test/template/tag_helper_test.rb b/actionpack/test/template/tag_helper_test.rb index c742683821..60b466a9ff 100644 --- a/actionpack/test/template/tag_helper_test.rb +++ b/actionpack/test/template/tag_helper_test.rb @@ -110,4 +110,11 @@ class TagHelperTest < ActionView::TestCase def test_disable_escaping assert_equal '<a href="&" />', tag('a', { :href => '&' }, false, false) end + + def test_data_attributes + ['data', :data].each { |data| + assert_dom_equal '<a data-a-number="1" data-array="[1,2,3]" data-hash="{"key":"value"}" data-string="hello" data-symbol="foo" />', + tag('a', { data => { :a_number => 1, :string => 'hello', :symbol => :foo, :array => [1, 2, 3], :hash => { :key => 'value'} } }) + } + end end diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index f2156c31de..2ec640c84c 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -93,9 +93,9 @@ class TestERBTemplate < ActiveSupport::TestCase end def test_refresh_with_templates - @template = new_template("Hello", :virtual_path => "test/foo") + @template = new_template("Hello", :virtual_path => "test/foo/bar") @template.locals = [:key] - @context.lookup_context.expects(:find_template).with("foo", "test", false, [:key]).returns("template") + @context.lookup_context.expects(:find_template).with("bar", "test/foo", false, [:key]).returns("template") assert_equal "template", @template.refresh(@context) end @@ -151,14 +151,6 @@ class TestERBTemplate < ActiveSupport::TestCase end end - def test_inline_template_is_only_equal_if_source_match - inline1 = ActionView::Template::Inline.new("sample", ERBHandler) - inline2 = ActionView::Template::Inline.new("sample", ERBHandler) - inline3 = ActionView::Template::Inline.new("other", ERBHandler) - assert inline1.eql?(inline2) - assert !inline1.eql?(inline3) - end - if "ruby".encoding_aware? def test_resulting_string_is_utf8 @template = new_template diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index b8a7d4259d..a6fdf806a4 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -69,6 +69,13 @@ class UrlHelperTest < ActiveSupport::TestCase ) end + def test_button_to_with_javascript_disable_with + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input data-disable-with=\"Greeting...\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :disable_with => "Greeting...") + ) + end + def test_button_to_with_remote_and_javascript_confirm assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", @@ -76,6 +83,20 @@ class UrlHelperTest < ActiveSupport::TestCase ) end + def test_button_to_with_remote_and_javascript_disable_with + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-disable-with=\"Greeting...\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :remote => true, :disable_with => "Greeting...") + ) + end + + def test_button_to_with_remote_and_javascript_confirm_and_javascript_disable_with + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-disable-with=\"Greeting...\" data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :remote => true, :confirm => "Are you sure?", :disable_with => "Greeting...") + ) + end + def test_button_to_with_remote_false assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", |