aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/examples/very_simple.rb4
-rw-r--r--actionpack/lib/abstract_controller.rb20
-rw-r--r--actionpack/lib/abstract_controller/helpers.rb2
-rw-r--r--actionpack/lib/abstract_controller/layouts.rb24
-rw-r--r--actionpack/lib/abstract_controller/rendering_controller.rb (renamed from actionpack/lib/abstract_controller/renderer.rb)6
-rw-r--r--actionpack/lib/action_controller.rb6
-rw-r--r--actionpack/lib/action_controller/base.rb6
-rw-r--r--actionpack/lib/action_controller/caching/fragments.rb4
-rw-r--r--actionpack/lib/action_controller/legacy/layout.rb2
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb7
-rw-r--r--actionpack/lib/action_controller/metal/layouts.rb2
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb115
-rw-r--r--actionpack/lib/action_controller/metal/render_options.rb10
-rw-r--r--actionpack/lib/action_controller/metal/rendering_controller.rb (renamed from actionpack/lib/action_controller/metal/renderer.rb)7
-rw-r--r--actionpack/lib/action_controller/metal/responder.rb181
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb2
-rw-r--r--actionpack/lib/action_controller/metal/verification.rb4
-rw-r--r--actionpack/lib/action_controller/routing/generation/polymorphic_routes.rb28
-rw-r--r--actionpack/lib/action_view/base.rb2
-rw-r--r--actionpack/lib/action_view/helpers/active_model_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb2
-rw-r--r--actionpack/lib/action_view/paths.rb10
-rw-r--r--actionpack/lib/action_view/render/partials.rb142
-rw-r--r--actionpack/lib/action_view/render/rendering.rb7
-rw-r--r--actionpack/lib/action_view/template/resolver.rb2
-rw-r--r--actionpack/test/abstract_controller/abstract_controller_test.rb10
-rw-r--r--actionpack/test/abstract_controller/helper_test.rb4
-rw-r--r--actionpack/test/abstract_controller/layouts_test.rb2
-rw-r--r--actionpack/test/activerecord/polymorphic_routes_test.rb55
-rw-r--r--actionpack/test/controller/caching_test.rb15
-rw-r--r--actionpack/test/controller/mime_responds_test.rb198
-rw-r--r--actionpack/test/controller/render_test.rb17
-rw-r--r--actionpack/test/controller/render_xml_test.rb4
-rw-r--r--actionpack/test/controller/routing_test.rb2
-rw-r--r--actionpack/test/fixtures/respond_with/edit.html.erb1
-rw-r--r--actionpack/test/fixtures/respond_with/new.html.erb1
-rw-r--r--actionpack/test/fixtures/respond_with/using_resource.html.erb1
-rw-r--r--actionpack/test/fixtures/respond_with/using_resource.js.rjs1
-rw-r--r--actionpack/test/lib/controller/fake_models.rb22
-rw-r--r--actionpack/test/template/number_helper_test.rb1
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))