aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2008-09-03 17:44:58 +0100
committerPratik Naik <pratiknaik@gmail.com>2008-09-03 17:44:58 +0100
commit2933f4481f8b70b3b809fab6e818d80c2af1b919 (patch)
treec83d1308545cc82215b90ab37208cc81b4712276 /actionpack
parent36ee17d458b86c5f3f371810160e8839d318bbf1 (diff)
parent10fe6a6d8940300dd6698ec38e9c9573404e687d (diff)
downloadrails-2933f4481f8b70b3b809fab6e818d80c2af1b919.tar.gz
rails-2933f4481f8b70b3b809fab6e818d80c2af1b919.tar.bz2
rails-2933f4481f8b70b3b809fab6e818d80c2af1b919.zip
Merge commit 'mainstream/master'
Conflicts: actionpack/lib/action_controller/resources.rb
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG24
-rw-r--r--actionpack/lib/action_controller/assertions/selector_assertions.rb86
-rw-r--r--actionpack/lib/action_controller/base.rb96
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb4
-rw-r--r--actionpack/lib/action_controller/caching/sweeping.rb6
-rw-r--r--actionpack/lib/action_controller/cgi_process.rb6
-rw-r--r--actionpack/lib/action_controller/components.rb5
-rw-r--r--actionpack/lib/action_controller/filters.rb8
-rw-r--r--actionpack/lib/action_controller/helpers.rb4
-rw-r--r--actionpack/lib/action_controller/http_authentication.rb2
-rw-r--r--actionpack/lib/action_controller/integration.rb8
-rw-r--r--actionpack/lib/action_controller/layout.rb80
-rw-r--r--actionpack/lib/action_controller/polymorphic_routes.rb6
-rw-r--r--actionpack/lib/action_controller/rescue.rb3
-rw-r--r--actionpack/lib/action_controller/resources.rb94
-rw-r--r--actionpack/lib/action_controller/response.rb2
-rw-r--r--actionpack/lib/action_controller/routing/builder.rb12
-rw-r--r--actionpack/lib/action_controller/routing/optimisations.rb5
-rw-r--r--actionpack/lib/action_controller/routing/route.rb2
-rw-r--r--actionpack/lib/action_controller/routing/route_set.rb6
-rw-r--r--actionpack/lib/action_controller/routing/segments.rb6
-rw-r--r--actionpack/lib/action_controller/session_management.rb4
-rw-r--r--actionpack/lib/action_controller/test_process.rb17
-rw-r--r--actionpack/lib/action_controller/verification.rb4
-rw-r--r--actionpack/lib/action_view/base.rb170
-rw-r--r--actionpack/lib/action_view/helpers/active_record_helper.rb12
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/prototype_helper.rb10
-rw-r--r--actionpack/lib/action_view/helpers/record_tag_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb2
-rw-r--r--actionpack/lib/action_view/partials.rb2
-rw-r--r--actionpack/lib/action_view/renderable.rb8
-rw-r--r--actionpack/lib/action_view/renderable_partial.rb10
-rw-r--r--actionpack/lib/action_view/template_handlers/builder.rb2
-rw-r--r--actionpack/lib/action_view/test_case.rb2
-rw-r--r--actionpack/test/controller/assert_select_test.rb49
-rw-r--r--actionpack/test/controller/base_test.rb8
-rw-r--r--actionpack/test/controller/components_test.rb66
-rw-r--r--actionpack/test/controller/filter_params_test.rb4
-rw-r--r--actionpack/test/controller/filters_test.rb26
-rw-r--r--actionpack/test/controller/integration_test.rb2
-rw-r--r--actionpack/test/controller/layout_test.rb49
-rw-r--r--actionpack/test/controller/new_render_test.rb981
-rw-r--r--actionpack/test/controller/render_test.rb898
-rw-r--r--actionpack/test/controller/resources_test.rb147
-rw-r--r--actionpack/test/controller/routing_test.rb29
-rw-r--r--actionpack/test/template/prototype_helper_test.rb15
-rw-r--r--actionpack/test/template/record_tag_helper_test.rb8
48 files changed, 1533 insertions, 1465 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index f6942b43f1..88af60ed62 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,29 @@
*Edge*
+* Add support for shallow nesting of routes. #838 [S. Brent Faulkner]
+
+ Example :
+
+ map.resources :users, :shallow => true do |user|
+ user.resources :posts
+ end
+
+ - GET /users/1/posts (maps to PostsController#index action as usual)
+ named route "user_posts" is added as usual.
+
+ - GET /posts/2 (maps to PostsController#show action as if it were not nested)
+ Additionally, named route "post" is added too.
+
+* Added button_to_remote helper. #3641 [Donald Piret, Tarmo Tänav]
+
+* Deprecate render_component. Please use render_component plugin from http://github.com/rails/render_component/tree/master [Pratik]
+
+* Routes may be restricted to lists of HTTP methods instead of a single method or :any. #407 [Brennan Dunn, Gaius Centus Novus]
+ map.resource :posts, :collection => { :search => [:get, :post] }
+ map.session 'session', :requirements => { :method => [:get, :post, :delete] }
+
+* Deprecated implicit local assignments when rendering partials [Josh Peek]
+
* Introduce current_cycle helper method to return the current value without bumping the cycle. #417 [Ken Collins]
* Allow polymorphic_url helper to take url options. #880 [Tarmo Tänav]
diff --git a/actionpack/lib/action_controller/assertions/selector_assertions.rb b/actionpack/lib/action_controller/assertions/selector_assertions.rb
index 9114894b1d..bcbb570e4b 100644
--- a/actionpack/lib/action_controller/assertions/selector_assertions.rb
+++ b/actionpack/lib/action_controller/assertions/selector_assertions.rb
@@ -396,54 +396,31 @@ module ActionController
# # The same, but shorter.
# assert_select "ol>li", 4
def assert_select_rjs(*args, &block)
- rjs_type = nil
- arg = args.shift
+ rjs_type = args.first.is_a?(Symbol) ? args.shift : nil
+ id = args.first.is_a?(String) ? args.shift : nil
# If the first argument is a symbol, it's the type of RJS statement we're looking
# for (update, replace, insertion, etc). Otherwise, we're looking for just about
# any RJS statement.
- if arg.is_a?(Symbol)
- rjs_type = arg
-
+ if rjs_type
if rjs_type == :insert
- arg = args.shift
- position = arg
- insertion = "insert_#{arg}".to_sym
- raise ArgumentError, "Unknown RJS insertion type #{arg}" unless RJS_STATEMENTS[insertion]
+ position = args.shift
+ insertion = "insert_#{position}".to_sym
+ raise ArgumentError, "Unknown RJS insertion type #{position}" unless RJS_STATEMENTS[insertion]
statement = "(#{RJS_STATEMENTS[insertion]})"
else
raise ArgumentError, "Unknown RJS statement type #{rjs_type}" unless RJS_STATEMENTS[rjs_type]
statement = "(#{RJS_STATEMENTS[rjs_type]})"
end
- arg = args.shift
else
statement = "#{RJS_STATEMENTS[:any]}"
end
- position ||= Regexp.new(RJS_INSERTIONS.join('|'))
# Next argument we're looking for is the element identifier. If missing, we pick
- # any element.
- if arg.is_a?(String)
- id = Regexp.quote(arg)
- arg = args.shift
- else
- id = "[^\"]*"
- end
-
- pattern =
- case rjs_type
- when :chained_replace, :chained_replace_html
- Regexp.new("\\$\\(\"#{id}\"\\)#{statement}\\(#{RJS_PATTERN_HTML}\\)", Regexp::MULTILINE)
- when :remove, :show, :hide, :toggle
- Regexp.new("#{statement}\\(\"#{id}\"\\)")
- when :replace, :replace_html
- Regexp.new("#{statement}\\(\"#{id}\", #{RJS_PATTERN_HTML}\\)")
- when :insert, :insert_html
- Regexp.new("Element.insert\\(\\\"#{id}\\\", \\{ #{position}: #{RJS_PATTERN_HTML} \\}\\);")
- else
- Regexp.union(Regexp.new("#{statement}\\(\"#{id}\", #{RJS_PATTERN_HTML}\\)"),
- Regexp.new("Element.insert\\(\\\"#{id}\\\", \\{ #{position}: #{RJS_PATTERN_HTML} \\}\\);"))
- end
+ # any element, otherwise we replace it in the statement.
+ pattern = Regexp.new(
+ id ? statement.gsub(RJS_ANY_ID, "\"#{id}\"") : statement
+ )
# Duplicate the body since the next step involves destroying it.
matches = nil
@@ -472,7 +449,13 @@ module ActionController
matches
else
# RJS statement not found.
- flunk args.shift || "No RJS statement that replaces or inserts HTML content."
+ case rjs_type
+ when :remove, :show, :hide, :toggle
+ flunk_message = "No RJS statement that #{rjs_type.to_s}s '#{id}' was rendered."
+ else
+ flunk_message = "No RJS statement that replaces or inserts HTML content."
+ end
+ flunk args.shift || flunk_message
end
end
@@ -582,26 +565,23 @@ module ActionController
protected
unless const_defined?(:RJS_STATEMENTS)
- RJS_STATEMENTS = {
- :replace => /Element\.replace/,
- :replace_html => /Element\.update/,
- :chained_replace => /\.replace/,
- :chained_replace_html => /\.update/,
- :remove => /Element\.remove/,
- :show => /Element\.show/,
- :hide => /Element\.hide/,
- :toggle => /Element\.toggle/
+ RJS_PATTERN_HTML = "\"((\\\\\"|[^\"])*)\""
+ RJS_ANY_ID = "\"([^\"])*\""
+ RJS_STATEMENTS = {
+ :chained_replace => "\\$\\(#{RJS_ANY_ID}\\)\\.replace\\(#{RJS_PATTERN_HTML}\\)",
+ :chained_replace_html => "\\$\\(#{RJS_ANY_ID}\\)\\.update\\(#{RJS_PATTERN_HTML}\\)",
+ :replace_html => "Element\\.update\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)",
+ :replace => "Element\\.replace\\(#{RJS_ANY_ID}, #{RJS_PATTERN_HTML}\\)"
}
- RJS_STATEMENTS[:any] = Regexp.new("(#{RJS_STATEMENTS.values.join('|')})")
- RJS_PATTERN_HTML = /"((\\"|[^"])*)"/
- RJS_INSERTIONS = [:top, :bottom, :before, :after]
+ [:remove, :show, :hide, :toggle].each do |action|
+ RJS_STATEMENTS[action] = "Element\\.#{action}\\(#{RJS_ANY_ID}\\)"
+ end
+ RJS_INSERTIONS = ["top", "bottom", "before", "after"]
RJS_INSERTIONS.each do |insertion|
- RJS_STATEMENTS["insert_#{insertion}".to_sym] = /Element.insert\(\"([^\"]*)\", \{ #{insertion.to_s.downcase}: #{RJS_PATTERN_HTML} \}\);/
+ RJS_STATEMENTS["insert_#{insertion}".to_sym] = "Element.insert\\(#{RJS_ANY_ID}, \\{ #{insertion}: #{RJS_PATTERN_HTML} \\}\\)"
end
- RJS_STATEMENTS[:insert_html] = Regexp.new(RJS_INSERTIONS.collect do |insertion|
- /Element.insert\(\"([^\"]*)\", \{ #{insertion.to_s.downcase}: #{RJS_PATTERN_HTML} \}\);/
- end.join('|'))
- RJS_PATTERN_EVERYTHING = Regexp.new("#{RJS_STATEMENTS[:any]}\\(\"([^\"]*)\", #{RJS_PATTERN_HTML}\\)", Regexp::MULTILINE)
+ RJS_STATEMENTS[:insert_html] = "Element.insert\\(#{RJS_ANY_ID}, \\{ (#{RJS_INSERTIONS.join('|')}): #{RJS_PATTERN_HTML} \\}\\)"
+ RJS_STATEMENTS[:any] = Regexp.new("(#{RJS_STATEMENTS.values.join('|')})")
RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/
end
@@ -615,8 +595,8 @@ module ActionController
root = HTML::Node.new(nil)
while true
- next if body.sub!(RJS_PATTERN_EVERYTHING) do |match|
- html = unescape_rjs($3)
+ next if body.sub!(RJS_STATEMENTS[:any]) do |match|
+ html = unescape_rjs(match)
matches = HTML::Document.new(html).root.children.select { |n| n.tag? }
root.children.concat matches
""
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 55e1d48949..670a049497 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -260,10 +260,11 @@ module ActionController #:nodoc:
include StatusCodes
+ cattr_reader :protected_instance_variables
# Controller specific instance variables which will not be accessible inside views.
- @@protected_view_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller
- @action_name @before_filter_chain_aborted @action_cache_path @_session @_cookies @_headers @_params
- @_flash @_response)
+ @@protected_instance_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller
+ @action_name @before_filter_chain_aborted @action_cache_path @_session @_cookies @_headers @_params
+ @_flash @_response)
# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
# and images to a dedicated asset server away from the main web server. Example:
@@ -393,16 +394,9 @@ module ActionController #:nodoc:
# directive. Values should always be specified as strings.
attr_internal :headers
- # Holds the hash of variables that are passed on to the template class to be made available to the view. This hash
- # is generated by taking a snapshot of all the instance variables in the current scope just before a template is rendered.
- attr_accessor :assigns
-
# Returns the name of the action this controller is processing.
attr_accessor :action_name
- # Templates that are exempt from layouts
- @@exempt_from_layout = Set.new([/\.rjs$/])
-
class << self
# Factory for the standard create, process loop where the controller is discarded after processing.
def process(request, response) #:nodoc:
@@ -520,13 +514,7 @@ module ActionController #:nodoc:
protected :filter_parameters
end
- # Don't render layouts for templates with the given extensions.
- def exempt_from_layout(*extensions)
- regexps = extensions.collect do |extension|
- extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/
- end
- @@exempt_from_layout.merge regexps
- end
+ delegate :exempt_from_layout, :to => 'ActionView::Base'
end
public
@@ -538,7 +526,6 @@ module ActionController #:nodoc:
assign_shortcuts(request, response)
initialize_current_url
assign_names
- forget_variables_added_to_assigns
log_processing
@@ -548,12 +535,16 @@ module ActionController #:nodoc:
@@guard.synchronize { send(method, *arguments) }
end
- response.prepare! unless component_request?
- response
+ send_response
ensure
process_cleanup
end
+ def send_response
+ response.prepare! unless component_request?
+ response
+ end
+
# Returns a URL that has been rewritten according to the options hash and the defined Routes.
# (For doing a complete redirect, use redirect_to).
#
@@ -859,7 +850,7 @@ module ActionController #:nodoc:
raise DoubleRenderError, "Can only render or redirect once per action" if performed?
if options.nil?
- return render_for_file(default_template_name, nil, true)
+ return render(:file => default_template_name, :layout => true)
elsif !extra_options.is_a?(Hash)
raise RenderError, "You called render with invalid options : #{options.inspect}, #{extra_options.inspect}"
else
@@ -870,6 +861,9 @@ module ActionController #:nodoc:
end
end
+ response.layout = layout = pick_layout(options)
+ logger.info("Rendering template within #{layout}") if logger && layout
+
if content_type = options[:content_type]
response.content_type = content_type.to_s
end
@@ -879,26 +873,21 @@ module ActionController #:nodoc:
end
if options.has_key?(:text)
- render_for_text(options[:text], options[:status])
+ text = layout ? @template.render(options.merge(:text => options[:text], :layout => layout)) : options[:text]
+ render_for_text(text, options[:status])
else
if file = options[:file]
- render_for_file(file, options[:status], nil, options[:locals] || {})
+ render_for_file(file, options[:status], layout, options[:locals] || {})
elsif template = options[:template]
- render_for_file(template, options[:status], true, options[:locals] || {})
+ render_for_file(template, options[:status], layout, options[:locals] || {})
elsif inline = options[:inline]
- add_variables_to_assigns
- render_for_text(@template.render(options), options[:status])
+ render_for_text(@template.render(options.merge(:layout => layout)), options[:status])
elsif action_name = options[:action]
- template = default_template_name(action_name.to_s)
- if options[:layout] && !template_exempt_from_layout?(template)
- render_with_a_layout(:file => template, :status => options[:status], :layout => true)
- else
- render_with_no_layout(:file => template, :status => options[:status])
- end
+ render_for_file(default_template_name(action_name.to_s), options[:status], layout)
elsif xml = options[:xml]
response.content_type ||= Mime::XML
@@ -912,12 +901,14 @@ module ActionController #:nodoc:
elsif options[:partial]
options[:partial] = default_template_name if options[:partial] == true
- add_variables_to_assigns
- render_for_text(@template.render(options), options[:status])
+ if layout
+ render_for_text(@template.render(:text => @template.render(options), :layout => layout), options[:status])
+ else
+ render_for_text(@template.render(options), options[:status])
+ end
elsif options[:update]
- add_variables_to_assigns
- @template.send! :evaluate_assigns
+ @template.send(:_evaluate_assigns_and_ivars)
generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block)
response.content_type = Mime::JS
@@ -927,7 +918,7 @@ module ActionController #:nodoc:
render_for_text(nil, options[:status])
else
- render_for_file(default_template_name, options[:status], true)
+ render_for_file(default_template_name, options[:status], layout)
end
end
end
@@ -938,7 +929,6 @@ module ActionController #:nodoc:
render(options, &block)
ensure
erase_render_results
- forget_variables_added_to_assigns
reset_variables_added_to_assigns
end
@@ -1123,10 +1113,9 @@ module ActionController #:nodoc:
private
- def render_for_file(template_path, status = nil, use_full_path = nil, locals = {}) #:nodoc:
- add_variables_to_assigns
+ def render_for_file(template_path, status = nil, layout = nil, locals = {}) #:nodoc:
logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger
- render_for_text(@template.render(:file => template_path, :locals => locals), status)
+ render_for_text @template.render(:file => template_path, :locals => locals, :layout => layout), status
end
def render_for_text(text = nil, status = nil, append_response = false) #:nodoc:
@@ -1161,7 +1150,6 @@ module ActionController #:nodoc:
@_session = @_response.session
@template = @_response.template
- @assigns = @_response.template.assigns
@_headers = @_response.headers
end
@@ -1225,27 +1213,10 @@ module ActionController #:nodoc:
hidden_actions
end
- def add_variables_to_assigns
- unless @variables_added
- add_instance_variables_to_assigns
- @variables_added = true
- end
- end
-
- def forget_variables_added_to_assigns
- @variables_added = nil
- end
-
def reset_variables_added_to_assigns
@template.instance_variable_set("@assigns_added", nil)
end
- def add_instance_variables_to_assigns
- (instance_variable_names - @@protected_view_variables).each do |var|
- @assigns[var[1..-1]] = instance_variable_get(var)
- end
- end
-
def request_origin
# this *needs* to be cached!
# otherwise you'd get different results if calling it more than once
@@ -1261,12 +1232,7 @@ module ActionController #:nodoc:
end
def template_exists?(template_name = default_template_name)
- @template.file_exists?(template_name)
- end
-
- def template_exempt_from_layout?(template_name = default_template_name)
- template_name = @template.pick_template(template_name).to_s if @template
- @@exempt_from_layout.any? { |ext| template_name =~ ext }
+ @template.send(:_pick_template, template_name) ? true : false
rescue ActionView::MissingTemplate
false
end
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index b27ec486c0..7c803a9830 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -90,7 +90,7 @@ module ActionController #:nodoc:
set_content_type!(controller, cache_path.extension)
options = { :text => cache }
options.merge!(:layout => true) if cache_layout?
- controller.send!(:render, options)
+ controller.__send__(:render, options)
false
else
controller.action_cache_path = cache_path
@@ -121,7 +121,7 @@ module ActionController #:nodoc:
end
def content_for_layout(controller)
- controller.response.layout && controller.response.template.instance_variable_get('@content_for_layout')
+ controller.response.layout && controller.response.template.instance_variable_get('@cached_content_for_layout')
end
end
diff --git a/actionpack/lib/action_controller/caching/sweeping.rb b/actionpack/lib/action_controller/caching/sweeping.rb
index 61559e9ec7..c7992d7769 100644
--- a/actionpack/lib/action_controller/caching/sweeping.rb
+++ b/actionpack/lib/action_controller/caching/sweeping.rb
@@ -83,13 +83,13 @@ module ActionController #:nodoc:
controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}"
action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}"
- send!(controller_callback_method_name) if respond_to?(controller_callback_method_name, true)
- send!(action_callback_method_name) if respond_to?(action_callback_method_name, true)
+ __send__(controller_callback_method_name) if respond_to?(controller_callback_method_name, true)
+ __send__(action_callback_method_name) if respond_to?(action_callback_method_name, true)
end
def method_missing(method, *arguments)
return if @controller.nil?
- @controller.send!(method, *arguments)
+ @controller.__send__(method, *arguments)
end
end
end
diff --git a/actionpack/lib/action_controller/cgi_process.rb b/actionpack/lib/action_controller/cgi_process.rb
index 0ca27b30db..d381af1b84 100644
--- a/actionpack/lib/action_controller/cgi_process.rb
+++ b/actionpack/lib/action_controller/cgi_process.rb
@@ -48,7 +48,7 @@ module ActionController #:nodoc:
def initialize(cgi, session_options = {})
@cgi = cgi
@session_options = session_options
- @env = @cgi.send!(:env_table)
+ @env = @cgi.__send__(:env_table)
super()
end
@@ -107,7 +107,7 @@ module ActionController #:nodoc:
end
def method_missing(method_id, *arguments)
- @cgi.send!(method_id, *arguments) rescue super
+ @cgi.__send__(method_id, *arguments) rescue super
end
private
@@ -164,7 +164,7 @@ end_msg
begin
output.write(@cgi.header(@headers))
- if @cgi.send!(:env_table)['REQUEST_METHOD'] == 'HEAD'
+ if @cgi.__send__(:env_table)['REQUEST_METHOD'] == 'HEAD'
return
elsif @body.respond_to?(:call)
# Flush the output now in case the @body Proc uses
diff --git a/actionpack/lib/action_controller/components.rb b/actionpack/lib/action_controller/components.rb
index 8275bd380a..f446b91e7e 100644
--- a/actionpack/lib/action_controller/components.rb
+++ b/actionpack/lib/action_controller/components.rb
@@ -38,6 +38,7 @@ module ActionController #:nodoc:
def self.included(base) #:nodoc:
base.class_eval do
include InstanceMethods
+ include ActiveSupport::Deprecation
extend ClassMethods
helper HelperMethods
@@ -64,7 +65,7 @@ module ActionController #:nodoc:
module HelperMethods
def render_component(options)
- @controller.send!(:render_component_as_string, options)
+ @controller.__send__(:render_component_as_string, options)
end
end
@@ -82,6 +83,7 @@ module ActionController #:nodoc:
render_for_text(component_response(options, true).body, response.headers["Status"])
end
end
+ deprecate :render_component => "Please install render_component plugin from http://github.com/rails/render_component/tree/master"
# Returns the component response as a string
def render_component_as_string(options) #:doc:
@@ -95,6 +97,7 @@ module ActionController #:nodoc:
end
end
end
+ deprecate :render_component_as_string => "Please install render_component plugin from http://github.com/rails/render_component/tree/master"
def flash_with_components(refresh = false) #:nodoc:
if !defined?(@_flash) || refresh
diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb
index 1d7236f18a..9022b8b279 100644
--- a/actionpack/lib/action_controller/filters.rb
+++ b/actionpack/lib/action_controller/filters.rb
@@ -199,8 +199,8 @@ module ActionController #:nodoc:
Proc.new do |controller, action|
method.before(controller)
- if controller.send!(:performed?)
- controller.send!(:halt_filter_chain, method, :rendered_or_redirected)
+ if controller.__send__(:performed?)
+ controller.__send__(:halt_filter_chain, method, :rendered_or_redirected)
else
begin
action.call
@@ -223,8 +223,8 @@ module ActionController #:nodoc:
def call(controller, &block)
super
- if controller.send!(:performed?)
- controller.send!(:halt_filter_chain, method, :rendered_or_redirected)
+ if controller.__send__(:performed?)
+ controller.__send__(:halt_filter_chain, method, :rendered_or_redirected)
end
end
end
diff --git a/actionpack/lib/action_controller/helpers.rb b/actionpack/lib/action_controller/helpers.rb
index ce5e8be54c..9cffa07b26 100644
--- a/actionpack/lib/action_controller/helpers.rb
+++ b/actionpack/lib/action_controller/helpers.rb
@@ -204,8 +204,8 @@ module ActionController #:nodoc:
begin
child.master_helper_module = Module.new
- child.master_helper_module.send! :include, master_helper_module
- child.send! :default_helper_module!
+ child.master_helper_module.__send__ :include, master_helper_module
+ child.__send__ :default_helper_module!
rescue MissingSourceFile => e
raise unless e.is_missing?("helpers/#{child.controller_path}_helper")
end
diff --git a/actionpack/lib/action_controller/http_authentication.rb b/actionpack/lib/action_controller/http_authentication.rb
index 31db012ef2..2ed810db7d 100644
--- a/actionpack/lib/action_controller/http_authentication.rb
+++ b/actionpack/lib/action_controller/http_authentication.rb
@@ -117,7 +117,7 @@ module ActionController
def authentication_request(controller, realm)
controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.gsub(/"/, "")}")
- controller.send! :render, :text => "HTTP Basic: Access denied.\n", :status => :unauthorized
+ controller.__send__ :render, :text => "HTTP Basic: Access denied.\n", :status => :unauthorized
end
end
end
diff --git a/actionpack/lib/action_controller/integration.rb b/actionpack/lib/action_controller/integration.rb
index 198a22e8dc..a98c1af7f9 100644
--- a/actionpack/lib/action_controller/integration.rb
+++ b/actionpack/lib/action_controller/integration.rb
@@ -444,7 +444,7 @@ EOF
reset! unless @integration_session
# reset the html_document variable, but only for new get/post calls
@html_document = nil unless %w(cookies assigns).include?(method)
- returning @integration_session.send!(method, *args) do
+ returning @integration_session.__send__(method, *args) do
copy_session_variables!
end
end
@@ -469,12 +469,12 @@ EOF
self.class.fixture_table_names.each do |table_name|
name = table_name.tr(".", "_")
next unless respond_to?(name)
- extras.send!(:define_method, name) { |*args| delegate.send(name, *args) }
+ extras.__send__(:define_method, name) { |*args| delegate.send(name, *args) }
end
end
# delegate add_assertion to the test case
- extras.send!(:define_method, :add_assertion) { test_result.add_assertion }
+ extras.__send__(:define_method, :add_assertion) { test_result.add_assertion }
session.extend(extras)
session.delegate = self
session.test_result = @_result
@@ -488,7 +488,7 @@ EOF
def copy_session_variables! #:nodoc:
return unless @integration_session
%w(controller response request).each do |var|
- instance_variable_set("@#{var}", @integration_session.send!(var))
+ instance_variable_set("@#{var}", @integration_session.__send__(var))
end
end
diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb
index 8b6febe254..3631ce86af 100644
--- a/actionpack/lib/action_controller/layout.rb
+++ b/actionpack/lib/action_controller/layout.rb
@@ -3,11 +3,6 @@ module ActionController #:nodoc:
def self.included(base)
base.extend(ClassMethods)
base.class_eval do
- # NOTE: Can't use alias_method_chain here because +render_without_layout+ is already
- # defined as a publicly exposed method
- alias_method :render_with_no_layout, :render
- alias_method :render, :render_with_a_layout
-
class << self
alias_method_chain :inherited, :layout
end
@@ -169,17 +164,17 @@ module ActionController #:nodoc:
# performance and have access to them as any normal template would.
def layout(template_name, conditions = {}, auto = false)
add_layout_conditions(conditions)
- write_inheritable_attribute "layout", template_name
- write_inheritable_attribute "auto_layout", auto
+ write_inheritable_attribute(:layout, template_name)
+ write_inheritable_attribute(:auto_layout, auto)
end
def layout_conditions #:nodoc:
- @layout_conditions ||= read_inheritable_attribute("layout_conditions")
+ @layout_conditions ||= read_inheritable_attribute(:layout_conditions)
end
def default_layout(format) #:nodoc:
- layout = read_inheritable_attribute("layout")
- return layout unless read_inheritable_attribute("auto_layout")
+ layout = read_inheritable_attribute(:layout)
+ return layout unless read_inheritable_attribute(:auto_layout)
@default_layout ||= {}
@default_layout[format] ||= default_layout_with_format(format, layout)
@default_layout[format]
@@ -199,7 +194,7 @@ module ActionController #:nodoc:
end
def add_layout_conditions(conditions)
- write_inheritable_hash "layout_conditions", normalize_conditions(conditions)
+ write_inheritable_hash(:layout_conditions, normalize_conditions(conditions))
end
def normalize_conditions(conditions)
@@ -221,10 +216,10 @@ module ActionController #:nodoc:
# object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return
# weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard.
def active_layout(passed_layout = nil)
- layout = passed_layout || self.class.default_layout(response.template.template_format)
+ layout = passed_layout || self.class.default_layout(default_template_format)
active_layout = case layout
when String then layout
- when Symbol then send!(layout)
+ when Symbol then __send__(layout)
when Proc then layout.call(self)
end
@@ -240,51 +235,24 @@ module ActionController #:nodoc:
end
end
- protected
- def render_with_a_layout(options = nil, extra_options = {}, &block) #:nodoc:
- template_with_options = options.is_a?(Hash)
-
- if (layout = pick_layout(template_with_options, options)) && apply_layout?(template_with_options, options)
- options = options.merge :layout => false if template_with_options
- logger.info("Rendering template within #{layout}") if logger
-
- content_for_layout = render_with_no_layout(options, extra_options, &block)
- erase_render_results
- add_variables_to_assigns
- @template.instance_variable_set("@content_for_layout", content_for_layout)
- response.layout = layout
- status = template_with_options ? options[:status] : nil
- render_for_text(@template.render(layout), status)
- else
- render_with_no_layout(options, extra_options, &block)
- end
- end
-
-
private
- def apply_layout?(template_with_options, options)
- return false if options == :update
- template_with_options ? candidate_for_layout?(options) : !template_exempt_from_layout?
- end
-
def candidate_for_layout?(options)
- (options.has_key?(:layout) && options[:layout] != false) ||
- options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing).compact.empty? &&
- !template_exempt_from_layout?(options[:template] || default_template_name(options[:action]))
+ options.values_at(:text, :xml, :json, :file, :inline, :partial, :nothing, :update).compact.empty? &&
+ !@template.__send__(:_exempt_from_layout?, options[:template] || default_template_name(options[:action]))
end
- def pick_layout(template_with_options, options)
- if template_with_options
- case layout = options[:layout]
- when FalseClass
- nil
- when NilClass, TrueClass
- active_layout if action_has_layout?
- else
- active_layout(layout)
+ def pick_layout(options)
+ if options.has_key?(:layout)
+ case layout = options.delete(:layout)
+ when FalseClass
+ nil
+ when NilClass, TrueClass
+ active_layout if action_has_layout? && !@template.__send__(:_exempt_from_layout?, default_template_name)
+ else
+ active_layout(layout)
end
else
- active_layout if action_has_layout?
+ active_layout if action_has_layout? && candidate_for_layout?(options)
end
end
@@ -304,7 +272,13 @@ module ActionController #:nodoc:
end
def layout_directory?(layout_name)
- @template.file_exists?("#{File.join('layouts', layout_name)}.#{@template.template_format}")
+ @template.__send__(:_pick_template, "#{File.join('layouts', layout_name)}.#{@template.template_format}") ? true : false
+ rescue ActionView::MissingTemplate
+ false
+ end
+
+ def default_template_format
+ response.template.template_format
end
end
end
diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/polymorphic_routes.rb
index 30564c7bb3..cc228c4230 100644
--- a/actionpack/lib/action_controller/polymorphic_routes.rb
+++ b/actionpack/lib/action_controller/polymorphic_routes.rb
@@ -108,7 +108,7 @@ module ActionController
args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options
end
- send!(named_route, *args)
+ __send__(named_route, *args)
end
# Returns the path component of a URL for the given record. It uses
@@ -149,7 +149,7 @@ module ActionController
if parent.is_a?(Symbol) || parent.is_a?(String)
string << "#{parent}_"
else
- string << "#{RecordIdentifier.send!("singular_class_name", parent)}_"
+ string << "#{RecordIdentifier.__send__("singular_class_name", parent)}_"
end
end
end
@@ -157,7 +157,7 @@ module ActionController
if record.is_a?(Symbol) || record.is_a?(String)
route << "#{record}_"
else
- route << "#{RecordIdentifier.send!("#{inflection}_class_name", record)}_"
+ route << "#{RecordIdentifier.__send__("#{inflection}_class_name", record)}_"
end
action_prefix(options) + namespace + route + routing_type(options).to_s
diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb
index b12d50c773..83c4218af4 100644
--- a/actionpack/lib/action_controller/rescue.rb
+++ b/actionpack/lib/action_controller/rescue.rb
@@ -177,11 +177,8 @@ module ActionController #:nodoc:
# Render detailed diagnostics for unhandled exceptions rescued from
# a controller action.
def rescue_action_locally(exception)
- add_variables_to_assigns
@template.instance_variable_set("@exception", exception)
@template.instance_variable_set("@rescues_path", File.dirname(rescues_path("stub")))
- @template.send!(:assign_variables_from_controller)
-
@template.instance_variable_set("@contents", @template.render(:file => template_path_for_local_rescue(exception)))
response.content_type = Mime::HTML
diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb
index becf6b0b63..872b0dab3d 100644
--- a/actionpack/lib/action_controller/resources.rb
+++ b/actionpack/lib/action_controller/resources.rb
@@ -85,16 +85,24 @@ module ActionController
@new_path ||= "#{path}/#{new_action}"
end
+ def shallow_path_prefix
+ @shallow_path_prefix ||= "#{path_prefix unless @options[:shallow]}"
+ end
+
def member_path
- @member_path ||= "#{path}/:id"
+ @member_path ||= "#{shallow_path_prefix}/#{path_segment}/:id"
end
def nesting_path_prefix
- @nesting_path_prefix ||= "#{path}/:#{singular}_id"
+ @nesting_path_prefix ||= "#{shallow_path_prefix}/#{path_segment}/:#{singular}_id"
+ end
+
+ def shallow_name_prefix
+ @shallow_name_prefix ||= "#{name_prefix unless @options[:shallow]}"
end
def nesting_name_prefix
- "#{name_prefix}#{singular}_"
+ "#{shallow_name_prefix}#{singular}_"
end
def action_separator
@@ -141,6 +149,8 @@ module ActionController
super
end
+ alias_method :shallow_path_prefix, :path_prefix
+ alias_method :shallow_name_prefix, :name_prefix
alias_method :member_path, :path
alias_method :nesting_path_prefix, :path
end
@@ -238,8 +248,9 @@ module ActionController
#
# The +resources+ method accepts the following options to customize the resulting routes:
# * <tt>:collection</tt> - Add named routes for other actions that operate on the collection.
- # Takes a hash of <tt>#{action} => #{method}</tt>, where method is <tt>:get</tt>/<tt>:post</tt>/<tt>:put</tt>/<tt>:delete</tt>
- # or <tt>:any</tt> if the method does not matter. These routes map to a URL like /messages/rss, with a route of +rss_messages_url+.
+ # Takes a hash of <tt>#{action} => #{method}</tt>, where method is <tt>:get</tt>/<tt>:post</tt>/<tt>:put</tt>/<tt>:delete</tt>,
+ # an array of any of the previous, or <tt>:any</tt> if the method does not matter.
+ # These routes map to a URL like /messages/rss, with a route of +rss_messages_url+.
# * <tt>:member</tt> - Same as <tt>:collection</tt>, but for actions that operate on a specific member.
# * <tt>:new</tt> - Same as <tt>:collection</tt>, but for actions that operate on the new \resource action.
# * <tt>:controller</tt> - Specify the controller name for the routes.
@@ -317,7 +328,32 @@ module ActionController
# comments_url(@article)
# comment_url(@article, @comment)
#
- # If <tt>map.resources</tt> is called with multiple \resources, they all get the same options applied.
+ # * <tt>:shallow</tt> - If true, paths for nested resources which reference a specific member
+ # (ie. those with an :id parameter) will not use the parent path prefix or name prefix.
+ #
+ # The <tt>:shallow</tt> option is inherited by any nested resource(s).
+ #
+ # For example, 'users', 'posts' and 'comments' all use shallow paths with the following nested resources:
+ #
+ # map.resources :users, :shallow => true do |user|
+ # user.resources :posts do |post|
+ # post.resources :comments
+ # end
+ # end
+ # # --> GET /users/1/posts (maps to the PostsController#index action as usual)
+ # # also adds the usual named route called "user_posts"
+ # # --> GET /posts/2 (maps to the PostsController#show action as if it were not nested)
+ # # also adds the named route called "post"
+ # # --> GET /posts/2/comments (maps to the CommentsController#index action)
+ # # also adds the named route called "post_comments"
+ # # --> GET /comments/2 (maps to the CommentsController#show action as if it were not nested)
+ # # also adds the named route called "comment"
+ #
+ # You may also use <tt>:shallow</tt> in combination with the +has_one+ and +has_many+ shorthand notations like:
+ #
+ # map.resources :users, :has_many => { :posts => :comments }, :shallow => true
+ #
+ # If <tt>map.resources</tt> is called with multiple resources, they all get the same options applied.
#
# Examples:
#
@@ -442,7 +478,7 @@ module ActionController
map_associations(resource, options)
if block_given?
- with_options(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], &block)
+ with_options(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], :shallow => options[:shallow], &block)
end
end
end
@@ -459,29 +495,45 @@ module ActionController
map_associations(resource, options)
if block_given?
- with_options(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], &block)
+ with_options(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], :shallow => options[:shallow], &block)
end
end
end
def map_associations(resource, options)
+ map_has_many_associations(resource, options.delete(:has_many), options) if options[:has_many]
+
path_prefix = "#{options.delete(:path_prefix)}#{resource.nesting_path_prefix}"
name_prefix = "#{options.delete(:name_prefix)}#{resource.nesting_name_prefix}"
- Array(options[:has_many]).each do |association|
- resources(association, :path_prefix => path_prefix, :name_prefix => name_prefix, :namespace => options[:namespace])
+ Array(options[:has_one]).each do |association|
+ resource(association, :path_prefix => path_prefix, :name_prefix => name_prefix, :namespace => options[:namespace], :shallow => options[:shallow])
end
+ end
- Array(options[:has_one]).each do |association|
- resource(association, :path_prefix => path_prefix, :name_prefix => name_prefix, :namespace => options[:namespace])
+ def map_has_many_associations(resource, associations, options)
+ case associations
+ when Hash
+ associations.each do |association,has_many|
+ map_has_many_associations(resource, association, options.merge(:has_many => has_many))
+ end
+ when Array
+ associations.each do |association|
+ map_has_many_associations(resource, association, options)
+ end
+ when Symbol, String
+ resources(associations, :path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], :shallow => options[:shallow], :has_many => options[:has_many])
+ else
end
end
def map_collection_actions(map, resource)
resource.collection_methods.each do |method, actions|
actions.each do |action|
- action_options = action_options_for(action, resource, method)
- map_named_routes(map, "#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}", action_options)
+ [method].flatten.each do |m|
+ action_options = action_options_for(action, resource, m)
+ map_named_routes(map, "#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}", action_options)
+ end
end
end
end
@@ -521,17 +573,19 @@ module ActionController
def map_member_actions(map, resource)
resource.member_methods.each do |method, actions|
actions.each do |action|
- action_options = action_options_for(action, resource, method)
+ [method].flatten.each do |m|
+ action_options = action_options_for(action, resource, m)
- action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash)
- action_path ||= Base.resources_path_names[action] || action
+ action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash)
+ action_path ||= Base.resources_path_names[action] || action
- map_named_routes(map, "#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action_path}", action_options)
+ map_named_routes(map, "#{action}_#{resource.shallow_name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action_path}", action_options)
+ end
end
end
show_action_options = action_options_for("show", resource)
- map_named_routes(map, "#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options)
+ map_named_routes(map, "#{resource.shallow_name_prefix}#{resource.singular}", resource.member_path, show_action_options)
update_action_options = action_options_for("update", resource)
map_unnamed_routes(map, resource.member_path, update_action_options)
@@ -574,4 +628,4 @@ end
class ActionController::Routing::RouteSet::Mapper
include ActionController::Resources
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/response.rb b/actionpack/lib/action_controller/response.rb
index 5dac4128bb..54a99996ef 100644
--- a/actionpack/lib/action_controller/response.rb
+++ b/actionpack/lib/action_controller/response.rb
@@ -129,8 +129,8 @@ module ActionController # :nodoc:
def prepare!
assign_default_content_type_and_charset!
- set_content_length!
handle_conditional_get!
+ set_content_length!
convert_content_type!
end
diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb
index 03427e41de..5704d9d01a 100644
--- a/actionpack/lib/action_controller/routing/builder.rb
+++ b/actionpack/lib/action_controller/routing/builder.rb
@@ -187,12 +187,14 @@ module ActionController
private
def validate_route_conditions(conditions)
if method = conditions[:method]
- if method == :head
- raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
- end
+ [method].flatten.each do |m|
+ if m == :head
+ raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
+ end
- unless HTTP_METHODS.include?(method.to_sym)
- raise ArgumentError, "Invalid HTTP method specified in route conditions: #{conditions.inspect}"
+ unless HTTP_METHODS.include?(m.to_sym)
+ raise ArgumentError, "Invalid HTTP method specified in route conditions: #{conditions.inspect}"
+ end
end
end
end
diff --git a/actionpack/lib/action_controller/routing/optimisations.rb b/actionpack/lib/action_controller/routing/optimisations.rb
index 0fe836606c..894d4109e4 100644
--- a/actionpack/lib/action_controller/routing/optimisations.rb
+++ b/actionpack/lib/action_controller/routing/optimisations.rb
@@ -103,9 +103,10 @@ module ActionController
end
# This case uses almost the same code as positional arguments,
- # but add an args.last.to_query on the end
+ # but add a question mark and args.last.to_query on the end,
+ # unless the last arg is empty
def generation_code
- super.insert(-2, '?#{args.last.to_query}')
+ super.insert(-2, '#{\'?\' + args.last.to_query unless args.last.empty?}')
end
# To avoid generating "http://localhost/?host=foo.example.com" we
diff --git a/actionpack/lib/action_controller/routing/route.rb b/actionpack/lib/action_controller/routing/route.rb
index 2106ac09e0..3b2cb28545 100644
--- a/actionpack/lib/action_controller/routing/route.rb
+++ b/actionpack/lib/action_controller/routing/route.rb
@@ -201,7 +201,7 @@ module ActionController
# recognition, not generation.
def recognition_conditions
result = ["(match = #{Regexp.new(recognition_pattern).inspect}.match(path))"]
- result << "conditions[:method] === env[:method]" if conditions[:method]
+ result << "[conditions[:method]].flatten.include?(env[:method])" if conditions[:method]
result
end
diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb
index 8dfc22f94f..9d48f289db 100644
--- a/actionpack/lib/action_controller/routing/route_set.rb
+++ b/actionpack/lib/action_controller/routing/route_set.rb
@@ -115,7 +115,7 @@ module ActionController
def install(destinations = [ActionController::Base, ActionView::Base], regenerate = false)
reset! if regenerate
Array(destinations).each do |dest|
- dest.send! :include, @module
+ dest.__send__(:include, @module)
end
end
@@ -353,7 +353,7 @@ module ActionController
if generate_all
# Used by caching to expire all paths for a resource
return routes.collect do |route|
- route.send!(method, options, merged, expire_on)
+ route.__send__(method, options, merged, expire_on)
end.compact
end
@@ -361,7 +361,7 @@ module ActionController
routes = routes_by_controller[controller][action][options.keys.sort_by { |x| x.object_id }]
routes.each do |route|
- results = route.send!(method, options, merged, expire_on)
+ results = route.__send__(method, options, merged, expire_on)
return results if results && (!results.is_a?(Array) || results.first)
end
end
diff --git a/actionpack/lib/action_controller/routing/segments.rb b/actionpack/lib/action_controller/routing/segments.rb
index 9d4b740a44..e5f174ae2c 100644
--- a/actionpack/lib/action_controller/routing/segments.rb
+++ b/actionpack/lib/action_controller/routing/segments.rb
@@ -160,7 +160,7 @@ module ActionController
s << "\n#{expiry_statement}"
end
- def interpolation_chunk(value_code = "#{local_name}")
+ def interpolation_chunk(value_code = local_name)
"\#{URI.escape(#{value_code}.to_s, ActionController::Routing::Segment::UNSAFE_PCHAR)}"
end
@@ -231,7 +231,7 @@ module ActionController
end
# Don't URI.escape the controller name since it may contain slashes.
- def interpolation_chunk(value_code = "#{local_name}")
+ def interpolation_chunk(value_code = local_name)
"\#{#{value_code}.to_s}"
end
@@ -251,7 +251,7 @@ module ActionController
end
class PathSegment < DynamicSegment #:nodoc:
- def interpolation_chunk(value_code = "#{local_name}")
+ def interpolation_chunk(value_code = local_name)
"\#{#{value_code}}"
end
diff --git a/actionpack/lib/action_controller/session_management.rb b/actionpack/lib/action_controller/session_management.rb
index 80a3ddd2c5..f5a1155a46 100644
--- a/actionpack/lib/action_controller/session_management.rb
+++ b/actionpack/lib/action_controller/session_management.rb
@@ -86,14 +86,14 @@ module ActionController #:nodoc:
raise ArgumentError, "only one of either :only or :except are allowed"
end
- write_inheritable_array("session_options", [options])
+ write_inheritable_array(:session_options, [options])
end
# So we can declare session options in the Rails initializer.
alias_method :session=, :session
def cached_session_options #:nodoc:
- @session_options ||= read_inheritable_attribute("session_options") || []
+ @session_options ||= read_inheritable_attribute(:session_options) || []
end
def session_options_for(request, action) #:nodoc:
diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb
index a11fa7cd10..cde1f2052b 100644
--- a/actionpack/lib/action_controller/test_process.rb
+++ b/actionpack/lib/action_controller/test_process.rb
@@ -3,6 +3,8 @@ require 'action_controller/test_case'
module ActionController #:nodoc:
class Base
+ attr_reader :assigns
+
# Process a test request called with a TestRequest object.
def self.process_test(request)
new.process_test(request)
@@ -14,7 +16,12 @@ module ActionController #:nodoc:
def process_with_test(*args)
returning process_without_test(*args) do
- add_variables_to_assigns
+ @assigns = {}
+ (instance_variable_names - @@protected_instance_variables).each do |var|
+ value = instance_variable_get(var)
+ @assigns[var[1..-1]] = value
+ response.template.assigns[var[1..-1]] = value if response
+ end
end
end
@@ -211,7 +218,7 @@ module ActionController #:nodoc:
# Returns the template of the file which was used to
# render this response (or nil)
def rendered_template
- template._first_render
+ template.send(:_first_render)
end
# A shortcut to the flash. Returns an empty hash if no session flash exists.
@@ -350,7 +357,7 @@ module ActionController #:nodoc:
alias local_path path
def method_missing(method_name, *args, &block) #:nodoc:
- @tempfile.send!(method_name, *args, &block)
+ @tempfile.__send__(method_name, *args, &block)
end
end
@@ -396,7 +403,7 @@ module ActionController #:nodoc:
def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
@request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
@request.env['HTTP_ACCEPT'] = 'text/javascript, text/html, application/xml, text/xml, */*'
- returning send!(request_method, action, parameters, session, flash) do
+ returning __send__(request_method, action, parameters, session, flash) do
@request.env.delete 'HTTP_X_REQUESTED_WITH'
@request.env.delete 'HTTP_ACCEPT'
end
@@ -429,7 +436,7 @@ module ActionController #:nodoc:
def build_request_uri(action, parameters)
unless @request.env['REQUEST_URI']
- options = @controller.send!(:rewrite_options, parameters)
+ options = @controller.__send__(:rewrite_options, parameters)
options.update(:only_path => true, :action => action)
url = ActionController::UrlRewriter.new(@request, parameters)
diff --git a/actionpack/lib/action_controller/verification.rb b/actionpack/lib/action_controller/verification.rb
index 35b12a7f13..7bf09ba6ea 100644
--- a/actionpack/lib/action_controller/verification.rb
+++ b/actionpack/lib/action_controller/verification.rb
@@ -80,7 +80,7 @@ module ActionController #:nodoc:
# array (may also be a single value).
def verify(options={})
before_filter :only => options[:only], :except => options[:except] do |c|
- c.send! :verify_action, options
+ c.__send__ :verify_action, options
end
end
end
@@ -116,7 +116,7 @@ module ActionController #:nodoc:
end
def apply_redirect_to(redirect_to_option) # :nodoc:
- (redirect_to_option.is_a?(Symbol) && redirect_to_option != :back) ? self.send!(redirect_to_option) : redirect_to_option
+ (redirect_to_option.is_a?(Symbol) && redirect_to_option != :back) ? self.__send__(redirect_to_option) : redirect_to_option
end
def apply_remaining_actions(options) # :nodoc:
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index c65048bfa0..6c4da9067d 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -162,7 +162,6 @@ module ActionView #:nodoc:
attr_accessor :base_path, :assigns, :template_extension
attr_accessor :controller
- attr_accessor :_first_render, :_last_render
attr_writer :template_format
@@ -185,6 +184,17 @@ module ActionView #:nodoc:
"deprecated and has no effect. Please remove it from your config files.", caller)
end
+ # Templates that are exempt from layouts
+ @@exempt_from_layout = Set.new([/\.rjs$/])
+
+ # Don't render layouts for templates with the given extensions.
+ def self.exempt_from_layout(*extensions)
+ regexps = extensions.collect do |extension|
+ extension.is_a?(Regexp) ? extension : /\.#{Regexp.escape(extension.to_s)}$/
+ end
+ @@exempt_from_layout.merge(regexps)
+ end
+
# Specify whether RJS responses should be wrapped in a try/catch block
# that alert()s the caught exception (and then re-raises it).
@@debug_rjs = false
@@ -246,33 +256,20 @@ module ActionView #:nodoc:
update_page(&block)
elsif options.is_a?(Hash)
options = options.reverse_merge(:locals => {})
-
- if partial_layout = options.delete(:layout)
- if block_given?
- begin
- @_proc_for_layout = block
- concat(render(options.merge(:partial => partial_layout)))
- ensure
- @_proc_for_layout = nil
- end
- else
- begin
- original_content_for_layout, @content_for_layout = @content_for_layout, render(options)
- render(options.merge(:partial => partial_layout))
- ensure
- @content_for_layout = original_content_for_layout
- end
- end
+ if options[:layout]
+ _render_with_layout(options, local_assigns, &block)
elsif options[:file]
if options[:use_full_path]
ActiveSupport::Deprecation.warn("use_full_path option has been deprecated and has no affect.", caller)
end
- pick_template(options[:file]).render_template(self, options[:locals])
+ _pick_template(options[:file]).render_template(self, options[:locals])
elsif options[:partial]
render_partial(options)
elsif options[:inline]
InlineTemplate.new(options[:inline], options[:type]).render(self, options[:locals])
+ elsif options[:text]
+ options[:text]
end
end
end
@@ -290,74 +287,95 @@ module ActionView #:nodoc:
end
end
- def file_exists?(template_path)
- pick_template(template_path) ? true : false
- rescue MissingTemplate
- false
- end
+ private
+ attr_accessor :_first_render, :_last_render
- # Gets the extension for an existing template with the given template_path.
- # Returns the format with the extension if that template exists.
- #
- # pick_template('users/show')
- # # => 'users/show.html.erb'
- #
- # pick_template('users/legacy')
- # # => 'users/legacy.rhtml'
- #
- def pick_template(template_path)
- return template_path if template_path.respond_to?(:render)
-
- path = template_path.sub(/^\//, '')
- if m = path.match(/(.*)\.(\w+)$/)
- template_file_name, template_file_extension = m[1], m[2]
- else
- template_file_name = path
- end
+ # Evaluate the local assigns and pushes them to the view.
+ def _evaluate_assigns_and_ivars #:nodoc:
+ unless @assigns_added
+ @assigns.each { |key, value| instance_variable_set("@#{key}", value) }
- # OPTIMIZE: Checks to lookup template in view path
- if template = self.view_paths["#{template_file_name}.#{template_format}"]
- template
- elsif template = self.view_paths[template_file_name]
- template
- elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.format_and_extension}"]
- template
- elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"]
- @template_format = :html
- template
- else
- template = Template.new(template_path, view_paths)
-
- if self.class.warn_cache_misses && logger
- logger.debug "[PERFORMANCE] Rendering a template that was " +
- "not found in view path. Templates outside the view path are " +
- "not cached and result in expensive disk operations. Move this " +
- "file into #{view_paths.join(':')} or add the folder to your " +
- "view path list"
+ if @controller
+ variables = @controller.instance_variables
+ variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
+ variables.each {|name| instance_variable_set(name, @controller.instance_variable_get(name)) }
+ end
+
+ @assigns_added = true
end
+ end
- template
+ def _set_controller_content_type(content_type) #:nodoc:
+ if controller.respond_to?(:response)
+ controller.response.content_type ||= content_type
+ end
end
- end
- memoize :pick_template
- private
- # Evaluate the local assigns and pushes them to the view.
- def evaluate_assigns
- unless @assigns_added
- assign_variables_from_controller
- @assigns_added = true
+ def _pick_template(template_path)
+ return template_path if template_path.respond_to?(:render)
+
+ path = template_path.sub(/^\//, '')
+ if m = path.match(/(.*)\.(\w+)$/)
+ template_file_name, template_file_extension = m[1], m[2]
+ else
+ template_file_name = path
+ end
+
+ # OPTIMIZE: Checks to lookup template in view path
+ if template = self.view_paths["#{template_file_name}.#{template_format}"]
+ template
+ elsif template = self.view_paths[template_file_name]
+ template
+ elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.format_and_extension}"]
+ template
+ elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"]
+ @template_format = :html
+ template
+ else
+ template = Template.new(template_path, view_paths)
+
+ if self.class.warn_cache_misses && logger
+ logger.debug "[PERFORMANCE] Rendering a template that was " +
+ "not found in view path. Templates outside the view path are " +
+ "not cached and result in expensive disk operations. Move this " +
+ "file into #{view_paths.join(':')} or add the folder to your " +
+ "view path list"
+ end
+
+ template
end
end
+ memoize :_pick_template
- # Assigns instance variables from the controller to the view.
- def assign_variables_from_controller
- @assigns.each { |key, value| instance_variable_set("@#{key}", value) }
+ def _exempt_from_layout?(template_path) #:nodoc:
+ template = _pick_template(template_path).to_s
+ @@exempt_from_layout.any? { |ext| template =~ ext }
+ rescue ActionView::MissingTemplate
+ return false
end
- def set_controller_content_type(content_type)
- if controller.respond_to?(:response)
- controller.response.content_type ||= content_type
+ def _render_with_layout(options, local_assigns, &block) #:nodoc:
+ partial_layout = options.delete(:layout)
+
+ if block_given?
+ begin
+ @_proc_for_layout = block
+ concat(render(options.merge(:partial => partial_layout)))
+ ensure
+ @_proc_for_layout = nil
+ end
+ else
+ begin
+ original_content_for_layout, @content_for_layout = @content_for_layout, render(options)
+ if (options[:inline] || options[:file] || options[:text])
+ @cached_content_for_layout = @content_for_layout
+ render(:file => partial_layout, :locals => local_assigns)
+ else
+ render(options.merge(:partial => partial_layout))
+ end
+ ensure
+ @content_for_layout = original_content_for_layout
+ end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index c339e10701..8b56d241ae 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -246,7 +246,7 @@ module ActionView
alias_method :tag_without_error_wrapping, :tag
def tag(name, options)
- if object.respond_to?("errors") && object.errors.respond_to?("on")
+ if object.respond_to?(:errors) && object.errors.respond_to?(:on)
error_wrapping(tag_without_error_wrapping(name, options), object.errors.on(@method_name))
else
tag_without_error_wrapping(name, options)
@@ -255,7 +255,7 @@ module ActionView
alias_method :content_tag_without_error_wrapping, :content_tag
def content_tag(name, value, options)
- if object.respond_to?("errors") && object.errors.respond_to?("on")
+ if object.respond_to?(:errors) && object.errors.respond_to?(:on)
error_wrapping(content_tag_without_error_wrapping(name, value, options), object.errors.on(@method_name))
else
content_tag_without_error_wrapping(name, value, options)
@@ -264,7 +264,7 @@ module ActionView
alias_method :to_date_select_tag_without_error_wrapping, :to_date_select_tag
def to_date_select_tag(options = {}, html_options = {})
- if object.respond_to?("errors") && object.errors.respond_to?("on")
+ if object.respond_to?(:errors) && object.errors.respond_to?(:on)
error_wrapping(to_date_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
else
to_date_select_tag_without_error_wrapping(options, html_options)
@@ -273,7 +273,7 @@ module ActionView
alias_method :to_datetime_select_tag_without_error_wrapping, :to_datetime_select_tag
def to_datetime_select_tag(options = {}, html_options = {})
- if object.respond_to?("errors") && object.errors.respond_to?("on")
+ if object.respond_to?(:errors) && object.errors.respond_to?(:on)
error_wrapping(to_datetime_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
else
to_datetime_select_tag_without_error_wrapping(options, html_options)
@@ -282,7 +282,7 @@ module ActionView
alias_method :to_time_select_tag_without_error_wrapping, :to_time_select_tag
def to_time_select_tag(options = {}, html_options = {})
- if object.respond_to?("errors") && object.errors.respond_to?("on")
+ if object.respond_to?(:errors) && object.errors.respond_to?(:on)
error_wrapping(to_time_select_tag_without_error_wrapping(options, html_options), object.errors.on(@method_name))
else
to_time_select_tag_without_error_wrapping(options, html_options)
@@ -298,7 +298,7 @@ module ActionView
end
def column_type
- object.send("column_for_attribute", @method_name).type
+ object.send(:column_for_attribute, @method_name).type
end
end
end
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 623ed1e8df..ed33f082b9 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -104,7 +104,7 @@ module ActionView
ASSETS_DIR = defined?(Rails.public_path) ? Rails.public_path : "public"
JAVASCRIPTS_DIR = "#{ASSETS_DIR}/javascripts"
STYLESHEETS_DIR = "#{ASSETS_DIR}/stylesheets"
- JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls'].map(&:to_s).freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
+ JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
# Returns a link tag that browsers and news readers can use to auto-detect
# an RSS or ATOM feed. The +type+ can either be <tt>:rss</tt> (default) or
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index e452b04b31..ff41a6d417 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -255,6 +255,14 @@ module ActionView
link_to_function(name, remote_function(options), html_options || options.delete(:html))
end
+ # Creates a button with an onclick event which calls a remote action
+ # via XMLHttpRequest
+ # The options for specifying the target with :url
+ # and defining callbacks is the same as link_to_remote.
+ def button_to_remote(name, options = {}, html_options = {})
+ button_to_function(name, remote_function(options), html_options)
+ end
+
# Periodically calls the specified url (<tt>options[:url]</tt>) every
# <tt>options[:frequency]</tt> seconds (default is 10). Usually used to
# update a specified div (<tt>options[:update]</tt>) with the results
@@ -1052,7 +1060,7 @@ module ActionView
js_options['asynchronous'] = options[:type] != :synchronous
js_options['method'] = method_option_to_s(options[:method]) if options[:method]
- js_options['insertion'] = options[:position].to_s.downcase if options[:position]
+ js_options['insertion'] = "'#{options[:position].to_s.downcase}'" if options[:position]
js_options['evalScripts'] = options[:script].nil? || options[:script]
if options[:form]
diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb
index 9bb235175e..0cdb70e217 100644
--- a/actionpack/lib/action_view/helpers/record_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb
@@ -49,9 +49,9 @@ module ActionView
#
def content_tag_for(tag_name, record, *args, &block)
prefix = args.first.is_a?(Hash) ? nil : args.shift
- options = args.first.is_a?(Hash) ? args.shift : {}
- concat content_tag(tag_name, capture(&block),
- options.merge({ :class => "#{dom_class(record)} #{options[:class]}".strip, :id => dom_id(record, prefix) }))
+ options = args.extract_options!
+ options.merge!({ :class => "#{dom_class(record)} #{options[:class]}".strip, :id => dom_id(record, prefix) })
+ content_tag(tag_name, options, &block)
end
end
end
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index ff6e588f62..ab1fdc80bc 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -298,7 +298,7 @@ module ActionView
""
else
textilized = RedCloth.new(text, [ :hard_breaks ])
- textilized.hard_breaks = true if textilized.respond_to?("hard_breaks=")
+ textilized.hard_breaks = true if textilized.respond_to?(:hard_breaks=)
textilized.to_html
end
end
diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb
index 443c49b870..373bb92dc4 100644
--- a/actionpack/lib/action_view/partials.rb
+++ b/actionpack/lib/action_view/partials.rb
@@ -196,7 +196,7 @@ module ActionView
path = "_#{partial_path}"
end
- pick_template(path)
+ _pick_template(path)
end
memoize :_pick_partial_template
end
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index fa45edd436..d960335220 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -26,11 +26,11 @@ module ActionView
def render(view, local_assigns = {})
compile(local_assigns)
- view._first_render ||= self
- view._last_render = self
+ view.send(:_first_render=, self) unless view.send(:_first_render)
+ view.send(:_last_render=, self)
- view.send(:evaluate_assigns)
- view.send(:set_controller_content_type, mime_type) if respond_to?(:mime_type)
+ view.send(:_evaluate_assigns_and_ivars)
+ view.send(:_set_controller_content_type, mime_type) if respond_to?(:mime_type)
view.send(method_name(local_assigns), local_assigns) do |*names|
if proc = view.instance_variable_get("@_proc_for_layout")
diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb
index 5203e57ead..123a9aebbc 100644
--- a/actionpack/lib/action_view/renderable_partial.rb
+++ b/actionpack/lib/action_view/renderable_partial.rb
@@ -27,8 +27,14 @@ module ActionView
def render_partial(view, object = nil, local_assigns = {}, as = nil)
object ||= local_assigns[:object] ||
- local_assigns[variable_name] ||
- view.controller.instance_variable_get("@#{variable_name}") if view.respond_to?(:controller)
+ local_assigns[variable_name]
+
+ if view.respond_to?(:controller)
+ object ||= ActiveSupport::Deprecation::DeprecatedObjectProxy.new(
+ view.controller.instance_variable_get("@#{variable_name}"),
+ "@#{variable_name} will no longer be implicitly assigned to #{variable_name}"
+ )
+ end
# Ensure correct object is reassigned to other accessors
local_assigns[:object] = local_assigns[variable_name] = object
diff --git a/actionpack/lib/action_view/template_handlers/builder.rb b/actionpack/lib/action_view/template_handlers/builder.rb
index 7d24a5c423..788dc93326 100644
--- a/actionpack/lib/action_view/template_handlers/builder.rb
+++ b/actionpack/lib/action_view/template_handlers/builder.rb
@@ -6,7 +6,7 @@ module ActionView
include Compilable
def compile(template)
- "set_controller_content_type(Mime::XML);" +
+ "_set_controller_content_type(Mime::XML);" +
"xml = ::Builder::XmlMarkup.new(:indent => 2);" +
"self.output_buffer = xml.target!;" +
template.source +
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index adbb37fd09..c69f9455b2 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -54,7 +54,7 @@ module ActionView
private
def method_missing(selector, *args)
controller = TestController.new
- return controller.send!(selector, *args) if ActionController::Routing::Routes.named_routes.helpers.include?(selector)
+ return controller.__send__(selector, *args) if ActionController::Routing::Routes.named_routes.helpers.include?(selector)
super
end
end
diff --git a/actionpack/test/controller/assert_select_test.rb b/actionpack/test/controller/assert_select_test.rb
index 1531e7c21a..08cbcbf302 100644
--- a/actionpack/test/controller/assert_select_test.rb
+++ b/actionpack/test/controller/assert_select_test.rb
@@ -433,6 +433,17 @@ class AssertSelectTest < Test::Unit::TestCase
assert_select_rjs :remove, "test1"
end
+ def test_assert_select_rjs_for_remove_offers_useful_error_when_assertion_fails
+ render_rjs do |page|
+ page.remove "test_with_typo"
+ end
+
+ assert_select_rjs :remove, "test1"
+
+ rescue Test::Unit::AssertionFailedError
+ assert_equal "No RJS statement that removes 'test1' was rendered.", $!.message
+ end
+
def test_assert_select_rjs_for_remove_ignores_block
render_rjs do |page|
page.remove "test1"
@@ -454,6 +465,17 @@ class AssertSelectTest < Test::Unit::TestCase
assert_select_rjs :show, "test1"
end
+ def test_assert_select_rjs_for_show_offers_useful_error_when_assertion_fails
+ render_rjs do |page|
+ page.show "test_with_typo"
+ end
+
+ assert_select_rjs :show, "test1"
+
+ rescue Test::Unit::AssertionFailedError
+ assert_equal "No RJS statement that shows 'test1' was rendered.", $!.message
+ end
+
def test_assert_select_rjs_for_show_ignores_block
render_rjs do |page|
page.show "test1"
@@ -475,6 +497,17 @@ class AssertSelectTest < Test::Unit::TestCase
assert_select_rjs :hide, "test1"
end
+ def test_assert_select_rjs_for_hide_offers_useful_error_when_assertion_fails
+ render_rjs do |page|
+ page.hide "test_with_typo"
+ end
+
+ assert_select_rjs :hide, "test1"
+
+ rescue Test::Unit::AssertionFailedError
+ assert_equal "No RJS statement that hides 'test1' was rendered.", $!.message
+ end
+
def test_assert_select_rjs_for_hide_ignores_block
render_rjs do |page|
page.hide "test1"
@@ -496,6 +529,17 @@ class AssertSelectTest < Test::Unit::TestCase
assert_select_rjs :toggle, "test1"
end
+ def test_assert_select_rjs_for_toggle_offers_useful_error_when_assertion_fails
+ render_rjs do |page|
+ page.toggle "test_with_typo"
+ end
+
+ assert_select_rjs :toggle, "test1"
+
+ rescue Test::Unit::AssertionFailedError
+ assert_equal "No RJS statement that toggles 'test1' was rendered.", $!.message
+ end
+
def test_assert_select_rjs_for_toggle_ignores_block
render_rjs do |page|
page.toggle "test1"
@@ -555,6 +599,11 @@ class AssertSelectTest < Test::Unit::TestCase
end
end
+ def test_assert_select_rjs_raise_errors
+ assert_raises(ArgumentError) { assert_select_rjs(:destroy) }
+ assert_raises(ArgumentError) { assert_select_rjs(:insert, :left) }
+ end
+
# Simple selection from a single result.
def test_nested_assert_select_rjs_with_single_result
render_rjs do |page|
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index d49cc2a9aa..738c016c6e 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -84,11 +84,11 @@ class ControllerInstanceTests < Test::Unit::TestCase
def test_action_methods
@empty_controllers.each do |c|
hide_mocha_methods_from_controller(c)
- assert_equal Set.new, c.send!(:action_methods), "#{c.controller_path} should be empty!"
+ assert_equal Set.new, c.__send__(:action_methods), "#{c.controller_path} should be empty!"
end
@non_empty_controllers.each do |c|
hide_mocha_methods_from_controller(c)
- assert_equal Set.new(%w(public_action)), c.send!(:action_methods), "#{c.controller_path} should not be empty!"
+ assert_equal Set.new(%w(public_action)), c.__send__(:action_methods), "#{c.controller_path} should not be empty!"
end
end
@@ -100,7 +100,7 @@ class ControllerInstanceTests < Test::Unit::TestCase
:expects, :mocha, :mocha_inspect, :reset_mocha, :stubba_object,
:stubba_method, :stubs, :verify, :__metaclass__, :__is_a__, :to_matcher,
]
- controller.class.send!(:hide_action, *mocha_methods)
+ controller.class.__send__(:hide_action, *mocha_methods)
end
end
@@ -140,7 +140,7 @@ class PerformActionTest < Test::Unit::TestCase
def test_method_missing_is_not_an_action_name
use_controller MethodMissingController
- assert ! @controller.send!(:action_methods).include?('method_missing')
+ assert ! @controller.__send__(:action_methods).include?('method_missing')
get :method_missing
assert_response :success
diff --git a/actionpack/test/controller/components_test.rb b/actionpack/test/controller/components_test.rb
index 71e8a18071..4d36fc411d 100644
--- a/actionpack/test/controller/components_test.rb
+++ b/actionpack/test/controller/components_test.rb
@@ -77,49 +77,64 @@ class ComponentsTest < Test::Unit::TestCase
end
def test_calling_from_controller
- get :calling_from_controller
- assert_equal "Lady of the House, speaking", @response.body
+ assert_deprecated do
+ get :calling_from_controller
+ assert_equal "Lady of the House, speaking", @response.body
+ end
end
def test_calling_from_controller_with_params
- get :calling_from_controller_with_params
- assert_equal "David of the House, speaking", @response.body
+ assert_deprecated do
+ get :calling_from_controller_with_params
+ assert_equal "David of the House, speaking", @response.body
+ end
end
def test_calling_from_controller_with_different_status_code
- get :calling_from_controller_with_different_status_code
- assert_equal 500, @response.response_code
+ assert_deprecated do
+ get :calling_from_controller_with_different_status_code
+ assert_equal 500, @response.response_code
+ end
end
def test_calling_from_template
- get :calling_from_template
- assert_equal "Ring, ring: Lady of the House, speaking", @response.body
+ assert_deprecated do
+ get :calling_from_template
+ assert_equal "Ring, ring: Lady of the House, speaking", @response.body
+ end
end
def test_etag_is_set_for_parent_template_when_calling_from_template
- get :calling_from_template
- expected_etag = etag_for("Ring, ring: Lady of the House, speaking")
- assert_equal expected_etag, @response.headers['ETag']
+ assert_deprecated do
+ get :calling_from_template
+ expected_etag = etag_for("Ring, ring: Lady of the House, speaking")
+ assert_equal expected_etag, @response.headers['ETag']
+ end
end
def test_internal_calling
- get :internal_caller
- assert_equal "Are you there? Yes, ma'am", @response.body
+ assert_deprecated do
+ get :internal_caller
+ assert_equal "Are you there? Yes, ma'am", @response.body
+ end
end
def test_flash
- get :set_flash
- assert_equal 'My stoney baby', flash[:notice]
- get :use_flash
- assert_equal 'My stoney baby', @response.body
- get :use_flash
- assert_equal 'no flash', @response.body
+ assert_deprecated do
+ get :set_flash
+ assert_equal 'My stoney baby', flash[:notice]
+ get :use_flash
+ assert_equal 'My stoney baby', @response.body
+ get :use_flash
+ assert_equal 'no flash', @response.body
+ end
end
def test_component_redirect_redirects
- get :calling_redirected
-
- assert_redirected_to :controller=>"callee", :action => "being_called"
+ assert_deprecated do
+ get :calling_redirected
+ assert_redirected_to :controller=>"callee", :action => "being_called"
+ end
end
def test_component_multiple_redirect_redirects
@@ -128,9 +143,10 @@ class ComponentsTest < Test::Unit::TestCase
end
def test_component_as_string_redirect_renders_redirected_action
- get :calling_redirected_as_string
-
- assert_equal "Lady of the House, speaking", @response.body
+ assert_deprecated do
+ get :calling_redirected_as_string
+ assert_equal "Lady of the House, speaking", @response.body
+ end
end
protected
diff --git a/actionpack/test/controller/filter_params_test.rb b/actionpack/test/controller/filter_params_test.rb
index c4de10181d..0b259a7980 100644
--- a/actionpack/test/controller/filter_params_test.rb
+++ b/actionpack/test/controller/filter_params_test.rb
@@ -27,7 +27,7 @@ class FilterParamTest < Test::Unit::TestCase
test_hashes.each do |before_filter, after_filter, filter_words|
FilterParamController.filter_parameter_logging(*filter_words)
- assert_equal after_filter, @controller.send!(:filter_parameters, before_filter)
+ assert_equal after_filter, @controller.__send__(:filter_parameters, before_filter)
filter_words.push('blah')
FilterParamController.filter_parameter_logging(*filter_words) do |key, value|
@@ -37,7 +37,7 @@ class FilterParamTest < Test::Unit::TestCase
before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
- assert_equal after_filter, @controller.send!(:filter_parameters, before_filter)
+ assert_equal after_filter, @controller.__send__(:filter_parameters, before_filter)
end
end
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 3652c482f1..dafa344473 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -111,15 +111,15 @@ class FilterTest < Test::Unit::TestCase
end
class OnlyConditionProcController < ConditionalFilterController
- before_filter(:only => :show) {|c| c.assigns["ran_proc_filter"] = true }
+ before_filter(:only => :show) {|c| c.instance_variable_set(:"@ran_proc_filter", true) }
end
class ExceptConditionProcController < ConditionalFilterController
- before_filter(:except => :show_without_filter) {|c| c.assigns["ran_proc_filter"] = true }
+ before_filter(:except => :show_without_filter) {|c| c.instance_variable_set(:"@ran_proc_filter", true) }
end
class ConditionalClassFilter
- def self.filter(controller) controller.assigns["ran_class_filter"] = true end
+ def self.filter(controller) controller.instance_variable_set(:"@ran_class_filter", true) end
end
class OnlyConditionClassController < ConditionalFilterController
@@ -131,7 +131,7 @@ class FilterTest < Test::Unit::TestCase
end
class AnomolousYetValidConditionController < ConditionalFilterController
- before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.assigns["ran_proc_filter1"] = true }, :except => :show_without_filter) { |c| c.assigns["ran_proc_filter2"] = true}
+ before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.instance_variable_set(:"@ran_proc_filter1", true)}, :except => :show_without_filter) { |c| c.instance_variable_set(:"@ran_proc_filter2", true)}
end
class ConditionalOptionsFilter < ConditionalFilterController
@@ -225,16 +225,16 @@ class FilterTest < Test::Unit::TestCase
end
class ProcController < PrependingController
- before_filter(proc { |c| c.assigns["ran_proc_filter"] = true })
+ before_filter(proc { |c| c.instance_variable_set(:"@ran_proc_filter", true) })
end
class ImplicitProcController < PrependingController
- before_filter { |c| c.assigns["ran_proc_filter"] = true }
+ before_filter { |c| c.instance_variable_set(:"@ran_proc_filter", true) }
end
class AuditFilter
def self.filter(controller)
- controller.assigns["was_audited"] = true
+ controller.instance_variable_set(:"@was_audited", true)
end
end
@@ -242,12 +242,12 @@ class FilterTest < Test::Unit::TestCase
def before(controller)
@execution_log = "before"
controller.class.execution_log << " before aroundfilter " if controller.respond_to? :execution_log
- controller.assigns["before_ran"] = true
+ controller.instance_variable_set(:"@before_ran", true)
end
def after(controller)
- controller.assigns["execution_log"] = @execution_log + " and after"
- controller.assigns["after_ran"] = true
+ controller.instance_variable_set(:"@execution_log", @execution_log + " and after")
+ controller.instance_variable_set(:"@after_ran", true)
controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log
end
end
@@ -364,7 +364,7 @@ class FilterTest < Test::Unit::TestCase
begin
yield
rescue ErrorToRescue => ex
- controller.send! :render, :text => "I rescued this: #{ex.inspect}"
+ controller.__send__ :render, :text => "I rescued this: #{ex.inspect}"
end
end
end
@@ -726,9 +726,9 @@ end
class ControllerWithProcFilter < PostsController
around_filter(:only => :no_raise) do |c,b|
- c.assigns['before'] = true
+ c.instance_variable_set(:"@before", true)
b.call
- c.assigns['after'] = true
+ c.instance_variable_set(:"@after", true)
end
end
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index c986941140..7e4c3e171a 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -243,7 +243,7 @@ class IntegrationTestUsesCorrectClass < ActionController::IntegrationTest
reset!
stub_integration_session(@integration_session)
%w( get post head put delete ).each do |verb|
- assert_nothing_raised("'#{verb}' should use integration test methods") { send!(verb, '/') }
+ assert_nothing_raised("'#{verb}' should use integration test methods") { __send__(verb, '/') }
end
end
end
diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb
index 71f110f241..1120fdbff5 100644
--- a/actionpack/test/controller/layout_test.rb
+++ b/actionpack/test/controller/layout_test.rb
@@ -79,53 +79,6 @@ class LayoutAutoDiscoveryTest < Test::Unit::TestCase
end
end
-class ExemptFromLayoutTest < Test::Unit::TestCase
- def setup
- @controller = LayoutTest.new
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
- end
-
- def test_rjs_exempt_from_layout
- assert @controller.send!(:template_exempt_from_layout?, 'test.rjs')
- end
-
- def test_rhtml_and_rxml_not_exempt_from_layout
- assert !@controller.send!(:template_exempt_from_layout?, 'test.rhtml')
- assert !@controller.send!(:template_exempt_from_layout?, 'test.rxml')
- end
-
- def test_other_extension_not_exempt_from_layout
- assert !@controller.send!(:template_exempt_from_layout?, 'test.random')
- end
-
- def test_add_extension_to_exempt_from_layout
- ['rpdf', :rpdf].each do |ext|
- assert_nothing_raised do
- ActionController::Base.exempt_from_layout ext
- end
- assert @controller.send!(:template_exempt_from_layout?, "test.#{ext}")
- end
- end
-
- def test_add_regexp_to_exempt_from_layout
- ActionController::Base.exempt_from_layout /\.rdoc/
- assert @controller.send!(:template_exempt_from_layout?, 'test.rdoc')
- end
-
- def test_rhtml_exempt_from_layout_status_should_prevent_layout_render
- ActionController::Base.exempt_from_layout :rhtml
-
- assert @controller.send!(:template_exempt_from_layout?, 'test.rhtml')
- assert @controller.send!(:template_exempt_from_layout?, 'hello.rhtml')
-
- get :hello
- assert_equal 'hello.rhtml', @response.body
- ActionController::Base.exempt_from_layout.delete(/\.rhtml$/)
- end
-end
-
-
class DefaultLayoutController < LayoutTest
end
@@ -179,8 +132,6 @@ class LayoutSetInResponseTest < Test::Unit::TestCase
ActionController::Base.exempt_from_layout :rhtml
@controller = RenderWithTemplateOptionController.new
- assert @controller.send(:template_exempt_from_layout?, 'alt/hello.rhtml')
-
get :hello
assert_equal "alt/hello.rhtml", @response.body.strip
diff --git a/actionpack/test/controller/new_render_test.rb b/actionpack/test/controller/new_render_test.rb
deleted file mode 100644
index 82919b7777..0000000000
--- a/actionpack/test/controller/new_render_test.rb
+++ /dev/null
@@ -1,981 +0,0 @@
-require 'abstract_unit'
-require 'controller/fake_models'
-
-class CustomersController < ActionController::Base
-end
-
-module Fun
- class GamesController < ActionController::Base
- def hello_world
- end
- end
-end
-
-module NewRenderTestHelper
- def rjs_helper_method_from_module
- page.visual_effect :highlight
- end
-end
-
-class LabellingFormBuilder < ActionView::Helpers::FormBuilder
-end
-
-class NewRenderTestController < ActionController::Base
- layout :determine_layout
-
- def self.controller_name; "test"; end
- def self.controller_path; "test"; end
-
- def hello_world
- end
-
- def render_hello_world
- render :template => "test/hello_world"
- end
-
- def render_hello_world_from_variable
- @person = "david"
- render :text => "hello #{@person}"
- end
-
- def render_action_hello_world
- render :action => "hello_world"
- end
-
- def render_action_hello_world_as_symbol
- render :action => :hello_world
- end
-
- def render_text_hello_world
- render :text => "hello world"
- end
-
- def render_text_hello_world_with_layout
- @variable_for_layout = ", I'm here!"
- render :text => "hello world", :layout => true
- end
-
- def hello_world_with_layout_false
- render :layout => false
- end
-
- def render_custom_code
- render :text => "hello world", :status => "404 Moved"
- end
-
- def render_file_with_instance_variables
- @secret = 'in the sauce'
- path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')
- render :file => path
- end
-
- def render_file_from_template
- @secret = 'in the sauce'
- @path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb'))
- end
-
- def render_file_with_locals
- path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb')
- render :file => path, :locals => {:secret => 'in the sauce'}
- end
-
- def render_file_not_using_full_path
- @secret = 'in the sauce'
- render :file => 'test/render_file_with_ivar'
- end
-
- def render_file_not_using_full_path_with_dot_in_path
- @secret = 'in the sauce'
- render :file => 'test/dot.directory/render_file_with_ivar'
- end
-
- def render_xml_hello
- @name = "David"
- render :template => "test/hello"
- end
-
- def greeting
- # let's just rely on the template
- end
-
- def layout_test
- render :action => "hello_world"
- end
-
- def layout_test_with_different_layout
- render :action => "hello_world", :layout => "standard"
- end
-
- def rendering_without_layout
- render :action => "hello_world", :layout => false
- end
-
- def layout_overriding_layout
- render :action => "hello_world", :layout => "standard"
- end
-
- def rendering_nothing_on_layout
- render :nothing => true
- end
-
- def builder_layout_test
- render :action => "hello"
- end
-
- def partials_list
- @test_unchanged = 'hello'
- @customers = [ Customer.new("david"), Customer.new("mary") ]
- render :action => "list"
- end
-
- def partial_only
- render :partial => true
- end
-
- def partial_only_with_layout
- render :partial => "partial_only", :layout => true
- end
-
- def partial_with_counter
- render :partial => "counter", :locals => { :counter_counter => 5 }
- end
-
- def partial_with_locals
- render :partial => "customer", :locals => { :customer => Customer.new("david") }
- end
-
- def partial_with_form_builder
- render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, @template, {}, Proc.new {})
- end
-
- def partial_with_form_builder_subclass
- render :partial => LabellingFormBuilder.new(:post, nil, @template, {}, Proc.new {})
- end
-
- def partial_collection
- render :partial => "customer", :collection => [ Customer.new("david"), Customer.new("mary") ]
- end
-
- def partial_collection_with_as
- render :partial => "customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => :customer
- end
-
- def partial_collection_with_spacer
- render :partial => "customer", :spacer_template => "partial_only", :collection => [ Customer.new("david"), Customer.new("mary") ]
- end
-
- def partial_collection_with_counter
- render :partial => "customer_counter", :collection => [ Customer.new("david"), Customer.new("mary") ]
- end
-
- def partial_collection_with_locals
- render :partial => "customer_greeting", :collection => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" }
- end
-
- def partial_collection_shorthand_with_locals
- render :partial => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" }
- end
-
- def partial_collection_shorthand_with_different_types_of_records
- render :partial => [
- BadCustomer.new("mark"),
- GoodCustomer.new("craig"),
- BadCustomer.new("john"),
- GoodCustomer.new("zach"),
- GoodCustomer.new("brandon"),
- BadCustomer.new("dan") ],
- :locals => { :greeting => "Bonjour" }
- end
-
- def partial_collection_shorthand_with_different_types_of_records_with_counter
- partial_collection_shorthand_with_different_types_of_records
- end
-
- def empty_partial_collection
- render :partial => "customer", :collection => []
- end
-
- def partial_with_hash_object
- render :partial => "hash_object", :object => {:first_name => "Sam"}
- end
-
- def partial_hash_collection
- render :partial => "hash_object", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ]
- end
-
- def partial_hash_collection_with_locals
- render :partial => "hash_greeting", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ], :locals => { :greeting => "Hola" }
- end
-
- def partial_with_implicit_local_assignment
- @customer = Customer.new("Marcel")
- render :partial => "customer"
- end
-
- def missing_partial
- render :partial => 'thisFileIsntHere'
- end
-
- def hello_in_a_string
- @customers = [ Customer.new("david"), Customer.new("mary") ]
- render :text => "How's there? " << render_to_string(:template => "test/list")
- end
-
- def render_to_string_with_assigns
- @before = "i'm before the render"
- render_to_string :text => "foo"
- @after = "i'm after the render"
- render :action => "test/hello_world"
- end
-
- def render_to_string_with_partial
- @partial_only = render_to_string :partial => "partial_only"
- @partial_with_locals = render_to_string :partial => "customer", :locals => { :customer => Customer.new("david") }
- render :action => "test/hello_world"
- end
-
- def render_to_string_with_exception
- render_to_string :file => "exception that will not be caught - this will certainly not work"
- end
-
- def render_to_string_with_caught_exception
- @before = "i'm before the render"
- begin
- render_to_string :file => "exception that will be caught- hope my future instance vars still work!"
- rescue
- end
- @after = "i'm after the render"
- render :action => "test/hello_world"
- end
-
- def accessing_params_in_template
- render :inline => "Hello: <%= params[:name] %>"
- end
-
- def accessing_request_in_template
- render :inline => "Hello: <%= request.host %>"
- end
-
- def accessing_logger_in_template
- render :inline => "<%= logger.class %>"
- end
-
- def accessing_action_name_in_template
- render :inline => "<%= action_name %>"
- end
-
- def accessing_controller_name_in_template
- render :inline => "<%= controller_name %>"
- end
-
- def accessing_params_in_template_with_layout
- render :layout => nil, :inline => "Hello: <%= params[:name] %>"
- end
-
- def render_with_explicit_template
- render :template => "test/hello_world"
- end
-
- def render_with_explicit_template_with_locals
- render :template => "test/render_file_with_locals", :locals => { :secret => 'area51' }
- end
-
- def double_render
- render :text => "hello"
- render :text => "world"
- end
-
- def double_redirect
- redirect_to :action => "double_render"
- redirect_to :action => "double_render"
- end
-
- def render_and_redirect
- render :text => "hello"
- redirect_to :action => "double_render"
- end
-
- def render_to_string_and_render
- @stuff = render_to_string :text => "here is some cached stuff"
- render :text => "Hi web users! #{@stuff}"
- end
-
- def rendering_with_conflicting_local_vars
- @name = "David"
- def @template.name() nil end
- render :action => "potential_conflicts"
- end
-
- def hello_world_from_rxml_using_action
- render :action => "hello_world_from_rxml.builder"
- end
-
- def hello_world_from_rxml_using_template
- render :template => "test/hello_world_from_rxml.builder"
- end
-
- def head_with_location_header
- head :location => "/foo"
- end
-
- def head_with_symbolic_status
- head :status => params[:status].intern
- end
-
- def head_with_integer_status
- head :status => params[:status].to_i
- end
-
- def head_with_string_status
- head :status => params[:status]
- end
-
- def head_with_custom_header
- head :x_custom_header => "something"
- end
-
- def head_with_status_code_first
- head :forbidden, :x_custom_header => "something"
- end
-
- def render_with_location
- render :xml => "<hello/>", :location => "http://example.com", :status => 201
- end
-
- def render_with_object_location
- customer = Customer.new("Some guy", 1)
- render :xml => "<customer/>", :location => customer_url(customer), :status => :created
- end
-
- def render_with_to_xml
- to_xmlable = Class.new do
- def to_xml
- "<i-am-xml/>"
- end
- end.new
-
- render :xml => to_xmlable
- end
-
- helper NewRenderTestHelper
- helper do
- def rjs_helper_method(value)
- page.visual_effect :highlight, value
- end
- end
-
- def enum_rjs_test
- render :update do |page|
- page.select('.product').each do |value|
- page.rjs_helper_method_from_module
- page.rjs_helper_method(value)
- page.sortable(value, :url => { :action => "order" })
- page.draggable(value)
- end
- end
- end
-
- def delete_with_js
- @project_id = 4
- end
-
- def render_js_with_explicit_template
- @project_id = 4
- render :template => 'test/delete_with_js'
- end
-
- def render_js_with_explicit_action_template
- @project_id = 4
- render :action => 'delete_with_js'
- end
-
- def update_page
- render :update do |page|
- page.replace_html 'balance', '$37,000,000.00'
- page.visual_effect :highlight, 'balance'
- end
- end
-
- def update_page_with_instance_variables
- @money = '$37,000,000.00'
- @div_id = 'balance'
- render :update do |page|
- page.replace_html @div_id, @money
- page.visual_effect :highlight, @div_id
- end
- end
-
- def action_talk_to_layout
- # Action template sets variable that's picked up by layout
- end
-
- def render_text_with_assigns
- @hello = "world"
- render :text => "foo"
- end
-
- def yield_content_for
- render :action => "content_for", :layout => "yield"
- end
-
- def render_content_type_from_body
- response.content_type = Mime::RSS
- render :text => "hello world!"
- end
-
- def render_call_to_partial_with_layout
- render :action => "calling_partial_with_layout"
- end
-
- def render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
- render :action => "calling_partial_with_layout"
- end
-
- def render_using_layout_around_block
- render :action => "using_layout_around_block"
- end
-
- def render_using_layout_around_block_with_args
- render :action => "using_layout_around_block_with_args"
- end
-
- def render_using_layout_around_block_in_main_layout_and_within_content_for_layout
- render :action => "using_layout_around_block"
- end
-
- def rescue_action(e) raise end
-
- private
- def determine_layout
- case action_name
- when "hello_world", "layout_test", "rendering_without_layout",
- "rendering_nothing_on_layout", "render_text_hello_world",
- "render_text_hello_world_with_layout",
- "hello_world_with_layout_false",
- "partial_only", "partial_only_with_layout",
- "accessing_params_in_template",
- "accessing_params_in_template_with_layout",
- "render_with_explicit_template",
- "render_js_with_explicit_template",
- "render_js_with_explicit_action_template",
- "delete_with_js", "update_page", "update_page_with_instance_variables"
-
- "layouts/standard"
- when "builder_layout_test"
- "layouts/builder"
- when "action_talk_to_layout", "layout_overriding_layout"
- "layouts/talk_from_action"
- when "render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout"
- "layouts/partial_with_layout"
- when "render_using_layout_around_block_in_main_layout_and_within_content_for_layout"
- "layouts/block_with_layout"
- end
- end
-end
-
-class NewRenderTest < Test::Unit::TestCase
- def setup
- @controller = NewRenderTestController.new
-
- # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
- # a more accurate simulation of what happens in "real life".
- @controller.logger = Logger.new(nil)
-
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
-
- @request.host = "www.nextangle.com"
- end
-
- def test_simple_show
- get :hello_world
- assert_response :success
- assert_template "test/hello_world"
- assert_equal "<html>Hello world!</html>", @response.body
- end
-
- def test_renders_default_template_for_missing_action
- get :'hyphen-ated'
- assert_template 'test/hyphen-ated'
- end
-
- def test_do_with_render
- get :render_hello_world
- assert_template "test/hello_world"
- end
-
- def test_do_with_render_from_variable
- get :render_hello_world_from_variable
- assert_equal "hello david", @response.body
- end
-
- def test_do_with_render_action
- get :render_action_hello_world
- assert_template "test/hello_world"
- end
-
- def test_do_with_render_action_as_symbol
- get :render_action_hello_world_as_symbol
- assert_template "test/hello_world"
- end
-
- def test_do_with_render_text
- get :render_text_hello_world
- assert_equal "hello world", @response.body
- end
-
- def test_do_with_render_text_and_layout
- get :render_text_hello_world_with_layout
- assert_equal "<html>hello world, I'm here!</html>", @response.body
- end
-
- def test_do_with_render_action_and_layout_false
- get :hello_world_with_layout_false
- assert_equal 'Hello world!', @response.body
- end
-
- def test_do_with_render_custom_code
- get :render_custom_code
- assert_response :missing
- end
-
- def test_render_file_with_instance_variables
- get :render_file_with_instance_variables
- assert_equal "The secret is in the sauce\n", @response.body
- end
-
- def test_render_file_not_using_full_path
- get :render_file_not_using_full_path
- assert_equal "The secret is in the sauce\n", @response.body
- end
-
- def test_render_file_not_using_full_path_with_dot_in_path
- get :render_file_not_using_full_path_with_dot_in_path
- assert_equal "The secret is in the sauce\n", @response.body
- end
-
- def test_render_file_with_locals
- get :render_file_with_locals
- assert_equal "The secret is in the sauce\n", @response.body
- end
-
- def test_render_file_from_template
- get :render_file_from_template
- assert_equal "The secret is in the sauce\n", @response.body
- end
-
- def test_attempt_to_access_object_method
- assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
- end
-
- def test_private_methods
- assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
- end
-
- def test_access_to_request_in_view
- get :accessing_request_in_template
- assert_equal "Hello: www.nextangle.com", @response.body
- end
-
- def test_access_to_logger_in_view
- get :accessing_logger_in_template
- assert_equal "Logger", @response.body
- end
-
- def test_access_to_action_name_in_view
- get :accessing_action_name_in_template
- assert_equal "accessing_action_name_in_template", @response.body
- end
-
- def test_access_to_controller_name_in_view
- get :accessing_controller_name_in_template
- assert_equal "test", @response.body # name is explicitly set to 'test' inside the controller.
- end
-
- def test_render_xml
- get :render_xml_hello
- assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body
- end
-
- def test_enum_rjs_test
- get :enum_rjs_test
- assert_equal <<-EOS.strip, @response.body
-$$(".product").each(function(value, index) {
-new Effect.Highlight(element,{});
-new Effect.Highlight(value,{});
-Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value)})}});
-new Draggable(value, {});
-});
-EOS
- end
-
- def test_render_xml_with_default
- get :greeting
- assert_equal "<p>This is grand!</p>\n", @response.body
- end
-
- def test_render_with_default_from_accept_header
- xhr :get, :greeting
- assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body
- end
-
- def test_render_rjs_with_default
- get :delete_with_js
- assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
- end
-
- def test_render_rjs_template_explicitly
- get :render_js_with_explicit_template
- assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
- end
-
- def test_rendering_rjs_action_explicitly
- get :render_js_with_explicit_action_template
- assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
- end
-
- def test_layout_rendering
- get :layout_test
- assert_equal "<html>Hello world!</html>", @response.body
- end
-
- def test_layout_test_with_different_layout
- get :layout_test_with_different_layout
- assert_equal "<html>Hello world!</html>", @response.body
- end
-
- def test_rendering_without_layout
- get :rendering_without_layout
- assert_equal "Hello world!", @response.body
- end
-
- def test_layout_overriding_layout
- get :layout_overriding_layout
- assert_no_match %r{<title>}, @response.body
- end
-
- def test_rendering_nothing_on_layout
- get :rendering_nothing_on_layout
- assert_equal " ", @response.body
- end
-
- def test_render_xml_with_layouts
- get :builder_layout_test
- assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body
- end
-
- def test_partial_only
- get :partial_only
- assert_equal "only partial", @response.body
- end
-
- def test_partial_only_with_layout
- get :partial_only_with_layout
- assert_equal "<html>only partial</html>", @response.body
- end
-
- def test_render_to_string
- assert_not_deprecated { get :hello_in_a_string }
- assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body
- end
-
- def test_render_to_string_doesnt_break_assigns
- get :render_to_string_with_assigns
- assert_equal "i'm before the render", assigns(:before)
- assert_equal "i'm after the render", assigns(:after)
- end
-
- def test_render_to_string_partial
- get :render_to_string_with_partial
- assert_equal "only partial", assigns(:partial_only)
- assert_equal "Hello: david", assigns(:partial_with_locals)
- end
-
- def test_bad_render_to_string_still_throws_exception
- assert_raises(ActionView::MissingTemplate) { get :render_to_string_with_exception }
- end
-
- def test_render_to_string_that_throws_caught_exception_doesnt_break_assigns
- assert_nothing_raised { get :render_to_string_with_caught_exception }
- assert_equal "i'm before the render", assigns(:before)
- assert_equal "i'm after the render", assigns(:after)
- end
-
- def test_nested_rendering
- get :hello_world
- assert_equal "Living in a nested world", Fun::GamesController.process(@request, @response).body
- end
-
- def test_accessing_params_in_template
- get :accessing_params_in_template, :name => "David"
- assert_equal "Hello: David", @response.body
- end
-
- def test_accessing_params_in_template_with_layout
- get :accessing_params_in_template_with_layout, :name => "David"
- assert_equal "<html>Hello: David</html>", @response.body
- end
-
- def test_render_with_explicit_template
- get :render_with_explicit_template
- assert_response :success
- end
-
- def test_double_render
- assert_raises(ActionController::DoubleRenderError) { get :double_render }
- end
-
- def test_double_redirect
- assert_raises(ActionController::DoubleRenderError) { get :double_redirect }
- end
-
- def test_render_and_redirect
- assert_raises(ActionController::DoubleRenderError) { get :render_and_redirect }
- end
-
- # specify the one exception to double render rule - render_to_string followed by render
- def test_render_to_string_and_render
- get :render_to_string_and_render
- assert_equal("Hi web users! here is some cached stuff", @response.body)
- end
-
- def test_rendering_with_conflicting_local_vars
- get :rendering_with_conflicting_local_vars
- assert_equal("First: David\nSecond: Stephan\nThird: David\nFourth: David\nFifth: ", @response.body)
- end
-
- def test_action_talk_to_layout
- get :action_talk_to_layout
- assert_equal "<title>Talking to the layout</title>\nAction was here!", @response.body
- end
-
- def test_partial_with_counter
- get :partial_with_counter
- assert_equal "5", @response.body
- end
-
- def test_partials_list
- get :partials_list
- assert_equal "goodbyeHello: davidHello: marygoodbye\n", @response.body
- end
-
- def test_partial_with_locals
- get :partial_with_locals
- assert_equal "Hello: david", @response.body
- end
-
- def test_partial_with_form_builder
- get :partial_with_form_builder
- assert_match(/<label/, @response.body)
- assert_template('test/_form')
- end
-
- def test_partial_with_form_builder_subclass
- get :partial_with_form_builder_subclass
- assert_match(/<label/, @response.body)
- assert_template('test/_labelling_form')
- end
-
- def test_partial_collection
- get :partial_collection
- assert_equal "Hello: davidHello: mary", @response.body
- end
-
- def test_partial_collection_with_as
- get :partial_collection_with_as
- assert_equal "david david davidmary mary mary", @response.body
- end
-
- def test_partial_collection_with_counter
- get :partial_collection_with_counter
- assert_equal "david0mary1", @response.body
- end
-
- def test_partial_collection_with_locals
- get :partial_collection_with_locals
- assert_equal "Bonjour: davidBonjour: mary", @response.body
- end
-
- def test_partial_collection_with_spacer
- get :partial_collection_with_spacer
- assert_equal "Hello: davidonly partialHello: mary", @response.body
- end
-
- def test_partial_collection_shorthand_with_locals
- get :partial_collection_shorthand_with_locals
- assert_equal "Bonjour: davidBonjour: mary", @response.body
- end
-
- def test_partial_collection_shorthand_with_different_types_of_records
- get :partial_collection_shorthand_with_different_types_of_records
- assert_equal "Bonjour bad customer: mark0Bonjour good customer: craig1Bonjour bad customer: john2Bonjour good customer: zach3Bonjour good customer: brandon4Bonjour bad customer: dan5", @response.body
- end
-
- def test_empty_partial_collection
- get :empty_partial_collection
- assert_equal " ", @response.body
- end
-
- def test_partial_with_hash_object
- get :partial_with_hash_object
- assert_equal "Sam\nmaS\n", @response.body
- end
-
- def test_hash_partial_collection
- get :partial_hash_collection
- assert_equal "Pratik\nkitarP\nAmy\nymA\n", @response.body
- end
-
- def test_partial_hash_collection_with_locals
- get :partial_hash_collection_with_locals
- assert_equal "Hola: PratikHola: Amy", @response.body
- end
-
- def test_partial_with_implicit_local_assignment
- get :partial_with_implicit_local_assignment
- assert_equal "Hello: Marcel", @response.body
- end
-
- def test_render_missing_partial_template
- assert_raises(ActionView::MissingTemplate) do
- get :missing_partial
- end
- end
-
- def test_render_text_with_assigns
- get :render_text_with_assigns
- assert_equal "world", assigns["hello"]
- end
-
- def test_template_with_locals
- get :render_with_explicit_template_with_locals
- assert_equal "The secret is area51\n", @response.body
- end
-
- def test_update_page
- get :update_page
- assert_template nil
- assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
- assert_equal 2, @response.body.split($/).length
- end
-
- def test_update_page_with_instance_variables
- get :update_page_with_instance_variables
- assert_template nil
- assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
- assert_match /balance/, @response.body
- assert_match /\$37/, @response.body
- end
-
- def test_yield_content_for
- assert_not_deprecated { get :yield_content_for }
- assert_equal "<title>Putting stuff in the title!</title>\n\nGreat stuff!\n", @response.body
- end
-
-
- def test_overwritting_rendering_relative_file_with_extension
- get :hello_world_from_rxml_using_template
- assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body
-
- get :hello_world_from_rxml_using_action
- assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body
- end
-
-
- def test_head_with_location_header
- get :head_with_location_header
- assert @response.body.blank?
- assert_equal "/foo", @response.headers["Location"]
- assert_response :ok
- end
-
- def test_head_with_custom_header
- get :head_with_custom_header
- assert @response.body.blank?
- assert_equal "something", @response.headers["X-Custom-Header"]
- assert_response :ok
- end
-
- def test_head_with_symbolic_status
- get :head_with_symbolic_status, :status => "ok"
- assert_equal "200 OK", @response.headers["Status"]
- assert_response :ok
-
- get :head_with_symbolic_status, :status => "not_found"
- assert_equal "404 Not Found", @response.headers["Status"]
- assert_response :not_found
-
- ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE.each do |status, code|
- get :head_with_symbolic_status, :status => status.to_s
- assert_equal code, @response.response_code
- assert_response status
- end
- end
-
- def test_head_with_integer_status
- ActionController::StatusCodes::STATUS_CODES.each do |code, message|
- get :head_with_integer_status, :status => code.to_s
- assert_equal message, @response.message
- end
- end
-
- def test_head_with_string_status
- get :head_with_string_status, :status => "404 Eat Dirt"
- assert_equal 404, @response.response_code
- assert_equal "Eat Dirt", @response.message
- assert_response :not_found
- end
-
- def test_head_with_status_code_first
- get :head_with_status_code_first
- assert_equal 403, @response.response_code
- assert_equal "Forbidden", @response.message
- assert_equal "something", @response.headers["X-Custom-Header"]
- assert_response :forbidden
- end
-
- def test_rendering_with_location_should_set_header
- get :render_with_location
- assert_equal "http://example.com", @response.headers["Location"]
- end
-
- def test_rendering_xml_should_call_to_xml_if_possible
- get :render_with_to_xml
- assert_equal "<i-am-xml/>", @response.body
- end
-
- def test_rendering_with_object_location_should_set_header_with_url_for
- ActionController::Routing::Routes.draw do |map|
- map.resources :customers
- map.connect ':controller/:action/:id'
- end
-
- get :render_with_object_location
- assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
- end
-
- def test_render_call_to_partial_with_layout
- get :render_call_to_partial_with_layout
- assert_equal "Before (David)\nInside from partial (David)\nAfter", @response.body
- end
-
- def test_render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
- get :render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
- assert_equal "Before (Anthony)\nInside from partial (Anthony)\nAfter\nBefore (David)\nInside from partial (David)\nAfter\nBefore (Ramm)\nInside from partial (Ramm)\nAfter", @response.body
- end
-
- def test_using_layout_around_block
- get :render_using_layout_around_block
- assert_equal "Before (David)\nInside from block\nAfter", @response.body
- end
-
- def test_using_layout_around_block_in_main_layout_and_within_content_for_layout
- get :render_using_layout_around_block_in_main_layout_and_within_content_for_layout
- assert_equal "Before (Anthony)\nInside from first block in layout\nAfter\nBefore (David)\nInside from block\nAfter\nBefore (Ramm)\nInside from second block in layout\nAfter\n", @response.body
- end
-
- def test_using_layout_around_block_with_args
- get :render_using_layout_around_block_with_args
- assert_equal "Before\narg1arg2\nAfter", @response.body
- end
-end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 3008f5ca03..af7b5dde62 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -8,7 +8,22 @@ module Fun
end
end
+class MockLogger
+ attr_reader :logged
+
+ def initialize
+ @logged = []
+ end
+
+ def method_missing(method, *args)
+ @logged << args.first
+ end
+end
+
class TestController < ActionController::Base
+ class LabellingFormBuilder < ActionView::Helpers::FormBuilder
+ end
+
layout :determine_layout
def hello_world
@@ -58,6 +73,57 @@ class TestController < ActionController::Base
render :text => "hello world"
end
+ def render_text_hello_world_with_layout
+ @variable_for_layout = ", I'm here!"
+ render :text => "hello world", :layout => true
+ end
+
+ def hello_world_with_layout_false
+ render :layout => false
+ end
+
+ def render_file_with_instance_variables
+ @secret = 'in the sauce'
+ path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb')
+ render :file => path
+ end
+
+ def render_file_not_using_full_path
+ @secret = 'in the sauce'
+ render :file => 'test/render_file_with_ivar'
+ end
+
+ def render_file_not_using_full_path_with_dot_in_path
+ @secret = 'in the sauce'
+ render :file => 'test/dot.directory/render_file_with_ivar'
+ end
+
+ def render_file_from_template
+ @secret = 'in the sauce'
+ @path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb'))
+ end
+
+ def render_file_with_locals
+ path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.erb')
+ render :file => path, :locals => {:secret => 'in the sauce'}
+ end
+
+ def accessing_request_in_template
+ render :inline => "Hello: <%= request.host %>"
+ end
+
+ def accessing_logger_in_template
+ render :inline => "<%= logger.class %>"
+ end
+
+ def accessing_action_name_in_template
+ render :inline => "<%= action_name %>"
+ end
+
+ def accessing_controller_name_in_template
+ render :inline => "<%= controller_name %>"
+ end
+
def render_json_hello_world
render :json => {:hello => 'world'}.to_json
end
@@ -126,7 +192,7 @@ class TestController < ActionController::Base
end
def builder_layout_test
- render :action => "hello"
+ render :action => "hello", :layout => "layouts/builder"
end
def builder_partial_test
@@ -168,8 +234,232 @@ class TestController < ActionController::Base
@foo = render_to_string :inline => "this is a test"
end
- def partial
- render :partial => 'partial'
+ def default_render
+ if @alternate_default_render
+ @alternate_default_render.call
+ else
+ render
+ end
+ end
+
+ def render_action_hello_world_as_symbol
+ render :action => :hello_world
+ end
+
+ def layout_test_with_different_layout
+ render :action => "hello_world", :layout => "standard"
+ end
+
+ def rendering_without_layout
+ render :action => "hello_world", :layout => false
+ end
+
+ def layout_overriding_layout
+ render :action => "hello_world", :layout => "standard"
+ end
+
+ def rendering_nothing_on_layout
+ render :nothing => true
+ end
+
+ def render_to_string_with_assigns
+ @before = "i'm before the render"
+ render_to_string :text => "foo"
+ @after = "i'm after the render"
+ render :action => "test/hello_world"
+ end
+
+ def render_to_string_with_exception
+ render_to_string :file => "exception that will not be caught - this will certainly not work"
+ end
+
+ def render_to_string_with_caught_exception
+ @before = "i'm before the render"
+ begin
+ render_to_string :file => "exception that will be caught- hope my future instance vars still work!"
+ rescue
+ end
+ @after = "i'm after the render"
+ render :action => "test/hello_world"
+ end
+
+ def accessing_params_in_template_with_layout
+ render :layout => nil, :inline => "Hello: <%= params[:name] %>"
+ end
+
+ def render_with_explicit_template
+ render :template => "test/hello_world"
+ end
+
+ def render_with_explicit_template_with_locals
+ render :template => "test/render_file_with_locals", :locals => { :secret => 'area51' }
+ end
+
+ def double_render
+ render :text => "hello"
+ render :text => "world"
+ end
+
+ def double_redirect
+ redirect_to :action => "double_render"
+ redirect_to :action => "double_render"
+ end
+
+ def render_and_redirect
+ render :text => "hello"
+ redirect_to :action => "double_render"
+ end
+
+ def render_to_string_and_render
+ @stuff = render_to_string :text => "here is some cached stuff"
+ render :text => "Hi web users! #{@stuff}"
+ end
+
+ def rendering_with_conflicting_local_vars
+ @name = "David"
+ def @template.name() nil end
+ render :action => "potential_conflicts"
+ end
+
+ def hello_world_from_rxml_using_action
+ render :action => "hello_world_from_rxml.builder"
+ end
+
+ def hello_world_from_rxml_using_template
+ render :template => "test/hello_world_from_rxml.builder"
+ end
+
+ module RenderTestHelper
+ def rjs_helper_method_from_module
+ page.visual_effect :highlight
+ end
+ end
+
+ helper RenderTestHelper
+ helper do
+ def rjs_helper_method(value)
+ page.visual_effect :highlight, value
+ end
+ end
+
+ def enum_rjs_test
+ render :update do |page|
+ page.select('.product').each do |value|
+ page.rjs_helper_method_from_module
+ page.rjs_helper_method(value)
+ page.sortable(value, :url => { :action => "order" })
+ page.draggable(value)
+ end
+ end
+ end
+
+ def delete_with_js
+ @project_id = 4
+ end
+
+ def render_js_with_explicit_template
+ @project_id = 4
+ render :template => 'test/delete_with_js'
+ end
+
+ def render_js_with_explicit_action_template
+ @project_id = 4
+ render :action => 'delete_with_js'
+ end
+
+ def update_page
+ render :update do |page|
+ page.replace_html 'balance', '$37,000,000.00'
+ page.visual_effect :highlight, 'balance'
+ end
+ end
+
+ def update_page_with_instance_variables
+ @money = '$37,000,000.00'
+ @div_id = 'balance'
+ render :update do |page|
+ page.replace_html @div_id, @money
+ page.visual_effect :highlight, @div_id
+ end
+ end
+
+ def update_page_with_view_method
+ render :update do |page|
+ page.replace_html 'person', pluralize(2, 'person')
+ end
+ end
+
+ def action_talk_to_layout
+ # Action template sets variable that's picked up by layout
+ end
+
+ def render_text_with_assigns
+ @hello = "world"
+ render :text => "foo"
+ end
+
+ def yield_content_for
+ render :action => "content_for", :layout => "yield"
+ end
+
+ def render_content_type_from_body
+ response.content_type = Mime::RSS
+ render :text => "hello world!"
+ end
+
+ def head_with_location_header
+ head :location => "/foo"
+ end
+
+ def head_with_symbolic_status
+ head :status => params[:status].intern
+ end
+
+ def head_with_integer_status
+ head :status => params[:status].to_i
+ end
+
+ def head_with_string_status
+ head :status => params[:status]
+ end
+
+ def head_with_custom_header
+ head :x_custom_header => "something"
+ end
+
+ def head_with_status_code_first
+ head :forbidden, :x_custom_header => "something"
+ end
+
+ def render_with_location
+ render :xml => "<hello/>", :location => "http://example.com", :status => 201
+ end
+
+ def render_with_object_location
+ customer = Customer.new("Some guy", 1)
+ render :xml => "<customer/>", :location => customer_url(customer), :status => :created
+ end
+
+ def render_with_to_xml
+ to_xmlable = Class.new do
+ def to_xml
+ "<i-am-xml/>"
+ end
+ end.new
+
+ render :xml => to_xmlable
+ end
+
+ def render_using_layout_around_block
+ render :action => "using_layout_around_block"
+ end
+
+ def render_using_layout_around_block_with_args
+ render :action => "using_layout_around_block_with_args"
+ end
+
+ def render_using_layout_around_block_in_main_layout_and_within_content_for_layout
+ render :action => "using_layout_around_block", :layout => "layouts/block_with_layout"
end
def partial_dot_html
@@ -192,12 +482,8 @@ class TestController < ActionController::Base
end
end
- def default_render
- if @alternate_default_render
- @alternate_default_render.call
- else
- render
- end
+ def partial
+ render :partial => 'partial'
end
def render_alternate_default
@@ -209,14 +495,126 @@ class TestController < ActionController::Base
end
end
- def rescue_action(e) raise end
+ def partial_only_with_layout
+ render :partial => "partial_only", :layout => true
+ end
+
+ def render_to_string_with_partial
+ @partial_only = render_to_string :partial => "partial_only"
+ @partial_with_locals = render_to_string :partial => "customer", :locals => { :customer => Customer.new("david") }
+ render :action => "test/hello_world"
+ end
+
+ def partial_with_counter
+ render :partial => "counter", :locals => { :counter_counter => 5 }
+ end
+
+ def partial_with_locals
+ render :partial => "customer", :locals => { :customer => Customer.new("david") }
+ end
+
+ def partial_with_form_builder
+ render :partial => ActionView::Helpers::FormBuilder.new(:post, nil, @template, {}, Proc.new {})
+ end
+
+ def partial_with_form_builder_subclass
+ render :partial => LabellingFormBuilder.new(:post, nil, @template, {}, Proc.new {})
+ end
+
+ def partial_collection
+ render :partial => "customer", :collection => [ Customer.new("david"), Customer.new("mary") ]
+ end
+
+ def partial_collection_with_as
+ render :partial => "customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => :customer
+ end
+
+ def partial_collection_with_counter
+ render :partial => "customer_counter", :collection => [ Customer.new("david"), Customer.new("mary") ]
+ end
+
+ def partial_collection_with_locals
+ render :partial => "customer_greeting", :collection => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" }
+ end
+
+ def partial_collection_with_spacer
+ render :partial => "customer", :spacer_template => "partial_only", :collection => [ Customer.new("david"), Customer.new("mary") ]
+ end
+
+ def partial_collection_shorthand_with_locals
+ render :partial => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" }
+ end
+
+ def partial_collection_shorthand_with_different_types_of_records
+ render :partial => [
+ BadCustomer.new("mark"),
+ GoodCustomer.new("craig"),
+ BadCustomer.new("john"),
+ GoodCustomer.new("zach"),
+ GoodCustomer.new("brandon"),
+ BadCustomer.new("dan") ],
+ :locals => { :greeting => "Bonjour" }
+ end
+
+ def empty_partial_collection
+ render :partial => "customer", :collection => []
+ end
+
+ def partial_collection_shorthand_with_different_types_of_records_with_counter
+ partial_collection_shorthand_with_different_types_of_records
+ end
+
+ def missing_partial
+ render :partial => 'thisFileIsntHere'
+ end
+
+ def partial_with_hash_object
+ render :partial => "hash_object", :object => {:first_name => "Sam"}
+ end
+
+ def partial_hash_collection
+ render :partial => "hash_object", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ]
+ end
+
+ def partial_hash_collection_with_locals
+ render :partial => "hash_greeting", :collection => [ {:first_name => "Pratik"}, {:first_name => "Amy"} ], :locals => { :greeting => "Hola" }
+ end
+
+ def partial_with_implicit_local_assignment
+ @customer = Customer.new("Marcel")
+ render :partial => "customer"
+ end
+
+ def render_call_to_partial_with_layout
+ render :action => "calling_partial_with_layout"
+ end
+
+ def render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
+ render :action => "calling_partial_with_layout", :layout => "layouts/partial_with_layout"
+ end
+
+ def rescue_action(e)
+ raise
+ end
private
def determine_layout
case action_name
- when "layout_test"; "layouts/standard"
- when "builder_layout_test"; "layouts/builder"
- when "render_symbol_json"; "layouts/standard" # to make sure layouts don't interfere
+ when "hello_world", "layout_test", "rendering_without_layout",
+ "rendering_nothing_on_layout", "render_text_hello_world",
+ "render_text_hello_world_with_layout",
+ "hello_world_with_layout_false",
+ "partial_only", "partial_only_with_layout",
+ "accessing_params_in_template",
+ "accessing_params_in_template_with_layout",
+ "render_with_explicit_template",
+ "render_js_with_explicit_template",
+ "render_js_with_explicit_action_template",
+ "delete_with_js", "update_page", "update_page_with_instance_variables"
+
+ "layouts/standard"
+ when "action_talk_to_layout", "layout_overriding_layout"
+ "layouts/talk_from_action"
end
end
end
@@ -227,13 +625,24 @@ class RenderTest < Test::Unit::TestCase
@response = ActionController::TestResponse.new
@controller = TestController.new
+ # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
+ # a more accurate simulation of what happens in "real life".
+ @controller.logger = Logger.new(nil)
+
@request.host = "www.nextangle.com"
end
def test_simple_show
get :hello_world
assert_response 200
+ assert_response :success
assert_template "test/hello_world"
+ assert_equal "<html>Hello world!</html>", @response.body
+ end
+
+ def test_renders_default_template_for_missing_action
+ get :'hyphen-ated'
+ assert_template 'test/hyphen-ated'
end
def test_render
@@ -290,6 +699,41 @@ class RenderTest < Test::Unit::TestCase
assert_equal "hello world", @response.body
end
+ def test_do_with_render_text_and_layout
+ get :render_text_hello_world_with_layout
+ assert_equal "<html>hello world, I'm here!</html>", @response.body
+ end
+
+ def test_do_with_render_action_and_layout_false
+ get :hello_world_with_layout_false
+ assert_equal 'Hello world!', @response.body
+ end
+
+ def test_render_file_with_instance_variables
+ get :render_file_with_instance_variables
+ assert_equal "The secret is in the sauce\n", @response.body
+ end
+
+ def test_render_file_not_using_full_path
+ get :render_file_not_using_full_path
+ assert_equal "The secret is in the sauce\n", @response.body
+ end
+
+ def test_render_file_not_using_full_path_with_dot_in_path
+ get :render_file_not_using_full_path_with_dot_in_path
+ assert_equal "The secret is in the sauce\n", @response.body
+ end
+
+ def test_render_file_with_locals
+ get :render_file_with_locals
+ assert_equal "The secret is in the sauce\n", @response.body
+ end
+
+ def test_render_file_from_template
+ get :render_file_from_template
+ assert_equal "The secret is in the sauce\n", @response.body
+ end
+
def test_render_json
get :render_json_hello_world
assert_equal '{"hello": "world"}', @response.body
@@ -317,6 +761,7 @@ class RenderTest < Test::Unit::TestCase
def test_render_custom_code
get :render_custom_code
assert_response 404
+ assert_response :missing
assert_equal 'hello world', @response.body
end
@@ -355,6 +800,26 @@ class RenderTest < Test::Unit::TestCase
assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
end
+ def test_access_to_request_in_view
+ get :accessing_request_in_template
+ assert_equal "Hello: www.nextangle.com", @response.body
+ end
+
+ def test_access_to_logger_in_view
+ get :accessing_logger_in_template
+ assert_equal "Logger", @response.body
+ end
+
+ def test_access_to_action_name_in_view
+ get :accessing_action_name_in_template
+ assert_equal "accessing_action_name_in_template", @response.body
+ end
+
+ def test_access_to_controller_name_in_view
+ get :accessing_controller_name_in_template
+ assert_equal "test", @response.body # name is explicitly set to 'test' inside the controller.
+ end
+
def test_render_xml
get :render_xml_hello
assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body
@@ -371,6 +836,19 @@ class RenderTest < Test::Unit::TestCase
assert_equal "<test>\n <hello/>\n</test>\n", @response.body
end
+ def test_enum_rjs_test
+ get :enum_rjs_test
+ body = %{
+ $$(".product").each(function(value, index) {
+ new Effect.Highlight(element,{});
+ new Effect.Highlight(value,{});
+ Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value)})}});
+ new Draggable(value, {});
+ });
+ }.gsub(/^ /, '').strip
+ assert_equal body, @response.body
+ end
+
def test_layout_rendering
get :layout_test
assert_equal "<html>Hello world!</html>", @response.body
@@ -381,14 +859,9 @@ class RenderTest < Test::Unit::TestCase
assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body
end
- # def test_partials_list
- # get :partials_list
- # assert_equal "goodbyeHello: davidHello: marygoodbye\n", process_request.body
- # end
-
- def test_partial_only
- get :partial_only
- assert_equal "only partial", @response.body
+ def test_partials_list
+ get :partials_list
+ assert_equal "goodbyeHello: davidHello: marygoodbye\n", @response.body
end
def test_render_to_string
@@ -438,6 +911,252 @@ class RenderTest < Test::Unit::TestCase
assert_equal '<test>passed formatted html erb</test>', @response.body
end
+ def test_should_render_xml_but_keep_custom_content_type
+ get :render_xml_with_custom_content_type
+ assert_equal "application/atomsvc+xml", @response.content_type
+ end
+
+ def test_render_with_default_from_accept_header
+ xhr :get, :greeting
+ assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body
+ end
+
+ def test_render_rjs_with_default
+ get :delete_with_js
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
+ end
+
+ def test_render_rjs_template_explicitly
+ get :render_js_with_explicit_template
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
+ end
+
+ def test_rendering_rjs_action_explicitly
+ get :render_js_with_explicit_action_template
+ assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
+ end
+
+ def test_layout_test_with_different_layout
+ get :layout_test_with_different_layout
+ assert_equal "<html>Hello world!</html>", @response.body
+ end
+
+ def test_rendering_without_layout
+ get :rendering_without_layout
+ assert_equal "Hello world!", @response.body
+ end
+
+ def test_layout_overriding_layout
+ get :layout_overriding_layout
+ assert_no_match %r{<title>}, @response.body
+ end
+
+ def test_rendering_nothing_on_layout
+ get :rendering_nothing_on_layout
+ assert_equal " ", @response.body
+ end
+
+ def test_render_to_string
+ assert_not_deprecated { get :hello_in_a_string }
+ assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body
+ end
+
+ def test_render_to_string_doesnt_break_assigns
+ get :render_to_string_with_assigns
+ assert_equal "i'm before the render", assigns(:before)
+ assert_equal "i'm after the render", assigns(:after)
+ end
+
+ def test_bad_render_to_string_still_throws_exception
+ assert_raises(ActionView::MissingTemplate) { get :render_to_string_with_exception }
+ end
+
+ def test_render_to_string_that_throws_caught_exception_doesnt_break_assigns
+ assert_nothing_raised { get :render_to_string_with_caught_exception }
+ assert_equal "i'm before the render", assigns(:before)
+ assert_equal "i'm after the render", assigns(:after)
+ end
+
+ def test_accessing_params_in_template_with_layout
+ get :accessing_params_in_template_with_layout, :name => "David"
+ assert_equal "<html>Hello: David</html>", @response.body
+ end
+
+ def test_render_with_explicit_template
+ get :render_with_explicit_template
+ assert_response :success
+ end
+
+ def test_double_render
+ assert_raises(ActionController::DoubleRenderError) { get :double_render }
+ end
+
+ def test_double_redirect
+ assert_raises(ActionController::DoubleRenderError) { get :double_redirect }
+ end
+
+ def test_render_and_redirect
+ assert_raises(ActionController::DoubleRenderError) { get :render_and_redirect }
+ end
+
+ # specify the one exception to double render rule - render_to_string followed by render
+ def test_render_to_string_and_render
+ get :render_to_string_and_render
+ assert_equal("Hi web users! here is some cached stuff", @response.body)
+ end
+
+ def test_rendering_with_conflicting_local_vars
+ get :rendering_with_conflicting_local_vars
+ assert_equal("First: David\nSecond: Stephan\nThird: David\nFourth: David\nFifth: ", @response.body)
+ end
+
+ def test_action_talk_to_layout
+ get :action_talk_to_layout
+ assert_equal "<title>Talking to the layout</title>\nAction was here!", @response.body
+ end
+
+ def test_render_text_with_assigns
+ get :render_text_with_assigns
+ assert_equal "world", assigns["hello"]
+ end
+
+ def test_template_with_locals
+ get :render_with_explicit_template_with_locals
+ assert_equal "The secret is area51\n", @response.body
+ end
+
+ def test_update_page
+ get :update_page
+ assert_template nil
+ assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
+ assert_equal 2, @response.body.split($/).length
+ end
+
+ def test_update_page_with_instance_variables
+ get :update_page_with_instance_variables
+ assert_template nil
+ assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
+ assert_match /balance/, @response.body
+ assert_match /\$37/, @response.body
+ end
+
+ def test_update_page_with_view_method
+ get :update_page_with_view_method
+ assert_template nil
+ assert_equal 'text/javascript; charset=utf-8', @response.headers['type']
+ assert_match /2 people/, @response.body
+ end
+
+ def test_yield_content_for
+ assert_not_deprecated { get :yield_content_for }
+ assert_equal "<title>Putting stuff in the title!</title>\n\nGreat stuff!\n", @response.body
+ end
+
+ def test_overwritting_rendering_relative_file_with_extension
+ get :hello_world_from_rxml_using_template
+ assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body
+
+ get :hello_world_from_rxml_using_action
+ assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body
+ end
+
+ def test_head_with_location_header
+ get :head_with_location_header
+ assert @response.body.blank?
+ assert_equal "/foo", @response.headers["Location"]
+ assert_response :ok
+ end
+
+ def test_head_with_custom_header
+ get :head_with_custom_header
+ assert @response.body.blank?
+ assert_equal "something", @response.headers["X-Custom-Header"]
+ assert_response :ok
+ end
+
+ def test_head_with_symbolic_status
+ get :head_with_symbolic_status, :status => "ok"
+ assert_equal "200 OK", @response.headers["Status"]
+ assert_response :ok
+
+ get :head_with_symbolic_status, :status => "not_found"
+ assert_equal "404 Not Found", @response.headers["Status"]
+ assert_response :not_found
+
+ ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE.each do |status, code|
+ get :head_with_symbolic_status, :status => status.to_s
+ assert_equal code, @response.response_code
+ assert_response status
+ end
+ end
+
+ def test_head_with_integer_status
+ ActionController::StatusCodes::STATUS_CODES.each do |code, message|
+ get :head_with_integer_status, :status => code.to_s
+ assert_equal message, @response.message
+ end
+ end
+
+ def test_head_with_string_status
+ get :head_with_string_status, :status => "404 Eat Dirt"
+ assert_equal 404, @response.response_code
+ assert_equal "Eat Dirt", @response.message
+ assert_response :not_found
+ end
+
+ def test_head_with_status_code_first
+ get :head_with_status_code_first
+ assert_equal 403, @response.response_code
+ assert_equal "Forbidden", @response.message
+ assert_equal "something", @response.headers["X-Custom-Header"]
+ assert_response :forbidden
+ end
+
+ def test_rendering_with_location_should_set_header
+ get :render_with_location
+ assert_equal "http://example.com", @response.headers["Location"]
+ end
+
+ def test_rendering_xml_should_call_to_xml_if_possible
+ get :render_with_to_xml
+ assert_equal "<i-am-xml/>", @response.body
+ end
+
+ def test_rendering_with_object_location_should_set_header_with_url_for
+ ActionController::Routing::Routes.draw do |map|
+ map.resources :customers
+ map.connect ':controller/:action/:id'
+ end
+
+ get :render_with_object_location
+ assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
+ end
+
+ def test_should_use_implicit_content_type
+ get :implicit_content_type, :format => 'atom'
+ assert_equal Mime::ATOM, @response.content_type
+ end
+
+ def test_using_layout_around_block
+ get :render_using_layout_around_block
+ assert_equal "Before (David)\nInside from block\nAfter", @response.body
+ end
+
+ def test_using_layout_around_block_in_main_layout_and_within_content_for_layout
+ get :render_using_layout_around_block_in_main_layout_and_within_content_for_layout
+ assert_equal "Before (Anthony)\nInside from first block in layout\nAfter\nBefore (David)\nInside from block\nAfter\nBefore (Ramm)\nInside from second block in layout\nAfter\n", @response.body
+ end
+
+ def test_using_layout_around_block_with_args
+ get :render_using_layout_around_block_with_args
+ assert_equal "Before\narg1arg2\nAfter", @response.body
+ end
+
+ def test_partial_only
+ get :partial_only
+ assert_equal "only partial", @response.body
+ end
+
def test_should_render_html_formatted_partial
get :partial
assert_equal 'partial html', @response.body
@@ -468,14 +1187,115 @@ class RenderTest < Test::Unit::TestCase
assert_equal %(Element.replace("foo", "partial html");), @response.body
end
- def test_should_render_xml_but_keep_custom_content_type
- get :render_xml_with_custom_content_type
- assert_equal "application/atomsvc+xml", @response.content_type
+ def test_partial_only_with_layout
+ get :partial_only_with_layout
+ assert_equal "<html>only partial</html>", @response.body
end
- def test_should_use_implicit_content_type
- get :implicit_content_type, :format => 'atom'
- assert_equal Mime::ATOM, @response.content_type
+ def test_render_to_string_partial
+ get :render_to_string_with_partial
+ assert_equal "only partial", assigns(:partial_only)
+ assert_equal "Hello: david", assigns(:partial_with_locals)
+ end
+
+ def test_partial_with_counter
+ get :partial_with_counter
+ assert_equal "5", @response.body
+ end
+
+ def test_partial_with_locals
+ get :partial_with_locals
+ assert_equal "Hello: david", @response.body
+ end
+
+ def test_partial_with_form_builder
+ get :partial_with_form_builder
+ assert_match(/<label/, @response.body)
+ assert_template('test/_form')
+ end
+
+ def test_partial_with_form_builder_subclass
+ get :partial_with_form_builder_subclass
+ assert_match(/<label/, @response.body)
+ assert_template('test/_labelling_form')
+ end
+
+ def test_partial_collection
+ get :partial_collection
+ assert_equal "Hello: davidHello: mary", @response.body
+ end
+
+ def test_partial_collection_with_as
+ get :partial_collection_with_as
+ assert_equal "david david davidmary mary mary", @response.body
+ end
+
+ def test_partial_collection_with_counter
+ get :partial_collection_with_counter
+ assert_equal "david0mary1", @response.body
+ end
+
+ def test_partial_collection_with_locals
+ get :partial_collection_with_locals
+ assert_equal "Bonjour: davidBonjour: mary", @response.body
+ end
+
+ def test_partial_collection_with_spacer
+ get :partial_collection_with_spacer
+ assert_equal "Hello: davidonly partialHello: mary", @response.body
+ end
+
+ def test_partial_collection_shorthand_with_locals
+ get :partial_collection_shorthand_with_locals
+ assert_equal "Bonjour: davidBonjour: mary", @response.body
+ end
+
+ def test_partial_collection_shorthand_with_different_types_of_records
+ get :partial_collection_shorthand_with_different_types_of_records
+ assert_equal "Bonjour bad customer: mark0Bonjour good customer: craig1Bonjour bad customer: john2Bonjour good customer: zach3Bonjour good customer: brandon4Bonjour bad customer: dan5", @response.body
+ end
+
+ def test_empty_partial_collection
+ get :empty_partial_collection
+ assert_equal " ", @response.body
+ end
+
+ def test_partial_with_hash_object
+ get :partial_with_hash_object
+ assert_equal "Sam\nmaS\n", @response.body
+ end
+
+ def test_hash_partial_collection
+ get :partial_hash_collection
+ assert_equal "Pratik\nkitarP\nAmy\nymA\n", @response.body
+ end
+
+ def test_partial_hash_collection_with_locals
+ get :partial_hash_collection_with_locals
+ assert_equal "Hola: PratikHola: Amy", @response.body
+ end
+
+ def test_partial_with_implicit_local_assignment
+ assert_deprecated do
+ get :partial_with_implicit_local_assignment
+ assert_equal "Hello: Marcel", @response.body
+ end
+ end
+
+ def test_render_missing_partial_template
+ assert_raises(ActionView::MissingTemplate) do
+ get :missing_partial
+ end
+ end
+
+ def test_render_call_to_partial_with_layout
+ get :render_call_to_partial_with_layout
+ assert_equal "Before (David)\nInside from partial (David)\nAfter", @response.body
+ end
+
+ def test_render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
+ get :render_call_to_partial_with_layout_in_main_layout_and_within_content_for_layout
+ assert_equal "Before (Anthony)\nInside from partial (Anthony)\nAfter\nBefore (David)\nInside from partial (David)\nAfter\nBefore (Ramm)\nInside from partial (Ramm)\nAfter", @response.body
end
end
@@ -501,6 +1321,12 @@ class EtagRenderTest < Test::Unit::TestCase
assert @response.body.empty?
end
+ def test_render_against_etag_request_should_have_no_content_length_when_match
+ @request.if_none_match = etag_for("hello david")
+ get :render_hello_world_from_variable
+ assert !@response.headers.has_key?("Content-Length")
+ end
+
def test_render_against_etag_request_should_200_when_no_match
@request.if_none_match = etag_for("hello somewhere else")
get :render_hello_world_from_variable
@@ -577,3 +1403,21 @@ class LastModifiedRenderTest < Test::Unit::TestCase
assert_equal @last_modified, @response.headers['Last-Modified']
end
end
+
+class RenderingLoggingTest < Test::Unit::TestCase
+ def setup
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ @controller = TestController.new
+
+ @request.host = "www.nextangle.com"
+ end
+
+ def test_logger_prints_layout_and_template_rendering_info
+ @controller.logger = MockLogger.new
+ get :layout_test
+ logged = @controller.logger.logged.find_all {|l| l =~ /render/i }
+ assert_equal "Rendering template within layouts/standard", logged[0]
+ assert_equal "Rendering test/hello_world", logged[1]
+ end
+end
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index e153b0cc98..1fea82e564 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -264,6 +264,19 @@ class ResourcesTest < Test::Unit::TestCase
end
end
+ def test_array_as_collection_or_member_method_value
+ with_restful_routing :messages, :collection => { :search => [:get, :post] }, :member => { :toggle => [:get, :post] } do
+ assert_restful_routes_for :messages do |options|
+ [:get, :post].each do |method|
+ assert_recognizes(options.merge(:action => 'search'), :path => "/messages/search", :method => method)
+ end
+ [:get, :post].each do |method|
+ assert_recognizes(options.merge(:action => 'toggle', :id => '1'), :path => '/messages/1/toggle', :method => method)
+ end
+ end
+ end
+ end
+
def test_with_new_action
with_restful_routing :messages, :new => { :preview => :post } do
preview_options = {:action => 'preview'}
@@ -366,6 +379,31 @@ class ResourcesTest < Test::Unit::TestCase
end
end
+ def test_shallow_nested_restful_routes
+ with_routing do |set|
+ set.draw do |map|
+ map.resources :threads, :shallow => true do |map|
+ map.resources :messages do |map|
+ map.resources :comments
+ end
+ end
+ end
+
+ assert_simply_restful_for :threads,
+ :shallow => true
+ assert_simply_restful_for :messages,
+ :name_prefix => 'thread_',
+ :path_prefix => 'threads/1/',
+ :shallow => true,
+ :options => { :thread_id => '1' }
+ assert_simply_restful_for :comments,
+ :name_prefix => 'message_',
+ :path_prefix => 'messages/2/',
+ :shallow => true,
+ :options => { :message_id => '2' }
+ end
+ end
+
def test_restful_routes_dont_generate_duplicates
with_restful_routing :messages do
routes = ActionController::Routing::Routes.routes
@@ -416,6 +454,32 @@ class ResourcesTest < Test::Unit::TestCase
end
end
+ def test_resources_has_many_hash_should_become_nested_resources
+ with_routing do |set|
+ set.draw do |map|
+ map.resources :threads, :has_many => { :messages => [ :comments, { :authors => :threads } ] }
+ end
+
+ assert_simply_restful_for :threads
+ assert_simply_restful_for :messages, :name_prefix => "thread_", :path_prefix => 'threads/1/', :options => { :thread_id => '1' }
+ assert_simply_restful_for :comments, :name_prefix => "thread_message_", :path_prefix => 'threads/1/messages/1/', :options => { :thread_id => '1', :message_id => '1' }
+ assert_simply_restful_for :authors, :name_prefix => "thread_message_", :path_prefix => 'threads/1/messages/1/', :options => { :thread_id => '1', :message_id => '1' }
+ assert_simply_restful_for :threads, :name_prefix => "thread_message_author_", :path_prefix => 'threads/1/messages/1/authors/1/', :options => { :thread_id => '1', :message_id => '1', :author_id => '1' }
+ end
+ end
+
+ def test_shallow_resource_has_many_should_become_shallow_nested_resources
+ with_routing do |set|
+ set.draw do |map|
+ map.resources :messages, :has_many => [ :comments, :authors ], :shallow => true
+ end
+
+ assert_simply_restful_for :messages, :shallow => true
+ assert_simply_restful_for :comments, :name_prefix => "message_", :path_prefix => 'messages/1/', :shallow => true, :options => { :message_id => '1' }
+ assert_simply_restful_for :authors, :name_prefix => "message_", :path_prefix => 'messages/1/', :shallow => true, :options => { :message_id => '1' }
+ end
+ end
+
def test_resource_has_one_should_become_nested_resources
with_routing do |set|
set.draw do |map|
@@ -427,6 +491,17 @@ class ResourcesTest < Test::Unit::TestCase
end
end
+ def test_shallow_resource_has_one_should_become_shallow_nested_resources
+ with_routing do |set|
+ set.draw do |map|
+ map.resources :messages, :has_one => :logo, :shallow => true
+ end
+
+ assert_simply_restful_for :messages, :shallow => true
+ assert_singleton_restful_for :logo, :name_prefix => 'message_', :path_prefix => 'messages/1/', :shallow => true, :options => { :message_id => '1' }
+ end
+ end
+
def test_singleton_resource_with_member_action
[:put, :post].each do |method|
with_singleton_resources :account, :member => { :reset => method } do
@@ -731,6 +806,13 @@ class ResourcesTest < Test::Unit::TestCase
options[:options] ||= {}
options[:options][:controller] = options[:controller] || controller_name.to_s
+ if options[:shallow]
+ options[:shallow_options] ||= {}
+ options[:shallow_options][:controller] = options[:options][:controller]
+ else
+ options[:shallow_options] = options[:options]
+ end
+
new_action = ActionController::Base.resources_path_names[:new] || "new"
edit_action = ActionController::Base.resources_path_names[:edit] || "edit"
if options[:path_names]
@@ -738,8 +820,10 @@ class ResourcesTest < Test::Unit::TestCase
edit_action = options[:path_names][:edit] if options[:path_names][:edit]
end
- collection_path = "/#{options[:path_prefix]}#{options[:as] || controller_name}"
- member_path = "#{collection_path}/1"
+ path = "#{options[:as] || controller_name}"
+ collection_path = "/#{options[:path_prefix]}#{path}"
+ shallow_path = "/#{options[:path_prefix] unless options[:shallow]}#{path}"
+ member_path = "#{shallow_path}/1"
new_path = "#{collection_path}/#{new_action}"
edit_member_path = "#{member_path}/#{edit_action}"
formatted_edit_member_path = "#{member_path}/#{edit_action}.xml"
@@ -747,10 +831,13 @@ class ResourcesTest < Test::Unit::TestCase
with_options(options[:options]) do |controller|
controller.assert_routing collection_path, :action => 'index'
controller.assert_routing new_path, :action => 'new'
- controller.assert_routing member_path, :action => 'show', :id => '1'
- controller.assert_routing edit_member_path, :action => 'edit', :id => '1'
controller.assert_routing "#{collection_path}.xml", :action => 'index', :format => 'xml'
controller.assert_routing "#{new_path}.xml", :action => 'new', :format => 'xml'
+ end
+
+ with_options(options[:shallow_options]) do |controller|
+ controller.assert_routing member_path, :action => 'show', :id => '1'
+ controller.assert_routing edit_member_path, :action => 'edit', :id => '1'
controller.assert_routing "#{member_path}.xml", :action => 'show', :id => '1', :format => 'xml'
controller.assert_routing formatted_edit_member_path, :action => 'edit', :id => '1', :format => 'xml'
end
@@ -758,18 +845,18 @@ class ResourcesTest < Test::Unit::TestCase
assert_recognizes(options[:options].merge(:action => 'index'), :path => collection_path, :method => :get)
assert_recognizes(options[:options].merge(:action => 'new'), :path => new_path, :method => :get)
assert_recognizes(options[:options].merge(:action => 'create'), :path => collection_path, :method => :post)
- assert_recognizes(options[:options].merge(:action => 'show', :id => '1'), :path => member_path, :method => :get)
- assert_recognizes(options[:options].merge(:action => 'edit', :id => '1'), :path => edit_member_path, :method => :get)
- assert_recognizes(options[:options].merge(:action => 'update', :id => '1'), :path => member_path, :method => :put)
- assert_recognizes(options[:options].merge(:action => 'destroy', :id => '1'), :path => member_path, :method => :delete)
-
- assert_recognizes(options[:options].merge(:action => 'index', :format => 'xml'), :path => "#{collection_path}.xml", :method => :get)
- assert_recognizes(options[:options].merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get)
- assert_recognizes(options[:options].merge(:action => 'create', :format => 'xml'), :path => "#{collection_path}.xml", :method => :post)
- assert_recognizes(options[:options].merge(:action => 'show', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :get)
- assert_recognizes(options[:options].merge(:action => 'edit', :id => '1', :format => 'xml'), :path => formatted_edit_member_path, :method => :get)
- assert_recognizes(options[:options].merge(:action => 'update', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :put)
- assert_recognizes(options[:options].merge(:action => 'destroy', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :delete)
+ assert_recognizes(options[:shallow_options].merge(:action => 'show', :id => '1'), :path => member_path, :method => :get)
+ assert_recognizes(options[:shallow_options].merge(:action => 'edit', :id => '1'), :path => edit_member_path, :method => :get)
+ assert_recognizes(options[:shallow_options].merge(:action => 'update', :id => '1'), :path => member_path, :method => :put)
+ assert_recognizes(options[:shallow_options].merge(:action => 'destroy', :id => '1'), :path => member_path, :method => :delete)
+
+ assert_recognizes(options[:options].merge(:action => 'index', :format => 'xml'), :path => "#{collection_path}.xml", :method => :get)
+ assert_recognizes(options[:options].merge(:action => 'new', :format => 'xml'), :path => "#{new_path}.xml", :method => :get)
+ assert_recognizes(options[:options].merge(:action => 'create', :format => 'xml'), :path => "#{collection_path}.xml", :method => :post)
+ assert_recognizes(options[:shallow_options].merge(:action => 'show', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :get)
+ assert_recognizes(options[:shallow_options].merge(:action => 'edit', :id => '1', :format => 'xml'), :path => formatted_edit_member_path, :method => :get)
+ assert_recognizes(options[:shallow_options].merge(:action => 'update', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :put)
+ assert_recognizes(options[:shallow_options].merge(:action => 'destroy', :id => '1', :format => 'xml'), :path => "#{member_path}.xml", :method => :delete)
yield options[:options] if block_given?
end
@@ -785,14 +872,24 @@ class ResourcesTest < Test::Unit::TestCase
options[:options] ||= {}
options[:options][:controller] = options[:controller] || controller_name.to_s
+ if options[:shallow]
+ options[:shallow_options] ||= {}
+ options[:shallow_options][:controller] = options[:options][:controller]
+ else
+ options[:shallow_options] = options[:options]
+ end
+
@controller = "#{options[:options][:controller].camelize}Controller".constantize.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
get :index, options[:options]
options[:options].delete :action
- full_prefix = "/#{options[:path_prefix]}#{options[:as] || controller_name}"
+ path = "#{options[:as] || controller_name}"
+ shallow_path = "/#{options[:path_prefix] unless options[:shallow]}#{path}"
+ full_path = "/#{options[:path_prefix]}#{path}"
name_prefix = options[:name_prefix]
+ shallow_prefix = "#{options[:name_prefix] unless options[:shallow]}"
new_action = "new"
edit_action = "edit"
@@ -801,15 +898,15 @@ class ResourcesTest < Test::Unit::TestCase
edit_action = options[:path_names][:edit] || "edit"
end
- assert_named_route "#{full_prefix}", "#{name_prefix}#{controller_name}_path", options[:options]
- assert_named_route "#{full_prefix}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge( :format => 'xml')
- assert_named_route "#{full_prefix}/1", "#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1')
- assert_named_route "#{full_prefix}/1.xml", "formatted_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml')
+ assert_named_route "#{full_path}", "#{name_prefix}#{controller_name}_path", options[:options]
+ assert_named_route "#{full_path}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge(:format => 'xml')
+ assert_named_route "#{shallow_path}/1", "#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1')
+ assert_named_route "#{shallow_path}/1.xml", "formatted_#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1', :format => 'xml')
- assert_named_route "#{full_prefix}/#{new_action}", "new_#{name_prefix}#{singular_name}_path", options[:options]
- assert_named_route "#{full_prefix}/#{new_action}.xml", "formatted_new_#{name_prefix}#{singular_name}_path", options[:options].merge( :format => 'xml')
- assert_named_route "#{full_prefix}/1/#{edit_action}", "edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1')
- assert_named_route "#{full_prefix}/1/#{edit_action}.xml", "formatted_edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml')
+ assert_named_route "#{full_path}/#{new_action}", "new_#{name_prefix}#{singular_name}_path", options[:options]
+ assert_named_route "#{full_path}/#{new_action}.xml", "formatted_new_#{name_prefix}#{singular_name}_path", options[:options].merge(:format => 'xml')
+ assert_named_route "#{shallow_path}/1/#{edit_action}", "edit_#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1')
+ assert_named_route "#{shallow_path}/1/#{edit_action}.xml", "formatted_edit_#{shallow_prefix}#{singular_name}_path", options[:shallow_options].merge(:id => '1', :format => 'xml')
yield options[:options] if block_given?
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 6cf134c26f..8bb1c49cbd 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -1297,6 +1297,29 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
end
end
+ def test_recognize_array_of_methods
+ Object.const_set(:BooksController, Class.new(ActionController::Base))
+ rs.draw do |r|
+ r.connect '/match', :controller => 'books', :action => 'get_or_post', :conditions => { :method => [:get, :post] }
+ r.connect '/match', :controller => 'books', :action => 'not_get_or_post'
+ end
+
+ @request = ActionController::TestRequest.new
+ @request.env["REQUEST_METHOD"] = 'POST'
+ @request.request_uri = "/match"
+ assert_nothing_raised { rs.recognize(@request) }
+ assert_equal 'get_or_post', @request.path_parameters[:action]
+
+ # have to recreate or else the RouteSet uses a cached version:
+ @request = ActionController::TestRequest.new
+ @request.env["REQUEST_METHOD"] = 'PUT'
+ @request.request_uri = "/match"
+ assert_nothing_raised { rs.recognize(@request) }
+ assert_equal 'not_get_or_post', @request.path_parameters[:action]
+ ensure
+ Object.send(:remove_const, :BooksController) rescue nil
+ end
+
def test_subpath_recognized
Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
@@ -1671,6 +1694,12 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
controller.send(:multi_url, 7, "hello", 5, :baz => "bar")
end
+ def test_named_route_url_method_with_ordered_parameters_and_empty_hash
+ controller = setup_named_route_test
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5",
+ controller.send(:multi_url, 7, "hello", 5, {})
+ end
+
def test_named_route_url_method_with_no_positional_arguments
controller = setup_named_route_test
assert_equal "http://named.route.test/people?baz=bar",
diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb
index abc9f930dd..a1f541fd7b 100644
--- a/actionpack/test/template/prototype_helper_test.rb
+++ b/actionpack/test/template/prototype_helper_test.rb
@@ -79,6 +79,8 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
link_to_remote("Remote outauthor", :failure => "alert(request.responseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:false, evalScripts:true}); return false;\">Remote outauthor</a>),
link_to_remote("Remote outauthor", :url => { :action => "whatnot" }, :type => :synchronous)
+ assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, insertion:'bottom'}); return false;\">Remote outauthor</a>),
+ link_to_remote("Remote outauthor", :url => { :action => "whatnot" }, :position => :bottom)
end
def test_link_to_remote_html_options
@@ -91,6 +93,19 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
link_to_remote("Remote", { :url => { :action => "whatnot's" } })
end
+ def test_button_to_remote
+ assert_dom_equal %(<input class=\"fine\" type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true});\" />),
+ button_to_remote("Remote outpost", { :url => { :action => "whatnot" }}, { :class => "fine" })
+ assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.reponseText)}});\" />),
+ button_to_remote("Remote outpost", :complete => "alert(request.reponseText)", :url => { :action => "whatnot" })
+ assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.reponseText)}});\" />),
+ button_to_remote("Remote outpost", :success => "alert(request.reponseText)", :url => { :action => "whatnot" })
+ assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}});\" />),
+ button_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot" })
+ assert_dom_equal %(<input type=\"button\" value=\"Remote outpost\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&amp;b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}});\" />),
+ button_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
+ end
+
def test_periodically_call_remote
assert_dom_equal %(<script type="text/javascript">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Updater('schremser_bier', 'http://www.example.com/mehr_bier', {asynchronous:true, evalScripts:true})}, 10)\n//]]>\n</script>),
periodically_call_remote(:update => "schremser_bier", :url => { :action => "mehr_bier" })
diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb
index 34a200b933..67aa047745 100644
--- a/actionpack/test/template/record_tag_helper_test.rb
+++ b/actionpack/test/template/record_tag_helper_test.rb
@@ -34,6 +34,14 @@ class RecordTagHelperTest < ActionView::TestCase
assert_dom_equal expected, actual
end
+ def test_block_not_in_erb_multiple_calls
+ expected = %(<div class="post bar" id="post_45">#{@post.body}</div>)
+ actual = div_for(@post, :class => "bar") { @post.body }
+ assert_dom_equal expected, actual
+ actual = div_for(@post, :class => "bar") { @post.body }
+ assert_dom_equal expected, actual
+ end
+
def test_block_works_with_content_tag_for_in_erb
__in_erb_template = ''
expected = %(<tr class="post" id="post_45">#{@post.body}</tr>)