diff options
Diffstat (limited to 'actionpack')
41 files changed, 665 insertions, 270 deletions
diff --git a/actionpack/examples/very_simple.rb b/actionpack/examples/very_simple.rb index 422c4c3298..6714185172 100644 --- a/actionpack/examples/very_simple.rb +++ b/actionpack/examples/very_simple.rb @@ -6,7 +6,7 @@ require "action_controller" class Kaigi < ActionController::Metal include AbstractController::Callbacks include ActionController::RackConvenience - include ActionController::Renderer + include ActionController::RenderingController include ActionController::Layouts include ActionView::Context @@ -47,4 +47,4 @@ app = Rack::Builder.new do map("/kaigi/alt") { run Kaigi.action(:alt) } end.to_app -Rack::Handler::Mongrel.run app, :Port => 3000
\ No newline at end of file +Rack::Handler::Mongrel.run app, :Port => 3000 diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb index f020abaa45..cdeb55b915 100644 --- a/actionpack/lib/abstract_controller.rb +++ b/actionpack/lib/abstract_controller.rb @@ -2,15 +2,15 @@ require "active_support/core_ext/module/attr_internal" require "active_support/core_ext/module/delegation" module AbstractController - autoload :Base, "abstract_controller/base" - autoload :Benchmarker, "abstract_controller/benchmarker" - autoload :Callbacks, "abstract_controller/callbacks" - autoload :Helpers, "abstract_controller/helpers" - autoload :Layouts, "abstract_controller/layouts" - autoload :Logger, "abstract_controller/logger" - autoload :Renderer, "abstract_controller/renderer" + autoload :Base, "abstract_controller/base" + autoload :Benchmarker, "abstract_controller/benchmarker" + autoload :Callbacks, "abstract_controller/callbacks" + autoload :Helpers, "abstract_controller/helpers" + autoload :Layouts, "abstract_controller/layouts" + autoload :Logger, "abstract_controller/logger" + autoload :RenderingController, "abstract_controller/rendering_controller" # === Exceptions - autoload :ActionNotFound, "abstract_controller/exceptions" - autoload :DoubleRenderError, "abstract_controller/exceptions" - autoload :Error, "abstract_controller/exceptions" + autoload :ActionNotFound, "abstract_controller/exceptions" + autoload :DoubleRenderError, "abstract_controller/exceptions" + autoload :Error, "abstract_controller/exceptions" end diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb index 5efa37fde3..04eaa02441 100644 --- a/actionpack/lib/abstract_controller/helpers.rb +++ b/actionpack/lib/abstract_controller/helpers.rb @@ -2,7 +2,7 @@ module AbstractController module Helpers extend ActiveSupport::Concern - include Renderer + include RenderingController included do extlib_inheritable_accessor(:_helpers) { Module.new } diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index 038598a3b3..0063d54149 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -2,7 +2,7 @@ module AbstractController module Layouts extend ActiveSupport::Concern - include Renderer + include RenderingController included do extlib_inheritable_accessor(:_layout_conditions) { Hash.new } @@ -76,7 +76,7 @@ module AbstractController when nil self.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1 def _layout(details) - if view_paths.find_by_parts?("#{_implied_layout_name}", details, "layouts") + if view_paths.exists?("#{_implied_layout_name}", details, "layouts") "#{_implied_layout_name}" else super @@ -89,16 +89,18 @@ module AbstractController end def render_to_body(options = {}) + # In the case of a partial with a layout, handle the layout + # here, and make sure the view does not try to handle it + layout = options.delete(:layout) if options.key?(:partial) + response = super - if options.key?(:partial) - # This is a little bit messy. We need to explicitly handle partial - # layouts here since the core lookup logic is in the view, but - # we need to determine the layout based on the controller - if options.key?(:layout) - layout = _layout_for_option(options[:layout], options[:_template].details) - response = layout.render(view_context, options[:locals]) { response } - end + # This is a little bit messy. We need to explicitly handle partial + # layouts here since the core lookup logic is in the view, but + # we need to determine the layout based on the controller + if layout + layout = _layout_for_option(layout, options[:_template].details) + response = layout.render(view_context, options[:locals] || {}) { response } end response @@ -131,7 +133,7 @@ module AbstractController def _find_layout(name, details) # TODO: Make prefix actually part of details in ViewPath#find_by_parts prefix = details.key?(:prefix) ? details.delete(:prefix) : "layouts" - view_paths.find_by_parts(name, details, prefix) + view_paths.find(name, details, prefix) end # Returns the default layout for this controller and a given set of details. diff --git a/actionpack/lib/abstract_controller/renderer.rb b/actionpack/lib/abstract_controller/rendering_controller.rb index da57d0ff4d..bb7891fbfd 100644 --- a/actionpack/lib/abstract_controller/renderer.rb +++ b/actionpack/lib/abstract_controller/rendering_controller.rb @@ -1,7 +1,7 @@ require "abstract_controller/logger" module AbstractController - module Renderer + module RenderingController extend ActiveSupport::Concern include AbstractController::Logger @@ -67,7 +67,7 @@ module AbstractController # # :api: plugin def render_to_string(options = {}) - AbstractController::Renderer.body_to_s(render_to_body(options)) + AbstractController::RenderingController.body_to_s(render_to_body(options)) end # Renders the template from an object. @@ -111,7 +111,7 @@ module AbstractController def _determine_template(options) name = (options[:_template_name] || action_name).to_s - options[:_template] ||= view_paths.find_by_parts( + options[:_template] ||= view_paths.find( name, { :formats => formats }, options[:_prefix], options[:_partial] ) end diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 22c2c4f499..37ff618edd 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -7,10 +7,10 @@ module ActionController autoload :RackConvenience, "action_controller/metal/rack_convenience" autoload :Rails2Compatibility, "action_controller/metal/compatibility" autoload :Redirector, "action_controller/metal/redirector" - autoload :Renderer, "action_controller/metal/renderer" + autoload :RenderingController, "action_controller/metal/rendering_controller" autoload :RenderOptions, "action_controller/metal/render_options" - autoload :Renderers, "action_controller/metal/render_options" autoload :Rescue, "action_controller/metal/rescuable" + autoload :Responder, "action_controller/metal/responder" autoload :Testing, "action_controller/metal/testing" autoload :UrlFor, "action_controller/metal/url_for" autoload :Session, "action_controller/metal/session" @@ -69,4 +69,4 @@ require 'active_support/core_ext/load_error' require 'active_support/core_ext/module/attr_internal' require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/name_error' -require 'active_support/inflector'
\ No newline at end of file +require 'active_support/inflector' diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 9d9f735e27..61f1c715c8 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -10,8 +10,8 @@ module ActionController include ActionController::HideActions include ActionController::UrlFor include ActionController::Redirector - include ActionController::Renderer - include ActionController::Renderers::All + include ActionController::RenderingController + include ActionController::RenderOptions::All include ActionController::Layouts include ActionController::ConditionalGet include ActionController::RackConvenience @@ -51,7 +51,7 @@ module ActionController def method_for_action(action_name) super || begin - if view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) + if view_paths.exists?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) "default_render" end end diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb index 95cba0e411..4ef600bea0 100644 --- a/actionpack/lib/action_controller/caching/fragments.rb +++ b/actionpack/lib/action_controller/caching/fragments.rb @@ -36,8 +36,8 @@ module ActionController #:nodoc: def fragment_for(buffer, name = {}, options = nil, &block) #:nodoc: if perform_caching - if cache = read_fragment(name, options) - buffer.concat(cache) + if fragment_exist?(name,options) + buffer.concat(read_fragment(name, options)) else pos = buffer.length block.call diff --git a/actionpack/lib/action_controller/legacy/layout.rb b/actionpack/lib/action_controller/legacy/layout.rb index 3f3d20b95f..43aea0eba2 100644 --- a/actionpack/lib/action_controller/legacy/layout.rb +++ b/actionpack/lib/action_controller/legacy/layout.rb @@ -191,7 +191,7 @@ module ActionController #:nodoc: def memoized_find_layout(layout, formats) #:nodoc: return layout if layout.nil? || layout.respond_to?(:render) prefix = layout.to_s =~ /layouts\// ? nil : "layouts" - view_paths.find_by_parts(layout.to_s, {:formats => formats}, prefix) + view_paths.find(layout.to_s, {:formats => formats}, prefix) end def find_layout(*args) diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index 6d35137428..8575d30335 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -55,14 +55,15 @@ module ActionController elsif args.empty? raise ArgumentError, "too few arguments to head" end - options = args.extract_options! - status = args.shift || options.delete(:status) || :ok + options = args.extract_options! + status = args.shift || options.delete(:status) || :ok + location = options.delete(:location) options.each do |key, value| headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s end - render :nothing => true, :status => status + render :nothing => true, :status => status, :location => location end # Sets the etag and/or last_modified on the response and checks it against diff --git a/actionpack/lib/action_controller/metal/layouts.rb b/actionpack/lib/action_controller/metal/layouts.rb index 365351b421..cac529b1ae 100644 --- a/actionpack/lib/action_controller/metal/layouts.rb +++ b/actionpack/lib/action_controller/metal/layouts.rb @@ -158,7 +158,7 @@ module ActionController module Layouts extend ActiveSupport::Concern - include ActionController::Renderer + include ActionController::RenderingController include AbstractController::Layouts module ClassMethods diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index f4a4007a43..c8d042acb5 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -177,106 +177,67 @@ module ActionController #:nodoc: # 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? - resource = options.delete(:with) - responder = Responder.new - + collector = Collector.new mimes = collect_mimes_from_class_level if mimes.empty? - mimes.each { |mime| responder.send(mime) } - block.call(responder) if block_given? + mimes.each { |mime| collector.send(mime) } + block.call(collector) if block_given? + + if format = request.negotiate_mime(collector.order) + self.formats = [format.to_sym] - if format = request.negotiate_mime(responder.order) - respond_to_block_or_template_or_resource(format, resource, - options, &responder.response_for(format)) + if response = collector.response_for(format) + response.call + else + default_render + end else head :not_acceptable end end - # 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: + # respond_with wraps a resource around a responder for default representation. + # First it invokes respond_to, if a response cannot be found (ie. no block + # for the request was given and template was not available), it instantiates + # an ActionController::Responder with the controller and resource. # - # class PeopleController < ApplicationController - # respond_to :html, :xml, :json + # ==== Example # - # def index - # @people = Person.find(:all) - # respond_with(@person) - # end + # def index + # @users = User.all + # respond_with(@users) # 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. + # It also accepts a block to be given. It's used to overwrite a default + # response: # - # 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: + # def destroy + # @user = User.find(params[:id]) + # flash[:notice] = "User was successfully created." if @user.save # - # 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 + # respond_with(@user) do |format| + # format.html { render } # 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 + # All options given to respond_with are sent to the underlying responder, + # except for the option :responder itself. Since the responder interface + # is quite simple (it just needs to respond to call), you can even give + # a proc to it. # def respond_with(resource, options={}, &block) - respond_to(options.merge!(:with => resource), &block) + respond_to(&block) + rescue ActionView::MissingTemplate + (options.delete(:responder) || responder).call(self, resource, options) end - protected - - def respond_to_block_or_template_or_resource(format, resource, options) - self.formats = [format.to_sym] - return yield if block_given? - - 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 + def responder + ActionController::Responder end + protected + # Collect mimes declared in the class method respond_to valid for the # current action. # @@ -296,7 +257,7 @@ module ActionController #:nodoc: end end - class Responder #:nodoc: + class Collector #:nodoc: attr_accessor :order def initialize diff --git a/actionpack/lib/action_controller/metal/render_options.rb b/actionpack/lib/action_controller/metal/render_options.rb index c6a965472f..0d69ca10df 100644 --- a/actionpack/lib/action_controller/metal/render_options.rb +++ b/actionpack/lib/action_controller/metal/render_options.rb @@ -47,7 +47,7 @@ module ActionController end end - module Renderers + module RenderOptions module Json extend RenderOption register_renderer :json @@ -94,10 +94,10 @@ module ActionController module All extend ActiveSupport::Concern - include ActionController::Renderers::Json - include ActionController::Renderers::Js - include ActionController::Renderers::Xml - include ActionController::Renderers::RJS + include ActionController::RenderOptions::Json + include ActionController::RenderOptions::Js + include ActionController::RenderOptions::Xml + include ActionController::RenderOptions::RJS end end end diff --git a/actionpack/lib/action_controller/metal/renderer.rb b/actionpack/lib/action_controller/metal/rendering_controller.rb index 31ba7e582a..5b1be763ad 100644 --- a/actionpack/lib/action_controller/metal/renderer.rb +++ b/actionpack/lib/action_controller/metal/rendering_controller.rb @@ -1,8 +1,8 @@ module ActionController - module Renderer + module RenderingController extend ActiveSupport::Concern - include AbstractController::Renderer + include AbstractController::RenderingController def process_action(*) self.formats = request.formats.map {|x| x.to_sym} @@ -53,9 +53,6 @@ module ActionController super end - def _render_partial(partial, options) - end - def _process_options(options) status, content_type, location = options.values_at(:status, :content_type, :location) self.status = status if status diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb new file mode 100644 index 0000000000..9ed99ca623 --- /dev/null +++ b/actionpack/lib/action_controller/metal/responder.rb @@ -0,0 +1,181 @@ +module ActionController #:nodoc: + # Responder is responsible to expose a resource for different mime requests, + # usually depending on the HTTP verb. The responder is triggered when + # respond_with is called. The simplest case to study is a GET request: + # + # class PeopleController < ApplicationController + # respond_to :html, :xml, :json + # + # def index + # @people = Person.find(:all) + # respond_with(@people) + # end + # end + # + # When a request comes, for example with format :xml, three steps happen: + # + # 1) respond_with searches for a template at people/index.xml; + # + # 2) if the template is not available, it will create a responder, passing + # the controller and the resource and invoke :to_xml on it; + # + # 3) if the responder does not respond_to :to_xml, call to_format on it. + # + # === Builtin HTTP verb semantics + # + # Rails default responder holds semantics for each HTTP verb. Depending on the + # content type, verb and the resource status, it will behave differently. + # + # Using Rails default responder, a POST request for creating an object could + # be written as: + # + # def create + # @user = User.new(params[:user]) + # flash[:notice] = 'User was successfully created.' if @user.save + # respond_with(@user) + # end + # + # Which is exactly the same as: + # + # def create + # @user = User.new(params[:user]) + # + # respond_to do |format| + # if @user.save + # flash[:notice] = 'User was successfully created.' + # format.html { redirect_to(@user) } + # format.xml { render :xml => @user, :status => :created, :location => @user } + # else + # format.html { render :action => "new" } + # format.xml { render :xml => @user.errors, :status => :unprocessable_entity } + # end + # end + # end + # + # The same happens for PUT and DELETE requests. + # + # === Nested resources + # + # You can given nested resource as you do in form_for and polymorphic_url. + # Consider the project has many tasks example. The create action for + # TasksController would be like: + # + # def create + # @project = Project.find(params[:project_id]) + # @task = @project.comments.build(params[:task]) + # flash[:notice] = 'Task was successfully created.' if @task.save + # respond_with([@project, @task]) + # end + # + # Giving an array of resources, you ensure that the responder will redirect to + # project_task_url instead of task_url. + # + # Namespaced and singleton resources requires a symbol to be given, as in + # polymorphic urls. If a project has one manager which has many tasks, it + # should be invoked as: + # + # respond_with([@project, :manager, @task]) + # + # Check polymorphic_url documentation for more examples. + # + class Responder + attr_reader :controller, :request, :format, :resource, :resource_location, :options + + def initialize(controller, resource, options={}) + @controller = controller + @request = controller.request + @format = controller.formats.first + @resource = resource.is_a?(Array) ? resource.last : resource + @resource_location = options[:location] || resource + @options = options + end + + delegate :head, :render, :redirect_to, :to => :controller + delegate :get?, :post?, :put?, :delete?, :to => :request + + # Undefine :to_json since it's defined on Object + undef_method :to_json + + # Initializes a new responder an invoke the proper format. If the format is + # not defined, call to_format. + # + def self.call(*args) + responder = new(*args) + method = :"to_#{responder.format}" + responder.respond_to?(method) ? responder.send(method) : responder.to_format + end + + # HTML format does not render the resource, it always attempt to render a + # template. + # + def to_html + if get? + render + elsif has_errors? + render :action => default_action + else + redirect_to resource_location + end + end + + # All others formats try to render the resource given instead. For this + # purpose a helper called display as a shortcut to render a resource with + # the current format. + # + def to_format + return render unless resourceful? + + if get? + display resource + elsif has_errors? + display resource.errors, :status => :unprocessable_entity + elsif post? + display resource, :status => :created, :location => resource_location + else + head :ok + end + end + + protected + + # Checks whether the resource responds to the current format or not. + # + def resourceful? + resource.respond_to?(:"to_#{format}") + end + + # display is just a shortcut to render a resource with the current format. + # + # display @user, :status => :ok + # + # For xml request is equivalent to: + # + # render :xml => @user, :status => :ok + # + # Options sent by the user are also used: + # + # respond_with(@user, :status => :created) + # display(@user, :status => :ok) + # + # Results in: + # + # render :xml => @user, :status => :created + # + def display(resource, given_options={}) + render given_options.merge!(options).merge!(format => resource) + end + + # Check if the resource has errors or not. + # + def has_errors? + resource.respond_to?(:errors) && !resource.errors.empty? + end + + # By default, render the :edit action for html requests with failure, unless + # the verb is post. + # + def default_action + request.post? ? :new : :edit + end + end +end diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb index f0317c6e99..57318e8747 100644 --- a/actionpack/lib/action_controller/metal/streaming.rb +++ b/actionpack/lib/action_controller/metal/streaming.rb @@ -6,7 +6,7 @@ module ActionController #:nodoc: module Streaming extend ActiveSupport::Concern - include ActionController::Renderer + include ActionController::RenderingController DEFAULT_SEND_FILE_OPTIONS = { :type => 'application/octet-stream'.freeze, diff --git a/actionpack/lib/action_controller/metal/verification.rb b/actionpack/lib/action_controller/metal/verification.rb index 951ae1bee1..d3d78e3749 100644 --- a/actionpack/lib/action_controller/metal/verification.rb +++ b/actionpack/lib/action_controller/metal/verification.rb @@ -2,7 +2,7 @@ module ActionController #:nodoc: module Verification #:nodoc: extend ActiveSupport::Concern - include AbstractController::Callbacks, Session, Flash, Renderer + include AbstractController::Callbacks, Session, Flash, RenderingController # This module provides a class-level method for specifying that certain # actions are guarded against being called without certain prerequisites @@ -127,4 +127,4 @@ module ActionController #:nodoc: end end end -end
\ No newline at end of file +end diff --git a/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb index 159d869a54..2adf3575a7 100644 --- a/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb +++ b/actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb @@ -50,6 +50,7 @@ module ActionController # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1" # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1" # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1" + # polymorphic_url(Comment) # => "http://example.com/comments" # # ==== Options # @@ -70,6 +71,9 @@ module ActionController # record = Comment.new # polymorphic_url(record) # same as comments_url() # + # # the class of a record will also map to the collection + # polymorphic_url(Comment) # same as comments_url() + # def polymorphic_url(record_or_hash_or_array, options = {}) if record_or_hash_or_array.kind_of?(Array) record_or_hash_or_array = record_or_hash_or_array.compact @@ -86,17 +90,19 @@ module ActionController else [ record_or_hash_or_array ] end - inflection = - case - when options[:action].to_s == "new" - args.pop - :singular - when record.respond_to?(:new_record?) && record.new_record? - args.pop - :plural - else - :singular - end + inflection = if options[:action].to_s == "new" + args.pop + :singular + elsif (record.respond_to?(:new_record?) && record.new_record?) || + (record.respond_to?(:destroyed?) && record.destroyed?) + args.pop + :plural + elsif record.is_a?(Class) + args.pop + :plural + else + :singular + end args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)} diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 9e696af83b..7932f01ebb 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -202,7 +202,7 @@ module ActionView #:nodoc: delegate :logger, :to => :controller, :allow_nil => true - delegate :find_by_parts, :to => :view_paths + delegate :find, :to => :view_paths include Context diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index 4fd7f7d83c..3e6e62237d 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -278,9 +278,7 @@ module ActionView end %w(tag content_tag to_date_select_tag to_datetime_select_tag to_time_select_tag).each do |meth| - define_method meth do |*| - error_wrapping(super) - end + module_eval "def #{meth}(*) error_wrapping(super) end" end def error_wrapping(html_tag) diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index e126b35e90..1abe7775e0 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -263,7 +263,7 @@ module ActionView escape = options.key?("escape") ? options.delete("escape") : true content = html_escape(content) if escape - content_tag :textarea, content, { "name" => name, "id" => sanitize_to_id(name) }.update(options.stringify_keys) + content_tag :textarea, content, { "name" => name, "id" => sanitize_to_id(name) }.update(options) end # Creates a check box form input tag. diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 999d5b34fc..897a7cc348 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -215,7 +215,7 @@ module ActionView delimiter ||= (options[:delimiter] || defaults[:delimiter]) begin - rounded_number = (Float(number) * (10 ** precision)).round.to_f / 10 ** precision + rounded_number = BigDecimal.new((Float(number) * (10 ** precision)).to_s).round.to_f / 10 ** precision number_with_delimiter("%01.#{precision}f" % rounded_number, :separator => separator, :delimiter => delimiter) diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb index 074b475819..4001757a9b 100644 --- a/actionpack/lib/action_view/paths.rb +++ b/actionpack/lib/action_view/paths.rb @@ -33,12 +33,12 @@ module ActionView #:nodoc: super(*objs.map { |obj| self.class.type_cast(obj) }) end - def find_by_parts(path, details = {}, prefix = nil, partial = false) + def find(path, details = {}, prefix = nil, partial = false) # template_path = path.sub(/^\//, '') template_path = path each do |load_path| - if template = load_path.find_by_parts(template_path, details, prefix, partial) + if template = load_path.find(template_path, details, prefix, partial) return template end end @@ -48,11 +48,11 @@ module ActionView #:nodoc: raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path} - #{details.inspect} - partial: #{!!partial}") end - def find_by_parts?(path, extension = nil, prefix = nil, partial = false) + def exists?(path, extension = nil, prefix = nil, partial = false) template_path = path.sub(/^\//, '') each do |load_path| - return true if template = load_path.find_by_parts(template_path, extension, prefix, partial) + return true if template = load_path.find(template_path, extension, prefix, partial) end false end @@ -62,7 +62,7 @@ module ActionView #:nodoc: template_path = original_template_path.sub(/^\//, '') each do |load_path| - if template = load_path.find_by_parts(template_path, format) + if template = load_path.find(template_path, format) return template # Try to find html version if the format is javascript elsif format == :js && html_fallback && template = load_path["#{template_path}.#{I18n.locale}.html"] diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 48cba9c02b..986d3af454 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -170,95 +170,117 @@ module ActionView # <%- end -%> # <% end %> module Partials - extend ActiveSupport::Memoizable extend ActiveSupport::Concern - included do - attr_accessor :_partial - end - - module ClassMethods - def _partial_names - @_partial_names ||= ActiveSupport::ConcurrentHash.new + class PartialRenderer + def self.partial_names + @partial_names ||= Hash.new {|h,k| h[k] = ActiveSupport::ConcurrentHash.new } end - end - def render_partial(options) - @assigns_added = false - # TODO: Handle other details here. - self.formats = options[:_details][:formats] - _render_partial(options) - end + def initialize(view_context, options, formats) + object = options[:partial] - def _render_partial(options, &block) #:nodoc: - options[:locals] ||= {} + @view, @formats = view_context, formats + @options = options || {} - path = partial = options[:partial] + if object.is_a?(String) + @path = object + elsif + @object = object + @path = partial_path unless collection + end - if partial.respond_to?(:to_ary) - return _render_partial_collection(partial, options, &block) - elsif !partial.is_a?(String) - options[:object] = object = partial - path = _partial_path(object) + @locals = options[:locals] || {} + @object ||= @options[:object] || @locals[:object] + @layout = options[:layout] end - _render_partial_object(_pick_partial_template(path), options, &block) - end + def render(&block) + template = find if @path - private - def _partial_path(object) - self.class._partial_names[[controller.class, object.class]] ||= begin - name = object.class.model_name - if controller_path && controller_path.include?("/") - File.join(File.dirname(controller_path), name.partial_path) - else - name.partial_path - end + if collection + render_collection(template, &block) + else + render_object(template, &block) end end - def _render_partial_template(template, locals, object, options = {}, &block) - options[:_template] = template - locals[:object] = locals[template.variable_name] = object - locals[options[:as]] = object if options[:as] + def render_template(template, &block) + @options[:_template] = template + @locals[:object] = @locals[template.variable_name] = @object + @locals[@options[:as]] = @object if @options[:as] - _render_single_template(template, locals, &block) + content = @view._render_single_template(template, @locals, &block) + return content if block_given? || !@layout + find(@layout).render(@view, @locals) { content } end - def _render_partial_object(template, options, &block) - if options.key?(:collection) - _render_partial_collection(options.delete(:collection), options, template, &block) - else - locals = (options[:locals] ||= {}) - object = options[:object] || locals[:object] || locals[template.variable_name] - - _render_partial_template(template, locals, object, options, &block) - end + def render_object(template, &block) + @object ||= @locals[template.variable_name] + render_template(template, &block) end - def _render_partial_collection(collection, options = {}, template = nil, &block) #:nodoc: - options[:_template] ||= template + def render_collection(passed_template = nil, &block) + @options[:_template] = passed_template return nil if collection.blank? - if options.key?(:spacer_template) - spacer = _render_partial(:partial => options[:spacer_template]) + if @options.key?(:spacer_template) + spacer = @view.render_partial( + :partial => @options[:spacer_template], :_details => @options[:_details]) end - locals, index = options[:locals] || {}, 0 + index = 0 - collection.map do |object| - tmp = template || _pick_partial_template(_partial_path(object)) - locals[tmp.counter_name] = index + collection.map do |@object| + @path = partial_path + template = passed_template || find + @locals[template.counter_name] = index index += 1 - _render_partial_template(tmp, locals, object, options, &block) + render_template(template, &block) end.join(spacer) end - def _pick_partial_template(partial_path) #:nodoc: - prefix = controller_path unless partial_path.include?(?/) - find_by_parts(partial_path, {:formats => formats}, prefix, true) + private + def collection + @collection ||= if @object.respond_to?(:to_ary) + @object + elsif @options.key?(:collection) + @options[:collection] || [] + end end + + def find(path = @path) + prefix = @view.controller.controller_path unless path.include?(?/) + @view.find(path, {:formats => @view.formats}, prefix, true) + end + + def partial_path(object = @object) + self.class.partial_names[@view.controller.class][object.class] ||= begin + return nil unless object.class.respond_to?(:model_name) + + name = object.class.model_name + path = @view.controller_path + if path && path.include?(?/) + File.join(File.dirname(path), name.partial_path) + else + name.partial_path + end + end + end + end + + def render_partial(options) + @assigns_added = false + # TODO: Handle other details here. + self.formats = options[:_details][:formats] if options[:_details] + _render_partial(options) + end + + def _render_partial(options, &block) #:nodoc: + PartialRenderer.new(self, options, formats).render(&block) + end + end end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 9c25fab6bb..c7afc56e3b 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -20,14 +20,13 @@ module ActionView if block_given? return concat(_render_partial(options.merge(:partial => layout), &block)) elsif options.key?(:partial) - layout = _pick_partial_template(layout) if layout - return _render_content(_render_partial(options), layout, options[:locals]) + return _render_partial(options) end - layout = find_by_parts(layout, {:formats => formats}) if layout + layout = find(layout, {:formats => formats}) if layout if file = options[:file] - template = find_by_parts(file, {:formats => formats}) + template = find(file, {:formats => formats}) _render_template(template, layout, :locals => options[:locals] || {}) elsif inline = options[:inline] _render_inline(inline, layout, options) diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index d15f53a11b..ebfc6cc8ce 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -10,7 +10,7 @@ module ActionView end # Normalizes the arguments and passes it on to find_template - def find_by_parts(*args) + def find(*args) find_all_by_parts(*args).first end diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb index 56ec6a6a31..9438a4dfc9 100644 --- a/actionpack/test/abstract_controller/abstract_controller_test.rb +++ b/actionpack/test/abstract_controller/abstract_controller_test.rb @@ -27,7 +27,7 @@ module AbstractController # Test Render mixin # ==== class RenderingController < AbstractController::Base - include Renderer + include ::AbstractController::RenderingController def _prefix() end @@ -65,8 +65,8 @@ module AbstractController self.response_body = render_to_string :_template_name => "naked_render.erb" end end - - class TestRenderer < ActiveSupport::TestCase + + class TestRenderingController < ActiveSupport::TestCase test "rendering templates works" do result = Me2.new.process(:index) assert_equal "Hello from index.erb", result.response_body @@ -139,10 +139,10 @@ module AbstractController private def self.layout(formats) begin - view_paths.find_by_parts(name.underscore, {:formats => formats}, "layouts") + view_paths.find(name.underscore, {:formats => formats}, "layouts") rescue ActionView::MissingTemplate begin - view_paths.find_by_parts("application", {:formats => formats}, "layouts") + view_paths.find("application", {:formats => formats}, "layouts") rescue ActionView::MissingTemplate end end diff --git a/actionpack/test/abstract_controller/helper_test.rb b/actionpack/test/abstract_controller/helper_test.rb index 0a2535f834..e9a60c0307 100644 --- a/actionpack/test/abstract_controller/helper_test.rb +++ b/actionpack/test/abstract_controller/helper_test.rb @@ -4,7 +4,7 @@ module AbstractController module Testing class ControllerWithHelpers < AbstractController::Base - include Renderer + include AbstractController::RenderingController include Helpers def render(string) @@ -40,4 +40,4 @@ module AbstractController end end -end
\ No newline at end of file +end diff --git a/actionpack/test/abstract_controller/layouts_test.rb b/actionpack/test/abstract_controller/layouts_test.rb index b28df7743f..42f73faa61 100644 --- a/actionpack/test/abstract_controller/layouts_test.rb +++ b/actionpack/test/abstract_controller/layouts_test.rb @@ -6,7 +6,7 @@ module AbstractControllerTests # Base controller for these tests class Base < AbstractController::Base - include AbstractController::Renderer + include AbstractController::RenderingController include AbstractController::Layouts self.view_paths = [ActionView::FixtureResolver.new( diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index 2036d1eeb5..37f1f6dff8 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -45,6 +45,12 @@ class PolymorphicRoutesTest < ActionController::TestCase assert_equal "http://example.com/projects/#{@project.id}", polymorphic_url(@project) end end + + def test_with_class + with_test_routes do + assert_equal "http://example.com/projects", polymorphic_url(@project.class) + end + end def test_with_new_record with_test_routes do @@ -52,6 +58,13 @@ class PolymorphicRoutesTest < ActionController::TestCase end end + def test_with_destroyed_record + with_test_routes do + @project.destroy + assert_equal "http://example.com/projects", polymorphic_url(@project) + end + end + def test_with_record_and_action with_test_routes do assert_equal "http://example.com/projects/new", polymorphic_url(@project, :action => 'new') @@ -129,6 +142,27 @@ class PolymorphicRoutesTest < ActionController::TestCase end end + def test_with_nested_destroyed + with_test_routes do + @project.save + @task.destroy + assert_equal "http://example.com/projects/#{@project.id}/tasks", polymorphic_url([@project, @task]) + end + end + + def test_with_nested_class + with_test_routes do + @project.save + assert_equal "http://example.com/projects/#{@project.id}/tasks", polymorphic_url([@project, @task.class]) + end + end + + def test_class_with_array_and_namespace + with_admin_test_routes do + assert_equal "http://example.com/admin/projects", polymorphic_url([:admin, @project.class]) + end + end + def test_new_with_array_and_namespace with_admin_test_routes do assert_equal "http://example.com/admin/projects/new", polymorphic_url([:admin, @project], :action => 'new') @@ -252,11 +286,24 @@ class PolymorphicRoutesTest < ActionController::TestCase end end + def test_with_irregular_plural_class + with_test_routes do + assert_equal "http://example.com/taxes", polymorphic_url(@tax.class) + end + end + def test_with_irregular_plural_new_record with_test_routes do assert_equal "http://example.com/taxes", polymorphic_url(@tax) end end + + def test_with_irregular_plural_destroyed_record + with_test_routes do + @tax.destroy + assert_equal "http://example.com/taxes", polymorphic_url(@tax) + end + end def test_with_irregular_plural_record_and_action with_test_routes do @@ -298,6 +345,12 @@ class PolymorphicRoutesTest < ActionController::TestCase end end + def test_class_with_irregular_plural_array_and_namespace + with_admin_test_routes do + assert_equal "http://example.com/admin/taxes", polymorphic_url([:admin, @tax.class]) + end + end + def test_unsaved_with_irregular_plural_array_and_namespace with_admin_test_routes do assert_equal "http://example.com/admin/taxes", polymorphic_url([:admin, @tax]) @@ -395,4 +448,4 @@ class PolymorphicRoutesTest < ActionController::TestCase end end -end
\ No newline at end of file +end diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index c286976315..68529cc8f7 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -625,6 +625,21 @@ class FragmentCachingTest < ActionController::TestCase assert !fragment_computed assert_equal 'generated till now -> fragment content', buffer end + + def test_fragment_for_logging + fragment_computed = false + + @controller.class.expects(:benchmark).with('Cached fragment exists?: views/expensive') + @controller.class.expects(:benchmark).with('Cached fragment miss: views/expensive') + @controller.class.expects(:benchmark).with('Cached fragment hit: views/expensive').never + + buffer = 'generated till now -> ' + @controller.fragment_for(buffer, 'expensive') { fragment_computed = true } + + assert fragment_computed + assert_equal 'generated till now -> ', buffer + end + end class FunctionalCachingController < ActionController::Base diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 117f4ea4f0..8319b5c573 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'controller/fake_models' class RespondToController < ActionController::Base layout :set_layout @@ -471,22 +472,10 @@ class RespondToControllerTest < 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 + respond_to :js, :only => [ :using_defaults, :using_resource ] def using_defaults respond_to do |format| @@ -498,20 +487,27 @@ class RespondWithController < ActionController::Base respond_to(:js, :xml) end + def default_overwritten + respond_to do |format| + format.html { render :text => "HTML" } + end + end + def using_resource - respond_with(RespondResource.new) + respond_with(Customer.new("david", 13)) end - def using_resource_with_options - respond_with(RespondResource.new, :status => :unprocessable_entity) do |format| - format.js - end + def using_resource_with_parent + respond_with([Quiz::Store.new("developer?", 11), Customer.new("david", 13)]) end - def default_overwritten - respond_to do |format| - format.html { render :text => "HTML" } - end + def using_resource_with_status_and_location + respond_with(Customer.new("david", 13), :location => "http://test.host/", :status => :created) + end + + def using_resource_with_responder + responder = proc { |c, r, o| c.render :text => "Resource name is #{r.name}" } + respond_with(Customer.new("david", 13), :responder => responder) end protected @@ -527,7 +523,7 @@ class InheritedRespondWithController < RespondWithController respond_to :xml, :json def index - respond_with(RespondResource.new) do |format| + respond_with(Customer.new("david", 13)) do |format| format.json { render :text => "JSON" } end end @@ -540,6 +536,11 @@ class RespondWithControllerTest < ActionController::TestCase super ActionController::Base.use_accept_header = true @request.host = "www.example.com" + + ActionController::Routing::Routes.draw do |map| + map.resources :customers + map.resources :quiz_stores, :has_many => :customers + end end def teardown @@ -576,11 +577,17 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal "<p>Hello world!</p>\n", @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_using_resource - @request.accept = "text/html" + @request.accept = "text/javascript" get :using_resource - assert_equal "text/html", @response.content_type - assert_equal "Hello world!", @response.body + assert_equal "text/javascript", @response.content_type + assert_equal '$("body").visualEffect("highlight");', @response.body @request.accept = "application/xml" get :using_resource @@ -593,24 +600,114 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_with_options + def test_using_resource_for_post_with_html + post :using_resource + assert_equal "text/html", @response.content_type + assert_equal 302, @response.status + assert_equal "http://www.example.com/customers/13", @response.location + assert @response.redirect? + + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + post :using_resource + assert_equal "text/html", @response.content_type + assert_equal 200, @response.status + assert_equal "New world!\n", @response.body + assert_nil @response.location + end + + def test_using_resource_for_post_with_xml @request.accept = "application/xml" - get :using_resource_with_options + + post :using_resource assert_equal "application/xml", @response.content_type - assert_equal 422, @response.status + assert_equal 201, @response.status assert_equal "XML", @response.body + assert_equal "http://www.example.com/customers/13", @response.location - @request.accept = "text/javascript" - get :using_resource_with_options - assert_equal "text/javascript", @response.content_type + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + post :using_resource + assert_equal "application/xml", @response.content_type assert_equal 422, @response.status - assert_equal "JS", @response.body + assert_equal errors.to_xml, @response.body + assert_nil @response.location end - def test_default_overwritten - get :default_overwritten + def test_using_resource_for_put_with_html + put :using_resource assert_equal "text/html", @response.content_type - assert_equal "HTML", @response.body + assert_equal 302, @response.status + assert_equal "http://www.example.com/customers/13", @response.location + assert @response.redirect? + + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + put :using_resource + assert_equal "text/html", @response.content_type + assert_equal 200, @response.status + assert_equal "Edit world!\n", @response.body + assert_nil @response.location + end + + def test_using_resource_for_put_with_xml + @request.accept = "application/xml" + + put :using_resource + assert_equal "application/xml", @response.content_type + assert_equal 200, @response.status + assert_equal " ", @response.body + + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + put :using_resource + assert_equal "application/xml", @response.content_type + assert_equal 422, @response.status + assert_equal errors.to_xml, @response.body + assert_nil @response.location + end + + def test_using_resource_for_delete_with_html + Customer.any_instance.stubs(:destroyed?).returns(true) + delete :using_resource + assert_equal "text/html", @response.content_type + assert_equal 302, @response.status + assert_equal "http://www.example.com/customers", @response.location + end + + def test_using_resource_for_delete_with_xml + Customer.any_instance.stubs(:destroyed?).returns(true) + @request.accept = "application/xml" + delete :using_resource + assert_equal "application/xml", @response.content_type + assert_equal 200, @response.status + assert_equal " ", @response.body + end + + def test_using_resource_with_parent_for_get + @request.accept = "application/xml" + get :using_resource_with_parent + assert_equal "application/xml", @response.content_type + assert_equal 200, @response.status + assert_equal "XML", @response.body + end + + def test_using_resource_with_parent_for_post + @request.accept = "application/xml" + + post :using_resource_with_parent + assert_equal "application/xml", @response.content_type + assert_equal 201, @response.status + assert_equal "XML", @response.body + assert_equal "http://www.example.com/quiz_stores/11/customers/13", @response.location + + errors = { :name => :invalid } + Customer.any_instance.stubs(:errors).returns(errors) + post :using_resource + assert_equal "application/xml", @response.content_type + assert_equal 422, @response.status + assert_equal errors.to_xml, @response.body + assert_nil @response.location end def test_clear_respond_to @@ -628,6 +725,29 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal "XML", @response.body end + def test_no_double_render_is_raised + @request.accept = "text/html" + assert_raise ActionView::MissingTemplate do + get :using_resource + end + end + + def test_using_resource_with_status_and_location + @request.accept = "text/html" + post :using_resource_with_status_and_location + assert @response.redirect? + assert_equal "http://test.host/", @response.location + + @request.accept = "application/xml" + get :using_resource_with_status_and_location + assert_equal 201, @response.status + end + + def test_using_resource_with_responder + get :using_resource_with_responder + assert_equal "Resource name is david", @response.body + end + def test_not_acceptable @request.accept = "application/xml" get :using_defaults @@ -642,14 +762,12 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal 406, @response.status @request.accept = "text/javascript" - get :using_resource + get :default_overwritten 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 @@ -658,7 +776,7 @@ class PostController < AbstractPostController around_filter :with_iphone def index - respond_to # It will use formats declared above + respond_to(:html, :iphone) end protected diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 947ffa9ea6..9546fdb50d 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -458,6 +458,10 @@ class TestController < ActionController::Base head :location => "/foo" end + def head_with_location_object + head :location => Customer.new("david", 1) + end + def head_with_symbolic_status head :status => params[:status].intern end @@ -618,6 +622,7 @@ class TestController < ActionController::Base end private + def determine_layout case action_name when "hello_world", "layout_test", "rendering_without_layout", @@ -1084,6 +1089,18 @@ class RenderTest < ActionController::TestCase assert_response :ok end + def test_head_with_location_object + ActionController::Routing::Routes.draw do |map| + map.resources :customers + map.connect ':controller/:action/:id' + end + + get :head_with_location_object + assert @response.body.blank? + assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"] + assert_response :ok + end + def test_head_with_custom_header get :head_with_custom_header assert @response.body.blank? diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb index 052b4f0b52..139f55d8bd 100644 --- a/actionpack/test/controller/render_xml_test.rb +++ b/actionpack/test/controller/render_xml_test.rb @@ -11,7 +11,7 @@ class TestController < ActionController::Base def render_with_object_location customer = Customer.new("Some guy", 1) - render :xml => "<customer/>", :location => customer_url(customer), :status => :created + render :xml => "<customer/>", :location => customer, :status => :created end def render_with_to_xml @@ -78,4 +78,4 @@ class RenderTest < ActionController::TestCase get :implicit_content_type, :format => 'atom' assert_equal Mime::ATOM, @response.content_type end -end
\ No newline at end of file +end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index fb83dba395..5f9ae6292c 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 require 'abstract_unit' require 'controller/fake_controllers' require 'active_support/dependencies' @@ -1179,7 +1180,6 @@ class LegacyRouteSetTests < Test::Unit::TestCase assert_equal({:controller => "content", :action => 'show_page', :id => 'foo'}, rs.recognize_path("/page/foo")) token = "\321\202\320\265\320\272\321\201\321\202" # 'text' in russian - token.force_encoding("UTF-8") if token.respond_to?(:force_encoding) escaped_token = CGI::escape(token) assert_equal '/page/' + escaped_token, rs.generate(:controller => 'content', :action => 'show_page', :id => token) diff --git a/actionpack/test/fixtures/respond_with/edit.html.erb b/actionpack/test/fixtures/respond_with/edit.html.erb new file mode 100644 index 0000000000..ae82dfa4fc --- /dev/null +++ b/actionpack/test/fixtures/respond_with/edit.html.erb @@ -0,0 +1 @@ +Edit world! diff --git a/actionpack/test/fixtures/respond_with/new.html.erb b/actionpack/test/fixtures/respond_with/new.html.erb new file mode 100644 index 0000000000..96c8f1b88b --- /dev/null +++ b/actionpack/test/fixtures/respond_with/new.html.erb @@ -0,0 +1 @@ +New world! diff --git a/actionpack/test/fixtures/respond_with/using_resource.html.erb b/actionpack/test/fixtures/respond_with/using_resource.html.erb deleted file mode 100644 index 6769dd60bd..0000000000 --- a/actionpack/test/fixtures/respond_with/using_resource.html.erb +++ /dev/null @@ -1 +0,0 @@ -Hello world!
\ No newline at end of file diff --git a/actionpack/test/fixtures/respond_with/using_resource.js.rjs b/actionpack/test/fixtures/respond_with/using_resource.js.rjs new file mode 100644 index 0000000000..737c175a4e --- /dev/null +++ b/actionpack/test/fixtures/respond_with/using_resource.js.rjs @@ -0,0 +1 @@ +page[:body].visual_effect :highlight diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index c6726432ec..0faf8f3f9a 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -4,9 +4,27 @@ class Customer < Struct.new(:name, :id) extend ActiveModel::Naming include ActiveModel::Conversion + undef_method :to_json + def to_param id.to_s end + + def to_xml + "XML" + end + + def to_js + "JS" + end + + def errors + [] + end + + def destroyed? + false + end end class BadCustomer < Customer @@ -24,4 +42,8 @@ module Quiz id.to_s end end + + class Store < Question + end end + diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 57b740032e..85a97d570c 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -88,6 +88,7 @@ class NumberHelperTest < ActionView::TestCase assert_equal("111.00", number_with_precision(111, :precision => 2)) assert_equal("111.235", number_with_precision("111.2346")) assert_equal("31.83", number_with_precision("31.825", :precision => 2)) + assert_equal("3268", number_with_precision((32.675 * 100.00), :precision => 0)) assert_equal("112", number_with_precision(111.50, :precision => 0)) assert_equal("1234567892", number_with_precision(1234567891.50, :precision => 0)) |