diff options
Diffstat (limited to 'actionpack')
29 files changed, 626 insertions, 181 deletions
diff --git a/actionpack/lib/action_controller/base/http_authentication.rb b/actionpack/lib/action_controller/base/http_authentication.rb index 2519f55269..525787bf92 100644 --- a/actionpack/lib/action_controller/base/http_authentication.rb +++ b/actionpack/lib/action_controller/base/http_authentication.rb @@ -276,7 +276,7 @@ module ActionController # # The nonce is opaque to the client. Composed of Time, and hash of Time with secret # key from the Rails session secret generated upon creation of project. Ensures - # the time cannot be modifed by client. + # the time cannot be modified by client. def nonce(time = Time.now) t = time.to_i hashed = [t, secret_key] diff --git a/actionpack/lib/action_controller/base/mime_responds.rb b/actionpack/lib/action_controller/base/mime_responds.rb index ed0d58dba1..f4a4007a43 100644 --- a/actionpack/lib/action_controller/base/mime_responds.rb +++ b/actionpack/lib/action_controller/base/mime_responds.rb @@ -1,5 +1,55 @@ module ActionController #:nodoc: module MimeResponds #:nodoc: + extend ActiveSupport::Concern + + included do + class_inheritable_reader :mimes_for_respond_to + clear_respond_to + end + + module ClassMethods + # Defines mimes that are rendered by default when invoking respond_with. + # + # Examples: + # + # respond_to :html, :xml, :json + # + # All actions on your controller will respond to :html, :xml and :json. + # + # But if you want to specify it based on your actions, you can use only and + # except: + # + # respond_to :html + # respond_to :xml, :json, :except => [ :edit ] + # + # The definition above explicits that all actions respond to :html. And all + # actions except :edit respond to :xml and :json. + # + # You can specify also only parameters: + # + # respond_to :rjs, :only => :create + # + def respond_to(*mimes) + options = mimes.extract_options! + + only_actions = Array(options.delete(:only)) + except_actions = Array(options.delete(:except)) + + mimes.each do |mime| + mime = mime.to_sym + mimes_for_respond_to[mime] = {} + mimes_for_respond_to[mime][:only] = only_actions unless only_actions.empty? + mimes_for_respond_to[mime][:except] = except_actions unless except_actions.empty? + end + end + + # Clear all mimes in respond_to. + # + def clear_respond_to + write_inheritable_attribute(:mimes_for_respond_to, ActiveSupport::OrderedHash.new) + end + end + # Without web-service support, an action which collects the data for displaying a list of people # might look something like this: # @@ -92,50 +142,187 @@ module ActionController #:nodoc: # environment.rb as follows. # # Mime::Type.register "image/jpg", :jpg - def respond_to(*types, &block) - raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block - block ||= lambda { |responder| types.each { |type| responder.send(type) } } - responder = Responder.new(self) - block.call(responder) - responder.respond - end + # + # Respond to also allows you to specify a common block for different formats by using any: + # + # def index + # @people = Person.find(:all) + # + # respond_to do |format| + # format.html + # format.any(:xml, :json) { render request.format.to_sym => @people } + # end + # end + # + # In the example above, if the format is xml, it will render: + # + # render :xml => @people + # + # Or if the format is json: + # + # render :json => @people + # + # Since this is a common pattern, you can use the class method respond_to + # with the respond_with method to have the same results: + # + # class PeopleController < ApplicationController + # respond_to :html, :xml, :json + # + # def index + # @people = Person.find(:all) + # respond_with(@person) + # end + # end + # + # Be sure to check respond_with and respond_to documentation for more examples. + # + def respond_to(*mimes, &block) + options = mimes.extract_options! + raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given? - class Responder #:nodoc: - - def initialize(controller) - @controller = controller - @request = controller.request - @response = controller.response + resource = options.delete(:with) + responder = Responder.new - @mime_type_priority = @request.formats + mimes = collect_mimes_from_class_level if mimes.empty? + mimes.each { |mime| responder.send(mime) } + block.call(responder) if block_given? - @order = [] - @responses = {} + if format = request.negotiate_mime(responder.order) + respond_to_block_or_template_or_resource(format, resource, + options, &responder.response_for(format)) + else + head :not_acceptable end + end - def custom(mime_type, &block) - mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s) + # respond_with allows you to respond an action with a given resource. It + # requires that you set your class with a :respond_to method with the + # formats allowed: + # + # class PeopleController < ApplicationController + # respond_to :html, :xml, :json + # + # def index + # @people = Person.find(:all) + # respond_with(@person) + # end + # end + # + # When a request comes with format :xml, the respond_with will first search + # for a template as person/index.xml, if the template is not available, it + # will see if the given resource responds to :to_xml. + # + # If neither are available, it will raise an error. + # + # Extra parameters given to respond_with are used when :to_format is invoked. + # This allows you to set status and location for several formats at the same + # time. Consider this restful controller response on create for both xml + # and json formats: + # + # class PeopleController < ApplicationController + # respond_to :xml, :json + # + # def create + # @person = Person.new(params[:person]) + # + # if @person.save + # respond_with(@person, :status => :ok, :location => person_url(@person)) + # else + # respond_with(@person.errors, :status => :unprocessable_entity) + # end + # end + # end + # + # Finally, respond_with also accepts blocks, as in respond_to. Let's take + # the same controller and create action above and add common html behavior: + # + # class PeopleController < ApplicationController + # respond_to :html, :xml, :json + # + # def create + # @person = Person.new(params[:person]) + # + # if @person.save + # options = { :status => :ok, :location => person_url(@person) } + # + # respond_with(@person, options) do |format| + # format.html { redirect_to options[:location] } + # end + # else + # respond_with(@person.errors, :status => :unprocessable_entity) do + # format.html { render :action => :new } + # end + # end + # end + # end + # + def respond_with(resource, options={}, &block) + respond_to(options.merge!(:with => resource), &block) + end - @order << mime_type + protected - @responses[mime_type] ||= Proc.new do - # TODO: Remove this when new base is merged in - @controller.formats = [mime_type.to_sym] - @controller.content_type = mime_type - @controller.template.formats = [mime_type.to_sym] + def respond_to_block_or_template_or_resource(format, resource, options) + self.formats = [format.to_sym] + return yield if block_given? - block_given? ? block.call : @controller.send(:render, :action => @controller.action_name) + begin + default_render + rescue ActionView::MissingTemplate => e + if resource && resource.respond_to?(:"to_#{format.to_sym}") + render options.merge(format.to_sym => resource) + else + raise e end end + end + + # Collect mimes declared in the class method respond_to valid for the + # current action. + # + def collect_mimes_from_class_level #:nodoc: + action = action_name.to_sym + + mimes_for_respond_to.keys.select do |mime| + config = mimes_for_respond_to[mime] + + if config[:except] + !config[:except].include?(action) + elsif config[:only] + config[:only].include?(action) + else + true + end + end + end + + class Responder #:nodoc: + attr_accessor :order + + def initialize + @order, @responses = [], {} + end def any(*args, &block) if args.any? args.each { |type| send(type, &block) } else - custom(@mime_type_priority.first, &block) + custom(Mime::ALL, &block) end end - + alias :all :any + + def custom(mime_type, &block) + mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s) + + @order << mime_type + @responses[mime_type] ||= block + end + + def response_for(mime) + @responses[mime] || @responses[Mime::ALL] + end + def self.generate_method_for_mime(mime) sym = mime.is_a?(Symbol) ? mime : mime.to_sym const = sym.to_s.upcase @@ -152,7 +339,7 @@ module ActionController #:nodoc: def method_missing(symbol, &block) mime_constant = Mime.const_get(symbol.to_s.upcase) - + if Mime::SET.include?(mime_constant) self.class.generate_method_for_mime(mime_constant) send(symbol, &block) @@ -161,25 +348,6 @@ module ActionController #:nodoc: end end - def respond - for priority in @mime_type_priority - if priority == Mime::ALL - @responses[@order.first].call - return - else - if @responses[priority] - @responses[priority].call - return # mime type match found, be happy and return - end - end - end - - if @order.include?(Mime::ALL) - @responses[Mime::ALL].call - else - @controller.send :head, :not_acceptable - end - end end end end diff --git a/actionpack/lib/action_controller/base/renderer.rb b/actionpack/lib/action_controller/base/renderer.rb index 2fab501302..572da451ff 100644 --- a/actionpack/lib/action_controller/base/renderer.rb +++ b/actionpack/lib/action_controller/base/renderer.rb @@ -11,11 +11,10 @@ module ActionController def render(options) super - options[:_template] ||= _action_view._partial self.content_type ||= begin mime = options[:_template].mime_type formats.include?(mime && mime.to_sym) || formats.include?(:all) ? mime : Mime::Type.lookup_by_extension(formats.first) - end + end.to_s response_body end diff --git a/actionpack/lib/action_controller/base/request_forgery_protection.rb b/actionpack/lib/action_controller/base/request_forgery_protection.rb index 6ba86cd0be..ad06657f86 100644 --- a/actionpack/lib/action_controller/base/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/base/request_forgery_protection.rb @@ -106,8 +106,7 @@ module ActionController #:nodoc: !request.content_type.nil? && request.content_type.verify_request? end - # Sets the token value for the current session. Pass a <tt>:secret</tt> option - # in +protect_from_forgery+ to add a custom salt to the hash. + # Sets the token value for the current session. def form_authenticity_token session[:_csrf_token] ||= ActiveSupport::SecureRandom.base64(32) end diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb index ce59866531..5b9ded83dd 100644 --- a/actionpack/lib/action_controller/routing.rb +++ b/actionpack/lib/action_controller/routing.rb @@ -139,7 +139,7 @@ module ActionController # # In routes.rb # map.with_options :controller => 'blog' do |blog| # blog.show '', :action => 'list' - # blog.delete 'delete/:id', :action => 'delete', + # blog.delete 'delete/:id', :action => 'delete' # blog.edit 'edit/:id', :action => 'edit' # end # diff --git a/actionpack/lib/action_controller/routing/generation/url_rewriter.rb b/actionpack/lib/action_controller/routing/generation/url_rewriter.rb index 16720b915b..9717582b5e 100644 --- a/actionpack/lib/action_controller/routing/generation/url_rewriter.rb +++ b/actionpack/lib/action_controller/routing/generation/url_rewriter.rb @@ -93,7 +93,7 @@ module ActionController # # * <tt>:only_path</tt> - If true, the relative url is returned. Defaults to +false+. # * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'. - # * <tt>:host</tt> - Specifies the host the link should be targetted at. + # * <tt>:host</tt> - Specifies the host the link should be targeted at. # If <tt>:only_path</tt> is false, this option must be # provided either explicitly, or via +default_url_options+. # * <tt>:port</tt> - Optionally specify the port to connect to. diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb index f5a4b1e1db..040a7e2cb6 100644 --- a/actionpack/lib/action_controller/routing/route_set.rb +++ b/actionpack/lib/action_controller/routing/route_set.rb @@ -155,7 +155,7 @@ module ActionController def define_url_helper(route, name, kind, options) selector = url_helper_name(name, kind) - # The segment keys used for positional paramters + # The segment keys used for positional parameters hash_access_method = hash_access_name(name, kind) diff --git a/actionpack/lib/action_controller/testing/test_case.rb b/actionpack/lib/action_controller/testing/test_case.rb index 7b4eda58e5..a11755b517 100644 --- a/actionpack/lib/action_controller/testing/test_case.rb +++ b/actionpack/lib/action_controller/testing/test_case.rb @@ -56,7 +56,7 @@ module ActionController # # ActionController::TestCase will automatically infer the controller under test # from the test class name. If the controller cannot be inferred from the test - # class name, you can explicity set it with +tests+. + # class name, you can explicitly set it with +tests+. # # class SpecialEdgeCaseWidgetsControllerTest < ActionController::TestCase # tests WidgetController @@ -182,7 +182,7 @@ module ActionController @controller.send(:initialize_current_url) end end - + # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local def rescue_action_in_public! @request.remote_addr = '208.77.188.166' # example.com diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 27f27e27fe..cc989d6625 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -84,7 +84,7 @@ module Mime end def lookup_by_extension(extension) - EXTENSION_LOOKUP[extension] + EXTENSION_LOOKUP[extension.to_s] end # Registers an alias that's not used on mime type lookup, but can be referenced directly. Especially useful for diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb index 7c28cac419..68f37d2f65 100644 --- a/actionpack/lib/action_dispatch/http/mime_types.rb +++ b/actionpack/lib/action_dispatch/http/mime_types.rb @@ -2,7 +2,6 @@ # http://www.iana.org/assignments/media-types/ Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml ) -Mime::Type.register "*/*", :all Mime::Type.register "text/plain", :text, [], %w(txt) Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript ) Mime::Type.register "text/css", :css @@ -18,4 +17,7 @@ Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form # http://www.ietf.org/rfc/rfc4627.txt # http://www.json.org/JSONRequest.html -Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
\ No newline at end of file +Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest ) + +# Create Mime::ALL but do not add it to the SET. +Mime::ALL = Mime::Type.new("*/*", :all, []) diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 3f23a5af7a..5f9463eb91 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -161,7 +161,7 @@ module ActionDispatch # GET /posts/5.xml | request.format => Mime::XML # GET /posts/5.xhtml | request.format => Mime::HTML # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt> - + # def format(view_path = []) @env["action_dispatch.request.format"] ||= if parameters[:format] @@ -173,13 +173,11 @@ module ActionDispatch end end + # Expand raw_formats by converting Mime::ALL to the Mime::SET. + # def formats if ActionController::Base.use_accept_header - if param = parameters[:format] - Array.wrap(Mime[param]) - else - accepts.dup - end.tap do |ret| + raw_formats.tap do |ret| if ret == ONLY_ALL ret.replace Mime::SET elsif all = ret.index(Mime::ALL) @@ -187,7 +185,7 @@ module ActionDispatch end end else - [format] + Mime::SET + raw_formats + Mime::SET end end @@ -232,7 +230,7 @@ module ActionDispatch def xml_http_request? !(@env['HTTP_X_REQUESTED_WITH'] !~ /XMLHttpRequest/i) end - alias xhr? :xml_http_request? + alias :xhr? :xml_http_request? # Which IP addresses are "trusted proxies" that can be stripped from # the right-hand-side of X-Forwarded-For @@ -485,7 +483,35 @@ EOM session['flash'] || {} end + # Receives an array of mimes and return the first user sent mime that + # matches the order array. + # + def negotiate_mime(order) + raw_formats.each do |priority| + if priority == Mime::ALL + return order.first + elsif order.include?(priority) + return priority + end + end + + order.include?(Mime::ALL) ? formats.first : nil + end + private + + def raw_formats + if ActionController::Base.use_accept_header + if param = parameters[:format] + Array.wrap(Mime[param]) + else + accepts.dup + end + else + [format] + end + end + def named_host?(host) !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)) end diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index 0f122d9232..4fd7f7d83c 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -160,11 +160,24 @@ module ActionView # # error_messages_for 'user' # + # You can also supply an object: + # + # error_messages_for @user + # + # This will use the last part of the model name in the presentation. For instance, if + # this is a MyKlass::User object, this will use "user" as the name in the String. This + # is taken from MyKlass::User.model_name.human, which can be overridden. + # # To specify more than one object, you simply list them; optionally, you can add an extra <tt>:object_name</tt> parameter, which # will be the name used in the header message: # # error_messages_for 'user_common', 'user', :object_name => 'user' # + # You can also use a number of objects, which will have the same naming semantics + # as a single object. + # + # error_messages_for @user, @post + # # If the objects cannot be located as instance variables, you can add an extra <tt>:object</tt> parameter which gives the actual # object (or array of objects to use): # @@ -176,15 +189,20 @@ module ActionView def error_messages_for(*params) options = params.extract_options!.symbolize_keys - if object = options.delete(:object) - objects = [object].flatten - else - objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact + objects = Array.wrap(options.delete(:object) || params).map do |object| + unless object.respond_to?(:to_model) + object = instance_variable_get("@#{object}") + object = convert_to_model(object) + else + object = object.to_model + options[:object_name] ||= object.class.model_name.human + end + object end - objects.map! {|o| convert_to_model(o) } + objects.compact! - count = objects.inject(0) {|sum, object| sum + object.errors.count } + count = objects.inject(0) {|sum, object| sum + object.errors.count } unless count.zero? html = {} [:id, :class].each do |key| diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 3fde79dfa4..081003bcf3 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -557,7 +557,7 @@ module ActionView # video_tag("trailer.ogg") # => # <video src="/videos/trailer.ogg" /> # video_tag("trailer.ogg", :controls => true, :autobuffer => true) # => - # <video autobuffer="true" controls="true" src="/videos/trailer.ogg" /> + # <video autobuffer="autobuffer" controls="controls" src="/videos/trailer.ogg" /> # video_tag("trailer.m4v", :size => "16x10", :poster => "screenshot.png") # => # <video src="/videos/trailer.m4v" width="16" height="10" poster="/images/screenshot.png" /> # video_tag("/trailers/hd.avi", :size => "16x16") # => diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 72fe9a3232..332743d55b 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -112,12 +112,12 @@ module ActionView # ==== Options # * <tt>:use_month_numbers</tt> - Set to true if you want to use month numbers rather than month names (e.g. # "2" instead of "February"). - # * <tt>:use_short_month</tt> - Set to true if you want to use the abbreviated month name instead of the full - # name (e.g. "Feb" instead of "February"). - # * <tt>:add_month_number</tt> - Set to true if you want to show both, the month's number and name (e.g. + # * <tt>:use_short_month</tt> - Set to true if you want to use abbreviated month names instead of full + # month names (e.g. "Feb" instead of "February"). + # * <tt>:add_month_numbers</tt> - Set to true if you want to use both month numbers and month names (e.g. # "2 - February" instead of "February"). # * <tt>:use_month_names</tt> - Set to an array with 12 month names if you want to customize month names. - # Note: You can also use Rails' new i18n functionality for this. + # Note: You can also use Rails' i18n functionality for this. # * <tt>:date_separator</tt> - Specifies a string to separate the date fields. Default is "" (i.e. nothing). # * <tt>:start_year</tt> - Set the start year for the year select. Default is <tt>Time.now.year - 5</tt>. # * <tt>:end_year</tt> - Set the end year for the year select. Default is <tt>Time.now.year + 5</tt>. @@ -128,7 +128,7 @@ module ActionView # as a hidden field instead of showing a select field. Also note that this implicitly sets :discard_day to true. # * <tt>:discard_year</tt> - Set to true if you don't want to show a year select. This includes the year # as a hidden field instead of showing a select field. - # * <tt>:order</tt> - Set to an array containing <tt>:day</tt>, <tt>:month</tt> and <tt>:year</tt> do + # * <tt>:order</tt> - Set to an array containing <tt>:day</tt>, <tt>:month</tt> and <tt>:year</tt> to # customize the order in which the select fields are shown. If you leave out any of the symbols, the respective # select will not be shown (like when you set <tt>:discard_xxx => true</tt>. Defaults to the order defined in # the respective locale (e.g. [:year, :month, :day] in the en locale that ships with Rails). diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 6adbab175f..8cb5882aab 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -167,31 +167,31 @@ module ActionView # # In addition to the <tt>:include_blank</tt> option documented above, # this method also supports a <tt>:model</tt> option, which defaults - # to TimeZone. This may be used by users to specify a different time - # zone model object. (See +time_zone_options_for_select+ for more - # information.) + # to ActiveSupport::TimeZone. This may be used by users to specify a + # different time zone model object. (See +time_zone_options_for_select+ + # for more information.) # - # You can also supply an array of TimeZone objects + # You can also supply an array of ActiveSupport::TimeZone objects # as +priority_zones+, so that they will be listed above the rest of the - # (long) list. (You can use TimeZone.us_zones as a convenience for - # obtaining a list of the US time zones, or a Regexp to select the zones + # (long) list. (You can use ActiveSupport::TimeZone.us_zones as a convenience + # for obtaining a list of the US time zones, or a Regexp to select the zones # of your choice) # # Finally, this method supports a <tt>:default</tt> option, which selects - # a default TimeZone if the object's time zone is +nil+. + # a default ActiveSupport::TimeZone if the object's time zone is +nil+. # # Examples: # time_zone_select( "user", "time_zone", nil, :include_blank => true) # # time_zone_select( "user", "time_zone", nil, :default => "Pacific Time (US & Canada)" ) # - # time_zone_select( "user", 'time_zone', TimeZone.us_zones, :default => "Pacific Time (US & Canada)") + # time_zone_select( "user", 'time_zone', ActiveSupport::TimeZone.us_zones, :default => "Pacific Time (US & Canada)") # - # time_zone_select( "user", 'time_zone', [ TimeZone['Alaska'], TimeZone['Hawaii'] ]) + # time_zone_select( "user", 'time_zone', [ ActiveSupport::TimeZone['Alaska'], ActiveSupport::TimeZone['Hawaii'] ]) # # time_zone_select( "user", 'time_zone', /Australia/) # - # time_zone_select( "user", "time_zone", TZInfo::Timezone.all.sort, :model => TZInfo::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 @@ -393,20 +393,20 @@ module ActionView end # Returns a string of option tags for pretty much any time zone in the - # world. Supply a TimeZone name as +selected+ to have it marked as the - # selected option tag. You can also supply an array of TimeZone objects - # as +priority_zones+, so that they will be listed above the rest of the - # (long) list. (You can use TimeZone.us_zones as a convenience for - # obtaining a list of the US time zones, or a Regexp to select the zones - # of your choice) + # world. Supply a ActiveSupport::TimeZone name as +selected+ to have it + # marked as the selected option tag. You can also supply an array of + # ActiveSupport::TimeZone objects as +priority_zones+, so that they will + # be listed above the rest of the (long) list. (You can use + # ActiveSupport::TimeZone.us_zones as a convenience for obtaining a list + # of the US time zones, or a Regexp to select the zones of your choice) # # The +selected+ parameter must be either +nil+, or a string that names - # a TimeZone. + # a ActiveSupport::TimeZone. # - # By default, +model+ is the TimeZone constant (which can be obtained - # in Active Record as a value object). The only requirement is that the - # +model+ parameter be an object that responds to +all+, and returns - # an array of objects that represent time zones. + # By default, +model+ is the ActiveSupport::TimeZone constant (which can + # be obtained in Active Record as a value object). The only requirement + # is that the +model+ parameter be an object that responds to +all+, and + # returns an array of objects that represent time zones. # # NOTE: Only the option tags are returned, you have to wrap this call in # a regular HTML select tag. diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 66d7592874..eea797abb5 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -8,7 +8,10 @@ module ActionView module TagHelper include ERB::Util - BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked).to_set + BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked autobuffer + autoplay controls loop selected hidden scoped async + defer reversed ismap seemless muted required + autofocus novalidate formnovalidate open).to_set BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|attr| attr.to_sym }) # Returns an empty HTML tag of type +name+ which by default is XHTML diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index ad0733a7e1..c3ce4c671e 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -436,7 +436,7 @@ module ActionView end # Returns the current cycle string after a cycle has been started. Useful - # for complex table highlighing or any other design need which requires + # for complex table highlighting or any other design need which requires # the current cycle string in more than one place. # # ==== Example @@ -544,7 +544,7 @@ module ActionView left, right = $`, $' # detect already linked URLs and URLs in the middle of a tag if left =~ /<[^>]+$/ && right =~ /^[^>]*>/ - # do not change string; URL is alreay linked + # do not change string; URL is already linked href else # don't include trailing punctuation character as part of the URL diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index de864f453c..c5a6d1f084 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -12,11 +12,11 @@ module ActionView # Returns the URL for the set of +options+ provided. This takes the # same options as +url_for+ in Action Controller (see the - # documentation for ActionController::Base#url_for). Note that by default - # <tt>:only_path</tt> is <tt>true</tt> so you'll get the relative /controller/action - # instead of the fully qualified URL like http://example.com/controller/action. + # documentation for <tt>ActionController::Base#url_for</tt>). Note that by default + # <tt>:only_path</tt> is <tt>true</tt> so you'll get the relative "/controller/action" + # instead of the fully qualified URL like "http://example.com/controller/action". # - # When called from a view, url_for returns an HTML escaped url. If you + # When called from a view, +url_for+ returns an HTML escaped url. If you # need an unescaped url, pass <tt>:escape => false</tt> in the +options+. # # ==== Options @@ -34,8 +34,8 @@ module ActionView # # If you instead of a hash pass a record (like an Active Record or Active Resource) as the options parameter, # you'll trigger the named route for that record. The lookup will happen on the name of the class. So passing - # a Workshop object will attempt to use the workshop_path route. If you have a nested route, such as - # admin_workshop_path you'll have to call that explicitly (it's impossible for url_for to guess that route). + # a Workshop object will attempt to use the +workshop_path+ route. If you have a nested route, such as + # +admin_workshop_path+ you'll have to call that explicitly (it's impossible for +url_for+ to guess that route). # # ==== Examples # <%= url_for(:action => 'index') %> @@ -97,10 +97,10 @@ module ActionView # Creates a link tag of the given +name+ using a URL created by the set # of +options+. See the valid options in the documentation for - # url_for. It's also possible to pass a string instead + # +url_for+. It's also possible to pass a string instead # of an options hash to get a link tag that uses the value of the string as the # href for the link, or use <tt>:back</tt> to link to the referrer - a JavaScript back - # link will be used in place of a referrer if none exists. If nil is passed as + # link will be used in place of a referrer if none exists. If +nil+ is passed as # a name, the link itself will become the name. # # ==== Signatures @@ -117,27 +117,22 @@ module ActionView # * <tt>:popup => true || array of window options</tt> - This will force the # link to open in a popup window. By passing true, a default browser window # will be opened with the URL. You can also specify an array of options - # that are passed-thru to JavaScripts window.open method. + # that are passed to the <tt>window.open</tt> JavaScript call. # * <tt>:method => symbol of HTTP verb</tt> - This modifier will dynamically # create an HTML form and immediately submit the form for processing using # the HTTP verb specified. Useful for having links perform a POST operation # in dangerous actions like deleting a record (which search bots can follow # while spidering your site). Supported verbs are <tt>:post</tt>, <tt>:delete</tt> and <tt>:put</tt>. # Note that if the user has JavaScript disabled, the request will fall back - # to using GET. If you are relying on the POST behavior, you should check - # for it in your controller's action by using the request object's methods - # for <tt>post?</tt>, <tt>delete?</tt> or <tt>put?</tt>. + # to using GET. If <tt>:href => '#'</tt> is used and the user has JavaScript + # disabled clicking the link will have no effect. If you are relying on the + # POST behavior, you should check for it in your controller's action by using + # the request object's methods for <tt>post?</tt>, <tt>delete?</tt> or <tt>put?</tt>. # * The +html_options+ will accept a hash of html attributes for the link tag. # - # Note that if the user has JavaScript disabled, the request will fall back - # to using GET. If <tt>:href => '#'</tt> is used and the user has JavaScript disabled - # clicking the link will have no effect. If you are relying on the POST - # behavior, your should check for it in your controller's action by using the - # request object's methods for <tt>post?</tt>, <tt>delete?</tt> or <tt>put?</tt>. - # # You can mix and match the +html_options+ with the exception of - # <tt>:popup</tt> and <tt>:method</tt> which will raise an ActionView::ActionViewError - # exception. + # <tt>:popup</tt> and <tt>:method</tt> which will raise an + # <tt>ActionView::ActionViewError</tt> exception. # # ==== Examples # Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments @@ -170,9 +165,11 @@ module ActionView # You can use a block as well if your link target is hard to fit into the name parameter. ERb example: # # <% link_to(@profile) do %> - # <strong><%= @profile.name %></strong> -- <span>Check it out!!</span> + # <strong><%= @profile.name %></strong> -- <span>Check it out!</span> # <% end %> - # # => <a href="/profiles/1"><strong>David</strong> -- <span>Check it out!!</span></a> + # # => <a href="/profiles/1"> + # <strong>David</strong> -- <span>Check it out!</span> + # </a> # # Classes and ids for CSS are easy to produce: # @@ -215,7 +212,9 @@ module ActionView # # => <a href="/images/9" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); # f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; # var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); - # m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); };return false;">Delete Image</a> + # m.setAttribute('value', 'delete');var s = document.createElement('input'); s.setAttribute('type', 'hidden'); + # s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'Q/ttlxPYZ6R77B+vZ1sBkhj21G2isO9dpE6UtOHBApg='); + # f.appendChild(s)f.appendChild(m);f.submit(); };return false;">Delete Image</a> def link_to(*args, &block) if block_given? options = args.first || {} @@ -246,21 +245,21 @@ module ActionView # by the set of +options+. This is the safest method to ensure links that # cause changes to your data are not triggered by search bots or accelerators. # If the HTML button does not work with your layout, you can also consider - # using the link_to method with the <tt>:method</tt> modifier as described in - # the link_to documentation. + # using the +link_to+ method with the <tt>:method</tt> modifier as described in + # the +link_to+ documentation. # - # The generated FORM element has a class name of <tt>button-to</tt> + # The generated form element has a class name of <tt>button-to</tt> # to allow styling of the form itself and its children. You can control # the form submission and input element behavior using +html_options+. # This method accepts the <tt>:method</tt> and <tt>:confirm</tt> modifiers - # described in the link_to documentation. If no <tt>:method</tt> modifier + # described in the +link_to+ documentation. If no <tt>:method</tt> modifier # is given, it will default to performing a POST operation. You can also # disable the button by passing <tt>:disabled => true</tt> in +html_options+. # If you are using RESTful routes, you can pass the <tt>:method</tt> # to change the HTTP verb used to submit the form. # # ==== Options - # The +options+ hash accepts the same options at url_for. + # The +options+ hash accepts the same options as url_for. # # There are a few special +html_options+: # * <tt>:method</tt> - Specifies the anchor name to be appended to the path. @@ -317,7 +316,7 @@ module ActionView # Creates a link tag of the given +name+ using a URL created by the set of # +options+ unless the current request URI is the same as the links, in # which case only the name is returned (or the given block is yielded, if - # one exists). You can give link_to_unless_current a block which will + # one exists). You can give +link_to_unless_current+ a block which will # specialize the default behavior (e.g., show a "Start Here" link rather # than the link's text). # @@ -343,7 +342,7 @@ module ActionView # <li><a href="/controller/about">About Us</a></li> # </ul> # - # The implicit block given to link_to_unless_current is evaluated if the current + # The implicit block given to +link_to_unless_current+ is evaluated if the current # action is the action given. So, if we had a comments page and wanted to render a # "Go Back" link instead of a link to the comments page, we could do something like this... # @@ -360,7 +359,7 @@ module ActionView # +options+ unless +condition+ is true, in which case only the name is # returned. To specialize the default behavior (i.e., show a login link rather # than just the plaintext link text), you can pass a block that - # accepts the name or the full argument list for link_to_unless. + # accepts the name or the full argument list for +link_to_unless+. # # ==== Examples # <%= link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) %> @@ -391,8 +390,8 @@ module ActionView # Creates a link tag of the given +name+ using a URL created by the set of # +options+ if +condition+ is true, in which case only the name is # returned. To specialize the default behavior, you can pass a block that - # accepts the name or the full argument list for link_to_unless (see the examples - # in link_to_unless). + # accepts the name or the full argument list for +link_to_unless+ (see the examples + # in +link_to_unless+). # # ==== Examples # <%= link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) %> @@ -416,27 +415,27 @@ module ActionView # also used as the name of the link unless +name+ is specified. Additional # HTML attributes for the link can be passed in +html_options+. # - # mail_to has several methods for hindering email harvesters and customizing + # +mail_to+ has several methods for hindering email harvesters and customizing # the email itself by passing special keys to +html_options+. # # ==== Options - # * <tt>:encode</tt> - This key will accept the strings "javascript" or "hex". - # Passing "javascript" will dynamically create and encode the mailto: link then + # * <tt>:encode</tt> - This key will accept the strings "javascript" or "hex". + # Passing "javascript" will dynamically create and encode the mailto link then # eval it into the DOM of the page. This method will not show the link on # the page if the user has JavaScript disabled. Passing "hex" will hex - # encode the +email_address+ before outputting the mailto: link. - # * <tt>:replace_at</tt> - When the link +name+ isn't provided, the + # encode the +email_address+ before outputting the mailto link. + # * <tt>:replace_at</tt> - When the link +name+ isn't provided, the # +email_address+ is used for the link label. You can use this option to # obfuscate the +email_address+ by substituting the @ sign with the string # given as the value. - # * <tt>:replace_dot</tt> - When the link +name+ isn't provided, the + # * <tt>:replace_dot</tt> - When the link +name+ isn't provided, the # +email_address+ is used for the link label. You can use this option to # obfuscate the +email_address+ by substituting the . in the email with the # string given as the value. - # * <tt>:subject</tt> - Preset the subject line of the email. + # * <tt>:subject</tt> - Preset the subject line of the email. # * <tt>:body</tt> - Preset the body of the email. - # * <tt>:cc</tt> - Carbon Copy addition recipients on the email. - # * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email. + # * <tt>:cc</tt> - Carbon Copy addition recipients on the email. + # * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email. # # ==== Examples # mail_to "me@domain.com" @@ -607,23 +606,23 @@ module ActionView submit_function << "f.submit();" end - # Processes the _html_options_ hash, converting the boolean + # Processes the +html_options+ hash, converting the boolean # attributes from true/false form into the form required by # HTML/XHTML. (An attribute is considered to be boolean if - # its name is listed in the given _bool_attrs_ array.) + # its name is listed in the given +bool_attrs+ array.) # - # More specifically, for each boolean attribute in _html_options_ + # More specifically, for each boolean attribute in +html_options+ # given as: # - # "attr" => bool_value + # "attr" => bool_value # - # if the associated _bool_value_ evaluates to true, it is + # if the associated +bool_value+ evaluates to true, it is # replaced with the attribute's name; otherwise the attribute is - # removed from the _html_options_ hash. (See the XHTML 1.0 spec, + # removed from the +html_options+ hash. (See the XHTML 1.0 spec, # section 4.5 "Attribute Minimization" for more: # http://www.w3.org/TR/xhtml1/#h-4.5) # - # Returns the updated _html_options_ hash, which is also modified + # Returns the updated +html_options+ hash, which is also modified # in place. # # Example: diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 93ca34c41c..117f4ea4f0 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -86,6 +86,7 @@ class RespondToController < ActionController::Base type.mobile { render :text => "Mobile" } end ensure + Mime::SET.delete(:mobile) Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } end @@ -98,6 +99,7 @@ class RespondToController < ActionController::Base end ensure + Mime::SET.delete(:mobile) Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) } end @@ -132,6 +134,7 @@ class RespondToController < ActionController::Base end ensure + Mime::SET.delete(:iphone) Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } end @@ -145,6 +148,7 @@ class RespondToController < ActionController::Base end ensure + Mime::SET.delete(:iphone) Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } end @@ -162,7 +166,7 @@ class RespondToController < ActionController::Base end end -class MimeControllerTest < ActionController::TestCase +class RespondToControllerTest < ActionController::TestCase tests RespondToController def setup @@ -436,10 +440,10 @@ class MimeControllerTest < ActionController::TestCase def test_render_action_for_html @controller.instance_eval do def render(*args) - unless args.empty? - @action = args.first[:action] || action_name - end - response.body = "#{@action} - #{@template.formats}" + @action = args.first[:action] unless args.empty? + @action ||= action_name + + response.body = "#{@action} - #{formats}" end end @@ -467,7 +471,185 @@ class MimeControllerTest < ActionController::TestCase end end +class RespondResource + undef_method :to_json + + def to_xml + "XML" + end + + def to_js + "JS" + end +end + +class RespondWithController < ActionController::Base + respond_to :html, :json + respond_to :xml, :except => :using_defaults + respond_to :js, :only => :using_defaults + + def using_defaults + respond_to do |format| + format.csv { render :text => "CSV" } + end + end + + def using_defaults_with_type_list + respond_to(:js, :xml) + end + + def using_resource + respond_with(RespondResource.new) + end + + def using_resource_with_options + respond_with(RespondResource.new, :status => :unprocessable_entity) do |format| + format.js + end + end + + def default_overwritten + respond_to do |format| + format.html { render :text => "HTML" } + end + end + +protected + + def _render_js(js, options) + self.content_type ||= Mime::JS + self.response_body = js.respond_to?(:to_js) ? js.to_js : js + end +end + +class InheritedRespondWithController < RespondWithController + clear_respond_to + respond_to :xml, :json + + def index + respond_with(RespondResource.new) do |format| + format.json { render :text => "JSON" } + end + end +end + +class RespondWithControllerTest < ActionController::TestCase + tests RespondWithController + + def setup + super + ActionController::Base.use_accept_header = true + @request.host = "www.example.com" + end + + def teardown + super + ActionController::Base.use_accept_header = false + end + + def test_using_defaults + @request.accept = "*/*" + get :using_defaults + assert_equal "text/html", @response.content_type + assert_equal 'Hello world!', @response.body + + @request.accept = "text/csv" + get :using_defaults + assert_equal "text/csv", @response.content_type + assert_equal "CSV", @response.body + + @request.accept = "text/javascript" + get :using_defaults + assert_equal "text/javascript", @response.content_type + assert_equal '$("body").visualEffect("highlight");', @response.body + end + + def test_using_defaults_with_type_list + @request.accept = "*/*" + get :using_defaults_with_type_list + assert_equal "text/javascript", @response.content_type + assert_equal '$("body").visualEffect("highlight");', @response.body + + @request.accept = "application/xml" + get :using_defaults_with_type_list + assert_equal "application/xml", @response.content_type + assert_equal "<p>Hello world!</p>\n", @response.body + end + + def test_using_resource + @request.accept = "text/html" + get :using_resource + assert_equal "text/html", @response.content_type + assert_equal "Hello world!", @response.body + + @request.accept = "application/xml" + get :using_resource + assert_equal "application/xml", @response.content_type + assert_equal "XML", @response.body + + @request.accept = "application/json" + assert_raise ActionView::MissingTemplate do + get :using_resource + end + end + + def test_using_resource_with_options + @request.accept = "application/xml" + get :using_resource_with_options + assert_equal "application/xml", @response.content_type + assert_equal 422, @response.status + assert_equal "XML", @response.body + + @request.accept = "text/javascript" + get :using_resource_with_options + assert_equal "text/javascript", @response.content_type + assert_equal 422, @response.status + assert_equal "JS", @response.body + end + + def test_default_overwritten + get :default_overwritten + assert_equal "text/html", @response.content_type + assert_equal "HTML", @response.body + end + + def test_clear_respond_to + @controller = InheritedRespondWithController.new + @request.accept = "text/html" + get :index + assert_equal 406, @response.status + end + + def test_first_in_respond_to_has_higher_priority + @controller = InheritedRespondWithController.new + @request.accept = "*/*" + get :index + assert_equal "application/xml", @response.content_type + assert_equal "XML", @response.body + end + + def test_not_acceptable + @request.accept = "application/xml" + get :using_defaults + assert_equal 406, @response.status + + @request.accept = "text/html" + get :using_defaults_with_type_list + assert_equal 406, @response.status + + @request.accept = "application/json" + get :using_defaults_with_type_list + assert_equal 406, @response.status + + @request.accept = "text/javascript" + get :using_resource + assert_equal 406, @response.status + end +end + class AbstractPostController < ActionController::Base + respond_to :html, :iphone + self.view_paths = File.dirname(__FILE__) + "/../fixtures/post_test/" end @@ -476,10 +658,7 @@ class PostController < AbstractPostController around_filter :with_iphone def index - respond_to do |type| - type.html - type.iphone - end + respond_to # It will use formats declared above end protected @@ -489,17 +668,12 @@ protected request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone" yield ensure + Mime::SET.delete(:iphone) Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) } end end class SuperPostController < PostController - def index - respond_to do |type| - type.html - type.iphone - end - end end class MimeControllerLayoutsTest < ActionController::TestCase diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 3a85db8aa5..8ebf9aa186 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -338,16 +338,11 @@ class RequestTest < ActiveSupport::TestCase end test "XMLHttpRequest" do - begin - ActionController::Base.use_accept_header, old = - false, ActionController::Base.use_accept_header - + with_accept_header false do request = stub_request 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest' request.expects(:parameters).at_least_once.returns({}) assert request.xhr? assert_equal Mime::JS, request.format - ensure - ActionController::Base.use_accept_header = old end end @@ -396,10 +391,54 @@ class RequestTest < ActiveSupport::TestCase assert_equal({"bar" => 2}, request.query_parameters) end + test "formats with accept header" do + with_accept_header true do + request = stub_request 'HTTP_ACCEPT' => 'text/html' + request.expects(:parameters).at_least_once.returns({}) + assert_equal [ Mime::HTML ], request.formats + + request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8' + request.expects(:parameters).at_least_once.returns({}) + assert_equal with_set(Mime::XML, Mime::HTML), request.formats + end + + with_accept_header false do + request = stub_request + request.expects(:parameters).at_least_once.returns({ :format => :txt }) + assert_equal with_set(Mime::TEXT), request.formats + end + end + + test "negotiate_mime" do + with_accept_header true do + request = stub_request 'HTTP_ACCEPT' => 'text/html' + request.expects(:parameters).at_least_once.returns({}) + + assert_equal nil, request.negotiate_mime([Mime::XML, Mime::JSON]) + assert_equal Mime::HTML, request.negotiate_mime([Mime::XML, Mime::HTML]) + assert_equal Mime::HTML, request.negotiate_mime([Mime::XML, Mime::ALL]) + + request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8' + request.expects(:parameters).at_least_once.returns({}) + assert_equal Mime::XML, request.negotiate_mime([Mime::XML, Mime::CSV]) + assert_equal Mime::CSV, request.negotiate_mime([Mime::CSV, Mime::YAML]) + end + end + protected def stub_request(env={}) ActionDispatch::Request.new(env) end + def with_set(*args) + args + Mime::SET + end + + def with_accept_header(value) + ActionController::Base.use_accept_header, old = value, ActionController::Base.use_accept_header + yield + ensure + ActionController::Base.use_accept_header = old + end end diff --git a/actionpack/test/fixtures/public/.gitignore b/actionpack/test/fixtures/public/.gitignore index 0c6759baec..312e635ee6 100644 --- a/actionpack/test/fixtures/public/.gitignore +++ b/actionpack/test/fixtures/public/.gitignore @@ -1 +1 @@ -absolute
\ No newline at end of file +absolute/* diff --git a/actionpack/test/fixtures/respond_with/using_defaults.html.erb b/actionpack/test/fixtures/respond_with/using_defaults.html.erb new file mode 100644 index 0000000000..6769dd60bd --- /dev/null +++ b/actionpack/test/fixtures/respond_with/using_defaults.html.erb @@ -0,0 +1 @@ +Hello world!
\ No newline at end of file diff --git a/actionpack/test/fixtures/respond_with/using_defaults.js.rjs b/actionpack/test/fixtures/respond_with/using_defaults.js.rjs new file mode 100644 index 0000000000..469fcd8e15 --- /dev/null +++ b/actionpack/test/fixtures/respond_with/using_defaults.js.rjs @@ -0,0 +1 @@ +page[:body].visual_effect :highlight
\ No newline at end of file diff --git a/actionpack/test/fixtures/respond_with/using_defaults_with_type_list.js.rjs b/actionpack/test/fixtures/respond_with/using_defaults_with_type_list.js.rjs new file mode 100644 index 0000000000..469fcd8e15 --- /dev/null +++ b/actionpack/test/fixtures/respond_with/using_defaults_with_type_list.js.rjs @@ -0,0 +1 @@ +page[:body].visual_effect :highlight
\ No newline at end of file diff --git a/actionpack/test/fixtures/respond_with/using_defaults_with_type_list.xml.builder b/actionpack/test/fixtures/respond_with/using_defaults_with_type_list.xml.builder new file mode 100644 index 0000000000..598d62e2fc --- /dev/null +++ b/actionpack/test/fixtures/respond_with/using_defaults_with_type_list.xml.builder @@ -0,0 +1 @@ +xml.p "Hello world!"
\ No newline at end of file diff --git a/actionpack/test/fixtures/respond_with/using_resource.html.erb b/actionpack/test/fixtures/respond_with/using_resource.html.erb new file mode 100644 index 0000000000..6769dd60bd --- /dev/null +++ b/actionpack/test/fixtures/respond_with/using_resource.html.erb @@ -0,0 +1 @@ +Hello world!
\ No newline at end of file diff --git a/actionpack/test/template/active_record_helper_i18n_test.rb b/actionpack/test/template/active_record_helper_i18n_test.rb index 63032e4e5c..047f81be29 100644 --- a/actionpack/test/template/active_record_helper_i18n_test.rb +++ b/actionpack/test/template/active_record_helper_i18n_test.rb @@ -3,11 +3,14 @@ require 'abstract_unit' class ActiveRecordHelperI18nTest < Test::Unit::TestCase include ActionView::Context include ActionView::Helpers::ActiveModelHelper - + attr_reader :request def setup @object = stub :errors => stub(:count => 1, :full_messages => ['full_messages']) + @object.stubs :to_model => @object + @object.stubs :class => stub(:model_name => stub(:human => "")) + @object_name = 'book_seller' @object_name_without_underscore = 'book seller' @@ -39,7 +42,7 @@ class ActiveRecordHelperI18nTest < Test::Unit::TestCase I18n.expects(:t).with('', :default => '', :count => 1, :scope => [:activerecord, :models]).once.returns '' error_messages_for(:object => @object, :locale => 'en') end - + def test_error_messages_for_given_object_name_it_translates_object_name I18n.expects(:t).with(:header, :locale => 'en', :scope => [:activerecord, :errors, :template], :count => 1, :model => @object_name_without_underscore).returns "1 error prohibited this #{@object_name_without_underscore} from being saved" I18n.expects(:t).with(@object_name, :default => @object_name_without_underscore, :count => 1, :scope => [:activerecord, :models]).once.returns @object_name_without_underscore diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb index b07ce6cf5d..ec3384f15d 100644 --- a/actionpack/test/template/active_record_helper_test.rb +++ b/actionpack/test/template/active_record_helper_test.rb @@ -295,6 +295,16 @@ class ActiveRecordHelperTest < ActionView::TestCase assert_equal '', error_messages_for('user', :object => nil) end + def test_error_messages_for_model_objects + error = error_messages_for(@post) + assert_dom_equal %(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>), + error + + error = error_messages_for(@user, @post) + assert_dom_equal %(<div class="errorExplanation" id="errorExplanation"><h2>2 errors prohibited this user from being saved</h2><p>There were problems with the following fields:</p><ul><li>User email can't be empty</li><li>Author name can't be empty</li></ul></div>), + error + end + def test_form_with_string_multipart assert_dom_equal( %(<form action="create" enctype="multipart/form-data" method="post"><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>\n<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Create" /></form>), diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index 921bfeb93a..08963946ab 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -158,8 +158,8 @@ class AssetTagHelperTest < ActionView::TestCase VideoLinkToTag = { %(video_tag("xml.ogg")) => %(<video src="/videos/xml.ogg" />), - %(video_tag("rss.m4v", :autoplay => true, :controls => true)) => %(<video autoplay="true" controls="true" src="/videos/rss.m4v" />), - %(video_tag("rss.m4v", :autobuffer => true)) => %(<video autobuffer="true" src="/videos/rss.m4v" />), + %(video_tag("rss.m4v", :autoplay => true, :controls => true)) => %(<video autoplay="autoplay" controls="controls" src="/videos/rss.m4v" />), + %(video_tag("rss.m4v", :autobuffer => true)) => %(<video autobuffer="autobuffer" src="/videos/rss.m4v" />), %(video_tag("gold.m4v", :size => "160x120")) => %(<video height="120" src="/videos/gold.m4v" width="160" />), %(video_tag("gold.m4v", "size" => "320x240")) => %(<video height="240" src="/videos/gold.m4v" width="320" />), %(video_tag("trailer.ogg", :poster => "screenshot.png")) => %(<video poster="/images/screenshot.png" src="/videos/trailer.ogg" />), @@ -168,7 +168,7 @@ class AssetTagHelperTest < ActionView::TestCase %(video_tag("error.avi", "size" => "x")) => %(<video src="/videos/error.avi" />), %(video_tag("http://media.rubyonrails.org/video/rails_blog_2.mov")) => %(<video src="http://media.rubyonrails.org/video/rails_blog_2.mov" />), %(video_tag(["multiple.ogg", "multiple.avi"])) => %(<video><source src="multiple.ogg" /><source src="multiple.avi" /></video>), - %(video_tag(["multiple.ogg", "multiple.avi"], :size => "160x120", :controls => true)) => %(<video controls="true" height="120" width="160"><source src="multiple.ogg" /><source src="multiple.avi" /></video>) + %(video_tag(["multiple.ogg", "multiple.avi"], :size => "160x120", :controls => true)) => %(<video controls="controls" height="120" width="160"><source src="multiple.ogg" /><source src="multiple.avi" /></video>) } AudioPathToTag = { @@ -187,7 +187,7 @@ class AssetTagHelperTest < ActionView::TestCase AudioLinkToTag = { %(audio_tag("xml.wav")) => %(<audio src="/audios/xml.wav" />), - %(audio_tag("rss.wav", :autoplay => true, :controls => true)) => %(<audio autoplay="true" controls="true" src="/audios/rss.wav" />), + %(audio_tag("rss.wav", :autoplay => true, :controls => true)) => %(<audio autoplay="autoplay" controls="controls" src="/audios/rss.wav" />), %(audio_tag("http://media.rubyonrails.org/audio/rails_blog_2.mov")) => %(<audio src="http://media.rubyonrails.org/audio/rails_blog_2.mov" />), } |