aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2008-06-25 12:12:30 +0100
committerPratik Naik <pratiknaik@gmail.com>2008-06-25 12:12:30 +0100
commit01571c0fd73a31f78411d6cad6484ddd82ec4778 (patch)
treed0565f7ad3fd5a65aafbf191170094b90d7ef543 /actionpack
parentb5e9badea281ce0c371ff1c00461febe66f4e2b2 (diff)
parent670e22e3724791f51d639f409930fba5af920081 (diff)
downloadrails-01571c0fd73a31f78411d6cad6484ddd82ec4778.tar.gz
rails-01571c0fd73a31f78411d6cad6484ddd82ec4778.tar.bz2
rails-01571c0fd73a31f78411d6cad6484ddd82ec4778.zip
Merge commit 'mainstream/master'
Conflicts: actionpack/lib/action_view/helpers/javascript_helper.rb activesupport/lib/active_support/dependencies.rb activesupport/lib/active_support/inflector.rb activesupport/lib/active_support/values/time_zone.rb
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG26
-rw-r--r--actionpack/Rakefile12
-rw-r--r--actionpack/lib/action_controller/assertions/response_assertions.rb2
-rwxr-xr-xactionpack/lib/action_controller/base.rb35
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb61
-rw-r--r--actionpack/lib/action_controller/caching/fragments.rb18
-rw-r--r--actionpack/lib/action_controller/dispatcher.rb6
-rw-r--r--actionpack/lib/action_controller/integration.rb9
-rw-r--r--actionpack/lib/action_controller/layout.rb2
-rw-r--r--actionpack/lib/action_controller/performance_test.rb16
-rw-r--r--actionpack/lib/action_controller/polymorphic_routes.rb37
-rw-r--r--actionpack/lib/action_controller/rack_process.rb54
-rw-r--r--actionpack/lib/action_controller/record_identifier.rb33
-rwxr-xr-xactionpack/lib/action_controller/request.rb9
-rw-r--r--actionpack/lib/action_controller/resources.rb6
-rw-r--r--actionpack/lib/action_controller/routing.rb2
-rw-r--r--actionpack/lib/action_controller/routing/segments.rb2
-rw-r--r--actionpack/lib/action_controller/templates/rescues/layout.erb2
-rw-r--r--actionpack/lib/action_controller/vendor/html-scanner/html/document.rb2
-rw-r--r--actionpack/lib/action_controller/verification.rb2
-rw-r--r--actionpack/lib/action_view.rb10
-rw-r--r--actionpack/lib/action_view/base.rb135
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb59
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb58
-rw-r--r--actionpack/lib/action_view/helpers/javascript_helper.rb141
-rw-r--r--actionpack/lib/action_view/helpers/prototype_helper.rb14
-rw-r--r--actionpack/lib/action_view/helpers/record_tag_helper.rb5
-rw-r--r--actionpack/lib/action_view/helpers/tag_helper.rb48
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb14
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb62
-rw-r--r--actionpack/lib/action_view/inline_template.rb9
-rw-r--r--actionpack/lib/action_view/partial_template.rb78
-rw-r--r--actionpack/lib/action_view/template.rb109
-rw-r--r--actionpack/lib/action_view/template_file.rb88
-rw-r--r--actionpack/lib/action_view/template_finder.rb177
-rw-r--r--actionpack/lib/action_view/template_handler.rb1
-rw-r--r--actionpack/lib/action_view/template_handlers.rb46
-rw-r--r--actionpack/lib/action_view/template_handlers/builder.rb7
-rw-r--r--actionpack/lib/action_view/template_handlers/compilable.rb10
-rw-r--r--actionpack/lib/action_view/template_handlers/erb.rb10
-rw-r--r--actionpack/lib/action_view/test_case.rb5
-rw-r--r--actionpack/lib/action_view/view_load_paths.rb103
-rw-r--r--actionpack/test/controller/action_pack_assertions_test.rb23
-rw-r--r--actionpack/test/controller/base_test.rb18
-rw-r--r--actionpack/test/controller/caching_test.rb72
-rw-r--r--actionpack/test/controller/capture_test.rb20
-rwxr-xr-xactionpack/test/controller/cgi_test.rb50
-rw-r--r--actionpack/test/controller/dispatcher_test.rb4
-rw-r--r--actionpack/test/controller/html-scanner/document_test.rb25
-rw-r--r--actionpack/test/controller/integration_test.rb93
-rw-r--r--actionpack/test/controller/integration_upload_test.rb2
-rw-r--r--actionpack/test/controller/new_render_test.rb29
-rw-r--r--actionpack/test/controller/polymorphic_routes_test.rb33
-rw-r--r--actionpack/test/controller/rack_test.rb64
-rw-r--r--actionpack/test/controller/request_test.rb3
-rw-r--r--actionpack/test/controller/routing_test.rb3235
-rw-r--r--actionpack/test/controller/verification_test.rb51
-rw-r--r--actionpack/test/controller/view_paths_test.rb111
-rw-r--r--actionpack/test/fixtures/test/block_content_for.erb2
-rw-r--r--actionpack/test/fixtures/test/erb_content_for.erb2
-rw-r--r--actionpack/test/fixtures/test/non_erb_block_content_for.builder2
-rw-r--r--actionpack/test/fixtures/test/render_file_from_template.html.erb1
-rwxr-xr-xactionpack/test/template/date_helper_test.rb12
-rw-r--r--actionpack/test/template/form_helper_test.rb251
-rw-r--r--actionpack/test/template/form_options_helper_test.rb36
-rw-r--r--actionpack/test/template/form_tag_helper_test.rb62
-rw-r--r--actionpack/test/template/javascript_helper_test.rb22
-rw-r--r--actionpack/test/template/prototype_helper_test.rb162
-rw-r--r--actionpack/test/template/record_tag_helper_test.rb36
-rw-r--r--actionpack/test/template/tag_helper_test.rb44
-rw-r--r--actionpack/test/template/template_file_test.rb95
-rw-r--r--actionpack/test/template/template_finder_test.rb73
-rw-r--r--actionpack/test/template/template_object_test.rb37
-rw-r--r--actionpack/test/template/text_helper_test.rb6
-rw-r--r--actionpack/test/template/url_helper_test.rb20
77 files changed, 3340 insertions, 2889 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 9622029362..a28bf66b88 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,3 +1,29 @@
+*Edge*
+
+* Fix polymorphic_url with singleton resources. #461 [Tammer Saleh]
+
+* Replaced TemplateFinder abstraction with ViewLoadPaths [Josh Peek]
+
+* Added block-call style to link_to [Sam Stephenson/DHH]. Example:
+
+ <% link_to(@profile) do %>
+ <strong><%= @profile.name %></strong> -- <span>Check it out!!</span>
+ <% end %>
+
+* Performance: integration test benchmarking and profiling. [Jeremy Kemper]
+
+* Make caching more aware of mime types. Ensure request format is not considered while expiring cache. [Jonathan del Strother]
+
+* Drop ActionController::Base.allow_concurrency flag [Josh Peek]
+
+* More efficient concat and capture helpers. Remove ActionView::Base.erb_variable. [Jeremy Kemper]
+
+* Added page.reload functionality. Resolves #277. [Sean Huber]
+
+* Fixed Request#remote_ip to only raise hell if the HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR doesn't match (not just if they're both present) [Mark Imbriaco, Bradford Folkens]
+
+* Allow caches_action to accept a layout option [José Valim]
+
* Added Rack processor [Ezra Zygmuntowicz, Josh Peek]
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index b37f756c1e..1880f21f67 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -49,12 +49,14 @@ Rake::RDocTask.new { |rdoc|
rdoc.title = "Action Pack -- On rails from request to response"
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.options << '--charset' << 'utf-8'
- rdoc.template = "#{ENV['template']}.rb" if ENV['template']
+ rdoc.template = ENV['template'] ? "#{ENV['template']}.rb" : '../doc/template/horo'
if ENV['DOC_FILES']
rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
else
rdoc.rdoc_files.include('README', 'RUNNING_UNIT_TESTS', 'CHANGELOG')
- rdoc.rdoc_files.include('lib/**/*.rb')
+ rdoc.rdoc_files.include(Dir['lib/**/*.rb'] -
+ Dir['lib/*/vendor/**/*.rb'])
+ rdoc.rdoc_files.exclude('lib/actionpack.rb')
end
}
@@ -132,13 +134,13 @@ task :update_js => [ :update_scriptaculous ]
desc "Publish the API documentation"
task :pgem => [:package] do
- Rake::SshFilePublisher.new("davidhh@wrath.rubyonrails.org", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
- `ssh davidhh@wrath.rubyonrails.org './gemupdate.sh'`
+ Rake::SshFilePublisher.new("wrath.rubyonrails.org", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
+ `ssh wrath.rubyonrails.org './gemupdate.sh'`
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
- Rake::SshDirPublisher.new("davidhh@wrath.rubyonrails.org", "public_html/ap", "doc").upload
+ Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/ap", "doc").upload
end
desc "Publish the release files to RubyForge."
diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/assertions/response_assertions.rb
index c5fc6c7966..3deda0b45a 100644
--- a/actionpack/lib/action_controller/assertions/response_assertions.rb
+++ b/actionpack/lib/action_controller/assertions/response_assertions.rb
@@ -97,7 +97,7 @@ module ActionController
value['controller'] = value['controller'].to_s
if key == :actual && value['controller'].first != '/' && !value['controller'].include?('/')
new_controller_path = ActionController::Routing.controller_relative_to(value['controller'], @controller.class.controller_path)
- value['controller'] = new_controller_path if value['controller'] != new_controller_path && ActionController::Routing.possible_controllers.include?(new_controller_path)
+ value['controller'] = new_controller_path if value['controller'] != new_controller_path && ActionController::Routing.possible_controllers.include?(new_controller_path) && @response.redirected_to.is_a?(Hash)
end
value['controller'] = value['controller'][1..-1] if value['controller'].first == '/' # strip leading hash
end
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 6222c3205d..817b270feb 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -283,13 +283,6 @@ module ActionController #:nodoc:
@@debug_routes = true
cattr_accessor :debug_routes
- # Indicates to Mongrel or Webrick whether to allow concurrent action
- # processing. Your controller actions and any other code they call must
- # also behave well when called from concurrent threads. Turned off by
- # default.
- @@allow_concurrency = false
- cattr_accessor :allow_concurrency
-
# Modern REST web services often need to submit complex data to the web application.
# The <tt>@@param_parsers</tt> hash lets you register handlers which will process the HTTP body and add parameters to the
# <tt>params</tt> hash. These handlers are invoked for POST and PUT requests.
@@ -428,8 +421,7 @@ module ActionController #:nodoc:
end
def view_paths=(value)
- @view_paths = value
- ActionView::TemplateFinder.process_view_paths(value)
+ @view_paths = ActionView::ViewLoadPaths.new(Array(value)) if value
end
# Adds a view_path to the front of the view_paths array.
@@ -441,8 +433,7 @@ module ActionController #:nodoc:
#
def prepend_view_path(path)
@view_paths = superclass.view_paths.dup if @view_paths.nil?
- view_paths.unshift(*path)
- ActionView::TemplateFinder.process_view_paths(path)
+ @view_paths.unshift(*path)
end
# Adds a view_path to the end of the view_paths array.
@@ -454,8 +445,7 @@ module ActionController #:nodoc:
#
def append_view_path(path)
@view_paths = superclass.view_paths.dup if @view_paths.nil?
- view_paths.push(*path)
- ActionView::TemplateFinder.process_view_paths(path)
+ @view_paths.push(*path)
end
# Replace sensitive parameter data from the request log.
@@ -613,8 +603,8 @@ module ActionController #:nodoc:
#
# This takes the current URL as is and only exchanges the action. In contrast, <tt>url_for :action => 'print'</tt>
# would have slashed-off the path components after the changed action.
- def url_for(options = nil) #:doc:
- case options || {}
+ def url_for(options = {}) #:doc:
+ case options
when String
options
when Hash
@@ -647,11 +637,11 @@ module ActionController #:nodoc:
# View load paths for controller.
def view_paths
- @template.finder.view_paths
+ @template.view_paths
end
def view_paths=(value)
- @template.finder.view_paths = value # Mutex needed
+ @template.view_paths = ViewLoadPaths.new(value)
end
# Adds a view_path to the front of the view_paths array.
@@ -661,7 +651,7 @@ module ActionController #:nodoc:
# self.prepend_view_path(["views/default", "views/custom"])
#
def prepend_view_path(path)
- @template.finder.prepend_view_path(path) # Mutex needed
+ @template.view_paths.unshift(*path)
end
# Adds a view_path to the end of the view_paths array.
@@ -671,7 +661,7 @@ module ActionController #:nodoc:
# self.append_view_path(["views/default", "views/custom"])
#
def append_view_path(path)
- @template.finder.append_view_path(path) # Mutex needed
+ @template.view_paths.push(*path)
end
protected
@@ -1232,7 +1222,7 @@ module ActionController #:nodoc:
end
def template_exists?(template_name = default_template_name)
- @template.finder.file_exists?(template_name)
+ @template.file_exists?(template_name)
end
def template_public?(template_name = default_template_name)
@@ -1240,9 +1230,8 @@ module ActionController #:nodoc:
end
def template_exempt_from_layout?(template_name = default_template_name)
- extension = @template && @template.finder.pick_template_extension(template_name)
- name_with_extension = !template_name.include?('.') && extension ? "#{template_name}.#{extension}" : template_name
- @@exempt_from_layout.any? { |ext| name_with_extension =~ ext }
+ template_name = @template.send(:template_file_from_name, template_name) if @template
+ @@exempt_from_layout.any? { |ext| template_name.to_s =~ ext }
end
def default_template_name(action_name = self.action_name)
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index 1ef9e60a21..65a36f7f98 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -40,6 +40,8 @@ module ActionController #:nodoc:
# controller.send(:list_url, c.params[:id]) }
# end
#
+ # If you pass :layout => false, it will only cache your action content. It is useful when your layout has dynamic information.
+ #
module Actions
def self.included(base) #:nodoc:
base.extend(ClassMethods)
@@ -54,7 +56,8 @@ module ActionController #:nodoc:
def caches_action(*actions)
return unless cache_configured?
options = actions.extract_options!
- around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path)), {:only => actions}.merge(options))
+ cache_filter = ActionCacheFilter.new(:layout => options.delete(:layout), :cache_path => options.delete(:cache_path))
+ around_filter(cache_filter, {:only => actions}.merge(options))
end
end
@@ -64,10 +67,10 @@ module ActionController #:nodoc:
if options[:action].is_a?(Array)
options[:action].dup.each do |action|
- expire_fragment(ActionCachePath.path_for(self, options.merge({ :action => action })))
+ expire_fragment(ActionCachePath.path_for(self, options.merge({ :action => action }), false))
end
else
- expire_fragment(ActionCachePath.path_for(self, options))
+ expire_fragment(ActionCachePath.path_for(self, options, false))
end
end
@@ -81,7 +84,9 @@ module ActionController #:nodoc:
if cache = controller.read_fragment(cache_path.path)
controller.rendered_action_cache = true
set_content_type!(controller, cache_path.extension)
- controller.send!(:render_for_text, cache)
+ options = { :text => cache }
+ options.merge!(:layout => true) if cache_layout?
+ controller.send!(:render, options)
false
else
controller.action_cache_path = cache_path
@@ -90,7 +95,8 @@ module ActionController #:nodoc:
def after(controller)
return if controller.rendered_action_cache || !caching_allowed(controller)
- controller.write_fragment(controller.action_cache_path.path, controller.response.body)
+ action_content = cache_layout? ? content_for_layout(controller) : controller.response.body
+ controller.write_fragment(controller.action_cache_path.path, action_content)
end
private
@@ -105,22 +111,38 @@ module ActionController #:nodoc:
def caching_allowed(controller)
controller.request.get? && controller.response.headers['Status'].to_i == 200
end
+
+ def cache_layout?
+ @options[:layout] == false
+ end
+
+ def content_for_layout(controller)
+ controller.response.layout && controller.response.template.instance_variable_get('@content_for_layout')
+ end
end
class ActionCachePath
attr_reader :path, :extension
class << self
- def path_for(controller, options)
- new(controller, options).path
+ def path_for(controller, options, infer_extension=true)
+ new(controller, options, infer_extension).path
end
end
-
- def initialize(controller, options = {})
- @extension = extract_extension(controller.request.path)
+
+ # When true, infer_extension will look up the cache path extension from the request's path & format.
+ # This is desirable when reading and writing the cache, but not when expiring the cache - expire_action should expire the same files regardless of the request format.
+ def initialize(controller, options = {}, infer_extension=true)
+ if infer_extension and options.is_a? Hash
+ request_extension = extract_extension(controller.request)
+ options = options.reverse_merge(:format => request_extension)
+ end
path = controller.url_for(options).split('://').last
normalize!(path)
- add_extension!(path, @extension)
+ if infer_extension
+ @extension = request_extension
+ add_extension!(path, @extension)
+ end
@path = URI.unescape(path)
end
@@ -130,13 +152,22 @@ module ActionController #:nodoc:
end
def add_extension!(path, extension)
- path << ".#{extension}" if extension
+ path << ".#{extension}" if extension and !path.ends_with?(extension)
end
-
- def extract_extension(file_path)
+
+ def extract_extension(request)
# Don't want just what comes after the last '.' to accommodate multi part extensions
# such as tar.gz.
- file_path[/^[^.]+\.(.+)$/, 1]
+ extension = request.path[/^[^.]+\.(.+)$/, 1]
+
+ # If there's no extension in the path, check request.format
+ if extension.nil?
+ extension = request.format.to_sym.to_s
+ if extension=='all'
+ extension = nil
+ end
+ end
+ extension
end
end
end
diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb
index 578e031a17..45946421fc 100644
--- a/actionpack/lib/action_controller/caching/fragments.rb
+++ b/actionpack/lib/action_controller/caching/fragments.rb
@@ -61,16 +61,18 @@ module ActionController #:nodoc:
end
def fragment_for(block, name = {}, options = nil) #:nodoc:
- unless perform_caching then block.call; return end
-
- buffer = yield
-
- if cache = read_fragment(name, options)
- buffer.concat(cache)
+ if perform_caching
+ buffer = yield
+
+ if cache = read_fragment(name, options)
+ buffer.concat(cache)
+ else
+ pos = buffer.length
+ block.call
+ write_fragment(name, buffer[pos..-1], options)
+ end
else
- pos = buffer.length
block.call
- write_fragment(name, buffer[pos..-1], options)
end
end
diff --git a/actionpack/lib/action_controller/dispatcher.rb b/actionpack/lib/action_controller/dispatcher.rb
index b40f1ba9be..7df987d525 100644
--- a/actionpack/lib/action_controller/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatcher.rb
@@ -125,7 +125,7 @@ module ActionController
def call(env)
@request = RackRequest.new(env)
- @response = RackResponse.new
+ @response = RackResponse.new(@request)
dispatch
end
@@ -134,14 +134,14 @@ module ActionController
run_callbacks :prepare_dispatch
Routing::Routes.reload
- ActionView::TemplateFinder.reload! unless ActionView::Base.cache_template_loading
+ ActionController::Base.view_paths.reload!
end
# Cleanup the application by clearing out loaded classes so they can
# be reloaded on the next request without restarting the server.
def cleanup_application
ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
- Dependencies.clear
+ ActiveSupport::Dependencies.clear
ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
end
diff --git a/actionpack/lib/action_controller/integration.rb b/actionpack/lib/action_controller/integration.rb
index 12e1b4d493..2a732448f2 100644
--- a/actionpack/lib/action_controller/integration.rb
+++ b/actionpack/lib/action_controller/integration.rb
@@ -1,9 +1,10 @@
-require 'stringio'
-require 'uri'
-
+require 'active_support/test_case'
require 'action_controller/dispatcher'
require 'action_controller/test_process'
+require 'stringio'
+require 'uri'
+
module ActionController
module Integration #:nodoc:
# An integration Session instance represents a set of requests and responses
@@ -580,7 +581,7 @@ EOF
# end
# end
# end
- class IntegrationTest < Test::Unit::TestCase
+ class IntegrationTest < ActiveSupport::TestCase
include Integration::Runner
# Work around a bug in test/unit caused by the default test being named
diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb
index b5b59f2d7c..0721f71498 100644
--- a/actionpack/lib/action_controller/layout.rb
+++ b/actionpack/lib/action_controller/layout.rb
@@ -304,7 +304,7 @@ module ActionController #:nodoc:
end
def layout_directory?(layout_name)
- @template.finder.find_template_extension_from_handler(File.join('layouts', layout_name))
+ @template.view_paths.find_template_file_for_path("#{File.join('layouts', layout_name)}.#{@template.template_format}.erb") ? true : false
end
end
end
diff --git a/actionpack/lib/action_controller/performance_test.rb b/actionpack/lib/action_controller/performance_test.rb
new file mode 100644
index 0000000000..85543fffae
--- /dev/null
+++ b/actionpack/lib/action_controller/performance_test.rb
@@ -0,0 +1,16 @@
+require 'action_controller/integration'
+require 'active_support/testing/performance'
+require 'active_support/testing/default'
+
+module ActionController
+ # An integration test that runs a code profiler on your test methods.
+ # Profiling output for combinations of each test method, measurement, and
+ # output format are written to your tmp/performance directory.
+ #
+ # By default, process_time is measured and both flat and graph_html output
+ # formats are written, so you'll have two output files per test method.
+ class PerformanceTest < ActionController::IntegrationTest
+ include ActiveSupport::Testing::Performance
+ include ActiveSupport::Testing::Default
+ end
+end
diff --git a/actionpack/lib/action_controller/polymorphic_routes.rb b/actionpack/lib/action_controller/polymorphic_routes.rb
index 509fa6a08e..7c30bf0778 100644
--- a/actionpack/lib/action_controller/polymorphic_routes.rb
+++ b/actionpack/lib/action_controller/polymorphic_routes.rb
@@ -48,6 +48,9 @@ module ActionController
#
# # calls post_url(post)
# polymorphic_url(post) # => "http://example.com/posts/1"
+ # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1"
+ # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1"
+ # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1"
#
# ==== Options
#
@@ -83,8 +86,6 @@ module ActionController
else [ record_or_hash_or_array ]
end
- args << format if format
-
inflection =
case
when options[:action].to_s == "new"
@@ -96,6 +97,9 @@ module ActionController
else
:singular
end
+
+ args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
+ args << format if format
named_route = build_named_route_call(record_or_hash_or_array, namespace, inflection, options)
send!(named_route, *args)
@@ -136,11 +140,19 @@ module ActionController
else
record = records.pop
route = records.inject("") do |string, parent|
- string << "#{RecordIdentifier.send!("singular_class_name", parent)}_"
+ if parent.is_a?(Symbol) || parent.is_a?(String)
+ string << "#{parent}_"
+ else
+ string << "#{RecordIdentifier.send!("singular_class_name", parent)}_"
+ end
end
end
- route << "#{RecordIdentifier.send!("#{inflection}_class_name", record)}_"
+ if record.is_a?(Symbol) || record.is_a?(String)
+ route << "#{record}_"
+ else
+ route << "#{RecordIdentifier.send!("#{inflection}_class_name", record)}_"
+ end
action_prefix(options) + namespace + route + routing_type(options).to_s
end
@@ -163,16 +175,17 @@ module ActionController
end
end
+ # Remove the first symbols from the array and return the url prefix
+ # implied by those symbols.
def extract_namespace(record_or_hash_or_array)
- returning "" do |namespace|
- if record_or_hash_or_array.is_a?(Array)
- record_or_hash_or_array.delete_if do |record_or_namespace|
- if record_or_namespace.is_a?(String) || record_or_namespace.is_a?(Symbol)
- namespace << "#{record_or_namespace}_"
- end
- end
- end
+ return "" unless record_or_hash_or_array.is_a?(Array)
+
+ namespace_keys = []
+ while (key = record_or_hash_or_array.first) && key.is_a?(String) || key.is_a?(Symbol)
+ namespace_keys << record_or_hash_or_array.shift
end
+
+ namespace_keys.map {|k| "#{k}_"}.join
end
end
end
diff --git a/actionpack/lib/action_controller/rack_process.rb b/actionpack/lib/action_controller/rack_process.rb
index f42212e740..58a0a9280d 100644
--- a/actionpack/lib/action_controller/rack_process.rb
+++ b/actionpack/lib/action_controller/rack_process.rb
@@ -4,6 +4,7 @@ require 'action_controller/session/cookie_store'
module ActionController #:nodoc:
class RackRequest < AbstractRequest #:nodoc:
attr_accessor :env, :session_options
+ attr_reader :cgi
class SessionFixationAttempt < StandardError #:nodoc:
end
@@ -48,21 +49,12 @@ module ActionController #:nodoc:
def cookies
return {} unless @env["HTTP_COOKIE"]
- if @env["rack.request.cookie_string"] == @env["HTTP_COOKIE"]
- @env["rack.request.cookie_hash"]
- else
+ unless @env["rack.request.cookie_string"] == @env["HTTP_COOKIE"]
@env["rack.request.cookie_string"] = @env["HTTP_COOKIE"]
- # According to RFC 2109:
- # If multiple cookies satisfy the criteria above, they are ordered in
- # the Cookie header such that those with more specific Path attributes
- # precede those with less specific. Ordering with respect to other
- # attributes (e.g., Domain) is unspecified.
- @env["rack.request.cookie_hash"] =
- parse_query(@env["rack.request.cookie_string"], ';,').inject({}) { |h, (k,v)|
- h[k] = Array === v ? v.first : v
- h
- }
+ @env["rack.request.cookie_hash"] = CGI::Cookie::parse(@env["rack.request.cookie_string"])
end
+
+ @env["rack.request.cookie_hash"]
end
def host_with_port_without_standard_port_handling
@@ -169,37 +161,13 @@ end_msg
def session_options_with_string_keys
@session_options_with_string_keys ||= DEFAULT_SESSION_OPTIONS.merge(@session_options).stringify_keys
end
-
- # From Rack::Utils
- def parse_query(qs, d = '&;')
- params = {}
- (qs || '').split(/[#{d}] */n).inject(params) { |h,p|
- k, v = unescape(p).split('=',2)
- if cur = params[k]
- if cur.class == Array
- params[k] << v
- else
- params[k] = [cur, v]
- end
- else
- params[k] = v
- end
- }
-
- return params
- end
-
- def unescape(s)
- s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
- [$1.delete('%')].pack('H*')
- }
- end
end
class RackResponse < AbstractResponse #:nodoc:
attr_accessor :status
- def initialize
+ def initialize(request)
+ @request = request
@writer = lambda { |x| @body << x }
@block = nil
super()
@@ -221,6 +189,8 @@ end_msg
if @body.respond_to?(:call)
@writer = lambda { |x| callback.call(x) }
@body.call(self, self)
+ elsif @body.is_a?(String)
+ @body.each_line(&callback)
else
@body.each(&callback)
end
@@ -270,9 +240,9 @@ end_msg
else cookies << cookie.to_s
end
- @output_cookies.each { |c| cookies << c.to_s } if @output_cookies
+ @request.cgi.output_cookies.each { |c| cookies << c.to_s } if @request.cgi.output_cookies
- headers['Set-Cookie'] = [headers['Set-Cookie'], cookies].compact.join("\n")
+ headers['Set-Cookie'] = [headers['Set-Cookie'], cookies].flatten.compact
end
options.each { |k,v| headers[k] = v }
@@ -283,6 +253,8 @@ end_msg
end
class CGIWrapper < ::CGI
+ attr_reader :output_cookies
+
def initialize(request, *args)
@request = request
@args = *args
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index 643ff7e5f4..742d290ad6 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -31,18 +31,21 @@ module ActionController
module RecordIdentifier
extend self
+ JOIN = '_'.freeze
+ NEW = 'new'.freeze
+
# Returns plural/singular for a record or class. Example:
#
# partial_path(post) # => "posts/post"
# partial_path(Person) # => "people/person"
# partial_path(Person, "admin/games") # => "admin/people/person"
def partial_path(record_or_class, controller_path = nil)
- klass = class_from_record_or_class(record_or_class)
+ name = model_name_from_record_or_class(record_or_class)
if controller_path && controller_path.include?("/")
- "#{File.dirname(controller_path)}/#{klass.name.tableize}/#{klass.name.demodulize.underscore}"
+ "#{File.dirname(controller_path)}/#{name.partial_path}"
else
- "#{klass.name.tableize}/#{klass.name.demodulize.underscore}"
+ name.partial_path
end
end
@@ -56,21 +59,25 @@ module ActionController
# dom_class(post, :edit) # => "edit_post"
# dom_class(Person, :edit) # => "edit_person"
def dom_class(record_or_class, prefix = nil)
- [ prefix, singular_class_name(record_or_class) ].compact * '_'
+ singular = singular_class_name(record_or_class)
+ prefix ? "#{prefix}#{JOIN}#{singular}" : singular
end
# The DOM id convention is to use the singular form of an object or class with the id following an underscore.
# If no id is found, prefix with "new_" instead. Examples:
#
- # dom_id(Post.new(:id => 45)) # => "post_45"
+ # dom_id(Post.find(45)) # => "post_45"
# dom_id(Post.new) # => "new_post"
#
# If you need to address multiple instances of the same class in the same view, you can prefix the dom_id:
#
- # dom_id(Post.new(:id => 45), :edit) # => "edit_post_45"
+ # dom_id(Post.find(45), :edit) # => "edit_post_45"
def dom_id(record, prefix = nil)
- prefix ||= 'new' unless record.id
- [ prefix, singular_class_name(record), record.id ].compact * '_'
+ if record_id = record.id
+ "#{dom_class(record, prefix)}#{JOIN}#{record_id}"
+ else
+ dom_class(record, prefix || NEW)
+ end
end
# Returns the plural class name of a record or class. Examples:
@@ -78,7 +85,7 @@ module ActionController
# plural_class_name(post) # => "posts"
# plural_class_name(Highrise::Person) # => "highrise_people"
def plural_class_name(record_or_class)
- singular_class_name(record_or_class).pluralize
+ model_name_from_record_or_class(record_or_class).plural
end
# Returns the singular class name of a record or class. Examples:
@@ -86,12 +93,12 @@ module ActionController
# singular_class_name(post) # => "post"
# singular_class_name(Highrise::Person) # => "highrise_person"
def singular_class_name(record_or_class)
- class_from_record_or_class(record_or_class).name.underscore.tr('/', '_')
+ model_name_from_record_or_class(record_or_class).singular
end
private
- def class_from_record_or_class(record_or_class)
- record_or_class.is_a?(Class) ? record_or_class : record_or_class.class
+ def model_name_from_record_or_class(record_or_class)
+ (record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb
index 914163a709..38f8e10fe7 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/request.rb
@@ -134,14 +134,15 @@ module ActionController
# REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma-
# delimited list in the case of multiple chained proxies; the last
# address which is not trusted is the originating IP.
-
def remote_ip
if TRUSTED_PROXIES !~ @env['REMOTE_ADDR']
return @env['REMOTE_ADDR']
end
+ remote_ips = @env['HTTP_X_FORWARDED_FOR'] && @env['HTTP_X_FORWARDED_FOR'].split(',')
+
if @env.include? 'HTTP_CLIENT_IP'
- if @env.include? 'HTTP_X_FORWARDED_FOR'
+ if remote_ips && !remote_ips.include?(@env['HTTP_CLIENT_IP'])
# We don't know which came from the proxy, and which from the user
raise ActionControllerError.new(<<EOM)
IP spoofing attack?!
@@ -149,11 +150,11 @@ HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}
HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}
EOM
end
+
return @env['HTTP_CLIENT_IP']
end
- if @env.include? 'HTTP_X_FORWARDED_FOR' then
- remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',')
+ if remote_ips
while remote_ips.size > 1 && TRUSTED_PROXIES =~ remote_ips.last.strip
remote_ips.pop
end
diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb
index 79ec2b13b7..b11aa5625b 100644
--- a/actionpack/lib/action_controller/resources.rb
+++ b/actionpack/lib/action_controller/resources.rb
@@ -72,7 +72,7 @@ module ActionController
end
def conditions
- @conditions = @options[:conditions] || {}
+ @conditions ||= @options[:conditions] || {}
end
def path
@@ -80,9 +80,9 @@ module ActionController
end
def new_path
- new_action = self.options[:path_names][:new] if self.options[:path_names]
+ new_action = self.options[:path_names][:new] if self.options[:path_names]
new_action ||= Base.resources_path_names[:new]
- @new_path ||= "#{path}/#{new_action}"
+ @new_path ||= "#{path}/#{new_action}"
end
def member_path
diff --git a/actionpack/lib/action_controller/routing.rb b/actionpack/lib/action_controller/routing.rb
index 6aa266513d..8846dcc504 100644
--- a/actionpack/lib/action_controller/routing.rb
+++ b/actionpack/lib/action_controller/routing.rb
@@ -369,7 +369,7 @@ module ActionController
Routes = RouteSet.new
- ::Inflector.module_eval do
+ ActiveSupport::Inflector.module_eval do
# Ensures that routes are reloaded when Rails inflections are updated.
def inflections_with_route_reloading(&block)
returning(inflections_without_route_reloading(&block)) {
diff --git a/actionpack/lib/action_controller/routing/segments.rb b/actionpack/lib/action_controller/routing/segments.rb
index 864e068004..f0ad066bad 100644
--- a/actionpack/lib/action_controller/routing/segments.rb
+++ b/actionpack/lib/action_controller/routing/segments.rb
@@ -249,7 +249,7 @@ module ActionController
end
def extract_value
- "#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| URI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
+ "#{local_name} = hash[:#{key}] && Array(hash[:#{key}]).collect { |path_component| URI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}"
end
def default
diff --git a/actionpack/lib/action_controller/templates/rescues/layout.erb b/actionpack/lib/action_controller/templates/rescues/layout.erb
index d38f3e67f9..4a04742e40 100644
--- a/actionpack/lib/action_controller/templates/rescues/layout.erb
+++ b/actionpack/lib/action_controller/templates/rescues/layout.erb
@@ -1,4 +1,4 @@
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Action Controller: Exception caught</title>
<style>
diff --git a/actionpack/lib/action_controller/vendor/html-scanner/html/document.rb b/actionpack/lib/action_controller/vendor/html-scanner/html/document.rb
index 607fd186b9..b8d73c350d 100644
--- a/actionpack/lib/action_controller/vendor/html-scanner/html/document.rb
+++ b/actionpack/lib/action_controller/vendor/html-scanner/html/document.rb
@@ -17,7 +17,7 @@ module HTML #:nodoc:
@root = Node.new(nil)
node_stack = [ @root ]
while token = tokenizer.next
- node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token)
+ node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token, strict)
node_stack.last.children << node unless node.tag? && node.closing == :close
if node.tag?
diff --git a/actionpack/lib/action_controller/verification.rb b/actionpack/lib/action_controller/verification.rb
index 9f606e7b7c..35b12a7f13 100644
--- a/actionpack/lib/action_controller/verification.rb
+++ b/actionpack/lib/action_controller/verification.rb
@@ -116,7 +116,7 @@ module ActionController #:nodoc:
end
def apply_redirect_to(redirect_to_option) # :nodoc:
- redirect_to_option.is_a?(Symbol) ? 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.rb b/actionpack/lib/action_view.rb
index 5f4126e4e9..973020a768 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -21,13 +21,9 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
-require 'action_view/template_handler'
-require 'action_view/template_handlers/compilable'
-require 'action_view/template_handlers/builder'
-require 'action_view/template_handlers/erb'
-require 'action_view/template_handlers/rjs'
-
-require 'action_view/template_finder'
+require 'action_view/template_handlers'
+require 'action_view/template_file'
+require 'action_view/view_load_paths'
require 'action_view/template'
require 'action_view/partial_template'
require 'action_view/inline_template'
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index c236666dcd..91a86470d3 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -1,17 +1,17 @@
module ActionView #:nodoc:
class ActionViewError < StandardError #:nodoc:
end
-
+
class MissingTemplate < ActionViewError #:nodoc:
end
- # Action View templates can be written in three ways. If the template file has a <tt>.erb</tt> (or <tt>.rhtml</tt>) extension then it uses a mixture of ERb
- # (included in Ruby) and HTML. If the template file has a <tt>.builder</tt> (or <tt>.rxml</tt>) extension then Jim Weirich's Builder::XmlMarkup library is used.
+ # Action View templates can be written in three ways. If the template file has a <tt>.erb</tt> (or <tt>.rhtml</tt>) extension then it uses a mixture of ERb
+ # (included in Ruby) and HTML. If the template file has a <tt>.builder</tt> (or <tt>.rxml</tt>) extension then Jim Weirich's Builder::XmlMarkup library is used.
# If the template file has a <tt>.rjs</tt> extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.
- #
+ #
# = ERb
- #
- # You trigger ERb by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the
+ #
+ # You trigger ERb by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the
# following loop for names:
#
# <b>Names of all the people</b>
@@ -51,7 +51,7 @@ module ActionView #:nodoc:
# <title><%= @page_title %></title>
#
# == Passing local variables to sub templates
- #
+ #
# You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values:
#
# <%= render "shared/header", { :headline => "Welcome", :person => person } %>
@@ -77,8 +77,8 @@ module ActionView #:nodoc:
#
# == Builder
#
- # Builder templates are a more programmatic alternative to ERb. They are especially useful for generating XML content. An XmlMarkup object
- # named +xml+ is automatically made available to templates with a <tt>.builder</tt> extension.
+ # Builder templates are a more programmatic alternative to ERb. They are especially useful for generating XML content. An XmlMarkup object
+ # named +xml+ is automatically made available to templates with a <tt>.builder</tt> extension.
#
# Here are some basic examples:
#
@@ -87,7 +87,7 @@ module ActionView #:nodoc:
# xml.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A Link</a>
# xml.target("name"=>"compile", "option"=>"fast") # => <target option="fast" name="compile"\>
# # NOTE: order of attributes is not specified.
- #
+ #
# Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following:
#
# xml.div {
@@ -111,7 +111,7 @@ module ActionView #:nodoc:
# xml.description "Basecamp: Recent items"
# xml.language "en-us"
# xml.ttl "40"
- #
+ #
# for item in @recent_items
# xml.item do
# xml.title(item_title(item))
@@ -119,7 +119,7 @@ module ActionView #:nodoc:
# xml.pubDate(item_pubDate(item))
# xml.guid(@person.firm.account.url + @recent_items.url(item))
# xml.link(@person.firm.account.url + @recent_items.url(item))
- #
+ #
# xml.tag!("dc:creator", item.author_name) if item_has_creator?(item)
# end
# end
@@ -130,12 +130,12 @@ module ActionView #:nodoc:
#
# == JavaScriptGenerator
#
- # JavaScriptGenerator templates end in <tt>.rjs</tt>. Unlike conventional templates which are used to
- # render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to
- # modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax
+ # JavaScriptGenerator templates end in <tt>.rjs</tt>. Unlike conventional templates which are used to
+ # render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to
+ # modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax
# and make updates to the page where the request originated from.
- #
- # An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block.
+ #
+ # An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block.
#
# When an <tt>.rjs</tt> action is called with +link_to_remote+, the generated JavaScript is automatically evaluated. Example:
#
@@ -145,48 +145,45 @@ module ActionView #:nodoc:
#
# page.replace_html 'sidebar', :partial => 'sidebar'
# page.remove "person-#{@person.id}"
- # page.visual_effect :highlight, 'user-list'
+ # page.visual_effect :highlight, 'user-list'
#
# This refreshes the sidebar, removes a person element and highlights the user list.
- #
+ #
# See the ActionView::Helpers::PrototypeHelper::GeneratorMethods documentation for more details.
class Base
include ERB::Util
- attr_reader :finder
attr_accessor :base_path, :assigns, :template_extension, :first_render
attr_accessor :controller
-
+
attr_writer :template_format
attr_accessor :current_render_extension
- # Specify trim mode for the ERB compiler. Defaults to '-'.
- # See ERb documentation for suitable values.
- @@erb_trim_mode = '-'
- cattr_accessor :erb_trim_mode
+ attr_accessor :output_buffer
+
+ class << self
+ delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB'
+ end
# Specify whether file modification times should be checked to see if a template needs recompilation
@@cache_template_loading = false
cattr_accessor :cache_template_loading
-
+
def self.cache_template_extensions=(*args)
ActiveSupport::Deprecation.warn("config.action_view.cache_template_extensions option has been deprecated and has no effect. " <<
"Please remove it from your config files.", caller)
end
# Specify whether RJS responses should be wrapped in a try/catch block
- # that alert()s the caught exception (and then re-raises it).
+ # that alert()s the caught exception (and then re-raises it).
@@debug_rjs = false
cattr_accessor :debug_rjs
-
- @@erb_variable = '_erbout'
- cattr_accessor :erb_variable
-
+
attr_internal :request
delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers,
- :flash, :logger, :action_name, :to => :controller
-
+ :flash, :logger, :action_name, :controller_name, :to => :controller
+
module CompiledTemplates #:nodoc:
# holds compiled template code
end
@@ -222,11 +219,17 @@ module ActionView #:nodoc:
@assigns = assigns_for_first_render
@assigns_added = nil
@controller = controller
- @finder = TemplateFinder.new(self, view_paths)
+ self.view_paths = view_paths
+ end
+
+ attr_reader :view_paths
+
+ def view_paths=(paths)
+ @view_paths = ViewLoadPaths.new(Array(paths))
end
- # Renders the template present at <tt>template_path</tt>. If <tt>use_full_path</tt> is set to true,
- # it's relative to the view_paths array, otherwise it's absolute. The hash in <tt>local_assigns</tt>
+ # Renders the template present at <tt>template_path</tt>. If <tt>use_full_path</tt> is set to true,
+ # it's relative to the view_paths array, otherwise it's absolute. The hash in <tt>local_assigns</tt>
# is made available as local variables.
def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc:
if defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base) && !template_path.include?("/")
@@ -241,11 +244,11 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
render :partial => 'signup' # no mailer_name necessary
END_ERROR
end
-
+
Template.new(self, template_path, use_full_path, local_assigns).render_template
end
-
- # Renders the template present at <tt>template_path</tt> (relative to the view_paths array).
+
+ # Renders the template present at <tt>template_path</tt> (relative to the view_paths array).
# The hash in <tt>local_assigns</tt> is made available as local variables.
def render(options = {}, local_assigns = {}, &block) #:nodoc:
if options.is_a?(String)
@@ -253,12 +256,13 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
elsif options == :update
update_page(&block)
elsif options.is_a?(Hash)
+ use_full_path = options[:use_full_path]
options = options.reverse_merge(:locals => {}, :use_full_path => true)
if partial_layout = options.delete(:layout)
if block_given?
- wrap_content_for_layout capture(&block) do
- concat(render(options.merge(:partial => partial_layout)), block.binding)
+ wrap_content_for_layout capture(&block) do
+ concat(render(options.merge(:partial => partial_layout)))
end
else
wrap_content_for_layout render(options) do
@@ -266,7 +270,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
end
end
elsif options[:file]
- render_file(options[:file], options[:use_full_path], options[:locals])
+ render_file(options[:file], use_full_path || false, options[:locals])
elsif options[:partial] && options[:collection]
render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals])
elsif options[:partial]
@@ -314,11 +318,16 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
end
end
+ def file_exists?(template_path)
+ view_paths.template_exists?(template_file_from_name(template_path))
+ end
+
private
def wrap_content_for_layout(content)
- original_content_for_layout = @content_for_layout
- @content_for_layout = content
- returning(yield) { @content_for_layout = original_content_for_layout }
+ original_content_for_layout, @content_for_layout = @content_for_layout, content
+ yield
+ ensure
+ @content_for_layout = original_content_for_layout
end
# Evaluate the local assigns and pushes them to the view.
@@ -333,11 +342,43 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
def assign_variables_from_controller
@assigns.each { |key, value| instance_variable_set("@#{key}", value) }
end
-
+
def execute(template)
send(template.method, template.locals) do |*names|
instance_variable_get "@content_for_#{names.first || 'layout'}"
- end
+ end
+ end
+
+ def template_file_from_name(template_name)
+ template_name = TemplateFile.from_path(template_name)
+ pick_template_extension(template_name) unless template_name.extension
+ end
+
+ # Gets the extension for an existing template with the given template_path.
+ # Returns the format with the extension if that template exists.
+ #
+ # pick_template_extension('users/show')
+ # # => 'html.erb'
+ #
+ # pick_template_extension('users/legacy')
+ # # => "rhtml"
+ #
+ def pick_template_extension(file)
+ if f = self.view_paths.find_template_file_for_path(file.dup_with_extension(template_format)) || file_from_first_render(file)
+ f
+ elsif template_format == :js && f = self.view_paths.find_template_file_for_path(file.dup_with_extension(:html))
+ @template_format = :html
+ f
+ else
+ nil
+ end
+ end
+
+ # Determine the template extension from the <tt>@first_render</tt> filename
+ def file_from_first_render(file)
+ if extension = File.basename(@first_render.to_s)[/^[^.]+\.(.+)$/, 1]
+ file.dup_with_extension(extension)
+ end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index 9ea06568cf..990c30b90d 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -31,20 +31,16 @@ module ActionView
# </body></html>
#
def capture(*args, &block)
- # execute the block
- begin
- buffer = eval(ActionView::Base.erb_variable, block.binding)
- rescue
- buffer = nil
- end
-
- if buffer.nil?
- capture_block(*args, &block).to_s
+ # Return captured buffer in erb.
+ if block_called_from_erb?(block)
+ with_output_buffer { block.call(*args) }
+
+ # Return block result otherwise, but protect buffer also.
else
- capture_erb_with_buffer(buffer, *args, &block).to_s
+ with_output_buffer { return block.call(*args) }
end
end
-
+
# Calling content_for stores a block of markup in an identifier for later use.
# You can make subsequent calls to the stored content in other templates or the layout
# by passing the identifier as an argument to <tt>yield</tt>.
@@ -121,40 +117,19 @@ module ActionView
# named <tt>@content_for_#{name_of_the_content_block}</tt>. The preferred usage is now
# <tt><%= yield :footer %></tt>.
def content_for(name, content = nil, &block)
- existing_content_for = instance_variable_get("@content_for_#{name}").to_s
- new_content_for = existing_content_for + (block_given? ? capture(&block) : content)
- instance_variable_set("@content_for_#{name}", new_content_for)
+ ivar = "@content_for_#{name}"
+ content = capture(&block) if block_given?
+ instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}")
+ nil
end
private
- def capture_block(*args, &block)
- block.call(*args)
- end
-
- def capture_erb(*args, &block)
- buffer = eval(ActionView::Base.erb_variable, block.binding)
- capture_erb_with_buffer(buffer, *args, &block)
- end
-
- def capture_erb_with_buffer(buffer, *args, &block)
- pos = buffer.length
- block.call(*args)
-
- # extract the block
- data = buffer[pos..-1]
-
- # replace it in the original with empty string
- buffer[pos..-1] = ''
-
- data
- end
-
- def erb_content_for(name, &block)
- eval "@content_for_#{name} = (@content_for_#{name} || '') + capture_erb(&block)"
- end
-
- def block_content_for(name, &block)
- eval "@content_for_#{name} = (@content_for_#{name} || '') + capture_block(&block)"
+ def with_output_buffer(buf = '')
+ self.output_buffer, old_buffer = buf, output_buffer
+ yield
+ output_buffer
+ ensure
+ self.output_buffer = old_buffer
end
end
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index af43397cb7..f952ada691 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -249,9 +249,9 @@ module ActionView
args.unshift object
end
- concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}), proc.binding)
+ concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}))
fields_for(object_name, *(args << options), &proc)
- concat('</form>', proc.binding)
+ concat('</form>')
end
def apply_form_for_options!(object_or_array, options) #:nodoc:
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index c0cba24be4..f22c12c9ad 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -306,7 +306,7 @@ module ActionView
#
# NOTE: Only the option tags are returned, you have to wrap this call in
# a regular HTML select tag.
- def time_zone_options_for_select(selected = nil, priority_zones = nil, model = TimeZone)
+ def time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone)
zone_options = ""
zones = model.all
@@ -419,7 +419,7 @@ module ActionView
value = value(object)
content_tag("select",
add_options(
- time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || TimeZone),
+ time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || ActiveSupport::TimeZone),
options, value
), html_options
)
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index ca58f4ba26..ccebec3692 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -6,7 +6,7 @@ module ActionView
# Provides a number of methods for creating form tags that doesn't rely on an Active Record object assigned to the template like
# FormHelper does. Instead, you provide the names and values manually.
#
- # NOTE: The HTML options <tt>disabled</tt>, <tt>readonly</tt>, and <tt>multiple</tt> can all be treated as booleans. So specifying
+ # NOTE: The HTML options <tt>disabled</tt>, <tt>readonly</tt>, and <tt>multiple</tt> can all be treated as booleans. So specifying
# <tt>:disabled => true</tt> will give <tt>disabled="disabled"</tt>.
module FormTagHelper
# Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like
@@ -20,15 +20,15 @@ module ActionView
# * A list of parameters to feed to the URL the form will be posted to.
#
# ==== Examples
- # form_tag('/posts')
+ # form_tag('/posts')
# # => <form action="/posts" method="post">
#
- # form_tag('/posts/1', :method => :put)
+ # form_tag('/posts/1', :method => :put)
# # => <form action="/posts/1" method="put">
#
- # form_tag('/upload', :multipart => true)
+ # form_tag('/upload', :multipart => true)
# # => <form action="/upload" method="post" enctype="multipart/form-data">
- #
+ #
# <% form_tag '/posts' do -%>
# <div><%= submit_tag 'Save' %></div>
# <% end -%>
@@ -88,7 +88,7 @@ module ActionView
# * <tt>:size</tt> - The number of visible characters that will fit in the input.
# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
# * Any other key creates standard HTML attributes for the tag.
- #
+ #
# ==== Examples
# text_field_tag 'name'
# # => <input id="name" name="name" type="text" />
@@ -146,13 +146,13 @@ module ActionView
# # => <input id="token" name="token" type="hidden" value="VUBJKB23UIVI1UU1VOBVI@" />
#
# hidden_field_tag 'collected_input', '', :onchange => "alert('Input collected!')"
- # # => <input id="collected_input" name="collected_input" onchange="alert('Input collected!')"
+ # # => <input id="collected_input" name="collected_input" onchange="alert('Input collected!')"
# # type="hidden" value="" />
def hidden_field_tag(name, value = nil, options = {})
text_field_tag(name, value, options.stringify_keys.update("type" => "hidden"))
end
- # Creates a file upload field. If you are using file uploads then you will also need
+ # Creates a file upload field. If you are using file uploads then you will also need
# to set the multipart option for the form tag:
#
# <%= form_tag { :action => "post" }, { :multipart => true } %>
@@ -160,7 +160,7 @@ module ActionView
# <%= submit_tag %>
# <%= end_form_tag %>
#
- # The specified URL will then be passed a File object containing the selected file, or if the field
+ # The specified URL will then be passed a File object containing the selected file, or if the field
# was left blank, a StringIO object.
#
# ==== Options
@@ -181,7 +181,7 @@ module ActionView
# # => <input id="resume" name="resume" type="file" value="~/resume.doc" />
#
# file_field_tag 'user_pic', :accept => 'image/png,image/gif,image/jpeg'
- # # => <input accept="image/png,image/gif,image/jpeg" id="user_pic" name="user_pic" type="file" />
+ # # => <input accept="image/png,image/gif,image/jpeg" id="user_pic" name="user_pic" type="file" />
#
# file_field_tag 'file', :accept => 'text/html', :class => 'upload', :value => 'index.html'
# # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
@@ -286,7 +286,7 @@ module ActionView
tag :input, html_options
end
- # Creates a radio button; use groups of radio buttons named the same to allow users to
+ # Creates a radio button; use groups of radio buttons named the same to allow users to
# select from a group of options.
#
# ==== Options
@@ -313,14 +313,14 @@ module ActionView
tag :input, html_options
end
- # Creates a submit button with the text <tt>value</tt> as the caption.
+ # Creates a submit button with the text <tt>value</tt> as the caption.
#
# ==== Options
# * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm
# prompt with the question specified. If the user accepts, the form is
# processed normally, otherwise no action is taken.
# * <tt>:disabled</tt> - If true, the user will not be able to use this input.
- # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a disabled version
+ # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a disabled version
# of the submit button when the form is submitted.
# * Any other key creates standard HTML options for the tag.
#
@@ -335,7 +335,7 @@ module ActionView
# # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
#
# submit_tag "Complete sale", :disable_with => "Please wait..."
- # # => <input name="commit" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();"
+ # # => <input name="commit" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();"
# # type="submit" value="Complete sale" />
#
# submit_tag nil, :class => "form_submit"
@@ -346,7 +346,7 @@ module ActionView
# # name="commit" type="submit" value="Edit" />
def submit_tag(value = "Save changes", options = {})
options.stringify_keys!
-
+
if disable_with = options.delete("disable_with")
options["onclick"] = [
"this.setAttribute('originalValue', this.value)",
@@ -358,15 +358,15 @@ module ActionView
"return result;",
].join(";")
end
-
+
if confirm = options.delete("confirm")
options["onclick"] ||= ''
options["onclick"] += "return #{confirm_javascript_function(confirm)};"
end
-
+
tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys)
end
-
+
# Displays an image which when clicked will submit the form.
#
# <tt>source</tt> is passed to AssetTagHelper#image_path
@@ -407,12 +407,12 @@ module ActionView
# # => <fieldset><legend>Your details</legend><p><input id="name" name="name" type="text" /></p></fieldset>
def field_set_tag(legend = nil, &block)
content = capture(&block)
- concat(tag(:fieldset, {}, true), block.binding)
- concat(content_tag(:legend, legend), block.binding) unless legend.blank?
- concat(content, block.binding)
- concat("</fieldset>", block.binding)
+ concat(tag(:fieldset, {}, true))
+ concat(content_tag(:legend, legend)) unless legend.blank?
+ concat(content)
+ concat("</fieldset>")
end
-
+
private
def html_options_for_form(url_for_options, options, *parameters_for_url)
returning options.stringify_keys do |html_options|
@@ -420,7 +420,7 @@ module ActionView
html_options["action"] = url_for(url_for_options, *parameters_for_url)
end
end
-
+
def extra_tags_for_form(html_options)
case method = html_options.delete("method").to_s
when /^get$/i # must be case-insentive, but can't use downcase as might be nil
@@ -434,17 +434,17 @@ module ActionView
content_tag(:div, tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag, :style => 'margin:0;padding:0')
end
end
-
+
def form_tag_html(html_options)
extra_tags = extra_tags_for_form(html_options)
tag(:form, html_options, true) + extra_tags
end
-
+
def form_tag_in_block(html_options, &block)
content = capture(&block)
- concat(form_tag_html(html_options), block.binding)
- concat(content, block.binding)
- concat("</form>", block.binding)
+ concat(form_tag_html(html_options))
+ concat(content)
+ concat("</form>")
end
def token_tag
diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index ed931e064f..00092adc87 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -4,10 +4,10 @@ require 'action_view/helpers/prototype_helper'
module ActionView
module Helpers
# Provides functionality for working with JavaScript in your views.
- #
+ #
# == Ajax, controls and visual effects
- #
- # * For information on using Ajax, see
+ #
+ # * For information on using Ajax, see
# ActionView::Helpers::PrototypeHelper.
# * For information on using controls and visual effects, see
# ActionView::Helpers::ScriptaculousHelper.
@@ -20,22 +20,22 @@ module ActionView
# and ActionView::Helpers::ScriptaculousHelper), you must do one of the
# following:
#
- # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD
- # section of your page (recommended): This function will return
+ # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD
+ # section of your page (recommended): This function will return
# references to the JavaScript files created by the +rails+ command in
# your <tt>public/javascripts</tt> directory. Using it is recommended as
- # the browser can then cache the libraries instead of fetching all the
+ # the browser can then cache the libraries instead of fetching all the
# functions anew on every request.
- # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but
+ # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but
# will only include the Prototype core library, which means you are able
- # to use all basic AJAX functionality. For the Scriptaculous-based
- # JavaScript helpers, like visual effects, autocompletion, drag and drop
+ # to use all basic AJAX functionality. For the Scriptaculous-based
+ # JavaScript helpers, like visual effects, autocompletion, drag and drop
# and so on, you should use the method described above.
# * Use <tt><%= define_javascript_functions %></tt>: this will copy all the
# JavaScript support functions within a single script block. Not
# recommended.
#
- # For documentation on +javascript_include_tag+ see
+ # For documentation on +javascript_include_tag+ see
# ActionView::Helpers::AssetTagHelper.
module JavaScriptHelper
unless const_defined? :JAVASCRIPT_PATH
@@ -53,7 +53,7 @@ module ActionView
#
# The +function+ argument can be omitted in favor of an +update_page+
# block, which evaluates to a string when the template is rendered
- # (instead of making an Ajax request first).
+ # (instead of making an Ajax request first).
#
# The +html_options+ will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"
#
@@ -79,28 +79,23 @@ module ActionView
# <a href="#" id="more_link" onclick="try {
# $(&quot;details&quot;).visualEffect(&quot;toggle_blind&quot;);
# $(&quot;more_link&quot;).update(&quot;Show me less&quot;);
- # }
- # catch (e) {
- # alert('RJS error:\n\n' + e.toString());
+ # }
+ # catch (e) {
+ # alert('RJS error:\n\n' + e.toString());
# alert('$(\&quot;details\&quot;).visualEffect(\&quot;toggle_blind\&quot;);
# \n$(\&quot;more_link\&quot;).update(\&quot;Show me less\&quot;);');
- # throw e
+ # throw e
# };
# return false;">Show me more</a>
#
def link_to_function(name, *args, &block)
- html_options = args.extract_options!
- function = args[0] || ''
-
- html_options.symbolize_keys!
- function = update_page(&block) if block_given?
- content_tag(
- "a", name,
- html_options.merge({
- :href => html_options[:href] || "#",
- :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function}; return false;"
- })
- )
+ html_options = args.extract_options!.symbolize_keys
+
+ function = block_given? ? update_page(&block) : args[0] || ''
+ onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
+ href = html_options[:href] || '#'
+
+ content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick))
end
# Returns a button with the given +name+ text that'll trigger a JavaScript +function+ using the
@@ -112,7 +107,7 @@ module ActionView
#
# The +function+ argument can be omitted in favor of an +update_page+
# block, which evaluates to a string when the template is rendered
- # (instead of making an Ajax request first).
+ # (instead of making an Ajax request first).
#
# The +html_options+ will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"
#
@@ -128,45 +123,56 @@ module ActionView
# page[:details].visual_effect :toggle_slide
# end
def button_to_function(name, *args, &block)
- html_options = args.extract_options!
- function = args[0] || ''
-
- html_options.symbolize_keys!
- function = update_page(&block) if block_given?
- tag(:input, html_options.merge({
- :type => "button", :value => name,
- :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
- }))
+ html_options = args.extract_options!.symbolize_keys
+
+ function = block_given? ? update_page(&block) : args[0] || ''
+ onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
+
+ tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
end
- # Includes the Action Pack JavaScript libraries inside a single <script>
+ # Includes the Action Pack JavaScript libraries inside a single <script>
# tag. The function first includes prototype.js and then its core extensions,
# (determined by filenames starting with "prototype").
# Afterwards, any additional scripts will be included in undefined order.
#
# Note: The recommended approach is to copy the contents of
# lib/action_view/helpers/javascripts/ into your application's
- # public/javascripts/ directory, and use +javascript_include_tag+ to
+ # public/javascripts/ directory, and use +javascript_include_tag+ to
# create remote <script> links.
def define_javascript_functions
javascript = "<script type=\"#{Mime::JS}\">"
-
- # load prototype.js and its extensions first
+
+ # load prototype.js and its extensions first
prototype_libs = Dir.glob(File.join(JAVASCRIPT_PATH, 'prototype*')).sort.reverse
- prototype_libs.each do |filename|
+ prototype_libs.each do |filename|
javascript << "\n" << IO.read(filename)
end
-
+
# load other libraries
- (Dir.glob(File.join(JAVASCRIPT_PATH, '*')) - prototype_libs).each do |filename|
+ (Dir.glob(File.join(JAVASCRIPT_PATH, '*')) - prototype_libs).each do |filename|
javascript << "\n" << IO.read(filename)
end
javascript << '</script>'
end
+
+ JS_ESCAPE_MAP = {
+ '\\' => '\\\\',
+ '</' => '<\/',
+ "\r\n" => '\n',
+ "\n" => '\n',
+ "\r" => '\n',
+ '"' => '\\"',
+ "'" => "\\'" }
+
# Escape carrier returns and single and double quotes for JavaScript segments.
def escape_javascript(javascript)
- (javascript || '').gsub('\\','\0\0').gsub('</','<\/').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
+ if javascript
+ javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }
+ else
+ ''
+ end
end
# Returns a JavaScript tag with the +content+ inside. Example:
@@ -180,7 +186,7 @@ module ActionView
# </script>
#
# +html_options+ may be a hash of attributes for the <script> tag. Example:
- # javascript_tag "alert('All is good')", :defer => 'defer'
+ # javascript_tag "alert('All is good')", :defer => 'defer'
# # => <script defer="defer" type="text/javascript">alert('All is good')</script>
#
# Instead of passing the content as an argument, you can also use a block
@@ -189,46 +195,45 @@ module ActionView
# alert('All is good')
# <% end -%>
def javascript_tag(content_or_options_with_block = nil, html_options = {}, &block)
- if block_given?
- html_options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
- content = capture(&block)
- else
- content = content_or_options_with_block
- end
+ content =
+ if block_given?
+ html_options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
+ capture(&block)
+ else
+ content_or_options_with_block
+ end
+
+ tag = content_tag(:script, javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
- javascript_tag = content_tag("script", javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
-
- if block_given? && block_is_within_action_view?(block)
- concat(javascript_tag, block.binding)
+ if block_called_from_erb?(block)
+ concat(tag)
else
- javascript_tag
+ tag
end
end
def javascript_cdata_section(content) #:nodoc:
"\n//#{cdata_section("\n#{content}\n//")}\n"
end
-
+
protected
def options_for_javascript(options)
- '{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}'
+ if options.empty?
+ '{}'
+ else
+ "{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
+ end
end
-
+
def array_or_string_for_javascript(option)
- js_option = if option.kind_of?(Array)
+ if option.kind_of?(Array)
"['#{option.join('\',\'')}']"
elsif !option.nil?
"'#{option}'"
end
- js_option
- end
-
- private
- def block_is_within_action_view?(block)
- eval("defined? _erbout", block.binding)
end
end
-
+
JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper
end
end
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index c731824f18..9f6e550c09 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -382,9 +382,9 @@ module ActionView
args.unshift object
end
- concat(form_remote_tag(options), proc.binding)
+ concat(form_remote_tag(options))
fields_for(object_name, *(args << options), &proc)
- concat('</form>', proc.binding)
+ concat('</form>')
end
alias_method :form_remote_for, :remote_form_for
@@ -868,6 +868,16 @@ module ActionView
record "window.location.href = #{url.inspect}"
end
+ # Reloads the browser's current +location+ using JavaScript
+ #
+ # Examples:
+ #
+ # # Generates: window.location.reload();
+ # page.reload
+ def reload
+ record 'window.location.reload()'
+ end
+
# Calls the JavaScript +function+, optionally with the given +arguments+.
#
# If a block is given, the block will be passed to a new JavaScriptGenerator;
diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb
index 66c596f3a9..9bb235175e 100644
--- a/actionpack/lib/action_view/helpers/record_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb
@@ -51,9 +51,8 @@ module ActionView
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) })),
- block.binding
+ options.merge({ :class => "#{dom_class(record)} #{options[:class]}".strip, :id => dom_id(record, prefix) }))
end
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb
index 999cbfb52a..aeafd3906d 100644
--- a/actionpack/lib/action_view/helpers/tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/tag_helper.rb
@@ -1,5 +1,6 @@
require 'cgi'
require 'erb'
+require 'set'
module ActionView
module Helpers #:nodoc:
@@ -8,16 +9,17 @@ module ActionView
module TagHelper
include ERB::Util
- BOOLEAN_ATTRIBUTES = Set.new(%w(disabled readonly multiple))
+ BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple).to_set
+ BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map(&:to_sym))
- # Returns an empty HTML tag of type +name+ which by default is XHTML
- # compliant. Set +open+ to true to create an open tag compatible
- # with HTML 4.0 and below. Add HTML attributes by passing an attributes
+ # Returns an empty HTML tag of type +name+ which by default is XHTML
+ # compliant. Set +open+ to true to create an open tag compatible
+ # with HTML 4.0 and below. Add HTML attributes by passing an attributes
# hash to +options+. Set +escape+ to false to disable attribute value
# escaping.
#
# ==== Options
- # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
+ # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
# <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
# symbols or strings for the attribute names.
#
@@ -28,7 +30,7 @@ module ActionView
# tag("br", nil, true)
# # => <br>
#
- # tag("input", { :type => 'text', :disabled => true })
+ # tag("input", { :type => 'text', :disabled => true })
# # => <input type="text" disabled="disabled" />
#
# tag("img", { :src => "open & shut.png" })
@@ -37,17 +39,17 @@ module ActionView
# tag("img", { :src => "open &amp; shut.png" }, false, false)
# # => <img src="open &amp; shut.png" />
def tag(name, options = nil, open = false, escape = true)
- "<#{name}#{tag_options(options, escape) if options}" + (open ? ">" : " />")
+ "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}"
end
# Returns an HTML block tag of type +name+ surrounding the +content+. Add
- # HTML attributes by passing an attributes hash to +options+.
+ # HTML attributes by passing an attributes hash to +options+.
# Instead of passing the content as an argument, you can also use a block
# in which case, you pass your +options+ as the second parameter.
# Set escape to false to disable attribute value escaping.
#
# ==== Options
- # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
+ # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
# <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
# symbols or strings for the attribute names.
#
@@ -66,12 +68,15 @@ module ActionView
def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
if block_given?
options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
- content = capture(&block)
- content_tag = content_tag_string(name, content, options, escape)
- block_is_within_action_view?(block) ? concat(content_tag, block.binding) : content_tag
+ content_tag = content_tag_string(name, capture(&block), options, escape)
+
+ if block_called_from_erb?(block)
+ concat(content_tag)
+ else
+ content_tag
+ end
else
- content = content_or_options_with_block
- content_tag_string(name, content, options, escape)
+ content_tag_string(name, content_or_options_with_block, options, escape)
end
end
@@ -103,6 +108,16 @@ module ActionView
end
private
+ BLOCK_CALLED_FROM_ERB = 'defined? __in_erb_template'
+
+ # Check whether we're called from an erb template.
+ # We'd return a string in any other case, but erb <%= ... %>
+ # can't take an <% end %> later on, so we have to use <% ... %>
+ # and implicitly concat.
+ def block_called_from_erb?(block)
+ block && eval(BLOCK_CALLED_FROM_ERB, block)
+ end
+
def content_tag_string(name, content, options, escape = true)
tag_options = tag_options(options, escape) if options
"<#{name}#{tag_options}>#{content}</#{name}>"
@@ -114,7 +129,6 @@ module ActionView
if escape
options.each do |key, value|
next unless value
- key = key.to_s
value = BOOLEAN_ATTRIBUTES.include?(key) ? key : escape_once(value)
attrs << %(#{key}="#{value}")
end
@@ -124,10 +138,6 @@ module ActionView
" #{attrs.sort * ' '}" unless attrs.empty?
end
end
-
- def block_is_within_action_view?(block)
- eval("defined? _erbout", block.binding)
- end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 669a285424..d98c5bd0d5 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -15,18 +15,22 @@ module ActionView
#
# ==== Examples
# <%
- # concat "hello", binding
+ # concat "hello"
# # is the equivalent of <%= "hello" %>
#
# if (logged_in == true):
- # concat "Logged in!", binding
+ # concat "Logged in!"
# else
- # concat link_to('login', :action => login), binding
+ # concat link_to('login', :action => login)
# end
# # will either display "Logged in!" or a login link
# %>
- def concat(string, binding)
- eval(ActionView::Base.erb_variable, binding) << string
+ def concat(string, unused_binding = nil)
+ if unused_binding
+ ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.")
+ end
+
+ output_buffer << string
end
if RUBY_VERSION < '1.9'
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 7bb189420b..89166fe19a 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -90,6 +90,13 @@ module ActionView
# link will be used in place of a referrer if none exists. If nil is passed as
# a name, the link itself will become the name.
#
+ # ==== Signatures
+ #
+ # link_to(name, options = {}, html_options = nil)
+ # link_to(options = {}, html_options = nil) do
+ # # name
+ # end
+ #
# ==== Options
# * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm
# prompt with the question specified. If the user accepts, the link is
@@ -147,6 +154,13 @@ module ActionView
# link_to "Profiles", :controller => "profiles"
# # => <a href="/profiles">Profiles</a>
#
+ # You can use a block as well if your link target is hard to fit into the name parameter. ERb example:
+ #
+ # <% link_to(@profile) do %>
+ # <strong><%= @profile.name %></strong> -- <span>Check it out!!</span>
+ # <% end %>
+ # # => <a href="/profiles/1"><strong>David</strong> -- <span>Check it out!!</span></a>
+ #
# Classes and ids for CSS are easy to produce:
#
# link_to "Articles", articles_path, :id => "news", :class => "article"
@@ -189,27 +203,37 @@ module ActionView
# f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;
# var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method');
# m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); };return false;">Delete Image</a>
- def link_to(name, options = {}, html_options = nil)
- url = case options
- when String
- options
- when :back
- @controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
+ def link_to(*args, &block)
+ if block_given?
+ options = args.first || {}
+ html_options = args.second
+ concat(link_to(capture(&block), options, html_options))
+ else
+ name = args.first
+ options = args.second || {}
+ html_options = args.third
+
+ url = case options
+ when String
+ options
+ when :back
+ @controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
+ else
+ self.url_for(options)
+ end
+
+ if html_options
+ html_options = html_options.stringify_keys
+ href = html_options['href']
+ convert_options_to_javascript!(html_options, url)
+ tag_options = tag_options(html_options)
else
- self.url_for(options)
+ tag_options = nil
end
-
- if html_options
- html_options = html_options.stringify_keys
- href = html_options['href']
- convert_options_to_javascript!(html_options, url)
- tag_options = tag_options(html_options)
- else
- tag_options = nil
+
+ href_attr = "href=\"#{url}\"" unless href
+ "<a #{href_attr}#{tag_options}>#{name || url}</a>"
end
-
- href_attr = "href=\"#{url}\"" unless href
- "<a #{href_attr}#{tag_options}>#{name || url}</a>"
end
# Generates a form containing a single button that submits to the URL created
@@ -511,7 +535,7 @@ module ActionView
when method
"#{method_javascript_function(method, url, href)}return false;"
when popup
- popup_javascript_function(popup) + 'return false;'
+ "#{popup_javascript_function(popup)}return false;"
else
html_options["onclick"]
end
diff --git a/actionpack/lib/action_view/inline_template.rb b/actionpack/lib/action_view/inline_template.rb
index 87c012d181..fd0ad48302 100644
--- a/actionpack/lib/action_view/inline_template.rb
+++ b/actionpack/lib/action_view/inline_template.rb
@@ -1,20 +1,17 @@
module ActionView #:nodoc:
class InlineTemplate < Template #:nodoc:
-
def initialize(view, source, locals = {}, type = nil)
@view = view
- @finder = @view.finder
-
+
@source = source
@extension = type
@locals = locals || {}
-
+
@handler = self.class.handler_class_for_extension(@extension).new(@view)
end
-
+
def method_key
@source
end
-
end
end
diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb
index 1fb3aaee02..0cf996ca04 100644
--- a/actionpack/lib/action_view/partial_template.rb
+++ b/actionpack/lib/action_view/partial_template.rb
@@ -1,70 +1,70 @@
module ActionView #:nodoc:
class PartialTemplate < Template #:nodoc:
-
attr_reader :variable_name, :object
-
+
def initialize(view, partial_path, object = nil, locals = {})
- @path, @variable_name = extract_partial_name_and_path(view, partial_path)
+ @view_controller = view.controller if view.respond_to?(:controller)
+ set_path_and_variable_name!(partial_path)
super(view, @path, true, locals)
add_object_to_local_assigns!(object)
# This is needed here in order to compile template with knowledge of 'counter'
- initialize_counter
-
+ initialize_counter!
+
# Prepare early. This is a performance optimization for partial collections
prepare!
end
-
+
def render
- ActionController::Base.benchmark("Rendered #{@path}", Logger::DEBUG, false) do
+ ActionController::Base.benchmark("Rendered #{@path.path_without_format_and_extension}", Logger::DEBUG, false) do
@handler.render(self)
end
end
-
+
def render_member(object)
- @locals[@counter_name] += 1
@locals[:object] = @locals[@variable_name] = object
-
+
template = render_template
+ @locals[@counter_name] += 1
@locals.delete(@variable_name)
@locals.delete(:object)
-
+
template
end
-
+
def counter=(num)
@locals[@counter_name] = num
end
private
+ def add_object_to_local_assigns!(object)
+ @locals[:object] ||=
+ @locals[@variable_name] ||=
+ if object.is_a?(ActionView::Base::ObjectWrapper)
+ object.value
+ else
+ object
+ end || @view_controller.instance_variable_get("@#{variable_name}")
+ end
- def add_object_to_local_assigns!(object)
- @locals[:object] ||=
- @locals[@variable_name] ||=
- if object.is_a?(ActionView::Base::ObjectWrapper)
- object.value
- else
- object
- end || @view.controller.instance_variable_get("@#{variable_name}")
- end
-
- def extract_partial_name_and_path(view, partial_path)
- path, partial_name = partial_pieces(view, partial_path)
- [File.join(path, "_#{partial_name}"), partial_name.split('/').last.split('.').first.to_sym]
- end
-
- def partial_pieces(view, partial_path)
- if partial_path.include?('/')
- return File.dirname(partial_path), File.basename(partial_path)
- else
- return view.controller.class.controller_path, partial_path
+ def set_path_and_variable_name!(partial_path)
+ if partial_path.include?('/')
+ @variable_name = File.basename(partial_path)
+ @path = "#{File.dirname(partial_path)}/_#{@variable_name}"
+ elsif @view_controller
+ @variable_name = partial_path
+ @path = "#{@view_controller.class.controller_path}/_#{@variable_name}"
+ else
+ @variable_name = partial_path
+ @path = "_#{@variable_name}"
+ end
+
+ @variable_name = @variable_name.sub(/\..*$/, '').to_sym
+ end
+
+ def initialize_counter!
+ @counter_name ||= "#{@variable_name}_counter".to_sym
+ @locals[@counter_name] = 0
end
- end
-
- def initialize_counter
- @counter_name ||= "#{@variable_name}_counter".to_sym
- @locals[@counter_name] = 0
- end
-
end
end
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 369526188f..4c3f252c10 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -1,19 +1,20 @@
module ActionView #:nodoc:
class Template #:nodoc:
+ extend TemplateHandlers
attr_accessor :locals
- attr_reader :handler, :path, :extension, :filename, :path_without_extension, :method
+ attr_reader :handler, :path, :extension, :filename, :method
def initialize(view, path, use_full_path, locals = {})
@view = view
- @finder = @view.finder
+ @paths = view.view_paths
- # Clear the forward slash at the beginning if exists
- @path = use_full_path ? path.sub(/^\//, '') : path
- @view.first_render ||= @path
+ @original_path = path
+ @path = TemplateFile.from_path(path, !use_full_path)
+ @view.first_render ||= @path.to_s
@source = nil # Don't read the source until we know that it is required
set_extension_and_file_name(use_full_path)
-
+
@locals = locals || {}
@handler = self.class.handler_class_for_extension(@extension).new(@view)
end
@@ -29,12 +30,16 @@ module ActionView #:nodoc:
raise TemplateError.new(self, @view.assigns, e)
end
end
-
+
def render
prepare!
@handler.render(self)
end
+ def path_without_extension
+ @path.path_without_extension
+ end
+
def source
@source ||= File.read(self.filename)
end
@@ -44,13 +49,13 @@ module ActionView #:nodoc:
end
def base_path_for_exception
- @finder.find_base_path_for("#{@path_without_extension}.#{@extension}") || @finder.view_paths.first
+ (@paths.find_load_path_for_path(@path) || @paths.first).to_s
end
-
+
def prepare!
@view.send :evaluate_assigns
@view.current_render_extension = @extension
-
+
if @handler.compilable?
@handler.compile_template(self) # compile the given template, if necessary
@method = @view.method_names[method_key] # Set the method name for this template and run it
@@ -58,70 +63,32 @@ module ActionView #:nodoc:
end
private
-
- def set_extension_and_file_name(use_full_path)
- @path_without_extension, @extension = @finder.path_and_extension(@path)
- if use_full_path
- if @extension
- @filename = @finder.pick_template(@path_without_extension, @extension)
+ def set_extension_and_file_name(use_full_path)
+ @extension = @path.extension
+
+ if use_full_path
+ unless @extension
+ @path = @view.send(:template_file_from_name, @path)
+ raise_missing_template_exception unless @path
+ @extension = @path.extension
+ end
+
+ if @path = @paths.find_template_file_for_path(path)
+ @filename = @path.full_path
+ @extension = @path.extension
+ end
else
- @extension = @finder.pick_template_extension(@path).to_s
- raise_missing_template_exception unless @extension
-
- @filename = @finder.pick_template(@path, @extension)
- @extension = @extension.gsub(/^.+\./, '') # strip off any formats
+ @filename = @path.full_path
end
- else
- @filename = @path
- end
-
- raise_missing_template_exception if @filename.blank?
- end
-
- def raise_missing_template_exception
- full_template_path = @path.include?('.') ? @path : "#{@path}.#{@view.template_format}.erb"
- display_paths = @finder.view_paths.join(':')
- template_type = (@path =~ /layouts/i) ? 'layout' : 'template'
- raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}")
- end
-
- # Template Handlers
-
- @@template_handlers = HashWithIndifferentAccess.new
- @@default_template_handlers = nil
-
- # Register a class that knows how to handle template files with the given
- # extension. This can be used to implement new template types.
- # The constructor for the class must take the ActiveView::Base instance
- # as a parameter, and the class must implement a +render+ method that
- # takes the contents of the template to render as well as the Hash of
- # local assigns available to the template. The +render+ method ought to
- # return the rendered template as a string.
- def self.register_template_handler(extension, klass)
- @@template_handlers[extension.to_sym] = klass
- TemplateFinder.update_extension_cache_for(extension.to_s)
- end
- def self.template_handler_extensions
- @@template_handlers.keys.map(&:to_s).sort
- end
-
- def self.register_default_template_handler(extension, klass)
- register_template_handler(extension, klass)
- @@default_template_handlers = klass
- end
-
- def self.handler_class_for_extension(extension)
- (extension && @@template_handlers[extension.to_sym]) || @@default_template_handlers
- end
-
- register_default_template_handler :erb, TemplateHandlers::ERB
- register_template_handler :rjs, TemplateHandlers::RJS
- register_template_handler :builder, TemplateHandlers::Builder
+ raise_missing_template_exception if @filename.blank?
+ end
- # TODO: Depreciate old template extensions
- register_template_handler :rhtml, TemplateHandlers::ERB
- register_template_handler :rxml, TemplateHandlers::Builder
-
+ def raise_missing_template_exception
+ full_template_path = @original_path.include?('.') ? @original_path : "#{@original_path}.#{@view.template_format}.erb"
+ display_paths = @paths.join(':')
+ template_type = (@original_path =~ /layouts/i) ? 'layout' : 'template'
+ raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}")
+ end
end
end
diff --git a/actionpack/lib/action_view/template_file.rb b/actionpack/lib/action_view/template_file.rb
new file mode 100644
index 0000000000..dd66482b3c
--- /dev/null
+++ b/actionpack/lib/action_view/template_file.rb
@@ -0,0 +1,88 @@
+module ActionView #:nodoc:
+ # TemplateFile abstracts the pattern of querying a file path for its
+ # path with or without its extension. The path is only the partial path
+ # from the load path root e.g. "hello/index.html.erb" not
+ # "app/views/hello/index.html.erb"
+ class TemplateFile
+ def self.from_path(path, use_full_path = false)
+ path.is_a?(self) ? path : new(path, use_full_path)
+ end
+
+ def self.from_full_path(load_path, full_path)
+ file = new(full_path.split(load_path).last)
+ file.load_path = load_path
+ file.freeze
+ end
+
+ attr_accessor :load_path, :base_path, :name, :format, :extension
+ delegate :to_s, :inspect, :to => :path
+
+ def initialize(path, use_full_path = false)
+ path = path.dup
+
+ # Clear the forward slash in the beginning unless using full path
+ trim_forward_slash!(path) unless use_full_path
+
+ @base_path, @name, @format, @extension = split(path)
+ end
+
+ def freeze
+ @load_path.freeze
+ @base_path.freeze
+ @name.freeze
+ @format.freeze
+ @extension.freeze
+ super
+ end
+
+ def format_and_extension
+ extensions = [format, extension].compact.join(".")
+ extensions.blank? ? nil : extensions
+ end
+
+ def full_path
+ if load_path
+ "#{load_path}/#{path}"
+ else
+ path
+ end
+ end
+
+ def path
+ base_path.to_s + [name, format, extension].compact.join(".")
+ end
+
+ def path_without_extension
+ base_path.to_s + [name, format].compact.join(".")
+ end
+
+ def path_without_format_and_extension
+ "#{base_path}#{name}"
+ end
+
+ def dup_with_extension(extension)
+ file = dup
+ file.extension = extension ? extension.to_s : nil
+ file
+ end
+
+ private
+ def trim_forward_slash!(path)
+ path.sub!(/^\//, '')
+ end
+
+ # Returns file split into an array
+ # [base_path, name, format, extension]
+ def split(file)
+ if m = file.match(/^(.*\/)?(\w+)\.?(\w+)?\.?(\w+)?\.?(\w+)?$/)
+ if m[5] # Mulipart formats
+ [m[1], m[2], "#{m[3]}.#{m[4]}", m[5]]
+ elsif m[4] # Single format
+ [m[1], m[2], m[3], m[4]]
+ else # No format
+ [m[1], m[2], nil, m[3]]
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_view/template_finder.rb b/actionpack/lib/action_view/template_finder.rb
deleted file mode 100644
index 83b7e27c09..0000000000
--- a/actionpack/lib/action_view/template_finder.rb
+++ /dev/null
@@ -1,177 +0,0 @@
-module ActionView #:nodoc:
- class TemplateFinder #:nodoc:
-
- class InvalidViewPath < StandardError #:nodoc:
- attr_reader :unprocessed_path
- def initialize(path)
- @unprocessed_path = path
- super("Unprocessed view path found: #{@unprocessed_path.inspect}. Set your view paths with #append_view_path, #prepend_view_path, or #view_paths=.")
- end
- end
-
- cattr_reader :processed_view_paths
- @@processed_view_paths = Hash.new {|hash, key| hash[key] = []}
-
- cattr_reader :file_extension_cache
- @@file_extension_cache = Hash.new {|hash, key|
- hash[key] = Hash.new {|hash, key| hash[key] = []}
- }
-
- class << self #:nodoc:
-
- # This method is not thread safe. Mutex should be used whenever this is accessed from an instance method
- def process_view_paths(*view_paths)
- view_paths.flatten.compact.each do |dir|
- next if @@processed_view_paths.has_key?(dir)
- @@processed_view_paths[dir] = []
-
- #
- # Dir.glob("#{dir}/**/*/**") reads all the directories in view path and templates inside those directories
- # Dir.glob("#{dir}/**") reads templates residing at top level of view path
- #
- (Dir.glob("#{dir}/**/*/**") | Dir.glob("#{dir}/**")).each do |file|
- unless File.directory?(file)
- @@processed_view_paths[dir] << file.split(dir).last.sub(/^\//, '')
-
- # Build extension cache
- extension = file.split(".").last
- if template_handler_extensions.include?(extension)
- key = file.split(dir).last.sub(/^\//, '').sub(/\.(\w+)$/, '')
- @@file_extension_cache[dir][key] << extension
- end
- end
- end
- end
- end
-
- def update_extension_cache_for(extension)
- @@processed_view_paths.keys.each do |dir|
- Dir.glob("#{dir}/**/*.#{extension}").each do |file|
- key = file.split(dir).last.sub(/^\//, '').sub(/\.(\w+)$/, '')
- @@file_extension_cache[dir][key] << extension
- end
- end
- end
-
- def template_handler_extensions
- ActionView::Template.template_handler_extensions
- end
-
- def reload!
- view_paths = @@processed_view_paths.keys
-
- @@processed_view_paths = Hash.new {|hash, key| hash[key] = []}
- @@file_extension_cache = Hash.new {|hash, key|
- hash[key] = Hash.new {|hash, key| hash[key] = []}
- }
-
- process_view_paths(view_paths)
- end
- end
-
- attr_accessor :view_paths
-
- def initialize(*args)
- @template = args.shift
-
- @view_paths = args.flatten
- @view_paths = @view_paths.respond_to?(:find) ? @view_paths.dup : [*@view_paths].compact
- check_view_paths(@view_paths)
- end
-
- def prepend_view_path(path)
- @view_paths.unshift(*path)
-
- self.class.process_view_paths(path)
- end
-
- def append_view_path(path)
- @view_paths.push(*path)
-
- self.class.process_view_paths(path)
- end
-
- def view_paths=(path)
- @view_paths = path
- self.class.process_view_paths(path)
- end
-
- def pick_template(template_path, extension)
- file_name = "#{template_path}.#{extension}"
- base_path = find_base_path_for(file_name)
- base_path.blank? ? false : "#{base_path}/#{file_name}"
- end
- alias_method :template_exists?, :pick_template
-
- def file_exists?(template_path)
- # Clear the forward slash in the beginning if exists
- template_path = template_path.sub(/^\//, '')
-
- template_file_name, template_file_extension = path_and_extension(template_path)
-
- if template_file_extension
- template_exists?(template_file_name, template_file_extension)
- else
- template_exists?(template_file_name, pick_template_extension(template_path))
- end
- end
-
- def find_base_path_for(template_file_name)
- @view_paths.find { |path| @@processed_view_paths[path].include?(template_file_name) }
- end
-
- # Returns the view path that the full path resides in.
- def extract_base_path_from(full_path)
- @view_paths.find { |p| full_path[0..p.size - 1] == p }
- end
-
- # Gets the extension for an existing template with the given template_path.
- # Returns the format with the extension if that template exists.
- #
- # pick_template_extension('users/show')
- # # => 'html.erb'
- #
- # pick_template_extension('users/legacy')
- # # => "rhtml"
- #
- def pick_template_extension(template_path)
- if extension = find_template_extension_from_handler(template_path, @template.template_format) || find_template_extension_from_first_render
- extension
- elsif @template.template_format == :js && extension = find_template_extension_from_handler(template_path, :html)
- @template.template_format = :html
- extension
- end
- end
-
- def find_template_extension_from_handler(template_path, template_format = @template.template_format)
- formatted_template_path = "#{template_path}.#{template_format}"
-
- view_paths.each do |path|
- if (extensions = @@file_extension_cache[path][formatted_template_path]).any?
- return "#{template_format}.#{extensions.first}"
- elsif (extensions = @@file_extension_cache[path][template_path]).any?
- return extensions.first.to_s
- end
- end
- nil
- end
-
- # Splits the path and extension from the given template_path and returns as an array.
- def path_and_extension(template_path)
- template_path_without_extension = template_path.sub(/\.(\w+)$/, '')
- [ template_path_without_extension, $1 ]
- end
-
- # Determine the template extension from the <tt>@first_render</tt> filename
- def find_template_extension_from_first_render
- File.basename(@template.first_render.to_s)[/^[^.]+\.(.+)$/, 1]
- end
-
- private
- def check_view_paths(view_paths)
- view_paths.each do |path|
- raise InvalidViewPath.new(path) unless @@processed_view_paths.has_key?(path)
- end
- end
- end
-end
diff --git a/actionpack/lib/action_view/template_handler.rb b/actionpack/lib/action_view/template_handler.rb
index ec407e3fb3..39e578e586 100644
--- a/actionpack/lib/action_view/template_handler.rb
+++ b/actionpack/lib/action_view/template_handler.rb
@@ -1,6 +1,5 @@
module ActionView
class TemplateHandler
-
def self.line_offset
0
end
diff --git a/actionpack/lib/action_view/template_handlers.rb b/actionpack/lib/action_view/template_handlers.rb
new file mode 100644
index 0000000000..1471e99e01
--- /dev/null
+++ b/actionpack/lib/action_view/template_handlers.rb
@@ -0,0 +1,46 @@
+require 'action_view/template_handler'
+require 'action_view/template_handlers/compilable'
+require 'action_view/template_handlers/builder'
+require 'action_view/template_handlers/erb'
+require 'action_view/template_handlers/rjs'
+
+module ActionView #:nodoc:
+ module TemplateHandlers #:nodoc:
+ def self.extended(base)
+ base.register_default_template_handler :erb, TemplateHandlers::ERB
+ base.register_template_handler :rjs, TemplateHandlers::RJS
+ base.register_template_handler :builder, TemplateHandlers::Builder
+
+ # TODO: Depreciate old template extensions
+ base.register_template_handler :rhtml, TemplateHandlers::ERB
+ base.register_template_handler :rxml, TemplateHandlers::Builder
+ end
+
+ @@template_handlers = {}
+ @@default_template_handlers = nil
+
+ # Register a class that knows how to handle template files with the given
+ # extension. This can be used to implement new template types.
+ # The constructor for the class must take the ActiveView::Base instance
+ # as a parameter, and the class must implement a +render+ method that
+ # takes the contents of the template to render as well as the Hash of
+ # local assigns available to the template. The +render+ method ought to
+ # return the rendered template as a string.
+ def register_template_handler(extension, klass)
+ @@template_handlers[extension.to_sym] = klass
+ end
+
+ def template_handler_extensions
+ @@template_handlers.keys.map(&:to_s).sort
+ end
+
+ def register_default_template_handler(extension, klass)
+ register_template_handler(extension, klass)
+ @@default_template_handlers = klass
+ end
+
+ def handler_class_for_extension(extension)
+ (extension && @@template_handlers[extension.to_sym]) || @@default_template_handlers
+ end
+ end
+end
diff --git a/actionpack/lib/action_view/template_handlers/builder.rb b/actionpack/lib/action_view/template_handlers/builder.rb
index f76d89777a..ee02ce1a6f 100644
--- a/actionpack/lib/action_view/template_handlers/builder.rb
+++ b/actionpack/lib/action_view/template_handlers/builder.rb
@@ -11,10 +11,11 @@ module ActionView
def compile(template)
content_type_handler = (@view.send!(:controller).respond_to?(:response) ? "controller.response" : "controller")
+
"#{content_type_handler}.content_type ||= Mime::XML\n" +
- "xml = ::Builder::XmlMarkup.new(:indent => 2)\n" +
- template.source +
- "\nxml.target!\n"
+ "xml = ::Builder::XmlMarkup.new(:indent => 2)\n" +
+ template.source +
+ "\nxml.target!\n"
end
def cache_fragment(block, name = {}, options = nil)
diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb
index 25bd0fea7f..783456ab53 100644
--- a/actionpack/lib/action_view/template_handlers/compilable.rb
+++ b/actionpack/lib/action_view/template_handlers/compilable.rb
@@ -106,7 +106,13 @@ module ActionView
locals_code << "#{key} = local_assigns[:#{key}]\n"
end
- "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend"
+ <<-end_src
+ def #{render_symbol}(local_assigns)
+ old_output_buffer = output_buffer;#{locals_code}#{body}
+ ensure
+ self.output_buffer = old_output_buffer
+ end
+ end_src
end
# Return true if the given template was compiled for a superset of the keys in local_assigns
@@ -125,4 +131,4 @@ module ActionView
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/template_handlers/erb.rb b/actionpack/lib/action_view/template_handlers/erb.rb
index 15a9064461..ac715e30c2 100644
--- a/actionpack/lib/action_view/template_handlers/erb.rb
+++ b/actionpack/lib/action_view/template_handlers/erb.rb
@@ -42,13 +42,19 @@ module ActionView
class ERB < TemplateHandler
include Compilable
+ # Specify trim mode for the ERB compiler. Defaults to '-'.
+ # See ERb documentation for suitable values.
+ cattr_accessor :erb_trim_mode
+ self.erb_trim_mode = '-'
+
def compile(template)
- ::ERB.new(template.source, nil, @view.erb_trim_mode).src
+ src = ::ERB.new(template.source, nil, erb_trim_mode, '@output_buffer').src
+ "__in_erb_template=true;#{src}"
end
def cache_fragment(block, name = {}, options = nil) #:nodoc:
@view.fragment_for(block, name, options) do
- eval(ActionView::Base.erb_variable, block.binding)
+ @view.response.template.output_buffer
end
end
end
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 16fedd9732..1a3c93c283 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -37,6 +37,8 @@ module ActionView
if helper_class && !self.class.ancestors.include?(helper_class)
self.class.send(:include, helper_class)
end
+
+ self.output_buffer = ''
end
class TestController < ActionController::Base
@@ -48,6 +50,9 @@ module ActionView
end
end
+ protected
+ attr_accessor :output_buffer
+
private
def method_missing(selector, *args)
controller = TestController.new
diff --git a/actionpack/lib/action_view/view_load_paths.rb b/actionpack/lib/action_view/view_load_paths.rb
new file mode 100644
index 0000000000..e873d96aa0
--- /dev/null
+++ b/actionpack/lib/action_view/view_load_paths.rb
@@ -0,0 +1,103 @@
+module ActionView #:nodoc:
+ class ViewLoadPaths < Array #:nodoc:
+ def self.type_cast(obj)
+ obj.is_a?(String) ? LoadPath.new(obj) : obj
+ end
+
+ class LoadPath #:nodoc:
+ attr_reader :path, :paths
+ delegate :to_s, :inspect, :to => :path
+
+ def initialize(path)
+ @path = path.freeze
+ reload!
+ end
+
+ def eql?(view_path)
+ view_path.is_a?(ViewPath) && @path == view_path.path
+ end
+
+ def hash
+ @path.hash
+ end
+
+ # Rebuild load path directory cache
+ def reload!
+ @paths = {}
+
+ files.each do |file|
+ @paths[file.path] = file
+ @paths[file.path_without_extension] ||= file
+ end
+
+ @paths.freeze
+ end
+
+ # Tries to find the extension for the template name.
+ # If it does not it exist, tries again without the format extension
+ # find_template_file_for_partial_path('users/show') => 'html.erb'
+ # find_template_file_for_partial_path('users/legacy') => 'rhtml'
+ def find_template_file_for_partial_path(file)
+ @paths[file.path] || @paths[file.path_without_extension] || @paths[file.path_without_format_and_extension]
+ end
+
+ private
+ # Get all the files and directories in the path
+ def files_in_path
+ Dir.glob("#{@path}/**/*/**") | Dir.glob("#{@path}/**")
+ end
+
+ # Create an array of all the files within the path
+ def files
+ files_in_path.map do |file|
+ TemplateFile.from_full_path(@path, file) unless File.directory?(file)
+ end.compact
+ end
+ end
+
+ def initialize(*args)
+ super(*args).map! { |obj| self.class.type_cast(obj) }
+ end
+
+ def reload!
+ each { |path| path.reload! }
+ end
+
+ def <<(obj)
+ super(self.class.type_cast(obj))
+ end
+
+ def push(*objs)
+ delete_paths!(objs)
+ super(*objs.map { |obj| self.class.type_cast(obj) })
+ end
+
+ def unshift(*objs)
+ delete_paths!(objs)
+ super(*objs.map { |obj| self.class.type_cast(obj) })
+ end
+
+ def template_exists?(file)
+ find_load_path_for_path(file) ? true : false
+ end
+
+ def find_load_path_for_path(file)
+ find { |path| path.paths[file.to_s] }
+ end
+
+ def find_template_file_for_path(file)
+ file = TemplateFile.from_path(file)
+ each do |path|
+ if f = path.find_template_file_for_partial_path(file)
+ return f
+ end
+ end
+ nil
+ end
+
+ private
+ def delete_paths!(paths)
+ paths.each { |p1| delete_if { |p2| p1.to_s == p2.to_s } }
+ end
+ end
+end
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index f152b1d19c..c25e9e1df6 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -137,6 +137,9 @@ class AssertResponseWithUnexpectedErrorController < ActionController::Base
end
end
+class UserController < ActionController::Base
+end
+
module Admin
class InnerModuleController < ActionController::Base
def index
@@ -174,7 +177,7 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
# let's get this party started
def setup
ActionController::Routing::Routes.reload
- ActionController::Routing.use_controllers!(%w(action_pack_assertions admin/inner_module content admin/user))
+ ActionController::Routing.use_controllers!(%w(action_pack_assertions admin/inner_module user content admin/user))
@controller = ActionPackAssertionsController.new
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
end
@@ -268,7 +271,7 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
assert_redirected_to admin_inner_module_path
end
end
-
+
def test_assert_redirected_to_top_level_named_route_from_nested_controller
with_routing do |set|
set.draw do |map|
@@ -277,11 +280,25 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
end
@controller = Admin::InnerModuleController.new
process :redirect_to_top_level_named_route
- # passes -> assert_redirected_to "http://test.host/action_pack_assertions/foo"
+ # assert_redirected_to "http://test.host/action_pack_assertions/foo" would pass because of exact match early return
assert_redirected_to "/action_pack_assertions/foo"
end
end
+ def test_assert_redirected_to_top_level_named_route_with_same_controller_name_in_both_namespaces
+ with_routing do |set|
+ set.draw do |map|
+ # this controller exists in the admin namespace as well which is the only difference from previous test
+ map.top_level '/user/:id', :controller => 'user', :action => 'index'
+ map.connect ':controller/:action/:id'
+ end
+ @controller = Admin::InnerModuleController.new
+ process :redirect_to_top_level_named_route
+ # assert_redirected_to top_level_url('foo') would pass because of exact match early return
+ assert_redirected_to top_level_path('foo')
+ end
+ end
+
# -- standard request/response object testing --------------------------------
# make sure that the template objects exist
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index b28717597e..34c0200fe8 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -169,6 +169,22 @@ class DefaultUrlOptionsTest < Test::Unit::TestCase
end
end
+class EmptyUrlOptionsTest < Test::Unit::TestCase
+ def setup
+ @controller = NonEmptyController.new
+
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+
+ @request.host = 'www.example.com'
+ end
+
+ def test_ensure_url_for_works_as_expected_when_called_with_no_options_if_default_url_options_is_not_set
+ get :public_action
+ assert_equal "http://www.example.com/non_empty/public_action", @controller.url_for
+ end
+end
+
class EnsureNamedRoutesWorksTicket22BugTest < Test::Unit::TestCase
def test_named_routes_still_work
ActionController::Routing::Routes.draw do |map|
@@ -180,4 +196,4 @@ class EnsureNamedRoutesWorksTicket22BugTest < Test::Unit::TestCase
ensure
ActionController::Routing::Routes.load!
end
-end \ No newline at end of file
+end
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index f9b6b87bc6..14cf0a86a1 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -156,6 +156,7 @@ class ActionCachingTestController < ActionController::Base
caches_action :show, :cache_path => 'http://test.host/custom/show'
caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
caches_action :with_layout
+ caches_action :layout_false, :layout => false
layout 'talk_from_action.erb'
@@ -181,11 +182,16 @@ class ActionCachingTestController < ActionController::Base
alias_method :show, :index
alias_method :edit, :index
alias_method :destroy, :index
+ alias_method :layout_false, :with_layout
def expire
expire_action :controller => 'action_caching_test', :action => 'index'
render :nothing => true
end
+ def expire_xml
+ expire_action :controller => 'action_caching_test', :action => 'index', :format => 'xml'
+ render :nothing => true
+ end
end
class MockTime < Time
@@ -211,6 +217,7 @@ class ActionCachingMockController
mocked_path = @mock_path
Object.new.instance_eval(<<-EVAL)
def path; '#{@mock_path}' end
+ def format; 'all' end
self
EVAL
end
@@ -263,6 +270,19 @@ class ActionCacheTest < Test::Unit::TestCase
assert_equal @response.body, read_fragment('hostname.com/action_caching_test/with_layout')
end
+ def test_action_cache_with_layout_and_layout_cache_false
+ get :layout_false
+ cached_time = content_to_cache
+ assert_not_equal cached_time, @response.body
+ assert fragment_exist?('hostname.com/action_caching_test/layout_false')
+ reset!
+
+ get :layout_false
+ assert_not_equal cached_time, @response.body
+
+ assert_equal cached_time, read_fragment('hostname.com/action_caching_test/layout_false')
+ end
+
def test_action_cache_conditional_options
@request.env['HTTP_ACCEPT'] = 'application/json'
get :index
@@ -311,6 +331,20 @@ class ActionCacheTest < Test::Unit::TestCase
assert_equal new_cached_time, @response.body
end
+ def test_cache_expiration_isnt_affected_by_request_format
+ get :index
+ cached_time = content_to_cache
+ reset!
+
+ @request.set_REQUEST_URI "/action_caching_test/expire.xml"
+ get :expire, :format => :xml
+ reset!
+
+ get :index
+ new_cached_time = content_to_cache
+ assert_not_equal cached_time, @response.body
+ end
+
def test_cache_is_scoped_by_subdomain
@request.host = 'jamis.hostname.com'
get :index
@@ -355,11 +389,35 @@ class ActionCacheTest < Test::Unit::TestCase
end
def test_xml_version_of_resource_is_treated_as_different_cache
- @mock_controller.mock_url_for = 'http://example.org/posts/'
- @mock_controller.mock_path = '/posts/index.xml'
- path_object = @path_class.new(@mock_controller, {})
- assert_equal 'xml', path_object.extension
- assert_equal 'example.org/posts/index.xml', path_object.path
+ with_routing do |set|
+ ActionController::Routing::Routes.draw do |map|
+ map.connect ':controller/:action.:format'
+ map.connect ':controller/:action'
+ end
+
+ get :index, :format => 'xml'
+ cached_time = content_to_cache
+ assert_equal cached_time, @response.body
+ assert fragment_exist?('hostname.com/action_caching_test/index.xml')
+ reset!
+
+ get :index, :format => 'xml'
+ assert_equal cached_time, @response.body
+ assert_equal 'application/xml', @response.content_type
+ reset!
+
+ @request.env['HTTP_ACCEPT'] = "application/xml"
+ get :index
+ assert_equal cached_time, @response.body
+ assert_equal 'application/xml', @response.content_type
+ reset!
+
+ get :expire_xml
+ reset!
+
+ get :index, :format => 'xml'
+ assert_not_equal cached_time, @response.body
+ end
end
def test_correct_content_type_is_returned_for_cache_hit
@@ -421,6 +479,8 @@ class FragmentCachingTest < Test::Unit::TestCase
@controller.request = @request
@controller.response = @response
@controller.send(:initialize_current_url)
+ @controller.send(:initialize_template_class, @response)
+ @controller.send(:assign_shortcuts, @request, @response)
end
def test_fragment_cache_key
@@ -510,7 +570,7 @@ class FragmentCachingTest < Test::Unit::TestCase
def test_cache_erb_fragment
@store.write('views/expensive', 'fragment content')
- _erbout = 'generated till now -> '
+ @controller.response.template.output_buffer = 'generated till now -> '
assert_equal( 'generated till now -> fragment content',
ActionView::TemplateHandlers::ERB.new(@controller).cache_fragment(Proc.new{ }, 'expensive'))
diff --git a/actionpack/test/controller/capture_test.rb b/actionpack/test/controller/capture_test.rb
index aaafea3920..2604844b84 100644
--- a/actionpack/test/controller/capture_test.rb
+++ b/actionpack/test/controller/capture_test.rb
@@ -11,16 +11,8 @@ class CaptureController < ActionController::Base
def content_for_with_parameter
render :layout => "talk_from_action"
end
-
- def content_for_concatenated
- render :layout => "talk_from_action"
- end
- def erb_content_for
- render :layout => "talk_from_action"
- end
-
- def block_content_for
+ def content_for_concatenated
render :layout => "talk_from_action"
end
@@ -62,21 +54,11 @@ class CaptureTest < Test::Unit::TestCase
assert_equal expected_content_for_output, @response.body
end
- def test_erb_content_for
- get :erb_content_for
- assert_equal expected_content_for_output, @response.body
- end
-
def test_should_set_content_for_with_parameter
get :content_for_with_parameter
assert_equal expected_content_for_output, @response.body
end
- def test_block_content_for
- get :block_content_for
- assert_equal expected_content_for_output, @response.body
- end
-
def test_non_erb_block_content_for
get :non_erb_block_content_for
assert_equal expected_content_for_output, @response.body
diff --git a/actionpack/test/controller/cgi_test.rb b/actionpack/test/controller/cgi_test.rb
index f0f3a4b826..1b1ded4615 100755
--- a/actionpack/test/controller/cgi_test.rb
+++ b/actionpack/test/controller/cgi_test.rb
@@ -115,35 +115,37 @@ class CgiRequestNeedsRewoundTest < BaseCgiTest
end
end
-class CgiResponseTest < BaseCgiTest
- def setup
- super
- @fake_cgi.expects(:header).returns("HTTP/1.0 200 OK\nContent-Type: text/html\n")
- @response = ActionController::CgiResponse.new(@fake_cgi)
- @output = StringIO.new('')
- end
-
- def test_simple_output
- @response.body = "Hello, World!"
+uses_mocha 'CGI Response' do
+ class CgiResponseTest < BaseCgiTest
+ def setup
+ super
+ @fake_cgi.expects(:header).returns("HTTP/1.0 200 OK\nContent-Type: text/html\n")
+ @response = ActionController::CgiResponse.new(@fake_cgi)
+ @output = StringIO.new('')
+ end
- @response.out(@output)
- assert_equal "HTTP/1.0 200 OK\nContent-Type: text/html\nHello, World!", @output.string
- end
+ def test_simple_output
+ @response.body = "Hello, World!"
- def test_head_request
- @fake_cgi.env_table['REQUEST_METHOD'] = 'HEAD'
- @response.body = "Hello, World!"
+ @response.out(@output)
+ assert_equal "HTTP/1.0 200 OK\nContent-Type: text/html\nHello, World!", @output.string
+ end
- @response.out(@output)
- assert_equal "HTTP/1.0 200 OK\nContent-Type: text/html\n", @output.string
- end
+ def test_head_request
+ @fake_cgi.env_table['REQUEST_METHOD'] = 'HEAD'
+ @response.body = "Hello, World!"
- def test_streaming_block
- @response.body = Proc.new do |response, output|
- 5.times { |n| output.write(n) }
+ @response.out(@output)
+ assert_equal "HTTP/1.0 200 OK\nContent-Type: text/html\n", @output.string
end
- @response.out(@output)
- assert_equal "HTTP/1.0 200 OK\nContent-Type: text/html\n01234", @output.string
+ def test_streaming_block
+ @response.body = Proc.new do |response, output|
+ 5.times { |n| output.write(n) }
+ end
+
+ @response.out(@output)
+ assert_equal "HTTP/1.0 200 OK\nContent-Type: text/html\n01234", @output.string
+ end
end
end
diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb
index eea0813ed5..911fcab67b 100644
--- a/actionpack/test/controller/dispatcher_test.rb
+++ b/actionpack/test/controller/dispatcher_test.rb
@@ -27,14 +27,14 @@ class DispatcherTest < Test::Unit::TestCase
def test_clears_dependencies_after_dispatch_if_in_loading_mode
ActionController::Routing::Routes.expects(:reload).once
- Dependencies.expects(:clear).once
+ ActiveSupport::Dependencies.expects(:clear).once
dispatch(@output, false)
end
def test_leaves_dependencies_after_dispatch_if_not_in_loading_mode
ActionController::Routing::Routes.expects(:reload).never
- Dependencies.expects(:clear).never
+ ActiveSupport::Dependencies.expects(:clear).never
dispatch
end
diff --git a/actionpack/test/controller/html-scanner/document_test.rb b/actionpack/test/controller/html-scanner/document_test.rb
index 0519533dbd..1c3facb9e3 100644
--- a/actionpack/test/controller/html-scanner/document_test.rb
+++ b/actionpack/test/controller/html-scanner/document_test.rb
@@ -120,4 +120,29 @@ HTML
assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => "")
assert doc.find(:tag => "div", :attributes => { :id => "map" }, :content => nil)
end
+
+ def test_parse_invalid_document
+ assert_nothing_raised do
+ doc = HTML::Document.new("<html>
+ <table>
+ <tr>
+ <td style=\"color: #FFFFFF; height: 17px; onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" style=\"cursor:pointer; height: 17px;\"; nowrap onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" onmouseout=\"this.bgColor='#0066cc'; this.style.color='#FFFFFF'\" onmouseover=\"this.bgColor='#ffffff'; this.style.color='#0033cc'\">About Us</td>
+ </tr>
+ </table>
+ </html>")
+ end
+ end
+
+ def test_invalid_document_raises_exception_when_strict
+ assert_raises RuntimeError do
+ doc = HTML::Document.new("<html>
+ <table>
+ <tr>
+ <td style=\"color: #FFFFFF; height: 17px; onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" style=\"cursor:pointer; height: 17px;\"; nowrap onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" onmouseout=\"this.bgColor='#0066cc'; this.style.color='#FFFFFF'\" onmouseover=\"this.bgColor='#ffffff'; this.style.color='#0033cc'\">About Us</td>
+ </tr>
+ </table>
+ </html>", true)
+ end
+ end
+
end
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index 62c00c5b9a..475e13897b 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'action_controller/integration'
+require 'action_controller/routing'
uses_mocha 'integration' do
@@ -12,12 +13,12 @@ end
class SessionTest < Test::Unit::TestCase
include IntegrationSessionStubbing
-
+
def setup
@session = ActionController::Integration::Session.new
stub_integration_session(@session)
end
-
+
def test_https_bang_works_and_sets_truth_by_default
assert !@session.https?
@session.https!
@@ -196,7 +197,7 @@ class SessionTest < Test::Unit::TestCase
@session.expects(:process).with(:head,path,params,headers_after_xhr)
@session.xml_http_request(:head,path,params,headers)
end
-
+
def test_xml_http_request_override_accept
path = "/index"; params = "blah"; headers = {:location => 'blah', "Accept" => "application/xml"}
headers_after_xhr = headers.merge(
@@ -227,7 +228,6 @@ class IntegrationTestTest < Test::Unit::TestCase
assert_equal ::ActionController::Integration::Session, session2.class
assert_not_equal session1, session2
end
-
end
# Tests that integration tests don't call Controller test methods for processing.
@@ -246,7 +246,90 @@ class IntegrationTestUsesCorrectClass < ActionController::IntegrationTest
assert_nothing_raised("'#{verb}' should use integration test methods") { send!(verb, '/') }
end
end
+end
+
+class IntegrationProcessTest < ActionController::IntegrationTest
+ class IntegrationController < ActionController::Base
+ session :off
+
+ def get
+ render :text => "OK", :status => 200
+ end
+
+ def post
+ render :text => "Created", :status => 201
+ end
+
+ def cookie_monster
+ cookies["cookie_1"] = nil
+ cookies["cookie_3"] = "chocolate"
+ render :text => "Gone", :status => 410
+ end
+ end
+ def test_get
+ with_test_route_set do
+ get '/get'
+ assert_equal 200, status
+ assert_equal "OK", status_message
+ assert_equal "200 OK", response.headers["Status"]
+ assert_equal ["200 OK"], headers["status"]
+ assert_equal [], response.headers["cookie"]
+ assert_equal [], headers["cookie"]
+ assert_equal({}, cookies)
+ assert_equal "OK", response.body
+ assert_kind_of HTML::Document, html_document
+ assert_equal 1, request_count
+ end
+ end
+
+ def test_post
+ with_test_route_set do
+ post '/post'
+ assert_equal 201, status
+ assert_equal "Created", status_message
+ assert_equal "201 Created", response.headers["Status"]
+ assert_equal ["201 Created"], headers["status"]
+ assert_equal [], response.headers["cookie"]
+ assert_equal [], headers["cookie"]
+ assert_equal({}, cookies)
+ assert_equal "Created", response.body
+ assert_kind_of HTML::Document, html_document
+ assert_equal 1, request_count
+ end
+ end
+
+ def test_cookie_monster
+ with_test_route_set do
+ self.cookies['cookie_1'] = "sugar"
+ self.cookies['cookie_2'] = "oatmeal"
+ get '/cookie_monster'
+ assert_equal 410, status
+ assert_equal "Gone", status_message
+ assert_equal "410 Gone", response.headers["Status"]
+ assert_equal ["410 Gone"], headers["status"]
+ assert_equal nil, response.headers["Set-Cookie"]
+ assert_equal ["cookie_1=; path=/", "cookie_3=chocolate; path=/"], headers['set-cookie']
+ assert_equal [[], ["chocolate"]], response.headers["cookie"]
+ assert_equal [], headers["cookie"]
+ assert_equal({"cookie_1"=>"", "cookie_2"=>"oatmeal", "cookie_3"=>"chocolate"}, cookies)
+ assert_equal "Gone", response.body
+ end
+ end
+
+ private
+ def with_test_route_set
+ with_routing do |set|
+ set.draw do |map|
+ map.with_options :controller => "IntegrationProcessTest::Integration" do |c|
+ c.connect '/get', :action => "get"
+ c.connect '/post', :action => "post"
+ c.connect '/cookie_monster', :action => "cookie_monster"
+ end
+ end
+ yield
+ end
+ end
end
-end # uses_mocha
+end
diff --git a/actionpack/test/controller/integration_upload_test.rb b/actionpack/test/controller/integration_upload_test.rb
index 33df1131cb..4af9b7e697 100644
--- a/actionpack/test/controller/integration_upload_test.rb
+++ b/actionpack/test/controller/integration_upload_test.rb
@@ -28,7 +28,7 @@ class SessionUploadTest < ActionController::IntegrationTest
# end
def test_post_with_upload
uses_mocha "test_post_with_upload" do
- Dependencies.stubs(:load?).returns(false)
+ ActiveSupport::Dependencies.stubs(:load?).returns(false)
with_routing do |set|
set.draw do |map|
map.update 'update', :controller => "upload_test", :action => "update", :method => :post
diff --git a/actionpack/test/controller/new_render_test.rb b/actionpack/test/controller/new_render_test.rb
index 6e2c6d90c6..b77b3ceffa 100644
--- a/actionpack/test/controller/new_render_test.rb
+++ b/actionpack/test/controller/new_render_test.rb
@@ -68,6 +68,11 @@ class NewRenderTestController < ActionController::Base
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')
@@ -215,7 +220,7 @@ class NewRenderTestController < ActionController::Base
render :action => "test/hello_world"
end
- def render_to_string_with_partial
+ 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"
@@ -246,11 +251,15 @@ class NewRenderTestController < ActionController::Base
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
@@ -531,6 +540,11 @@ class NewRenderTest < Test::Unit::TestCase
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 }
@@ -549,12 +563,17 @@ class NewRenderTest < Test::Unit::TestCase
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
@@ -742,7 +761,7 @@ EOS
def test_partial_collection_with_counter
get :partial_collection_with_counter
- assert_equal "david1mary2", @response.body
+ assert_equal "david0mary1", @response.body
end
def test_partial_collection_with_locals
@@ -762,7 +781,7 @@ EOS
def test_partial_collection_shorthand_with_different_types_of_records
get :partial_collection_shorthand_with_different_types_of_records
- assert_equal "Bonjour bad customer: mark1Bonjour good customer: craig2Bonjour bad customer: john3Bonjour good customer: zach4Bonjour good customer: brandon5Bonjour bad customer: dan6", @response.body
+ 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
diff --git a/actionpack/test/controller/polymorphic_routes_test.rb b/actionpack/test/controller/polymorphic_routes_test.rb
index 4ec0d3cd4e..3f52526f08 100644
--- a/actionpack/test/controller/polymorphic_routes_test.rb
+++ b/actionpack/test/controller/polymorphic_routes_test.rb
@@ -118,6 +118,39 @@ uses_mocha 'polymorphic URL helpers' do
polymorphic_url([:site, :admin, @article, @response, @tag])
end
+ def test_nesting_with_array_ending_in_singleton_resource
+ expects(:article_response_url).with(@article)
+ polymorphic_url([@article, :response])
+ end
+
+ def test_nesting_with_array_containing_singleton_resource
+ @tag = Tag.new
+ @tag.save
+ expects(:article_response_tag_url).with(@article, @tag)
+ polymorphic_url([@article, :response, @tag])
+ end
+
+ def test_nesting_with_array_containing_namespace_and_singleton_resource
+ @tag = Tag.new
+ @tag.save
+ expects(:admin_article_response_tag_url).with(@article, @tag)
+ polymorphic_url([:admin, @article, :response, @tag])
+ end
+
+ def test_nesting_with_array_containing_singleton_resource_and_format
+ @tag = Tag.new
+ @tag.save
+ expects(:formatted_article_response_tag_url).with(@article, @tag, :pdf)
+ formatted_polymorphic_url([@article, :response, @tag, :pdf])
+ end
+
+ def test_nesting_with_array_containing_singleton_resource_and_format_option
+ @tag = Tag.new
+ @tag.save
+ expects(:article_response_tag_url).with(@article, @tag, :pdf)
+ polymorphic_url([@article, :response, @tag], :format => :pdf)
+ end
+
# TODO: Needs to be updated to correctly know about whether the object is in a hash or not
def xtest_with_hash
expects(:article_url).with(@article)
diff --git a/actionpack/test/controller/rack_test.rb b/actionpack/test/controller/rack_test.rb
index cd4151783e..856f24bbdb 100644
--- a/actionpack/test/controller/rack_test.rb
+++ b/actionpack/test/controller/rack_test.rb
@@ -3,11 +3,40 @@ require 'action_controller/rack_process'
class BaseRackTest < Test::Unit::TestCase
def setup
- @env = {"HTTP_MAX_FORWARDS"=>"10", "SERVER_NAME"=>"glu.ttono.us:8007", "FCGI_ROLE"=>"RESPONDER", "HTTP_X_FORWARDED_HOST"=>"glu.ttono.us", "HTTP_ACCEPT_ENCODING"=>"gzip, deflate", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.5.1 (KHTML, like Gecko) Safari/312.3.1", "PATH_INFO"=>"", "HTTP_ACCEPT_LANGUAGE"=>"en", "HTTP_HOST"=>"glu.ttono.us:8007", "SERVER_PROTOCOL"=>"HTTP/1.1", "REDIRECT_URI"=>"/dispatch.fcgi", "SCRIPT_NAME"=>"/dispatch.fcgi", "SERVER_ADDR"=>"207.7.108.53", "REMOTE_ADDR"=>"207.7.108.53", "SERVER_SOFTWARE"=>"lighttpd/1.4.5", "HTTP_COOKIE"=>"_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes", "HTTP_X_FORWARDED_SERVER"=>"glu.ttono.us", "REQUEST_URI"=>"/admin", "DOCUMENT_ROOT"=>"/home/kevinc/sites/typo/public", "SERVER_PORT"=>"8007", "QUERY_STRING"=>"", "REMOTE_PORT"=>"63137", "GATEWAY_INTERFACE"=>"CGI/1.1", "HTTP_X_FORWARDED_FOR"=>"65.88.180.234", "HTTP_ACCEPT"=>"*/*", "SCRIPT_FILENAME"=>"/home/kevinc/sites/typo/public/dispatch.fcgi", "REDIRECT_STATUS"=>"200", "REQUEST_METHOD"=>"GET"}
+ @env = {
+ "HTTP_MAX_FORWARDS" => "10",
+ "SERVER_NAME" => "glu.ttono.us:8007",
+ "FCGI_ROLE" => "RESPONDER",
+ "HTTP_X_FORWARDED_HOST" => "glu.ttono.us",
+ "HTTP_ACCEPT_ENCODING" => "gzip, deflate",
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)",
+ "PATH_INFO" => "",
+ "HTTP_ACCEPT_LANGUAGE" => "en",
+ "HTTP_HOST" => "glu.ttono.us:8007",
+ "SERVER_PROTOCOL" => "HTTP/1.1",
+ "REDIRECT_URI" => "/dispatch.fcgi",
+ "SCRIPT_NAME" => "/dispatch.fcgi",
+ "SERVER_ADDR" => "207.7.108.53",
+ "REMOTE_ADDR" => "207.7.108.53",
+ "SERVER_SOFTWARE" => "lighttpd/1.4.5",
+ "HTTP_COOKIE" => "_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes",
+ "HTTP_X_FORWARDED_SERVER" => "glu.ttono.us",
+ "REQUEST_URI" => "/admin",
+ "DOCUMENT_ROOT" => "/home/kevinc/sites/typo/public",
+ "SERVER_PORT" => "8007",
+ "QUERY_STRING" => "",
+ "REMOTE_PORT" => "63137",
+ "GATEWAY_INTERFACE" => "CGI/1.1",
+ "HTTP_X_FORWARDED_FOR" => "65.88.180.234",
+ "HTTP_ACCEPT" => "*/*",
+ "SCRIPT_FILENAME" => "/home/kevinc/sites/typo/public/dispatch.fcgi",
+ "REDIRECT_STATUS" => "200",
+ "REQUEST_METHOD" => "GET"
+ }
+ @request = ActionController::RackRequest.new(@env)
# some Nokia phone browsers omit the space after the semicolon separator.
# some developers have grown accustomed to using comma in cookie values.
- @alt_cookie_fmt_request_hash = {"HTTP_COOKIE"=>"_session_id=c84ace847,96670c052c6ceb2451fb0f2;is_admin=yes"}
- @request = ActionController::RackRequest.new(@env)
+ @alt_cookie_fmt_request = ActionController::RackRequest.new(@env.merge({"HTTP_COOKIE"=>"_session_id=c84ace847,96670c052c6ceb2451fb0f2;is_admin=yes"}))
end
def default_test; end
@@ -71,11 +100,11 @@ class RackRequestTest < BaseRackTest
end
def test_cookie_syntax_resilience
- cookies = CGI::Cookie::parse(@env["HTTP_COOKIE"]);
+ cookies = @request.cookies
assert_equal ["c84ace84796670c052c6ceb2451fb0f2"], cookies["_session_id"], cookies.inspect
assert_equal ["yes"], cookies["is_admin"], cookies.inspect
- alt_cookies = CGI::Cookie::parse(@alt_cookie_fmt_request_hash["HTTP_COOKIE"]);
+ alt_cookies = @alt_cookie_fmt_request.cookies
assert_equal ["c84ace847,96670c052c6ceb2451fb0f2"], alt_cookies["_session_id"], alt_cookies.inspect
assert_equal ["yes"], alt_cookies["is_admin"], alt_cookies.inspect
end
@@ -118,7 +147,7 @@ end
class RackResponseTest < BaseRackTest
def setup
super
- @response = ActionController::RackResponse.new
+ @response = ActionController::RackResponse.new(@request)
@output = StringIO.new('')
end
@@ -127,7 +156,7 @@ class RackResponseTest < BaseRackTest
status, headers, body = @response.out(@output)
assert_equal 200, status
- assert_equal({"Content-Type" => "text/html", "Cache-Control" => "no-cache", "Set-Cookie" => ""}, headers)
+ assert_equal({"Content-Type" => "text/html", "Cache-Control" => "no-cache", "Set-Cookie" => []}, headers)
parts = []
body.each { |part| parts << part }
@@ -141,10 +170,29 @@ class RackResponseTest < BaseRackTest
status, headers, body = @response.out(@output)
assert_equal 200, status
- assert_equal({"Content-Type" => "text/html", "Cache-Control" => "no-cache", "Set-Cookie" => ""}, headers)
+ assert_equal({"Content-Type" => "text/html", "Cache-Control" => "no-cache", "Set-Cookie" => []}, headers)
parts = []
body.each { |part| parts << part }
assert_equal ["0", "1", "2", "3", "4"], parts
end
+
+ def test_set_session_cookie
+ cookie = CGI::Cookie.new({"name" => "name", "value" => "Josh"})
+ @request.cgi.send :instance_variable_set, '@output_cookies', [cookie]
+
+ @response.body = "Hello, World!"
+
+ status, headers, body = @response.out(@output)
+ assert_equal 200, status
+ assert_equal({
+ "Content-Type" => "text/html",
+ "Cache-Control" => "no-cache",
+ "Set-Cookie" => ["name=Josh; path="]
+ }, headers)
+
+ parts = []
+ body.each { |part| parts << part }
+ assert_equal ["Hello, World!"], parts
+ end
end
diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb
index 82ddfec8e8..2bd489b2c7 100644
--- a/actionpack/test/controller/request_test.rb
+++ b/actionpack/test/controller/request_test.rb
@@ -59,6 +59,9 @@ class RequestTest < Test::Unit::TestCase
assert_match /HTTP_X_FORWARDED_FOR="9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4"/, e.message
assert_match /HTTP_CLIENT_IP="8.8.8.8"/, e.message
+ @request.env['HTTP_X_FORWARDED_FOR'] = '8.8.8.8, 9.9.9.9'
+ assert_equal '8.8.8.8', @request.remote_ip
+
@request.env.delete 'HTTP_CLIENT_IP'
@request.env.delete 'HTTP_X_FORWARDED_FOR'
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 5e5503fd52..07c13ebbf7 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -59,647 +59,30 @@ class UriReservedCharactersRoutingTest < Test::Unit::TestCase
end
end
-class LegacyRouteSetTests < Test::Unit::TestCase
- attr_reader :rs
- def setup
- # These tests assume optimisation is on, so re-enable it.
- ActionController::Base.optimise_named_routes = true
-
- @rs = ::ActionController::Routing::RouteSet.new
- @rs.draw {|m| m.connect ':controller/:action/:id' }
-
- ActionController::Routing.use_controllers! %w(content admin/user admin/news_feed)
- end
-
- def test_default_setup
- assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content"))
- assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list"))
- assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10"))
-
- assert_equal({:controller => "admin/user", :action => 'show', :id => '10'}, rs.recognize_path("/admin/user/show/10"))
-
- assert_equal '/admin/user/show/10', rs.generate(:controller => 'admin/user', :action => 'show', :id => 10)
-
- assert_equal '/admin/user/show', rs.generate({:action => 'show'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
- assert_equal '/admin/user/list/10', rs.generate({}, {:controller => 'admin/user', :action => 'list', :id => '10'})
-
- assert_equal '/admin/stuff', rs.generate({:controller => 'stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
- assert_equal '/stuff', rs.generate({:controller => '/stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
- end
-
- def test_ignores_leading_slash
- @rs.draw {|m| m.connect '/:controller/:action/:id'}
- test_default_setup
- end
-
- def test_time_recognition
- # We create many routes to make situation more realistic
- @rs = ::ActionController::Routing::RouteSet.new
- @rs.draw { |map|
- map.frontpage '', :controller => 'search', :action => 'new'
- map.resources :videos do |video|
- video.resources :comments
- video.resource :file, :controller => 'video_file'
- video.resource :share, :controller => 'video_shares'
- video.resource :abuse, :controller => 'video_abuses'
- end
- map.resources :abuses, :controller => 'video_abuses'
- map.resources :video_uploads
- map.resources :video_visits
-
- map.resources :users do |user|
- user.resource :settings
- user.resources :videos
- end
- map.resources :channels do |channel|
- channel.resources :videos, :controller => 'channel_videos'
- end
- map.resource :session
- map.resource :lost_password
- map.search 'search', :controller => 'search'
- map.resources :pages
- map.connect ':controller/:action/:id'
- }
- n = 1000
- if RunTimeTests
- GC.start
- rectime = Benchmark.realtime do
- n.times do
- rs.recognize_path("/videos/1234567", {:method => :get})
- rs.recognize_path("/videos/1234567/abuse", {:method => :get})
- rs.recognize_path("/users/1234567/settings", {:method => :get})
- rs.recognize_path("/channels/1234567", {:method => :get})
- rs.recognize_path("/session/new", {:method => :get})
- rs.recognize_path("/admin/user/show/10", {:method => :get})
- end
- end
- puts "\n\nRecognition (#{rs.routes.size} routes):"
- per_url = rectime / (n * 6)
- puts "#{per_url * 1000} ms/url"
- puts "#{1 / per_url} url/s\n\n"
- end
- end
- def test_time_generation
- n = 5000
- if RunTimeTests
- GC.start
- pairs = [
- [{:controller => 'content', :action => 'index'}, {:controller => 'content', :action => 'show'}],
- [{:controller => 'content'}, {:controller => 'content', :action => 'index'}],
- [{:controller => 'content', :action => 'list'}, {:controller => 'content', :action => 'index'}],
- [{:controller => 'content', :action => 'show', :id => '10'}, {:controller => 'content', :action => 'list'}],
- [{:controller => 'admin/user', :action => 'index'}, {:controller => 'admin/user', :action => 'show'}],
- [{:controller => 'admin/user'}, {:controller => 'admin/user', :action => 'index'}],
- [{:controller => 'admin/user', :action => 'list'}, {:controller => 'admin/user', :action => 'index'}],
- [{:controller => 'admin/user', :action => 'show', :id => '10'}, {:controller => 'admin/user', :action => 'list'}],
- ]
- p = nil
- gentime = Benchmark.realtime do
- n.times do
- pairs.each {|(a, b)| rs.generate(a, b)}
- end
- end
-
- puts "\n\nGeneration (RouteSet): (#{(n * 8)} urls)"
- per_url = gentime / (n * 8)
- puts "#{per_url * 1000} ms/url"
- puts "#{1 / per_url} url/s\n\n"
- end
- end
-
- def test_route_with_colon_first
- rs.draw do |map|
- map.connect '/:controller/:action/:id', :action => 'index', :id => nil
- map.connect ':url', :controller => 'tiny_url', :action => 'translate'
- end
- end
-
- def test_route_with_regexp_for_controller
- rs.draw do |map|
- map.connect ':controller/:admintoken/:action/:id', :controller => /admin\/.+/
- map.connect ':controller/:action/:id'
- end
- assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"},
- rs.recognize_path("/admin/user/foo"))
- assert_equal({:controller => "content", :action => "foo"}, rs.recognize_path("/content/foo"))
- assert_equal '/admin/user/foo', rs.generate(:controller => "admin/user", :admintoken => "foo", :action => "index")
- assert_equal '/content/foo', rs.generate(:controller => "content", :action => "foo")
- end
-
- def test_route_with_regexp_and_dot
- rs.draw do |map|
- map.connect ':controller/:action/:file',
- :controller => /admin|user/,
- :action => /upload|download/,
- :defaults => {:file => nil},
- :requirements => {:file => %r{[^/]+(\.[^/]+)?}}
- end
- # Without a file extension
- assert_equal '/user/download/file',
- rs.generate(:controller => "user", :action => "download", :file => "file")
- assert_equal(
- {:controller => "user", :action => "download", :file => "file"},
- rs.recognize_path("/user/download/file"))
-
- # Now, let's try a file with an extension, really a dot (.)
- assert_equal '/user/download/file.jpg',
- rs.generate(
- :controller => "user", :action => "download", :file => "file.jpg")
- assert_equal(
- {:controller => "user", :action => "download", :file => "file.jpg"},
- rs.recognize_path("/user/download/file.jpg"))
- end
-
- def test_basic_named_route
- rs.add_named_route :home, '', :controller => 'content', :action => 'list'
- x = setup_for_named_route
- assert_equal("http://named.route.test/",
- x.send(:home_url))
- end
-
- def test_basic_named_route_with_relative_url_root
- rs.add_named_route :home, '', :controller => 'content', :action => 'list'
- x = setup_for_named_route
- x.relative_url_root="/foo"
- assert_equal("http://named.route.test/foo/",
- x.send(:home_url))
- assert_equal "/foo/", x.send(:home_path)
- end
-
- def test_named_route_with_option
- rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page'
- x = setup_for_named_route
- assert_equal("http://named.route.test/page/new%20stuff",
- x.send(:page_url, :title => 'new stuff'))
- end
-
- def test_named_route_with_default
- rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage'
- x = setup_for_named_route
- assert_equal("http://named.route.test/page/AboutRails",
- x.send(:page_url, :title => "AboutRails"))
-
- end
-
- def test_named_route_with_nested_controller
- rs.add_named_route :users, 'admin/user', :controller => 'admin/user', :action => 'index'
- x = setup_for_named_route
- assert_equal("http://named.route.test/admin/user",
- x.send(:users_url))
- end
-
- uses_mocha "named route optimisation" do
- def test_optimised_named_route_call_never_uses_url_for
- rs.add_named_route :users, 'admin/user', :controller => '/admin/user', :action => 'index'
- rs.add_named_route :user, 'admin/user/:id', :controller=>'/admin/user', :action=>'show'
- x = setup_for_named_route
- x.expects(:url_for).never
- x.send(:users_url)
- x.send(:users_path)
- x.send(:user_url, 2, :foo=>"bar")
- x.send(:user_path, 3, :bar=>"foo")
- end
-
- def test_optimised_named_route_with_host
- rs.add_named_route :pages, 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com'
- x = setup_for_named_route
- x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once
- x.send(:pages_url)
- end
- end
-
- def setup_for_named_route
- klass = Class.new(MockController)
- rs.install_helpers(klass)
- klass.new(rs)
- end
-
- def test_named_route_without_hash
- rs.draw do |map|
- map.normal ':controller/:action/:id'
- end
- end
-
- def test_named_route_root
- rs.draw do |map|
- map.root :controller => "hello"
- end
- x = setup_for_named_route
- assert_equal("http://named.route.test/", x.send(:root_url))
- assert_equal("/", x.send(:root_path))
- end
-
- def test_named_route_with_regexps
- rs.draw do |map|
- map.article 'page/:year/:month/:day/:title', :controller => 'page', :action => 'show',
- :year => /\d+/, :month => /\d+/, :day => /\d+/
- map.connect ':controller/:action/:id'
- end
- x = setup_for_named_route
- # assert_equal(
- # {:controller => 'page', :action => 'show', :title => 'hi', :use_route => :article, :only_path => false},
- # x.send(:article_url, :title => 'hi')
- # )
- assert_equal(
- "http://named.route.test/page/2005/6/10/hi",
- x.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6)
- )
- end
-
- def test_changing_controller
- assert_equal '/admin/stuff/show/10', rs.generate(
- {:controller => 'stuff', :action => 'show', :id => 10},
- {:controller => 'admin/user', :action => 'index'}
- )
- end
-
- def test_paths_escaped
- rs.draw do |map|
- map.path 'file/*path', :controller => 'content', :action => 'show_file'
- map.connect ':controller/:action/:id'
- end
-
- # No + to space in URI escaping, only for query params.
- results = rs.recognize_path "/file/hello+world/how+are+you%3F"
- assert results, "Recognition should have succeeded"
- assert_equal ['hello+world', 'how+are+you?'], results[:path]
-
- # Use %20 for space instead.
- results = rs.recognize_path "/file/hello%20world/how%20are%20you%3F"
- assert results, "Recognition should have succeeded"
- assert_equal ['hello world', 'how are you?'], results[:path]
-
- results = rs.recognize_path "/file"
- assert results, "Recognition should have succeeded"
- assert_equal [], results[:path]
- end
-
- def test_paths_slashes_unescaped_with_ordered_parameters
- rs.add_named_route :path, '/file/*path', :controller => 'content'
-
- # No / to %2F in URI, only for query params.
- x = setup_for_named_route
- assert_equal("/file/hello/world", x.send(:path_path, 'hello/world'))
- end
-
- def test_non_controllers_cannot_be_matched
- rs.draw do |map|
- map.connect ':controller/:action/:id'
- end
- assert_raises(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") }
- end
-
- def test_paths_do_not_accept_defaults
- assert_raises(ActionController::RoutingError) do
- rs.draw do |map|
- map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => %w(fake default)
- map.connect ':controller/:action/:id'
- end
- end
-
- rs.draw do |map|
- map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => []
- map.connect ':controller/:action/:id'
- end
- end
-
- def test_should_list_options_diff_when_routing_requirements_dont_match
- rs.draw do |map|
- map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
- end
- exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post") }
- assert_match /^post_url failed to generate/, exception.message
- from_match = exception.message.match(/from \{[^\}]+\}/).to_s
- assert_match /:bad_param=>"foo"/, from_match
- assert_match /:action=>"show"/, from_match
- assert_match /:controller=>"post"/, from_match
-
- expected_match = exception.message.match(/expected: \{[^\}]+\}/).to_s
- assert_no_match /:bad_param=>"foo"/, expected_match
- assert_match /:action=>"show"/, expected_match
- assert_match /:controller=>"post"/, expected_match
-
- diff_match = exception.message.match(/diff: \{[^\}]+\}/).to_s
- assert_match /:bad_param=>"foo"/, diff_match
- assert_no_match /:action=>"show"/, diff_match
- assert_no_match /:controller=>"post"/, diff_match
- end
-
- # this specifies the case where your formerly would get a very confusing error message with an empty diff
- def test_should_have_better_error_message_when_options_diff_is_empty
- rs.draw do |map|
- map.content '/content/:query', :controller => 'content', :action => 'show'
- end
-
- exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") }
- assert_match %r[:action=>"show"], exception.message
- assert_match %r[:controller=>"content"], exception.message
- assert_match %r[you may have ambiguous routes, or you may need to supply additional parameters for this route], exception.message
- assert_match %r[content_url has the following required parameters: \["content", :query\] - are they all satisfied?], exception.message
- end
-
- def test_dynamic_path_allowed
- rs.draw do |map|
- map.connect '*path', :controller => 'content', :action => 'show_file'
- end
-
- assert_equal '/pages/boo', rs.generate(:controller => 'content', :action => 'show_file', :path => %w(pages boo))
- end
-
- def test_dynamic_recall_paths_allowed
- rs.draw do |map|
- map.connect '*path', :controller => 'content', :action => 'show_file'
- end
-
- recall_path = ActionController::Routing::PathSegment::Result.new(%w(pages boo))
- assert_equal '/pages/boo', rs.generate({}, :controller => 'content', :action => 'show_file', :path => recall_path)
- end
-
- def test_backwards
- rs.draw do |map|
- map.connect 'page/:id/:action', :controller => 'pages', :action => 'show'
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/page/20', rs.generate({:id => 20}, {:controller => 'pages', :action => 'show'})
- assert_equal '/page/20', rs.generate(:controller => 'pages', :id => 20, :action => 'show')
- assert_equal '/pages/boo', rs.generate(:controller => 'pages', :action => 'boo')
- end
-
- def test_route_with_fixnum_default
- rs.draw do |map|
- map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page')
- assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => 1)
- assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => '1')
- assert_equal '/page/10', rs.generate(:controller => 'content', :action => 'show_page', :id => 10)
-
- assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page"))
- assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page/1"))
- assert_equal({:controller => "content", :action => 'show_page', :id => '10'}, rs.recognize_path("/page/10"))
- end
-
- # For newer revision
- def test_route_with_text_default
- rs.draw do |map|
- map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/page/foo', rs.generate(:controller => 'content', :action => 'show_page', :id => 'foo')
- assert_equal({:controller => "content", :action => 'show_page', :id => 'foo'}, rs.recognize_path("/page/foo"))
-
- token = "\321\202\320\265\320\272\321\201\321\202" # 'text' in russian
- escaped_token = CGI::escape(token)
-
- assert_equal '/page/' + escaped_token, rs.generate(:controller => 'content', :action => 'show_page', :id => token)
- assert_equal({:controller => "content", :action => 'show_page', :id => token}, rs.recognize_path("/page/#{escaped_token}"))
- end
-
- def test_action_expiry
- assert_equal '/content', rs.generate({:controller => 'content'}, {:controller => 'content', :action => 'show'})
- end
-
- def test_recognition_with_uppercase_controller_name
- assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/Content"))
- assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/ConTent/list"))
- assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/CONTENT/show/10"))
-
- # these used to work, before the routes rewrite, but support for this was pulled in the new version...
- #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/NewsFeed"))
- #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/News_Feed"))
- end
-
- def test_requirement_should_prevent_optional_id
- rs.draw do |map|
- map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
- end
-
- assert_equal '/post/10', rs.generate(:controller => 'post', :action => 'show', :id => 10)
-
- assert_raises ActionController::RoutingError do
- rs.generate(:controller => 'post', :action => 'show')
- end
- end
-
- def test_both_requirement_and_optional
- rs.draw do |map|
- map.blog('test/:year', :controller => 'post', :action => 'show',
- :defaults => { :year => nil },
- :requirements => { :year => /\d{4}/ }
- )
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/test', rs.generate(:controller => 'post', :action => 'show')
- assert_equal '/test', rs.generate(:controller => 'post', :action => 'show', :year => nil)
-
- x = setup_for_named_route
- assert_equal("http://named.route.test/test",
- x.send(:blog_url))
- end
-
- def test_set_to_nil_forgets
- rs.draw do |map|
- map.connect 'pages/:year/:month/:day', :controller => 'content', :action => 'list_pages', :month => nil, :day => nil
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/pages/2005',
- rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005)
- assert_equal '/pages/2005/6',
- rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6)
- assert_equal '/pages/2005/6/12',
- rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12)
-
- assert_equal '/pages/2005/6/4',
- rs.generate({:day => 4}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
-
- assert_equal '/pages/2005/6',
- rs.generate({:day => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
-
- assert_equal '/pages/2005',
- rs.generate({:day => nil, :month => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
- end
-
- def test_url_with_no_action_specified
- rs.draw do |map|
- map.connect '', :controller => 'content'
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
- assert_equal '/', rs.generate(:controller => 'content')
- end
-
- def test_named_url_with_no_action_specified
- rs.draw do |map|
- map.home '', :controller => 'content'
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
- assert_equal '/', rs.generate(:controller => 'content')
-
- x = setup_for_named_route
- assert_equal("http://named.route.test/",
- x.send(:home_url))
- end
-
- def test_url_generated_when_forgetting_action
- [{:controller => 'content', :action => 'index'}, {:controller => 'content'}].each do |hash|
- rs.draw do |map|
- map.home '', hash
- map.connect ':controller/:action/:id'
- end
- assert_equal '/', rs.generate({:action => nil}, {:controller => 'content', :action => 'hello'})
- assert_equal '/', rs.generate({:controller => 'content'})
- assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'})
- end
- end
-
- def test_named_route_method
- rs.draw do |map|
- map.categories 'categories', :controller => 'content', :action => 'categories'
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/categories', rs.generate(:controller => 'content', :action => 'categories')
- assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'})
- end
-
- def test_named_routes_array
- test_named_route_method
- assert_equal [:categories], rs.named_routes.names
- end
-
- def test_nil_defaults
- rs.draw do |map|
- map.connect 'journal',
- :controller => 'content',
- :action => 'list_journal',
- :date => nil, :user_id => nil
- map.connect ':controller/:action/:id'
- end
-
- assert_equal '/journal', rs.generate(:controller => 'content', :action => 'list_journal', :date => nil, :user_id => nil)
- end
-
- def setup_request_method_routes_for(method)
- @request = ActionController::TestRequest.new
- @request.env["REQUEST_METHOD"] = method
- @request.request_uri = "/match"
-
- rs.draw do |r|
- r.connect '/match', :controller => 'books', :action => 'get', :conditions => { :method => :get }
- r.connect '/match', :controller => 'books', :action => 'post', :conditions => { :method => :post }
- r.connect '/match', :controller => 'books', :action => 'put', :conditions => { :method => :put }
- r.connect '/match', :controller => 'books', :action => 'delete', :conditions => { :method => :delete }
- end
- end
-
- %w(GET POST PUT DELETE).each do |request_method|
- define_method("test_request_method_recognized_with_#{request_method}") do
- begin
- Object.const_set(:BooksController, Class.new(ActionController::Base))
-
- setup_request_method_routes_for(request_method)
-
- assert_nothing_raised { rs.recognize(@request) }
- assert_equal request_method.downcase, @request.path_parameters[:action]
- ensure
- Object.send(:remove_const, :BooksController) rescue nil
- end
- end
- end
-
- def test_subpath_recognized
- Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
-
- rs.draw do |r|
- r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
- r.connect '/items/:id/:action', :controller => 'subpath_books'
- r.connect '/posts/new/:action', :controller => 'subpath_books'
- r.connect '/posts/:id', :controller => 'subpath_books', :action => "show"
- end
-
- hash = rs.recognize_path "/books/17/edit"
- assert_not_nil hash
- assert_equal %w(subpath_books 17 edit), [hash[:controller], hash[:id], hash[:action]]
-
- hash = rs.recognize_path "/items/3/complete"
- assert_not_nil hash
- assert_equal %w(subpath_books 3 complete), [hash[:controller], hash[:id], hash[:action]]
-
- hash = rs.recognize_path "/posts/new/preview"
- assert_not_nil hash
- assert_equal %w(subpath_books preview), [hash[:controller], hash[:action]]
-
- hash = rs.recognize_path "/posts/7"
- assert_not_nil hash
- assert_equal %w(subpath_books show 7), [hash[:controller], hash[:action], hash[:id]]
- ensure
- Object.send(:remove_const, :SubpathBooksController) rescue nil
- end
-
- def test_subpath_generated
- Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
-
- rs.draw do |r|
- r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
- r.connect '/items/:id/:action', :controller => 'subpath_books'
- r.connect '/posts/new/:action', :controller => 'subpath_books'
- end
-
- assert_equal "/books/7/edit", rs.generate(:controller => "subpath_books", :id => 7, :action => "edit")
- assert_equal "/items/15/complete", rs.generate(:controller => "subpath_books", :id => 15, :action => "complete")
- assert_equal "/posts/new/preview", rs.generate(:controller => "subpath_books", :action => "preview")
- ensure
- Object.send(:remove_const, :SubpathBooksController) rescue nil
- end
-
- def test_failed_requirements_raises_exception_with_violated_requirements
- rs.draw do |r|
- r.foo_with_requirement 'foos/:id', :controller=>'foos', :requirements=>{:id=>/\d+/}
- end
-
- x = setup_for_named_route
- assert_raises(ActionController::RoutingError) do
- x.send(:foo_with_requirement_url, "I am Against the requirements")
- end
- end
-end
-
class SegmentTest < Test::Unit::TestCase
-
def test_first_segment_should_interpolate_for_structure
s = ROUTING::Segment.new
def s.interpolation_statement(array) 'hello' end
assert_equal 'hello', s.continue_string_structure([])
end
-
+
def test_interpolation_statement
s = ROUTING::StaticSegment.new
s.value = "Hello"
assert_equal "Hello", eval(s.interpolation_statement([]))
assert_equal "HelloHello", eval(s.interpolation_statement([s]))
-
+
s2 = ROUTING::StaticSegment.new
s2.value = "-"
assert_equal "Hello-Hello", eval(s.interpolation_statement([s, s2]))
-
+
s3 = ROUTING::StaticSegment.new
s3.value = "World"
assert_equal "Hello-World", eval(s3.interpolation_statement([s, s2]))
end
-
end
class StaticSegmentTest < Test::Unit::TestCase
-
def test_interpolation_chunk_should_respect_raw
s = ROUTING::StaticSegment.new
s.value = 'Hello World'
@@ -713,28 +96,26 @@ class StaticSegmentTest < Test::Unit::TestCase
def test_regexp_chunk_should_escape_specials
s = ROUTING::StaticSegment.new
-
+
s.value = 'Hello*World'
assert_equal 'Hello\*World', s.regexp_chunk
-
+
s.value = 'HelloWorld'
assert_equal 'HelloWorld', s.regexp_chunk
end
-
+
def test_regexp_chunk_should_add_question_mark_for_optionals
s = ROUTING::StaticSegment.new
s.value = "/"
s.is_optional = true
assert_equal "/?", s.regexp_chunk
-
+
s.value = "hello"
assert_equal "(?:hello)?", s.regexp_chunk
end
-
end
class DynamicSegmentTest < Test::Unit::TestCase
-
def segment
unless @segment
@segment = ROUTING::DynamicSegment.new
@@ -742,126 +123,126 @@ class DynamicSegmentTest < Test::Unit::TestCase
end
@segment
end
-
+
def test_extract_value
s = ROUTING::DynamicSegment.new
s.key = :a
-
+
hash = {:a => '10', :b => '20'}
assert_equal '10', eval(s.extract_value)
-
+
hash = {:b => '20'}
assert_equal nil, eval(s.extract_value)
-
+
s.default = '20'
assert_equal '20', eval(s.extract_value)
end
-
+
def test_default_local_name
assert_equal 'a_value', segment.local_name,
"Unexpected name -- all value_check tests will fail!"
end
-
+
def test_presence_value_check
a_value = 10
assert eval(segment.value_check)
end
-
+
def test_regexp_value_check_rejects_nil
segment.regexp = /\d+/
a_value = nil
assert ! eval(segment.value_check)
end
-
+
def test_optional_regexp_value_check_should_accept_nil
segment.regexp = /\d+/
segment.is_optional = true
a_value = nil
assert eval(segment.value_check)
end
-
+
def test_regexp_value_check_rejects_no_match
segment.regexp = /\d+/
-
+
a_value = "Hello20World"
assert ! eval(segment.value_check)
-
+
a_value = "20Hi"
assert ! eval(segment.value_check)
end
-
+
def test_regexp_value_check_accepts_match
segment.regexp = /\d+/
-
+
a_value = "30"
assert eval(segment.value_check)
end
-
+
def test_value_check_fails_on_nil
a_value = nil
assert ! eval(segment.value_check)
end
-
+
def test_optional_value_needs_no_check
segment.is_optional = true
a_value = nil
assert_equal nil, segment.value_check
end
-
+
def test_regexp_value_check_should_accept_match_with_default
segment.regexp = /\d+/
segment.default = '200'
-
+
a_value = '100'
assert eval(segment.value_check)
end
-
+
def test_expiry_should_not_trigger_once_expired
expired = true
hash = merged = {:a => 2, :b => 3}
options = {:b => 3}
expire_on = Hash.new { raise 'No!!!' }
-
+
eval(segment.expiry_statement)
rescue RuntimeError
flunk "Expiry check should not have occurred!"
end
-
+
def test_expiry_should_occur_according_to_expire_on
expired = false
hash = merged = {:a => 2, :b => 3}
options = {:b => 3}
-
+
expire_on = {:b => true, :a => false}
eval(segment.expiry_statement)
assert !expired
assert_equal({:a => 2, :b => 3}, hash)
-
+
expire_on = {:b => true, :a => true}
eval(segment.expiry_statement)
assert expired
assert_equal({:b => 3}, hash)
end
-
+
def test_extraction_code_should_return_on_nil
hash = merged = {:b => 3}
options = {:b => 3}
a_value = nil
-
+
# Local jump because of return inside eval.
assert_raises(LocalJumpError) { eval(segment.extraction_code) }
end
-
+
def test_extraction_code_should_return_on_mismatch
segment.regexp = /\d+/
hash = merged = {:a => 'Hi', :b => '3'}
options = {:b => '3'}
a_value = nil
-
+
# Local jump because of return inside eval.
assert_raises(LocalJumpError) { eval(segment.extraction_code) }
end
-
+
def test_extraction_code_should_accept_value_and_set_local
hash = merged = {:a => 'Hi', :b => '3'}
options = {:b => '3'}
@@ -871,45 +252,45 @@ class DynamicSegmentTest < Test::Unit::TestCase
eval(segment.extraction_code)
assert_equal 'Hi', a_value
end
-
+
def test_extraction_should_work_without_value_check
segment.default = 'hi'
hash = merged = {:b => '3'}
options = {:b => '3'}
a_value = nil
expired = true
-
+
eval(segment.extraction_code)
assert_equal 'hi', a_value
end
-
+
def test_extraction_code_should_perform_expiry
expired = false
hash = merged = {:a => 'Hi', :b => '3'}
options = {:b => '3'}
expire_on = {:a => true}
a_value = nil
-
+
eval(segment.extraction_code)
assert_equal 'Hi', a_value
assert expired
assert_equal options, hash
end
-
+
def test_interpolation_chunk_should_replace_value
a_value = 'Hi'
assert_equal a_value, eval(%("#{segment.interpolation_chunk}"))
end
-
+
def test_interpolation_chunk_should_accept_nil
a_value = nil
assert_equal '', eval(%("#{segment.interpolation_chunk('a_value')}"))
end
-
+
def test_value_regexp_should_be_nil_without_regexp
assert_equal nil, segment.value_regexp
end
-
+
def test_value_regexp_should_match_exacly
segment.regexp = /\d+/
assert_no_match segment.value_regexp, "Hello 10 World"
@@ -917,12 +298,12 @@ class DynamicSegmentTest < Test::Unit::TestCase
assert_no_match segment.value_regexp, "10 World"
assert_match segment.value_regexp, "10"
end
-
+
def test_regexp_chunk_should_return_string
segment.regexp = /\d+/
assert_kind_of String, segment.regexp_chunk
end
-
+
def test_build_pattern_non_optional_with_no_captures
# Non optional
a_segment = ROUTING::DynamicSegment.new
@@ -958,264 +339,23 @@ class DynamicSegmentTest < Test::Unit::TestCase
end
class ControllerSegmentTest < Test::Unit::TestCase
-
def test_regexp_should_only_match_possible_controllers
ActionController::Routing.with_controllers %w(admin/accounts admin/users account pages) do
cs = ROUTING::ControllerSegment.new :controller
regexp = %r{\A#{cs.regexp_chunk}\Z}
-
+
ActionController::Routing.possible_controllers.each do |name|
assert_match regexp, name
assert_no_match regexp, "#{name}_fake"
-
+
match = regexp.match name
assert_equal name, match[1]
end
end
end
-
-end
-
-uses_mocha 'RouteTest' do
-
- class MockController
- attr_accessor :routes
-
- def initialize(routes)
- self.routes = routes
- end
-
- def url_for(options)
- only_path = options.delete(:only_path)
-
- port = options.delete(:port) || 80
- port_string = port == 80 ? '' : ":#{port}"
-
- host = options.delete(:host) || "named.route.test"
- anchor = "##{options.delete(:anchor)}" if options.key?(:anchor)
-
- path = routes.generate(options)
-
- only_path ? "#{path}#{anchor}" : "http://#{host}#{port_string}#{path}#{anchor}"
- end
-
- def request
- @request ||= MockRequest.new(:host => "named.route.test", :method => :get)
- end
-
- def relative_url_root=(value)
- request.relative_url_root=value
- end
- end
-
- class MockRequest
- attr_accessor :path, :path_parameters, :host, :subdomains, :domain,
- :method, :relative_url_root
-
- def initialize(values={})
- values.each { |key, value| send("#{key}=", value) }
- if values[:host]
- subdomain, self.domain = values[:host].split(/\./, 2)
- self.subdomains = [subdomain]
- end
- end
-
- def protocol
- "http://"
- end
-
- def host_with_port
- (subdomains * '.') + '.' + domain
- end
- end
-
-class RouteTest < Test::Unit::TestCase
-
- def setup
- @route = ROUTING::Route.new
- end
-
- def slash_segment(is_optional = false)
- returning ROUTING::DividerSegment.new('/') do |s|
- s.is_optional = is_optional
- end
- end
-
- def default_route
- unless defined?(@default_route)
- @default_route = ROUTING::Route.new
-
- @default_route.segments << (s = ROUTING::StaticSegment.new)
- s.value = '/'
- s.raw = true
-
- @default_route.segments << (s = ROUTING::DynamicSegment.new)
- s.key = :controller
-
- @default_route.segments << slash_segment(:optional)
- @default_route.segments << (s = ROUTING::DynamicSegment.new)
- s.key = :action
- s.default = 'index'
- s.is_optional = true
-
- @default_route.segments << slash_segment(:optional)
- @default_route.segments << (s = ROUTING::DynamicSegment.new)
- s.key = :id
- s.is_optional = true
-
- @default_route.segments << slash_segment(:optional)
- end
- @default_route
- end
-
- def test_default_route_recognition
- expected = {:controller => 'accounts', :action => 'show', :id => '10'}
- assert_equal expected, default_route.recognize('/accounts/show/10')
- assert_equal expected, default_route.recognize('/accounts/show/10/')
-
- expected[:id] = 'jamis'
- assert_equal expected, default_route.recognize('/accounts/show/jamis/')
-
- expected.delete :id
- assert_equal expected, default_route.recognize('/accounts/show')
- assert_equal expected, default_route.recognize('/accounts/show/')
-
- expected[:action] = 'index'
- assert_equal expected, default_route.recognize('/accounts/')
- assert_equal expected, default_route.recognize('/accounts')
-
- assert_equal nil, default_route.recognize('/')
- assert_equal nil, default_route.recognize('/accounts/how/goood/it/is/to/be/free')
- end
-
- def test_default_route_should_omit_default_action
- o = {:controller => 'accounts', :action => 'index'}
- assert_equal '/accounts', default_route.generate(o, o, {})
- end
-
- def test_default_route_should_include_default_action_when_id_present
- o = {:controller => 'accounts', :action => 'index', :id => '20'}
- assert_equal '/accounts/index/20', default_route.generate(o, o, {})
- end
-
- def test_default_route_should_work_with_action_but_no_id
- o = {:controller => 'accounts', :action => 'list_all'}
- assert_equal '/accounts/list_all', default_route.generate(o, o, {})
- end
-
- def test_default_route_should_uri_escape_pluses
- expected = { :controller => 'accounts', :action => 'show', :id => 'hello world' }
- assert_equal expected, default_route.recognize('/accounts/show/hello world')
- assert_equal expected, default_route.recognize('/accounts/show/hello%20world')
- assert_equal '/accounts/show/hello%20world', default_route.generate(expected, expected, {})
-
- expected[:id] = 'hello+world'
- assert_equal expected, default_route.recognize('/accounts/show/hello+world')
- assert_equal expected, default_route.recognize('/accounts/show/hello%2Bworld')
- assert_equal '/accounts/show/hello+world', default_route.generate(expected, expected, {})
- end
-
- def test_matches_controller_and_action
- # requirement_for should only be called for the action and controller _once_
- @route.expects(:requirement_for).with(:controller).times(1).returns('pages')
- @route.expects(:requirement_for).with(:action).times(1).returns('show')
-
- @route.requirements = {:controller => 'pages', :action => 'show'}
- assert @route.matches_controller_and_action?('pages', 'show')
- assert !@route.matches_controller_and_action?('not_pages', 'show')
- assert !@route.matches_controller_and_action?('pages', 'not_show')
- end
-
- def test_parameter_shell
- page_url = ROUTING::Route.new
- page_url.requirements = {:controller => 'pages', :action => 'show', :id => /\d+/}
- assert_equal({:controller => 'pages', :action => 'show'}, page_url.parameter_shell)
- end
-
- def test_defaults
- route = ROUTING::RouteBuilder.new.build '/users/:id.:format', :controller => "users", :action => "show", :format => "html"
- assert_equal(
- { :controller => "users", :action => "show", :format => "html" },
- route.defaults)
- end
-
- def test_builder_complains_without_controller
- assert_raises(ArgumentError) do
- ROUTING::RouteBuilder.new.build '/contact', :contoller => "contact", :action => "index"
- end
- end
-
- def test_significant_keys_for_default_route
- keys = default_route.significant_keys.sort_by {|k| k.to_s }
- assert_equal [:action, :controller, :id], keys
- end
-
- def test_significant_keys
- user_url = ROUTING::Route.new
- user_url.segments << (s = ROUTING::StaticSegment.new)
- s.value = '/'
- s.raw = true
-
- user_url.segments << (s = ROUTING::StaticSegment.new)
- s.value = 'user'
-
- user_url.segments << (s = ROUTING::StaticSegment.new)
- s.value = '/'
- s.raw = true
- s.is_optional = true
-
- user_url.segments << (s = ROUTING::DynamicSegment.new)
- s.key = :user
-
- user_url.segments << (s = ROUTING::StaticSegment.new)
- s.value = '/'
- s.raw = true
- s.is_optional = true
-
- user_url.requirements = {:controller => 'users', :action => 'show'}
-
- keys = user_url.significant_keys.sort_by { |k| k.to_s }
- assert_equal [:action, :controller, :user], keys
- end
-
- def test_build_empty_query_string
- assert_equal '', @route.build_query_string({})
- end
-
- def test_build_query_string_with_nil_value
- assert_equal '', @route.build_query_string({:x => nil})
- end
-
- def test_simple_build_query_string
- assert_equal '?x=1&y=2', order_query_string(@route.build_query_string(:x => '1', :y => '2'))
- end
-
- def test_convert_ints_build_query_string
- assert_equal '?x=1&y=2', order_query_string(@route.build_query_string(:x => 1, :y => 2))
- end
-
- def test_escape_spaces_build_query_string
- assert_equal '?x=hello+world&y=goodbye+world', order_query_string(@route.build_query_string(:x => 'hello world', :y => 'goodbye world'))
- end
-
- def test_expand_array_build_query_string
- assert_equal '?x%5B%5D=1&x%5B%5D=2', order_query_string(@route.build_query_string(:x => [1, 2]))
- end
-
- def test_escape_spaces_build_query_string_selected_keys
- assert_equal '?x=hello+world', order_query_string(@route.build_query_string({:x => 'hello world', :y => 'goodbye world'}, [:x]))
- end
-
- private
- def order_query_string(qs)
- '?' + qs[1..-1].split('&').sort.join('&')
- end
end
-end # uses_mocha
-
class RouteBuilderTest < Test::Unit::TestCase
-
def builder
@builder ||= ROUTING::RouteBuilder.new
end
@@ -1244,7 +384,7 @@ class RouteBuilderTest < Test::Unit::TestCase
assert_kind_of ROUTING::StaticSegment, segment
assert_equal 'ulysses', segment.value
end
-
+
def test_segment_for_action
segment, rest = builder.segment_for ':action'
assert_equal '', rest
@@ -1252,7 +392,7 @@ class RouteBuilderTest < Test::Unit::TestCase
assert_equal :action, segment.key
assert_equal 'index', segment.default
end
-
+
def test_segment_for_dynamic
segment, rest = builder.segment_for ':login'
assert_equal '', rest
@@ -1261,7 +401,7 @@ class RouteBuilderTest < Test::Unit::TestCase
assert_equal nil, segment.default
assert ! segment.optional?
end
-
+
def test_segment_for_with_rest
segment, rest = builder.segment_for ':login/:action'
assert_equal :login, segment.key
@@ -1273,105 +413,104 @@ class RouteBuilderTest < Test::Unit::TestCase
assert_equal :action, segment.key
assert_equal '', rest
end
-
+
def test_segments_for
segments = builder.segments_for_route_path '/:controller/:action/:id'
-
+
assert_kind_of ROUTING::DividerSegment, segments[0]
assert_equal '/', segments[2].value
-
+
assert_kind_of ROUTING::DynamicSegment, segments[1]
assert_equal :controller, segments[1].key
-
+
assert_kind_of ROUTING::DividerSegment, segments[2]
assert_equal '/', segments[2].value
-
+
assert_kind_of ROUTING::DynamicSegment, segments[3]
assert_equal :action, segments[3].key
-
+
assert_kind_of ROUTING::DividerSegment, segments[4]
assert_equal '/', segments[4].value
-
+
assert_kind_of ROUTING::DynamicSegment, segments[5]
assert_equal :id, segments[5].key
end
-
+
def test_segment_for_action
s, r = builder.segment_for(':action/something/else')
assert_equal '/something/else', r
assert_equal :action, s.key
end
-
+
def test_action_default_should_not_trigger_on_prefix
s, r = builder.segment_for ':action_name/something/else'
assert_equal '/something/else', r
assert_equal :action_name, s.key
assert_equal nil, s.default
end
-
+
def test_divide_route_options
segments = builder.segments_for_route_path '/cars/:action/:person/:car/'
defaults, requirements = builder.divide_route_options(segments,
:action => 'buy', :person => /\w+/, :car => /\w+/,
:defaults => {:person => nil, :car => nil}
)
-
+
assert_equal({:action => 'buy', :person => nil, :car => nil}, defaults)
assert_equal({:person => /\w+/, :car => /\w+/}, requirements)
end
-
+
def test_assign_route_options
segments = builder.segments_for_route_path '/cars/:action/:person/:car/'
defaults = {:action => 'buy', :person => nil, :car => nil}
requirements = {:person => /\w+/, :car => /\w+/}
-
+
route_requirements = builder.assign_route_options(segments, defaults, requirements)
assert_equal({}, route_requirements)
-
+
assert_equal :action, segments[3].key
assert_equal 'buy', segments[3].default
-
+
assert_equal :person, segments[5].key
assert_equal %r/\w+/, segments[5].regexp
assert segments[5].optional?
-
+
assert_equal :car, segments[7].key
assert_equal %r/\w+/, segments[7].regexp
assert segments[7].optional?
end
-
+
def test_assign_route_options_with_anchor_chars
segments = builder.segments_for_route_path '/cars/:action/:person/:car/'
defaults = {:action => 'buy', :person => nil, :car => nil}
requirements = {:person => /\w+/, :car => /^\w+$/}
-
+
assert_raises ArgumentError do
route_requirements = builder.assign_route_options(segments, defaults, requirements)
end
-
+
requirements[:car] = /[^\/]+/
route_requirements = builder.assign_route_options(segments, defaults, requirements)
end
-
def test_optional_segments_preceding_required_segments
segments = builder.segments_for_route_path '/cars/:action/:person/:car/'
defaults = {:action => 'buy', :person => nil, :car => "model-t"}
assert builder.assign_route_options(segments, defaults, {}).empty?
-
+
0.upto(1) { |i| assert !segments[i].optional?, "segment #{i} is optional and it shouldn't be" }
assert segments[2].optional?
-
+
assert_equal nil, builder.warn_output # should only warn on the :person segment
end
-
+
def test_segmentation_of_dot_path
segments = builder.segments_for_route_path '/books/:action.rss'
assert builder.assign_route_options(segments, {}, {}).empty?
assert_equal 6, segments.length # "/", "books", "/", ":action", ".", "rss"
assert !segments.any? { |seg| seg.optional? }
end
-
+
def test_segmentation_of_dynamic_dot_path
segments = builder.segments_for_route_path '/books/:action.:format'
assert builder.assign_route_options(segments, {}, {}).empty?
@@ -1379,56 +518,56 @@ class RouteBuilderTest < Test::Unit::TestCase
assert !segments.any? { |seg| seg.optional? }
assert_kind_of ROUTING::DynamicSegment, segments.last
end
-
+
def test_assignment_of_default_options
segments = builder.segments_for_route_path '/:controller/:action/:id/'
action, id = segments[-4], segments[-2]
-
+
assert_equal :action, action.key
assert_equal :id, id.key
assert ! action.optional?
assert ! id.optional?
-
+
builder.assign_default_route_options(segments)
-
+
assert_equal 'index', action.default
assert action.optional?
assert id.optional?
end
-
+
def test_assignment_of_default_options_respects_existing_defaults
segments = builder.segments_for_route_path '/:controller/:action/:id/'
action, id = segments[-4], segments[-2]
-
+
assert_equal :action, action.key
assert_equal :id, id.key
action.default = 'show'
action.is_optional = true
-
+
id.default = 'Welcome'
id.is_optional = true
-
+
builder.assign_default_route_options(segments)
-
+
assert_equal 'show', action.default
assert action.optional?
assert_equal 'Welcome', id.default
assert id.optional?
end
-
+
def test_assignment_of_default_options_respects_regexps
segments = builder.segments_for_route_path '/:controller/:action/:id/'
action = segments[-4]
-
+
assert_equal :action, action.key
action.regexp = /show|in/ # Use 'in' to check partial matches
-
+
builder.assign_default_route_options(segments)
-
+
assert_equal nil, action.default
assert ! action.optional?
end
-
+
def test_assignment_of_is_optional_when_default
segments = builder.segments_for_route_path '/books/:action.rss'
assert_equal segments[3].key, :action
@@ -1436,44 +575,44 @@ class RouteBuilderTest < Test::Unit::TestCase
builder.ensure_required_segments(segments)
assert ! segments[3].optional?
end
-
+
def test_is_optional_is_assigned_to_default_segments
segments = builder.segments_for_route_path '/books/:action'
builder.assign_route_options(segments, {:action => 'index'}, {})
-
+
assert_equal segments[3].key, :action
assert segments[3].optional?
assert_kind_of ROUTING::DividerSegment, segments[2]
assert segments[2].optional?
end
-
+
# XXX is optional not being set right?
# /blah/:defaulted_segment <-- is the second slash optional? it should be.
-
+
def test_route_build
ActionController::Routing.with_controllers %w(users pages) do
r = builder.build '/:controller/:action/:id/', :action => nil
-
+
[0, 2, 4].each do |i|
assert_kind_of ROUTING::DividerSegment, r.segments[i]
assert_equal '/', r.segments[i].value
assert r.segments[i].optional? if i > 1
end
-
+
assert_kind_of ROUTING::DynamicSegment, r.segments[1]
assert_equal :controller, r.segments[1].key
assert_equal nil, r.segments[1].default
-
+
assert_kind_of ROUTING::DynamicSegment, r.segments[3]
assert_equal :action, r.segments[3].key
assert_equal 'index', r.segments[3].default
-
+
assert_kind_of ROUTING::DynamicSegment, r.segments[5]
assert_equal :id, r.segments[5].key
assert r.segments[5].optional?
end
end
-
+
def test_slashes_are_implied
routes = [
builder.build('/:controller/:action/:id/', :action => nil),
@@ -1487,866 +626,1699 @@ class RouteBuilderTest < Test::Unit::TestCase
assert_equal expected, found, "Route #{i + 1} has #{found} segments, expected #{expected}"
end
end
-
end
+class RoutingTest < Test::Unit::TestCase
+ def test_possible_controllers
+ true_controller_paths = ActionController::Routing.controller_paths
+ ActionController::Routing.use_controllers! nil
+ silence_warnings do
+ Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + '/controller_fixtures')
+ end
-class RouteSetTest < Test::Unit::TestCase
+ ActionController::Routing.controller_paths = [
+ RAILS_ROOT, RAILS_ROOT + '/app/controllers', RAILS_ROOT + '/vendor/plugins/bad_plugin/lib'
+ ]
- def set
- @set ||= ROUTING::RouteSet.new
+ assert_equal ["admin/user", "plugin", "user"], ActionController::Routing.possible_controllers.sort
+ ensure
+ if true_controller_paths
+ ActionController::Routing.controller_paths = true_controller_paths
+ end
+ ActionController::Routing.use_controllers! nil
+ Object.send(:remove_const, :RAILS_ROOT) rescue nil
end
- def request
- @request ||= MockRequest.new(:host => "named.routes.test", :method => :get)
+ def test_possible_controllers_are_reset_on_each_load
+ true_possible_controllers = ActionController::Routing.possible_controllers
+ true_controller_paths = ActionController::Routing.controller_paths
+
+ ActionController::Routing.use_controllers! nil
+ root = File.dirname(__FILE__) + '/controller_fixtures'
+
+ ActionController::Routing.controller_paths = []
+ assert_equal [], ActionController::Routing.possible_controllers
+
+ ActionController::Routing::Routes.load!
+ ActionController::Routing.controller_paths = [
+ root, root + '/app/controllers', root + '/vendor/plugins/bad_plugin/lib'
+ ]
+
+ assert_equal ["admin/user", "plugin", "user"], ActionController::Routing.possible_controllers.sort
+ ensure
+ ActionController::Routing.controller_paths = true_controller_paths
+ ActionController::Routing.use_controllers! true_possible_controllers
+ Object.send(:remove_const, :RAILS_ROOT) rescue nil
+
+ ActionController::Routing::Routes.clear!
+ ActionController::Routing::Routes.load_routes!
end
- def test_generate_extras
- set.draw { |m| m.connect ':controller/:action/:id' }
- path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
- assert_equal "/foo/bar/15", path
- assert_equal %w(that this), extras.map(&:to_s).sort
+ def test_with_controllers
+ c = %w(admin/accounts admin/users account pages)
+ ActionController::Routing.with_controllers c do
+ assert_equal c, ActionController::Routing.possible_controllers
+ end
end
- def test_extra_keys
- set.draw { |m| m.connect ':controller/:action/:id' }
- extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
- assert_equal %w(that this), extras.map(&:to_s).sort
+ def test_normalize_unix_paths
+ load_paths = %w(. config/../app/controllers config/../app//helpers script/../config/../vendor/rails/actionpack/lib vendor/rails/railties/builtin/rails_info app/models lib script/../config/../foo/bar/../../app/models .foo/../.bar foo.bar/../config)
+ paths = ActionController::Routing.normalize_paths(load_paths)
+ assert_equal %w(vendor/rails/railties/builtin/rails_info vendor/rails/actionpack/lib app/controllers app/helpers app/models config .bar lib .), paths
end
-
- def test_generate_extras_not_first
- set.draw do |map|
- map.connect ':controller/:action/:id.:format'
- map.connect ':controller/:action/:id'
- end
- path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
- assert_equal "/foo/bar/15", path
- assert_equal %w(that this), extras.map(&:to_s).sort
+
+ def test_normalize_windows_paths
+ load_paths = %w(. config\\..\\app\\controllers config\\..\\app\\\\helpers script\\..\\config\\..\\vendor\\rails\\actionpack\\lib vendor\\rails\\railties\\builtin\\rails_info app\\models lib script\\..\\config\\..\\foo\\bar\\..\\..\\app\\models .foo\\..\\.bar foo.bar\\..\\config)
+ paths = ActionController::Routing.normalize_paths(load_paths)
+ assert_equal %w(vendor\\rails\\railties\\builtin\\rails_info vendor\\rails\\actionpack\\lib app\\controllers app\\helpers app\\models config .bar lib .), paths
end
-
- def test_generate_not_first
- set.draw do |map|
- map.connect ':controller/:action/:id.:format'
- map.connect ':controller/:action/:id'
- end
- assert_equal "/foo/bar/15?this=hello", set.generate(:controller => "foo", :action => "bar", :id => 15, :this => "hello")
+
+ def test_routing_helper_module
+ assert_kind_of Module, ActionController::Routing::Helpers
+
+ h = ActionController::Routing::Helpers
+ c = Class.new
+ assert ! c.ancestors.include?(h)
+ ActionController::Routing::Routes.install_helpers c
+ assert c.ancestors.include?(h)
end
-
- def test_extra_keys_not_first
- set.draw do |map|
- map.connect ':controller/:action/:id.:format'
- map.connect ':controller/:action/:id'
+end
+
+uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
+ class MockController
+ attr_accessor :routes
+
+ def initialize(routes)
+ self.routes = routes
end
- extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
- assert_equal %w(that this), extras.map(&:to_s).sort
- end
- def test_draw
- assert_equal 0, set.routes.size
- set.draw do |map|
- map.connect '/hello/world', :controller => 'a', :action => 'b'
+ def url_for(options)
+ only_path = options.delete(:only_path)
+
+ port = options.delete(:port) || 80
+ port_string = port == 80 ? '' : ":#{port}"
+
+ host = options.delete(:host) || "named.route.test"
+ anchor = "##{options.delete(:anchor)}" if options.key?(:anchor)
+
+ path = routes.generate(options)
+
+ only_path ? "#{path}#{anchor}" : "http://#{host}#{port_string}#{path}#{anchor}"
end
- assert_equal 1, set.routes.size
- end
-
- def test_named_draw
- assert_equal 0, set.routes.size
- set.draw do |map|
- map.hello '/hello/world', :controller => 'a', :action => 'b'
+
+ def request
+ @request ||= MockRequest.new(:host => "named.route.test", :method => :get)
end
- assert_equal 1, set.routes.size
- assert_equal set.routes.first, set.named_routes[:hello]
- end
-
- def test_later_named_routes_take_precedence
- set.draw do |map|
- map.hello '/hello/world', :controller => 'a', :action => 'b'
- map.hello '/hello', :controller => 'a', :action => 'b'
+
+ def relative_url_root=(value)
+ request.relative_url_root=value
end
- assert_equal set.routes.last, set.named_routes[:hello]
end
- def setup_named_route_test
- set.draw do |map|
- map.show '/people/:id', :controller => 'people', :action => 'show'
- map.index '/people', :controller => 'people', :action => 'index'
- map.multi '/people/go/:foo/:bar/joe/:id', :controller => 'people', :action => 'multi'
- map.users '/admin/users', :controller => 'admin/users', :action => 'index'
+ class MockRequest
+ attr_accessor :path, :path_parameters, :host, :subdomains, :domain,
+ :method, :relative_url_root
+
+ def initialize(values={})
+ values.each { |key, value| send("#{key}=", value) }
+ if values[:host]
+ subdomain, self.domain = values[:host].split(/\./, 2)
+ self.subdomains = [subdomain]
+ end
+ end
+
+ def protocol
+ "http://"
end
- klass = Class.new(MockController)
- set.install_helpers(klass)
- klass.new(set)
+ def host_with_port
+ (subdomains * '.') + '.' + domain
+ end
end
- def test_named_route_hash_access_method
- controller = setup_named_route_test
+ class LegacyRouteSetTests < Test::Unit::TestCase
+ attr_reader :rs
- assert_equal(
- { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => false },
- controller.send(:hash_for_show_url, :id => 5))
+ def setup
+ # These tests assume optimisation is on, so re-enable it.
+ ActionController::Base.optimise_named_routes = true
- assert_equal(
- { :controller => 'people', :action => 'index', :use_route => :index, :only_path => false },
- controller.send(:hash_for_index_url))
-
- assert_equal(
- { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => true },
- controller.send(:hash_for_show_path, :id => 5)
- )
- end
+ @rs = ::ActionController::Routing::RouteSet.new
+ @rs.draw {|m| m.connect ':controller/:action/:id' }
- def test_named_route_url_method
- controller = setup_named_route_test
-
- assert_equal "http://named.route.test/people/5", controller.send(:show_url, :id => 5)
- assert_equal "/people/5", controller.send(:show_path, :id => 5)
-
- assert_equal "http://named.route.test/people", controller.send(:index_url)
- assert_equal "/people", controller.send(:index_path)
+ ActionController::Routing.use_controllers! %w(content admin/user admin/news_feed)
+ end
- assert_equal "http://named.route.test/admin/users", controller.send(:users_url)
- assert_equal '/admin/users', controller.send(:users_path)
- assert_equal '/admin/users', set.generate(controller.send(:hash_for_users_url), {:controller => 'users', :action => 'index'})
- end
+ def test_default_setup
+ assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content"))
+ assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list"))
+ assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10"))
- def test_named_route_url_method_with_anchor
- controller = setup_named_route_test
+ assert_equal({:controller => "admin/user", :action => 'show', :id => '10'}, rs.recognize_path("/admin/user/show/10"))
- assert_equal "http://named.route.test/people/5#location", controller.send(:show_url, :id => 5, :anchor => 'location')
- assert_equal "/people/5#location", controller.send(:show_path, :id => 5, :anchor => 'location')
+ assert_equal '/admin/user/show/10', rs.generate(:controller => 'admin/user', :action => 'show', :id => 10)
- assert_equal "http://named.route.test/people#location", controller.send(:index_url, :anchor => 'location')
- assert_equal "/people#location", controller.send(:index_path, :anchor => 'location')
+ assert_equal '/admin/user/show', rs.generate({:action => 'show'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
+ assert_equal '/admin/user/list/10', rs.generate({}, {:controller => 'admin/user', :action => 'list', :id => '10'})
- assert_equal "http://named.route.test/admin/users#location", controller.send(:users_url, :anchor => 'location')
- assert_equal '/admin/users#location', controller.send(:users_path, :anchor => 'location')
+ assert_equal '/admin/stuff', rs.generate({:controller => 'stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
+ assert_equal '/stuff', rs.generate({:controller => '/stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
+ end
- assert_equal "http://named.route.test/people/go/7/hello/joe/5#location",
- controller.send(:multi_url, 7, "hello", 5, :anchor => 'location')
+ def test_ignores_leading_slash
+ @rs.draw {|m| m.connect '/:controller/:action/:id'}
+ test_default_setup
+ end
- assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar#location",
- controller.send(:multi_url, 7, "hello", 5, :baz => "bar", :anchor => 'location')
+ def test_time_recognition
+ # We create many routes to make situation more realistic
+ @rs = ::ActionController::Routing::RouteSet.new
+ @rs.draw { |map|
+ map.frontpage '', :controller => 'search', :action => 'new'
+ map.resources :videos do |video|
+ video.resources :comments
+ video.resource :file, :controller => 'video_file'
+ video.resource :share, :controller => 'video_shares'
+ video.resource :abuse, :controller => 'video_abuses'
+ end
+ map.resources :abuses, :controller => 'video_abuses'
+ map.resources :video_uploads
+ map.resources :video_visits
- assert_equal "http://named.route.test/people?baz=bar#location",
- controller.send(:index_url, :baz => "bar", :anchor => 'location')
- end
-
- def test_named_route_url_method_with_port
- controller = setup_named_route_test
- assert_equal "http://named.route.test:8080/people/5", controller.send(:show_url, 5, :port=>8080)
- end
-
- def test_named_route_url_method_with_host
- controller = setup_named_route_test
- assert_equal "http://some.example.com/people/5", controller.send(:show_url, 5, :host=>"some.example.com")
- end
-
+ map.resources :users do |user|
+ user.resource :settings
+ user.resources :videos
+ end
+ map.resources :channels do |channel|
+ channel.resources :videos, :controller => 'channel_videos'
+ end
+ map.resource :session
+ map.resource :lost_password
+ map.search 'search', :controller => 'search'
+ map.resources :pages
+ map.connect ':controller/:action/:id'
+ }
+ n = 1000
+ if RunTimeTests
+ GC.start
+ rectime = Benchmark.realtime do
+ n.times do
+ rs.recognize_path("/videos/1234567", {:method => :get})
+ rs.recognize_path("/videos/1234567/abuse", {:method => :get})
+ rs.recognize_path("/users/1234567/settings", {:method => :get})
+ rs.recognize_path("/channels/1234567", {:method => :get})
+ rs.recognize_path("/session/new", {:method => :get})
+ rs.recognize_path("/admin/user/show/10", {:method => :get})
+ end
+ end
+ puts "\n\nRecognition (#{rs.routes.size} routes):"
+ per_url = rectime / (n * 6)
+ puts "#{per_url * 1000} ms/url"
+ puts "#{1 / per_url} url/s\n\n"
+ end
+ end
+ def test_time_generation
+ n = 5000
+ if RunTimeTests
+ GC.start
+ pairs = [
+ [{:controller => 'content', :action => 'index'}, {:controller => 'content', :action => 'show'}],
+ [{:controller => 'content'}, {:controller => 'content', :action => 'index'}],
+ [{:controller => 'content', :action => 'list'}, {:controller => 'content', :action => 'index'}],
+ [{:controller => 'content', :action => 'show', :id => '10'}, {:controller => 'content', :action => 'list'}],
+ [{:controller => 'admin/user', :action => 'index'}, {:controller => 'admin/user', :action => 'show'}],
+ [{:controller => 'admin/user'}, {:controller => 'admin/user', :action => 'index'}],
+ [{:controller => 'admin/user', :action => 'list'}, {:controller => 'admin/user', :action => 'index'}],
+ [{:controller => 'admin/user', :action => 'show', :id => '10'}, {:controller => 'admin/user', :action => 'list'}],
+ ]
+ p = nil
+ gentime = Benchmark.realtime do
+ n.times do
+ pairs.each {|(a, b)| rs.generate(a, b)}
+ end
+ end
- def test_named_route_url_method_with_ordered_parameters
- 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
+ puts "\n\nGeneration (RouteSet): (#{(n * 8)} urls)"
+ per_url = gentime / (n * 8)
+ puts "#{per_url * 1000} ms/url"
+ puts "#{1 / per_url} url/s\n\n"
+ end
+ end
- def test_named_route_url_method_with_ordered_parameters_and_hash
- controller = setup_named_route_test
- assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar",
- controller.send(:multi_url, 7, "hello", 5, :baz => "bar")
- 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",
- controller.send(:index_url, :baz => "bar")
- end
-
- def test_draw_default_route
- ActionController::Routing.with_controllers(['users']) do
- set.draw do |map|
- map.connect '/:controller/:action/:id'
+ def test_route_with_colon_first
+ rs.draw do |map|
+ map.connect '/:controller/:action/:id', :action => 'index', :id => nil
+ map.connect ':url', :controller => 'tiny_url', :action => 'translate'
end
+ end
- assert_equal 1, set.routes.size
- route = set.routes.first
+ def test_route_with_regexp_for_controller
+ rs.draw do |map|
+ map.connect ':controller/:admintoken/:action/:id', :controller => /admin\/.+/
+ map.connect ':controller/:action/:id'
+ end
+ assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"},
+ rs.recognize_path("/admin/user/foo"))
+ assert_equal({:controller => "content", :action => "foo"}, rs.recognize_path("/content/foo"))
+ assert_equal '/admin/user/foo', rs.generate(:controller => "admin/user", :admintoken => "foo", :action => "index")
+ assert_equal '/content/foo', rs.generate(:controller => "content", :action => "foo")
+ end
- assert route.segments.last.optional?
+ def test_route_with_regexp_and_dot
+ rs.draw do |map|
+ map.connect ':controller/:action/:file',
+ :controller => /admin|user/,
+ :action => /upload|download/,
+ :defaults => {:file => nil},
+ :requirements => {:file => %r{[^/]+(\.[^/]+)?}}
+ end
+ # Without a file extension
+ assert_equal '/user/download/file',
+ rs.generate(:controller => "user", :action => "download", :file => "file")
+ assert_equal(
+ {:controller => "user", :action => "download", :file => "file"},
+ rs.recognize_path("/user/download/file"))
+
+ # Now, let's try a file with an extension, really a dot (.)
+ assert_equal '/user/download/file.jpg',
+ rs.generate(
+ :controller => "user", :action => "download", :file => "file.jpg")
+ assert_equal(
+ {:controller => "user", :action => "download", :file => "file.jpg"},
+ rs.recognize_path("/user/download/file.jpg"))
+ end
+
+ def test_basic_named_route
+ rs.add_named_route :home, '', :controller => 'content', :action => 'list'
+ x = setup_for_named_route
+ assert_equal("http://named.route.test/",
+ x.send(:home_url))
+ end
- assert_equal '/users/show/10', set.generate(:controller => 'users', :action => 'show', :id => 10)
- assert_equal '/users/index/10', set.generate(:controller => 'users', :id => 10)
+ def test_basic_named_route_with_relative_url_root
+ rs.add_named_route :home, '', :controller => 'content', :action => 'list'
+ x = setup_for_named_route
+ x.relative_url_root="/foo"
+ assert_equal("http://named.route.test/foo/",
+ x.send(:home_url))
+ assert_equal "/foo/", x.send(:home_path)
+ end
- assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10'))
- assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10/'))
+ def test_named_route_with_option
+ rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page'
+ x = setup_for_named_route
+ assert_equal("http://named.route.test/page/new%20stuff",
+ x.send(:page_url, :title => 'new stuff'))
end
- end
- def test_draw_default_route_with_default_controller
- ActionController::Routing.with_controllers(['users']) do
- set.draw do |map|
- map.connect '/:controller/:action/:id', :controller => 'users'
- end
- assert_equal({:controller => 'users', :action => 'index'}, set.recognize_path('/'))
+ def test_named_route_with_default
+ rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage'
+ x = setup_for_named_route
+ assert_equal("http://named.route.test/page/AboutRails",
+ x.send(:page_url, :title => "AboutRails"))
+
end
- end
- def test_route_with_parameter_shell
- ActionController::Routing.with_controllers(['users', 'pages']) do
- set.draw do |map|
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/
- map.connect '/:controller/:action/:id'
+ def test_named_route_with_nested_controller
+ rs.add_named_route :users, 'admin/user', :controller => 'admin/user', :action => 'index'
+ x = setup_for_named_route
+ assert_equal("http://named.route.test/admin/user",
+ x.send(:users_url))
+ end
+
+ def test_optimised_named_route_call_never_uses_url_for
+ rs.add_named_route :users, 'admin/user', :controller => '/admin/user', :action => 'index'
+ rs.add_named_route :user, 'admin/user/:id', :controller=>'/admin/user', :action=>'show'
+ x = setup_for_named_route
+ x.expects(:url_for).never
+ x.send(:users_url)
+ x.send(:users_path)
+ x.send(:user_url, 2, :foo=>"bar")
+ x.send(:user_path, 3, :bar=>"foo")
+ end
+
+ def test_optimised_named_route_with_host
+ rs.add_named_route :pages, 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com'
+ x = setup_for_named_route
+ x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once
+ x.send(:pages_url)
+ end
+
+ def setup_for_named_route
+ klass = Class.new(MockController)
+ rs.install_helpers(klass)
+ klass.new(rs)
+ end
+
+ def test_named_route_without_hash
+ rs.draw do |map|
+ map.normal ':controller/:action/:id'
+ end
+ end
+
+ def test_named_route_root
+ rs.draw do |map|
+ map.root :controller => "hello"
end
+ x = setup_for_named_route
+ assert_equal("http://named.route.test/", x.send(:root_url))
+ assert_equal("/", x.send(:root_path))
+ end
- assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages'))
- assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages/index'))
- assert_equal({:controller => 'pages', :action => 'list'}, set.recognize_path('/pages/list'))
+ def test_named_route_with_regexps
+ rs.draw do |map|
+ map.article 'page/:year/:month/:day/:title', :controller => 'page', :action => 'show',
+ :year => /\d+/, :month => /\d+/, :day => /\d+/
+ map.connect ':controller/:action/:id'
+ end
+ x = setup_for_named_route
+ # assert_equal(
+ # {:controller => 'page', :action => 'show', :title => 'hi', :use_route => :article, :only_path => false},
+ # x.send(:article_url, :title => 'hi')
+ # )
+ assert_equal(
+ "http://named.route.test/page/2005/6/10/hi",
+ x.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6)
+ )
+ end
- assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/pages/show/10'))
- assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
+ def test_changing_controller
+ assert_equal '/admin/stuff/show/10', rs.generate(
+ {:controller => 'stuff', :action => 'show', :id => 10},
+ {:controller => 'admin/user', :action => 'index'}
+ )
end
- end
- def test_route_requirements_with_anchor_chars_are_invalid
- assert_raises ArgumentError do
- set.draw do |map|
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /^\d+/
+ def test_paths_escaped
+ rs.draw do |map|
+ map.path 'file/*path', :controller => 'content', :action => 'show_file'
+ map.connect ':controller/:action/:id'
end
+
+ # No + to space in URI escaping, only for query params.
+ results = rs.recognize_path "/file/hello+world/how+are+you%3F"
+ assert results, "Recognition should have succeeded"
+ assert_equal ['hello+world', 'how+are+you?'], results[:path]
+
+ # Use %20 for space instead.
+ results = rs.recognize_path "/file/hello%20world/how%20are%20you%3F"
+ assert results, "Recognition should have succeeded"
+ assert_equal ['hello world', 'how are you?'], results[:path]
+
+ results = rs.recognize_path "/file"
+ assert results, "Recognition should have succeeded"
+ assert_equal [], results[:path]
end
- assert_raises ArgumentError do
- set.draw do |map|
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\A\d+/
+
+ def test_paths_slashes_unescaped_with_ordered_parameters
+ rs.add_named_route :path, '/file/*path', :controller => 'content'
+
+ # No / to %2F in URI, only for query params.
+ x = setup_for_named_route
+ assert_equal("/file/hello/world", x.send(:path_path, 'hello/world'))
+ end
+
+ def test_non_controllers_cannot_be_matched
+ rs.draw do |map|
+ map.connect ':controller/:action/:id'
end
+ assert_raises(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") }
end
- assert_raises ArgumentError do
- set.draw do |map|
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+$/
+
+ def test_paths_do_not_accept_defaults
+ assert_raises(ActionController::RoutingError) do
+ rs.draw do |map|
+ map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => %w(fake default)
+ map.connect ':controller/:action/:id'
+ end
+ end
+
+ rs.draw do |map|
+ map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => []
+ map.connect ':controller/:action/:id'
end
end
- assert_raises ArgumentError do
- set.draw do |map|
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\Z/
+
+ def test_should_list_options_diff_when_routing_requirements_dont_match
+ rs.draw do |map|
+ map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
end
+ exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post") }
+ assert_match /^post_url failed to generate/, exception.message
+ from_match = exception.message.match(/from \{[^\}]+\}/).to_s
+ assert_match /:bad_param=>"foo"/, from_match
+ assert_match /:action=>"show"/, from_match
+ assert_match /:controller=>"post"/, from_match
+
+ expected_match = exception.message.match(/expected: \{[^\}]+\}/).to_s
+ assert_no_match /:bad_param=>"foo"/, expected_match
+ assert_match /:action=>"show"/, expected_match
+ assert_match /:controller=>"post"/, expected_match
+
+ diff_match = exception.message.match(/diff: \{[^\}]+\}/).to_s
+ assert_match /:bad_param=>"foo"/, diff_match
+ assert_no_match /:action=>"show"/, diff_match
+ assert_no_match /:controller=>"post"/, diff_match
+ end
+
+ # this specifies the case where your formerly would get a very confusing error message with an empty diff
+ def test_should_have_better_error_message_when_options_diff_is_empty
+ rs.draw do |map|
+ map.content '/content/:query', :controller => 'content', :action => 'show'
+ end
+
+ exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") }
+ assert_match %r[:action=>"show"], exception.message
+ assert_match %r[:controller=>"content"], exception.message
+ assert_match %r[you may have ambiguous routes, or you may need to supply additional parameters for this route], exception.message
+ assert_match %r[content_url has the following required parameters: \["content", :query\] - are they all satisfied?], exception.message
end
- assert_raises ArgumentError do
- set.draw do |map|
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\z/
+
+ def test_dynamic_path_allowed
+ rs.draw do |map|
+ map.connect '*path', :controller => 'content', :action => 'show_file'
+ end
+
+ assert_equal '/pages/boo', rs.generate(:controller => 'content', :action => 'show_file', :path => %w(pages boo))
+ end
+
+ def test_dynamic_recall_paths_allowed
+ rs.draw do |map|
+ map.connect '*path', :controller => 'content', :action => 'show_file'
end
+
+ recall_path = ActionController::Routing::PathSegment::Result.new(%w(pages boo))
+ assert_equal '/pages/boo', rs.generate({}, :controller => 'content', :action => 'show_file', :path => recall_path)
end
- assert_nothing_raised do
- set.draw do |map|
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/, :name => /^(david|jamis)/
+
+ def test_backwards
+ rs.draw do |map|
+ map.connect 'page/:id/:action', :controller => 'pages', :action => 'show'
+ map.connect ':controller/:action/:id'
+ end
+
+ assert_equal '/page/20', rs.generate({:id => 20}, {:controller => 'pages', :action => 'show'})
+ assert_equal '/page/20', rs.generate(:controller => 'pages', :id => 20, :action => 'show')
+ assert_equal '/pages/boo', rs.generate(:controller => 'pages', :action => 'boo')
+ end
+
+ def test_route_with_fixnum_default
+ rs.draw do |map|
+ map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1
+ map.connect ':controller/:action/:id'
+ end
+
+ assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page')
+ assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => 1)
+ assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => '1')
+ assert_equal '/page/10', rs.generate(:controller => 'content', :action => 'show_page', :id => 10)
+
+ assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page"))
+ assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page/1"))
+ assert_equal({:controller => "content", :action => 'show_page', :id => '10'}, rs.recognize_path("/page/10"))
+ end
+
+ # For newer revision
+ def test_route_with_text_default
+ rs.draw do |map|
+ map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1
+ map.connect ':controller/:action/:id'
+ end
+
+ assert_equal '/page/foo', rs.generate(:controller => 'content', :action => 'show_page', :id => 'foo')
+ assert_equal({:controller => "content", :action => 'show_page', :id => 'foo'}, rs.recognize_path("/page/foo"))
+
+ token = "\321\202\320\265\320\272\321\201\321\202" # 'text' in russian
+ escaped_token = CGI::escape(token)
+
+ assert_equal '/page/' + escaped_token, rs.generate(:controller => 'content', :action => 'show_page', :id => token)
+ assert_equal({:controller => "content", :action => 'show_page', :id => token}, rs.recognize_path("/page/#{escaped_token}"))
+ end
+
+ def test_action_expiry
+ assert_equal '/content', rs.generate({:controller => 'content'}, {:controller => 'content', :action => 'show'})
+ end
+
+ def test_recognition_with_uppercase_controller_name
+ assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/Content"))
+ assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/ConTent/list"))
+ assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/CONTENT/show/10"))
+
+ # these used to work, before the routes rewrite, but support for this was pulled in the new version...
+ #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/NewsFeed"))
+ #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/News_Feed"))
+ end
+
+ def test_requirement_should_prevent_optional_id
+ rs.draw do |map|
+ map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
end
+
+ assert_equal '/post/10', rs.generate(:controller => 'post', :action => 'show', :id => 10)
+
assert_raises ActionController::RoutingError do
- set.generate :controller => 'pages', :action => 'show', :id => 10
+ rs.generate(:controller => 'post', :action => 'show')
end
end
- end
- def test_non_path_route_requirements_match_all
- set.draw do |map|
- map.connect 'page/37s', :controller => 'pages', :action => 'show', :name => /(jamis|david)/
+ def test_both_requirement_and_optional
+ rs.draw do |map|
+ map.blog('test/:year', :controller => 'post', :action => 'show',
+ :defaults => { :year => nil },
+ :requirements => { :year => /\d{4}/ }
+ )
+ map.connect ':controller/:action/:id'
+ end
+
+ assert_equal '/test', rs.generate(:controller => 'post', :action => 'show')
+ assert_equal '/test', rs.generate(:controller => 'post', :action => 'show', :year => nil)
+
+ x = setup_for_named_route
+ assert_equal("http://named.route.test/test",
+ x.send(:blog_url))
end
- assert_equal '/page/37s', set.generate(:controller => 'pages', :action => 'show', :name => 'jamis')
- assert_raises ActionController::RoutingError do
- set.generate(:controller => 'pages', :action => 'show', :name => 'not_jamis')
+
+ def test_set_to_nil_forgets
+ rs.draw do |map|
+ map.connect 'pages/:year/:month/:day', :controller => 'content', :action => 'list_pages', :month => nil, :day => nil
+ map.connect ':controller/:action/:id'
+ end
+
+ assert_equal '/pages/2005',
+ rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005)
+ assert_equal '/pages/2005/6',
+ rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6)
+ assert_equal '/pages/2005/6/12',
+ rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12)
+
+ assert_equal '/pages/2005/6/4',
+ rs.generate({:day => 4}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
+
+ assert_equal '/pages/2005/6',
+ rs.generate({:day => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
+
+ assert_equal '/pages/2005',
+ rs.generate({:day => nil, :month => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
end
- assert_raises ActionController::RoutingError do
- set.generate(:controller => 'pages', :action => 'show', :name => 'nor_jamis_and_david')
+
+ def test_url_with_no_action_specified
+ rs.draw do |map|
+ map.connect '', :controller => 'content'
+ map.connect ':controller/:action/:id'
+ end
+
+ assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
+ assert_equal '/', rs.generate(:controller => 'content')
end
- end
-
- def test_recognize_with_encoded_id_and_regex
- set.draw do |map|
- map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /[a-zA-Z0-9\+]+/
+
+ def test_named_url_with_no_action_specified
+ rs.draw do |map|
+ map.home '', :controller => 'content'
+ map.connect ':controller/:action/:id'
+ end
+
+ assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
+ assert_equal '/', rs.generate(:controller => 'content')
+
+ x = setup_for_named_route
+ assert_equal("http://named.route.test/",
+ x.send(:home_url))
end
- assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
- assert_equal({:controller => 'pages', :action => 'show', :id => 'hello+world'}, set.recognize_path('/page/hello+world'))
- end
+ def test_url_generated_when_forgetting_action
+ [{:controller => 'content', :action => 'index'}, {:controller => 'content'}].each do |hash|
+ rs.draw do |map|
+ map.home '', hash
+ map.connect ':controller/:action/:id'
+ end
+ assert_equal '/', rs.generate({:action => nil}, {:controller => 'content', :action => 'hello'})
+ assert_equal '/', rs.generate({:controller => 'content'})
+ assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'})
+ end
+ end
- def test_recognize_with_conditions
- Object.const_set(:PeopleController, Class.new)
+ def test_named_route_method
+ rs.draw do |map|
+ map.categories 'categories', :controller => 'content', :action => 'categories'
+ map.connect ':controller/:action/:id'
+ end
- set.draw do |map|
- map.with_options(:controller => "people") do |people|
- people.people "/people", :action => "index", :conditions => { :method => :get }
- people.connect "/people", :action => "create", :conditions => { :method => :post }
- people.person "/people/:id", :action => "show", :conditions => { :method => :get }
- people.connect "/people/:id", :action => "update", :conditions => { :method => :put }
- people.connect "/people/:id", :action => "destroy", :conditions => { :method => :delete }
+ assert_equal '/categories', rs.generate(:controller => 'content', :action => 'categories')
+ assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'})
+ end
+
+ def test_named_routes_array
+ test_named_route_method
+ assert_equal [:categories], rs.named_routes.names
+ end
+
+ def test_nil_defaults
+ rs.draw do |map|
+ map.connect 'journal',
+ :controller => 'content',
+ :action => 'list_journal',
+ :date => nil, :user_id => nil
+ map.connect ':controller/:action/:id'
end
+
+ assert_equal '/journal', rs.generate(:controller => 'content', :action => 'list_journal', :date => nil, :user_id => nil)
end
- request.path = "/people"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("index", request.path_parameters[:action])
-
- request.method = :post
- assert_nothing_raised { set.recognize(request) }
- assert_equal("create", request.path_parameters[:action])
-
- request.method = :put
- assert_nothing_raised { set.recognize(request) }
- assert_equal("update", request.path_parameters[:action])
+ def setup_request_method_routes_for(method)
+ @request = ActionController::TestRequest.new
+ @request.env["REQUEST_METHOD"] = method
+ @request.request_uri = "/match"
- begin
- request.method = :bacon
- set.recognize(request)
- flunk 'Should have raised NotImplemented'
- rescue ActionController::NotImplemented => e
- assert_equal [:get, :post, :put, :delete], e.allowed_methods
+ rs.draw do |r|
+ r.connect '/match', :controller => 'books', :action => 'get', :conditions => { :method => :get }
+ r.connect '/match', :controller => 'books', :action => 'post', :conditions => { :method => :post }
+ r.connect '/match', :controller => 'books', :action => 'put', :conditions => { :method => :put }
+ r.connect '/match', :controller => 'books', :action => 'delete', :conditions => { :method => :delete }
+ end
end
- request.path = "/people/5"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("show", request.path_parameters[:action])
- assert_equal("5", request.path_parameters[:id])
+ %w(GET POST PUT DELETE).each do |request_method|
+ define_method("test_request_method_recognized_with_#{request_method}") do
+ begin
+ Object.const_set(:BooksController, Class.new(ActionController::Base))
+
+ setup_request_method_routes_for(request_method)
- request.method = :put
- assert_nothing_raised { set.recognize(request) }
- assert_equal("update", request.path_parameters[:action])
- assert_equal("5", request.path_parameters[:id])
+ assert_nothing_raised { rs.recognize(@request) }
+ assert_equal request_method.downcase, @request.path_parameters[:action]
+ ensure
+ Object.send(:remove_const, :BooksController) rescue nil
+ end
+ end
+ end
- request.method = :delete
- assert_nothing_raised { set.recognize(request) }
- assert_equal("destroy", request.path_parameters[:action])
- assert_equal("5", request.path_parameters[:id])
+ def test_subpath_recognized
+ Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
- begin
- request.method = :post
- set.recognize(request)
- flunk 'Should have raised MethodNotAllowed'
- rescue ActionController::MethodNotAllowed => e
- assert_equal [:get, :put, :delete], e.allowed_methods
+ rs.draw do |r|
+ r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
+ r.connect '/items/:id/:action', :controller => 'subpath_books'
+ r.connect '/posts/new/:action', :controller => 'subpath_books'
+ r.connect '/posts/:id', :controller => 'subpath_books', :action => "show"
+ end
+
+ hash = rs.recognize_path "/books/17/edit"
+ assert_not_nil hash
+ assert_equal %w(subpath_books 17 edit), [hash[:controller], hash[:id], hash[:action]]
+
+ hash = rs.recognize_path "/items/3/complete"
+ assert_not_nil hash
+ assert_equal %w(subpath_books 3 complete), [hash[:controller], hash[:id], hash[:action]]
+
+ hash = rs.recognize_path "/posts/new/preview"
+ assert_not_nil hash
+ assert_equal %w(subpath_books preview), [hash[:controller], hash[:action]]
+
+ hash = rs.recognize_path "/posts/7"
+ assert_not_nil hash
+ assert_equal %w(subpath_books show 7), [hash[:controller], hash[:action], hash[:id]]
+ ensure
+ Object.send(:remove_const, :SubpathBooksController) rescue nil
end
- ensure
- Object.send(:remove_const, :PeopleController)
- end
-
- def test_recognize_with_alias_in_conditions
- Object.const_set(:PeopleController, Class.new)
+ def test_subpath_generated
+ Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
+
+ rs.draw do |r|
+ r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
+ r.connect '/items/:id/:action', :controller => 'subpath_books'
+ r.connect '/posts/new/:action', :controller => 'subpath_books'
+ end
- set.draw do |map|
- map.people "/people", :controller => 'people', :action => "index",
- :conditions => { :method => :get }
- map.root :people
+ assert_equal "/books/7/edit", rs.generate(:controller => "subpath_books", :id => 7, :action => "edit")
+ assert_equal "/items/15/complete", rs.generate(:controller => "subpath_books", :id => 15, :action => "complete")
+ assert_equal "/posts/new/preview", rs.generate(:controller => "subpath_books", :action => "preview")
+ ensure
+ Object.send(:remove_const, :SubpathBooksController) rescue nil
end
- request.path = "/people"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("people", request.path_parameters[:controller])
- assert_equal("index", request.path_parameters[:action])
+ def test_failed_requirements_raises_exception_with_violated_requirements
+ rs.draw do |r|
+ r.foo_with_requirement 'foos/:id', :controller=>'foos', :requirements=>{:id=>/\d+/}
+ end
- request.path = "/"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("people", request.path_parameters[:controller])
- assert_equal("index", request.path_parameters[:action])
- ensure
- Object.send(:remove_const, :PeopleController)
- end
-
- def test_typo_recognition
- Object.const_set(:ArticlesController, Class.new)
-
- set.draw do |map|
- map.connect 'articles/:year/:month/:day/:title',
- :controller => 'articles', :action => 'permalink',
- :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/
- end
-
- request.path = "/articles/2005/11/05/a-very-interesting-article"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("permalink", request.path_parameters[:action])
- assert_equal("2005", request.path_parameters[:year])
- assert_equal("11", request.path_parameters[:month])
- assert_equal("05", request.path_parameters[:day])
- assert_equal("a-very-interesting-article", request.path_parameters[:title])
-
- ensure
- Object.send(:remove_const, :ArticlesController)
+ x = setup_for_named_route
+ assert_raises(ActionController::RoutingError) do
+ x.send(:foo_with_requirement_url, "I am Against the requirements")
+ end
+ end
end
- def test_routing_traversal_does_not_load_extra_classes
- assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
- set.draw do |map|
- map.connect '/profile', :controller => 'profile'
+ class RouteTest < Test::Unit::TestCase
+ def setup
+ @route = ROUTING::Route.new
end
- request.path = '/profile'
+ def slash_segment(is_optional = false)
+ returning ROUTING::DividerSegment.new('/') do |s|
+ s.is_optional = is_optional
+ end
+ end
- set.recognize(request) rescue nil
-
- assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
- end
+ def default_route
+ unless defined?(@default_route)
+ @default_route = ROUTING::Route.new
+
+ @default_route.segments << (s = ROUTING::StaticSegment.new)
+ s.value = '/'
+ s.raw = true
+
+ @default_route.segments << (s = ROUTING::DynamicSegment.new)
+ s.key = :controller
+
+ @default_route.segments << slash_segment(:optional)
+ @default_route.segments << (s = ROUTING::DynamicSegment.new)
+ s.key = :action
+ s.default = 'index'
+ s.is_optional = true
- def test_recognize_with_conditions_and_format
- Object.const_set(:PeopleController, Class.new)
+ @default_route.segments << slash_segment(:optional)
+ @default_route.segments << (s = ROUTING::DynamicSegment.new)
+ s.key = :id
+ s.is_optional = true
- set.draw do |map|
- map.with_options(:controller => "people") do |people|
- people.person "/people/:id", :action => "show", :conditions => { :method => :get }
- people.connect "/people/:id", :action => "update", :conditions => { :method => :put }
- people.connect "/people/:id.:_format", :action => "show", :conditions => { :method => :get }
+ @default_route.segments << slash_segment(:optional)
end
+ @default_route
end
- request.path = "/people/5"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("show", request.path_parameters[:action])
- assert_equal("5", request.path_parameters[:id])
+ def test_default_route_recognition
+ expected = {:controller => 'accounts', :action => 'show', :id => '10'}
+ assert_equal expected, default_route.recognize('/accounts/show/10')
+ assert_equal expected, default_route.recognize('/accounts/show/10/')
- request.method = :put
- assert_nothing_raised { set.recognize(request) }
- assert_equal("update", request.path_parameters[:action])
+ expected[:id] = 'jamis'
+ assert_equal expected, default_route.recognize('/accounts/show/jamis/')
- request.path = "/people/5.png"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("show", request.path_parameters[:action])
- assert_equal("5", request.path_parameters[:id])
- assert_equal("png", request.path_parameters[:_format])
- ensure
- Object.send(:remove_const, :PeopleController)
- end
+ expected.delete :id
+ assert_equal expected, default_route.recognize('/accounts/show')
+ assert_equal expected, default_route.recognize('/accounts/show/')
- def test_generate_with_default_action
- set.draw do |map|
- map.connect "/people", :controller => "people"
- map.connect "/people/list", :controller => "people", :action => "list"
+ expected[:action] = 'index'
+ assert_equal expected, default_route.recognize('/accounts/')
+ assert_equal expected, default_route.recognize('/accounts')
+
+ assert_equal nil, default_route.recognize('/')
+ assert_equal nil, default_route.recognize('/accounts/how/goood/it/is/to/be/free')
end
- url = set.generate(:controller => "people", :action => "list")
- assert_equal "/people/list", url
- end
-
- def test_root_map
- Object.const_set(:PeopleController, Class.new)
+ def test_default_route_should_omit_default_action
+ o = {:controller => 'accounts', :action => 'index'}
+ assert_equal '/accounts', default_route.generate(o, o, {})
+ end
- set.draw { |map| map.root :controller => "people" }
+ def test_default_route_should_include_default_action_when_id_present
+ o = {:controller => 'accounts', :action => 'index', :id => '20'}
+ assert_equal '/accounts/index/20', default_route.generate(o, o, {})
+ end
- request.path = ""
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("people", request.path_parameters[:controller])
- assert_equal("index", request.path_parameters[:action])
- ensure
- Object.send(:remove_const, :PeopleController)
- end
-
-
- def test_namespace
- Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
+ def test_default_route_should_work_with_action_but_no_id
+ o = {:controller => 'accounts', :action => 'list_all'}
+ assert_equal '/accounts/list_all', default_route.generate(o, o, {})
+ end
+
+ def test_default_route_should_uri_escape_pluses
+ expected = { :controller => 'accounts', :action => 'show', :id => 'hello world' }
+ assert_equal expected, default_route.recognize('/accounts/show/hello world')
+ assert_equal expected, default_route.recognize('/accounts/show/hello%20world')
+ assert_equal '/accounts/show/hello%20world', default_route.generate(expected, expected, {})
+
+ expected[:id] = 'hello+world'
+ assert_equal expected, default_route.recognize('/accounts/show/hello+world')
+ assert_equal expected, default_route.recognize('/accounts/show/hello%2Bworld')
+ assert_equal '/accounts/show/hello+world', default_route.generate(expected, expected, {})
+ end
- set.draw do |map|
-
- map.namespace 'api' do |api|
- api.route 'inventory', :controller => "products", :action => 'inventory'
+ def test_matches_controller_and_action
+ # requirement_for should only be called for the action and controller _once_
+ @route.expects(:requirement_for).with(:controller).times(1).returns('pages')
+ @route.expects(:requirement_for).with(:action).times(1).returns('show')
+
+ @route.requirements = {:controller => 'pages', :action => 'show'}
+ assert @route.matches_controller_and_action?('pages', 'show')
+ assert !@route.matches_controller_and_action?('not_pages', 'show')
+ assert !@route.matches_controller_and_action?('pages', 'not_show')
+ end
+
+ def test_parameter_shell
+ page_url = ROUTING::Route.new
+ page_url.requirements = {:controller => 'pages', :action => 'show', :id => /\d+/}
+ assert_equal({:controller => 'pages', :action => 'show'}, page_url.parameter_shell)
+ end
+
+ def test_defaults
+ route = ROUTING::RouteBuilder.new.build '/users/:id.:format', :controller => "users", :action => "show", :format => "html"
+ assert_equal(
+ { :controller => "users", :action => "show", :format => "html" },
+ route.defaults)
+ end
+
+ def test_builder_complains_without_controller
+ assert_raises(ArgumentError) do
+ ROUTING::RouteBuilder.new.build '/contact', :contoller => "contact", :action => "index"
end
-
end
- request.path = "/api/inventory"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("api/products", request.path_parameters[:controller])
- assert_equal("inventory", request.path_parameters[:action])
- ensure
- Object.send(:remove_const, :Api)
+ def test_significant_keys_for_default_route
+ keys = default_route.significant_keys.sort_by {|k| k.to_s }
+ assert_equal [:action, :controller, :id], keys
+ end
+
+ def test_significant_keys
+ user_url = ROUTING::Route.new
+ user_url.segments << (s = ROUTING::StaticSegment.new)
+ s.value = '/'
+ s.raw = true
+
+ user_url.segments << (s = ROUTING::StaticSegment.new)
+ s.value = 'user'
+
+ user_url.segments << (s = ROUTING::StaticSegment.new)
+ s.value = '/'
+ s.raw = true
+ s.is_optional = true
+
+ user_url.segments << (s = ROUTING::DynamicSegment.new)
+ s.key = :user
+
+ user_url.segments << (s = ROUTING::StaticSegment.new)
+ s.value = '/'
+ s.raw = true
+ s.is_optional = true
+
+ user_url.requirements = {:controller => 'users', :action => 'show'}
+
+ keys = user_url.significant_keys.sort_by { |k| k.to_s }
+ assert_equal [:action, :controller, :user], keys
+ end
+
+ def test_build_empty_query_string
+ assert_equal '', @route.build_query_string({})
+ end
+
+ def test_build_query_string_with_nil_value
+ assert_equal '', @route.build_query_string({:x => nil})
+ end
+
+ def test_simple_build_query_string
+ assert_equal '?x=1&y=2', order_query_string(@route.build_query_string(:x => '1', :y => '2'))
+ end
+
+ def test_convert_ints_build_query_string
+ assert_equal '?x=1&y=2', order_query_string(@route.build_query_string(:x => 1, :y => 2))
+ end
+
+ def test_escape_spaces_build_query_string
+ assert_equal '?x=hello+world&y=goodbye+world', order_query_string(@route.build_query_string(:x => 'hello world', :y => 'goodbye world'))
+ end
+
+ def test_expand_array_build_query_string
+ assert_equal '?x%5B%5D=1&x%5B%5D=2', order_query_string(@route.build_query_string(:x => [1, 2]))
+ end
+
+ def test_escape_spaces_build_query_string_selected_keys
+ assert_equal '?x=hello+world', order_query_string(@route.build_query_string({:x => 'hello world', :y => 'goodbye world'}, [:x]))
+ end
+
+ private
+ def order_query_string(qs)
+ '?' + qs[1..-1].split('&').sort.join('&')
+ end
end
-
- def test_namespaced_root_map
- Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
+ class RouteSetTest < Test::Unit::TestCase
+ def set
+ @set ||= ROUTING::RouteSet.new
+ end
+
+ def request
+ @request ||= MockRequest.new(:host => "named.routes.test", :method => :get)
+ end
+
+ def test_generate_extras
+ set.draw { |m| m.connect ':controller/:action/:id' }
+ path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
+ assert_equal "/foo/bar/15", path
+ assert_equal %w(that this), extras.map(&:to_s).sort
+ end
+
+ def test_extra_keys
+ set.draw { |m| m.connect ':controller/:action/:id' }
+ extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
+ assert_equal %w(that this), extras.map(&:to_s).sort
+ end
- set.draw do |map|
-
- map.namespace 'api' do |api|
- api.root :controller => "products"
+ def test_generate_extras_not_first
+ set.draw do |map|
+ map.connect ':controller/:action/:id.:format'
+ map.connect ':controller/:action/:id'
end
-
+ path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
+ assert_equal "/foo/bar/15", path
+ assert_equal %w(that this), extras.map(&:to_s).sort
end
- request.path = "/api"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("api/products", request.path_parameters[:controller])
- assert_equal("index", request.path_parameters[:action])
- ensure
- Object.send(:remove_const, :Api)
- end
+ def test_generate_not_first
+ set.draw do |map|
+ map.connect ':controller/:action/:id.:format'
+ map.connect ':controller/:action/:id'
+ end
+ assert_equal "/foo/bar/15?this=hello", set.generate(:controller => "foo", :action => "bar", :id => 15, :this => "hello")
+ end
- def test_generate_finds_best_fit
- set.draw do |map|
- map.connect "/people", :controller => "people", :action => "index"
- map.connect "/ws/people", :controller => "people", :action => "index", :ws => true
+ def test_extra_keys_not_first
+ set.draw do |map|
+ map.connect ':controller/:action/:id.:format'
+ map.connect ':controller/:action/:id'
+ end
+ extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
+ assert_equal %w(that this), extras.map(&:to_s).sort
end
- url = set.generate(:controller => "people", :action => "index", :ws => true)
- assert_equal "/ws/people", url
- end
+ def test_draw
+ assert_equal 0, set.routes.size
+ set.draw do |map|
+ map.connect '/hello/world', :controller => 'a', :action => 'b'
+ end
+ assert_equal 1, set.routes.size
+ end
- def test_generate_changes_controller_module
- set.draw { |map| map.connect ':controller/:action/:id' }
- current = { :controller => "bling/bloop", :action => "bap", :id => 9 }
- url = set.generate({:controller => "foo/bar", :action => "baz", :id => 7}, current)
- assert_equal "/foo/bar/baz/7", url
- end
+ def test_named_draw
+ assert_equal 0, set.routes.size
+ set.draw do |map|
+ map.hello '/hello/world', :controller => 'a', :action => 'b'
+ end
+ assert_equal 1, set.routes.size
+ assert_equal set.routes.first, set.named_routes[:hello]
+ end
- def test_id_is_not_impossibly_sticky
- set.draw do |map|
- map.connect 'foo/:number', :controller => "people", :action => "index"
- map.connect ':controller/:action/:id'
+ def test_later_named_routes_take_precedence
+ set.draw do |map|
+ map.hello '/hello/world', :controller => 'a', :action => 'b'
+ map.hello '/hello', :controller => 'a', :action => 'b'
+ end
+ assert_equal set.routes.last, set.named_routes[:hello]
end
- url = set.generate({:controller => "people", :action => "index", :number => 3},
- {:controller => "people", :action => "index", :id => "21"})
- assert_equal "/foo/3", url
- end
+ def setup_named_route_test
+ set.draw do |map|
+ map.show '/people/:id', :controller => 'people', :action => 'show'
+ map.index '/people', :controller => 'people', :action => 'index'
+ map.multi '/people/go/:foo/:bar/joe/:id', :controller => 'people', :action => 'multi'
+ map.users '/admin/users', :controller => 'admin/users', :action => 'index'
+ end
- def test_id_is_sticky_when_it_ought_to_be
- set.draw do |map|
- map.connect ':controller/:id/:action'
+ klass = Class.new(MockController)
+ set.install_helpers(klass)
+ klass.new(set)
end
- url = set.generate({:action => "destroy"}, {:controller => "people", :action => "show", :id => "7"})
- assert_equal "/people/7/destroy", url
- end
+ def test_named_route_hash_access_method
+ controller = setup_named_route_test
+
+ assert_equal(
+ { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => false },
+ controller.send(:hash_for_show_url, :id => 5))
+
+ assert_equal(
+ { :controller => 'people', :action => 'index', :use_route => :index, :only_path => false },
+ controller.send(:hash_for_index_url))
- def test_use_static_path_when_possible
- set.draw do |map|
- map.connect 'about', :controller => "welcome", :action => "about"
- map.connect ':controller/:action/:id'
+ assert_equal(
+ { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => true },
+ controller.send(:hash_for_show_path, :id => 5)
+ )
end
- url = set.generate({:controller => "welcome", :action => "about"},
- {:controller => "welcome", :action => "get", :id => "7"})
- assert_equal "/about", url
- end
+ def test_named_route_url_method
+ controller = setup_named_route_test
- def test_generate
- set.draw { |map| map.connect ':controller/:action/:id' }
+ assert_equal "http://named.route.test/people/5", controller.send(:show_url, :id => 5)
+ assert_equal "/people/5", controller.send(:show_path, :id => 5)
- args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" }
- assert_equal "/foo/bar/7?x=y", set.generate(args)
- assert_equal ["/foo/bar/7", [:x]], set.generate_extras(args)
- assert_equal [:x], set.extra_keys(args)
- end
+ assert_equal "http://named.route.test/people", controller.send(:index_url)
+ assert_equal "/people", controller.send(:index_path)
- def test_named_routes_are_never_relative_to_modules
- set.draw do |map|
- map.connect "/connection/manage/:action", :controller => 'connection/manage'
- map.connect "/connection/connection", :controller => "connection/connection"
- map.family_connection "/connection", :controller => "connection"
+ assert_equal "http://named.route.test/admin/users", controller.send(:users_url)
+ assert_equal '/admin/users', controller.send(:users_path)
+ assert_equal '/admin/users', set.generate(controller.send(:hash_for_users_url), {:controller => 'users', :action => 'index'})
end
- url = set.generate({:controller => "connection"}, {:controller => 'connection/manage'})
- assert_equal "/connection/connection", url
+ def test_named_route_url_method_with_anchor
+ controller = setup_named_route_test
- url = set.generate({:use_route => :family_connection, :controller => "connection"}, {:controller => 'connection/manage'})
- assert_equal "/connection", url
- end
-
- def test_action_left_off_when_id_is_recalled
- set.draw do |map|
- map.connect ':controller/:action/:id'
+ assert_equal "http://named.route.test/people/5#location", controller.send(:show_url, :id => 5, :anchor => 'location')
+ assert_equal "/people/5#location", controller.send(:show_path, :id => 5, :anchor => 'location')
+
+ assert_equal "http://named.route.test/people#location", controller.send(:index_url, :anchor => 'location')
+ assert_equal "/people#location", controller.send(:index_path, :anchor => 'location')
+
+ assert_equal "http://named.route.test/admin/users#location", controller.send(:users_url, :anchor => 'location')
+ assert_equal '/admin/users#location', controller.send(:users_path, :anchor => 'location')
+
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5#location",
+ controller.send(:multi_url, 7, "hello", 5, :anchor => 'location')
+
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar#location",
+ controller.send(:multi_url, 7, "hello", 5, :baz => "bar", :anchor => 'location')
+
+ assert_equal "http://named.route.test/people?baz=bar#location",
+ controller.send(:index_url, :baz => "bar", :anchor => 'location')
end
- assert_equal '/post', set.generate(
- {:controller => 'post', :action => 'index'},
- {:controller => 'post', :action => 'show', :id => '10'}
- )
- end
-
- def test_query_params_will_be_shown_when_recalled
- set.draw do |map|
- map.connect 'show_post/:parameter', :controller => 'post', :action => 'show'
- map.connect ':controller/:action/:id'
+
+ def test_named_route_url_method_with_port
+ controller = setup_named_route_test
+ assert_equal "http://named.route.test:8080/people/5", controller.send(:show_url, 5, :port=>8080)
end
- assert_equal '/post/edit?parameter=1', set.generate(
- {:action => 'edit', :parameter => 1},
- {:controller => 'post', :action => 'show', :parameter => 1}
- )
- end
- def test_expiry_determination_should_consider_values_with_to_param
- set.draw { |map| map.connect 'projects/:project_id/:controller/:action' }
- assert_equal '/projects/1/post/show', set.generate(
- {:action => 'show', :project_id => 1},
- {:controller => 'post', :action => 'show', :project_id => '1'})
- end
+ def test_named_route_url_method_with_host
+ controller = setup_named_route_test
+ assert_equal "http://some.example.com/people/5", controller.send(:show_url, 5, :host=>"some.example.com")
+ end
- def test_generate_all
- set.draw do |map|
- map.connect 'show_post/:id', :controller => 'post', :action => 'show'
- map.connect ':controller/:action/:id'
+ def test_named_route_url_method_with_ordered_parameters
+ 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
- all = set.generate(
- {:action => 'show', :id => 10, :generate_all => true},
- {:controller => 'post', :action => 'show'}
- )
- assert_equal 2, all.length
- assert_equal '/show_post/10', all.first
- assert_equal '/post/show/10', all.last
- end
-
- def test_named_route_in_nested_resource
- set.draw do |map|
- map.resources :projects do |project|
- project.milestones 'milestones', :controller => 'milestones', :action => 'index'
- end
- end
-
- request.path = "/projects/1/milestones"
- request.method = :get
- assert_nothing_raised { set.recognize(request) }
- assert_equal("milestones", request.path_parameters[:controller])
- assert_equal("index", request.path_parameters[:action])
- end
-
- def test_setting_root_in_namespace_using_symbol
- assert_nothing_raised do
+
+ def test_named_route_url_method_with_ordered_parameters_and_hash
+ controller = setup_named_route_test
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar",
+ controller.send(:multi_url, 7, "hello", 5, :baz => "bar")
+ 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",
+ controller.send(:index_url, :baz => "bar")
+ end
+
+ def test_draw_default_route
+ ActionController::Routing.with_controllers(['users']) do
+ set.draw do |map|
+ map.connect '/:controller/:action/:id'
+ end
+
+ assert_equal 1, set.routes.size
+ route = set.routes.first
+
+ assert route.segments.last.optional?
+
+ assert_equal '/users/show/10', set.generate(:controller => 'users', :action => 'show', :id => 10)
+ assert_equal '/users/index/10', set.generate(:controller => 'users', :id => 10)
+
+ assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10'))
+ assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10/'))
+ end
+ end
+
+ def test_draw_default_route_with_default_controller
+ ActionController::Routing.with_controllers(['users']) do
+ set.draw do |map|
+ map.connect '/:controller/:action/:id', :controller => 'users'
+ end
+ assert_equal({:controller => 'users', :action => 'index'}, set.recognize_path('/'))
+ end
+ end
+
+ def test_route_with_parameter_shell
+ ActionController::Routing.with_controllers(['users', 'pages']) do
+ set.draw do |map|
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/
+ map.connect '/:controller/:action/:id'
+ end
+
+ assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages'))
+ assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages/index'))
+ assert_equal({:controller => 'pages', :action => 'list'}, set.recognize_path('/pages/list'))
+
+ assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/pages/show/10'))
+ assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
+ end
+ end
+
+ def test_route_requirements_with_anchor_chars_are_invalid
+ assert_raises ArgumentError do
+ set.draw do |map|
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /^\d+/
+ end
+ end
+ assert_raises ArgumentError do
+ set.draw do |map|
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\A\d+/
+ end
+ end
+ assert_raises ArgumentError do
+ set.draw do |map|
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+$/
+ end
+ end
+ assert_raises ArgumentError do
+ set.draw do |map|
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\Z/
+ end
+ end
+ assert_raises ArgumentError do
+ set.draw do |map|
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\z/
+ end
+ end
+ assert_nothing_raised do
+ set.draw do |map|
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/, :name => /^(david|jamis)/
+ end
+ assert_raises ActionController::RoutingError do
+ set.generate :controller => 'pages', :action => 'show', :id => 10
+ end
+ end
+ end
+
+ def test_non_path_route_requirements_match_all
set.draw do |map|
- map.namespace :admin do |admin|
- admin.root :controller => 'home'
+ map.connect 'page/37s', :controller => 'pages', :action => 'show', :name => /(jamis|david)/
+ end
+ assert_equal '/page/37s', set.generate(:controller => 'pages', :action => 'show', :name => 'jamis')
+ assert_raises ActionController::RoutingError do
+ set.generate(:controller => 'pages', :action => 'show', :name => 'not_jamis')
+ end
+ assert_raises ActionController::RoutingError do
+ set.generate(:controller => 'pages', :action => 'show', :name => 'nor_jamis_and_david')
+ end
+ end
+
+ def test_recognize_with_encoded_id_and_regex
+ set.draw do |map|
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /[a-zA-Z0-9\+]+/
+ end
+
+ assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
+ assert_equal({:controller => 'pages', :action => 'show', :id => 'hello+world'}, set.recognize_path('/page/hello+world'))
+ end
+
+ def test_recognize_with_conditions
+ Object.const_set(:PeopleController, Class.new)
+
+ set.draw do |map|
+ map.with_options(:controller => "people") do |people|
+ people.people "/people", :action => "index", :conditions => { :method => :get }
+ people.connect "/people", :action => "create", :conditions => { :method => :post }
+ people.person "/people/:id", :action => "show", :conditions => { :method => :get }
+ people.connect "/people/:id", :action => "update", :conditions => { :method => :put }
+ people.connect "/people/:id", :action => "destroy", :conditions => { :method => :delete }
end
end
+
+ request.path = "/people"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("index", request.path_parameters[:action])
+
+ request.method = :post
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("create", request.path_parameters[:action])
+
+ request.method = :put
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("update", request.path_parameters[:action])
+
+ begin
+ request.method = :bacon
+ set.recognize(request)
+ flunk 'Should have raised NotImplemented'
+ rescue ActionController::NotImplemented => e
+ assert_equal [:get, :post, :put, :delete], e.allowed_methods
+ end
+
+ request.path = "/people/5"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("show", request.path_parameters[:action])
+ assert_equal("5", request.path_parameters[:id])
+
+ request.method = :put
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("update", request.path_parameters[:action])
+ assert_equal("5", request.path_parameters[:id])
+
+ request.method = :delete
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("destroy", request.path_parameters[:action])
+ assert_equal("5", request.path_parameters[:id])
+
+ begin
+ request.method = :post
+ set.recognize(request)
+ flunk 'Should have raised MethodNotAllowed'
+ rescue ActionController::MethodNotAllowed => e
+ assert_equal [:get, :put, :delete], e.allowed_methods
+ end
+
+ ensure
+ Object.send(:remove_const, :PeopleController)
end
- end
-
- def test_setting_root_in_namespace_using_string
- assert_nothing_raised do
+
+ def test_recognize_with_alias_in_conditions
+ Object.const_set(:PeopleController, Class.new)
+
+ set.draw do |map|
+ map.people "/people", :controller => 'people', :action => "index",
+ :conditions => { :method => :get }
+ map.root :people
+ end
+
+ request.path = "/people"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("people", request.path_parameters[:controller])
+ assert_equal("index", request.path_parameters[:action])
+
+ request.path = "/"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("people", request.path_parameters[:controller])
+ assert_equal("index", request.path_parameters[:action])
+ ensure
+ Object.send(:remove_const, :PeopleController)
+ end
+
+ def test_typo_recognition
+ Object.const_set(:ArticlesController, Class.new)
+
set.draw do |map|
- map.namespace 'admin' do |admin|
- admin.root :controller => 'home'
+ map.connect 'articles/:year/:month/:day/:title',
+ :controller => 'articles', :action => 'permalink',
+ :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/
+ end
+
+ request.path = "/articles/2005/11/05/a-very-interesting-article"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("permalink", request.path_parameters[:action])
+ assert_equal("2005", request.path_parameters[:year])
+ assert_equal("11", request.path_parameters[:month])
+ assert_equal("05", request.path_parameters[:day])
+ assert_equal("a-very-interesting-article", request.path_parameters[:title])
+
+ ensure
+ Object.send(:remove_const, :ArticlesController)
+ end
+
+ def test_routing_traversal_does_not_load_extra_classes
+ assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
+ set.draw do |map|
+ map.connect '/profile', :controller => 'profile'
+ end
+
+ request.path = '/profile'
+
+ set.recognize(request) rescue nil
+
+ assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
+ end
+
+ def test_recognize_with_conditions_and_format
+ Object.const_set(:PeopleController, Class.new)
+
+ set.draw do |map|
+ map.with_options(:controller => "people") do |people|
+ people.person "/people/:id", :action => "show", :conditions => { :method => :get }
+ people.connect "/people/:id", :action => "update", :conditions => { :method => :put }
+ people.connect "/people/:id.:_format", :action => "show", :conditions => { :method => :get }
end
end
+
+ request.path = "/people/5"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("show", request.path_parameters[:action])
+ assert_equal("5", request.path_parameters[:id])
+
+ request.method = :put
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("update", request.path_parameters[:action])
+
+ request.path = "/people/5.png"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("show", request.path_parameters[:action])
+ assert_equal("5", request.path_parameters[:id])
+ assert_equal("png", request.path_parameters[:_format])
+ ensure
+ Object.send(:remove_const, :PeopleController)
end
- end
- def test_route_requirements_with_unsupported_regexp_options_must_error
- assert_raises ArgumentError do
+ def test_generate_with_default_action
set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => /(david|jamis)/m}
+ map.connect "/people", :controller => "people"
+ map.connect "/people/list", :controller => "people", :action => "list"
end
+
+ url = set.generate(:controller => "people", :action => "list")
+ assert_equal "/people/list", url
end
- end
- def test_route_requirements_with_supported_options_must_not_error
- assert_nothing_raised do
+ def test_root_map
+ Object.const_set(:PeopleController, Class.new)
+
+ set.draw { |map| map.root :controller => "people" }
+
+ request.path = ""
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("people", request.path_parameters[:controller])
+ assert_equal("index", request.path_parameters[:action])
+ ensure
+ Object.send(:remove_const, :PeopleController)
+ end
+
+ def test_namespace
+ Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
+
set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => /(david|jamis)/i}
+
+ map.namespace 'api' do |api|
+ api.route 'inventory', :controller => "products", :action => 'inventory'
+ end
+
end
+
+ request.path = "/api/inventory"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("api/products", request.path_parameters[:controller])
+ assert_equal("inventory", request.path_parameters[:action])
+ ensure
+ Object.send(:remove_const, :Api)
end
- assert_nothing_raised do
+
+ def test_namespaced_root_map
+ Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
+
set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => / # Desperately overcommented regexp
- ( #Either
- david #The Creator
- | #Or
- jamis #The Deployer
- )/x}
+
+ map.namespace 'api' do |api|
+ api.root :controller => "products"
+ end
+
end
+
+ request.path = "/api"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("api/products", request.path_parameters[:controller])
+ assert_equal("index", request.path_parameters[:action])
+ ensure
+ Object.send(:remove_const, :Api)
end
- end
- def test_route_requirement_recognize_with_ignore_case
- set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => /(david|jamis)/i}
+ def test_generate_finds_best_fit
+ set.draw do |map|
+ map.connect "/people", :controller => "people", :action => "index"
+ map.connect "/ws/people", :controller => "people", :action => "index", :ws => true
+ end
+
+ url = set.generate(:controller => "people", :action => "index", :ws => true)
+ assert_equal "/ws/people", url
end
- assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
- assert_raises ActionController::RoutingError do
- set.recognize_path('/page/davidjamis')
+
+ def test_generate_changes_controller_module
+ set.draw { |map| map.connect ':controller/:action/:id' }
+ current = { :controller => "bling/bloop", :action => "bap", :id => 9 }
+ url = set.generate({:controller => "foo/bar", :action => "baz", :id => 7}, current)
+ assert_equal "/foo/bar/baz/7", url
end
- assert_equal({:controller => 'pages', :action => 'show', :name => 'DAVID'}, set.recognize_path('/page/DAVID'))
- end
- def test_route_requirement_generate_with_ignore_case
- set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => /(david|jamis)/i}
+ def test_id_is_not_impossibly_sticky
+ set.draw do |map|
+ map.connect 'foo/:number', :controller => "people", :action => "index"
+ map.connect ':controller/:action/:id'
+ end
+
+ url = set.generate({:controller => "people", :action => "index", :number => 3},
+ {:controller => "people", :action => "index", :id => "21"})
+ assert_equal "/foo/3", url
end
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
- assert_equal "/page/david", url
- assert_raises ActionController::RoutingError do
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
+
+ def test_id_is_sticky_when_it_ought_to_be
+ set.draw do |map|
+ map.connect ':controller/:id/:action'
+ end
+
+ url = set.generate({:action => "destroy"}, {:controller => "people", :action => "show", :id => "7"})
+ assert_equal "/people/7/destroy", url
end
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
- assert_equal "/page/JAMIS", url
- end
- def test_route_requirement_recognize_with_extended_syntax
- set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => / # Desperately overcommented regexp
- ( #Either
- david #The Creator
- | #Or
- jamis #The Deployer
- )/x}
+ def test_use_static_path_when_possible
+ set.draw do |map|
+ map.connect 'about', :controller => "welcome", :action => "about"
+ map.connect ':controller/:action/:id'
+ end
+
+ url = set.generate({:controller => "welcome", :action => "about"},
+ {:controller => "welcome", :action => "get", :id => "7"})
+ assert_equal "/about", url
end
- assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
- assert_equal({:controller => 'pages', :action => 'show', :name => 'david'}, set.recognize_path('/page/david'))
- assert_raises ActionController::RoutingError do
- set.recognize_path('/page/david #The Creator')
+
+ def test_generate
+ set.draw { |map| map.connect ':controller/:action/:id' }
+
+ args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" }
+ assert_equal "/foo/bar/7?x=y", set.generate(args)
+ assert_equal ["/foo/bar/7", [:x]], set.generate_extras(args)
+ assert_equal [:x], set.extra_keys(args)
end
- assert_raises ActionController::RoutingError do
- set.recognize_path('/page/David')
+
+ def test_named_routes_are_never_relative_to_modules
+ set.draw do |map|
+ map.connect "/connection/manage/:action", :controller => 'connection/manage'
+ map.connect "/connection/connection", :controller => "connection/connection"
+ map.family_connection "/connection", :controller => "connection"
+ end
+
+ url = set.generate({:controller => "connection"}, {:controller => 'connection/manage'})
+ assert_equal "/connection/connection", url
+
+ url = set.generate({:use_route => :family_connection, :controller => "connection"}, {:controller => 'connection/manage'})
+ assert_equal "/connection", url
end
- end
- def test_route_requirement_generate_with_extended_syntax
- set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => / # Desperately overcommented regexp
- ( #Either
- david #The Creator
- | #Or
- jamis #The Deployer
- )/x}
+ def test_action_left_off_when_id_is_recalled
+ set.draw do |map|
+ map.connect ':controller/:action/:id'
+ end
+ assert_equal '/post', set.generate(
+ {:controller => 'post', :action => 'index'},
+ {:controller => 'post', :action => 'show', :id => '10'}
+ )
end
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
- assert_equal "/page/david", url
- assert_raises ActionController::RoutingError do
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
+
+ def test_query_params_will_be_shown_when_recalled
+ set.draw do |map|
+ map.connect 'show_post/:parameter', :controller => 'post', :action => 'show'
+ map.connect ':controller/:action/:id'
+ end
+ assert_equal '/post/edit?parameter=1', set.generate(
+ {:action => 'edit', :parameter => 1},
+ {:controller => 'post', :action => 'show', :parameter => 1}
+ )
end
- assert_raises ActionController::RoutingError do
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
+
+ def test_expiry_determination_should_consider_values_with_to_param
+ set.draw { |map| map.connect 'projects/:project_id/:controller/:action' }
+ assert_equal '/projects/1/post/show', set.generate(
+ {:action => 'show', :project_id => 1},
+ {:controller => 'post', :action => 'show', :project_id => '1'})
end
- end
- def test_route_requirement_generate_with_xi_modifiers
- set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => / # Desperately overcommented regexp
- ( #Either
- david #The Creator
- | #Or
- jamis #The Deployer
- )/xi}
+ def test_generate_all
+ set.draw do |map|
+ map.connect 'show_post/:id', :controller => 'post', :action => 'show'
+ map.connect ':controller/:action/:id'
+ end
+ all = set.generate(
+ {:action => 'show', :id => 10, :generate_all => true},
+ {:controller => 'post', :action => 'show'}
+ )
+ assert_equal 2, all.length
+ assert_equal '/show_post/10', all.first
+ assert_equal '/post/show/10', all.last
end
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
- assert_equal "/page/JAMIS", url
- end
- def test_route_requirement_recognize_with_xi_modifiers
- set.draw do |map|
- map.connect 'page/:name', :controller => 'pages',
- :action => 'show',
- :requirements => {:name => / # Desperately overcommented regexp
- ( #Either
- david #The Creator
- | #Or
- jamis #The Deployer
- )/xi}
+ def test_named_route_in_nested_resource
+ set.draw do |map|
+ map.resources :projects do |project|
+ project.milestones 'milestones', :controller => 'milestones', :action => 'index'
+ end
+ end
+
+ request.path = "/projects/1/milestones"
+ request.method = :get
+ assert_nothing_raised { set.recognize(request) }
+ assert_equal("milestones", request.path_parameters[:controller])
+ assert_equal("index", request.path_parameters[:action])
end
- assert_equal({:controller => 'pages', :action => 'show', :name => 'JAMIS'}, set.recognize_path('/page/JAMIS'))
- end
-
-end
+ def test_setting_root_in_namespace_using_symbol
+ assert_nothing_raised do
+ set.draw do |map|
+ map.namespace :admin do |admin|
+ admin.root :controller => 'home'
+ end
+ end
+ end
+ end
-class RoutingTest < Test::Unit::TestCase
-
- def test_possible_controllers
- true_controller_paths = ActionController::Routing.controller_paths
+ def test_setting_root_in_namespace_using_string
+ assert_nothing_raised do
+ set.draw do |map|
+ map.namespace 'admin' do |admin|
+ admin.root :controller => 'home'
+ end
+ end
+ end
+ end
- ActionController::Routing.use_controllers! nil
+ def test_route_requirements_with_unsupported_regexp_options_must_error
+ assert_raises ArgumentError do
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => /(david|jamis)/m}
+ end
+ end
+ end
- silence_warnings do
- Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + '/controller_fixtures')
+ def test_route_requirements_with_supported_options_must_not_error
+ assert_nothing_raised do
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => /(david|jamis)/i}
+ end
+ end
+ assert_nothing_raised do
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => / # Desperately overcommented regexp
+ ( #Either
+ david #The Creator
+ | #Or
+ jamis #The Deployer
+ )/x}
+ end
+ end
end
- ActionController::Routing.controller_paths = [
- RAILS_ROOT, RAILS_ROOT + '/app/controllers', RAILS_ROOT + '/vendor/plugins/bad_plugin/lib'
- ]
-
- assert_equal ["admin/user", "plugin", "user"], ActionController::Routing.possible_controllers.sort
- ensure
- if true_controller_paths
- ActionController::Routing.controller_paths = true_controller_paths
+ def test_route_requirement_recognize_with_ignore_case
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => /(david|jamis)/i}
+ end
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
+ assert_raises ActionController::RoutingError do
+ set.recognize_path('/page/davidjamis')
+ end
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'DAVID'}, set.recognize_path('/page/DAVID'))
end
- ActionController::Routing.use_controllers! nil
- Object.send(:remove_const, :RAILS_ROOT) rescue nil
- end
-
- def test_possible_controllers_are_reset_on_each_load
- true_possible_controllers = ActionController::Routing.possible_controllers
- true_controller_paths = ActionController::Routing.controller_paths
-
- ActionController::Routing.use_controllers! nil
- root = File.dirname(__FILE__) + '/controller_fixtures'
-
- ActionController::Routing.controller_paths = []
- assert_equal [], ActionController::Routing.possible_controllers
-
- ActionController::Routing::Routes.load!
- ActionController::Routing.controller_paths = [
- root, root + '/app/controllers', root + '/vendor/plugins/bad_plugin/lib'
- ]
-
- assert_equal ["admin/user", "plugin", "user"], ActionController::Routing.possible_controllers.sort
- ensure
- ActionController::Routing.controller_paths = true_controller_paths
- ActionController::Routing.use_controllers! true_possible_controllers
- Object.send(:remove_const, :RAILS_ROOT) rescue nil
-
- ActionController::Routing::Routes.clear!
- ActionController::Routing::Routes.load_routes!
- end
-
- def test_with_controllers
- c = %w(admin/accounts admin/users account pages)
- ActionController::Routing.with_controllers c do
- assert_equal c, ActionController::Routing.possible_controllers
+
+ def test_route_requirement_generate_with_ignore_case
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => /(david|jamis)/i}
+ end
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
+ assert_equal "/page/david", url
+ assert_raises ActionController::RoutingError do
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
+ end
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
+ assert_equal "/page/JAMIS", url
end
- end
- def test_normalize_unix_paths
- load_paths = %w(. config/../app/controllers config/../app//helpers script/../config/../vendor/rails/actionpack/lib vendor/rails/railties/builtin/rails_info app/models lib script/../config/../foo/bar/../../app/models .foo/../.bar foo.bar/../config)
- paths = ActionController::Routing.normalize_paths(load_paths)
- assert_equal %w(vendor/rails/railties/builtin/rails_info vendor/rails/actionpack/lib app/controllers app/helpers app/models config .bar lib .), paths
- end
+ def test_route_requirement_recognize_with_extended_syntax
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => / # Desperately overcommented regexp
+ ( #Either
+ david #The Creator
+ | #Or
+ jamis #The Deployer
+ )/x}
+ end
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'david'}, set.recognize_path('/page/david'))
+ assert_raises ActionController::RoutingError do
+ set.recognize_path('/page/david #The Creator')
+ end
+ assert_raises ActionController::RoutingError do
+ set.recognize_path('/page/David')
+ end
+ end
- def test_normalize_windows_paths
- load_paths = %w(. config\\..\\app\\controllers config\\..\\app\\\\helpers script\\..\\config\\..\\vendor\\rails\\actionpack\\lib vendor\\rails\\railties\\builtin\\rails_info app\\models lib script\\..\\config\\..\\foo\\bar\\..\\..\\app\\models .foo\\..\\.bar foo.bar\\..\\config)
- paths = ActionController::Routing.normalize_paths(load_paths)
- assert_equal %w(vendor\\rails\\railties\\builtin\\rails_info vendor\\rails\\actionpack\\lib app\\controllers app\\helpers app\\models config .bar lib .), paths
- end
-
- def test_routing_helper_module
- assert_kind_of Module, ActionController::Routing::Helpers
-
- h = ActionController::Routing::Helpers
- c = Class.new
- assert ! c.ancestors.include?(h)
- ActionController::Routing::Routes.install_helpers c
- assert c.ancestors.include?(h)
- end
+ def test_route_requirement_generate_with_extended_syntax
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => / # Desperately overcommented regexp
+ ( #Either
+ david #The Creator
+ | #Or
+ jamis #The Deployer
+ )/x}
+ end
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
+ assert_equal "/page/david", url
+ assert_raises ActionController::RoutingError do
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
+ end
+ assert_raises ActionController::RoutingError do
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
+ end
+ end
-end
+ def test_route_requirement_generate_with_xi_modifiers
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => / # Desperately overcommented regexp
+ ( #Either
+ david #The Creator
+ | #Or
+ jamis #The Deployer
+ )/xi}
+ end
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
+ assert_equal "/page/JAMIS", url
+ end
-uses_mocha 'route loading' do
- class RouteLoadingTest < Test::Unit::TestCase
+ def test_route_requirement_recognize_with_xi_modifiers
+ set.draw do |map|
+ map.connect 'page/:name', :controller => 'pages',
+ :action => 'show',
+ :requirements => {:name => / # Desperately overcommented regexp
+ ( #Either
+ david #The Creator
+ | #Or
+ jamis #The Deployer
+ )/xi}
+ end
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'JAMIS'}, set.recognize_path('/page/JAMIS'))
+ end
+ end
+ class RouteLoadingTest < Test::Unit::TestCase
def setup
routes.instance_variable_set '@routes_last_modified', nil
silence_warnings { Object.const_set :RAILS_ROOT, '.' }
@@ -2392,12 +2364,12 @@ uses_mocha 'route loading' do
end
def test_adding_inflections_forces_reload
- Inflector::Inflections.instance.expects(:uncountable).with('equipment')
+ ActiveSupport::Inflector::Inflections.instance.expects(:uncountable).with('equipment')
routes.expects(:reload!)
- Inflector.inflections { |inflect| inflect.uncountable('equipment') }
+ ActiveSupport::Inflector.inflections { |inflect| inflect.uncountable('equipment') }
end
-
+
def test_load_with_configuration
routes.configuration_file = "foobarbaz"
File.expects(:stat).returns(@stat)
@@ -2407,9 +2379,8 @@ uses_mocha 'route loading' do
end
private
- def routes
- ActionController::Routing::Routes
- end
-
+ def routes
+ ActionController::Routing::Routes
+ end
end
end
diff --git a/actionpack/test/controller/verification_test.rb b/actionpack/test/controller/verification_test.rb
index d6fde35f83..b289443129 100644
--- a/actionpack/test/controller/verification_test.rb
+++ b/actionpack/test/controller/verification_test.rb
@@ -21,10 +21,10 @@ class VerificationTest < Test::Unit::TestCase
verify :only => :guarded_by_method, :method => :post,
:redirect_to => { :action => "unguarded" }
-
+
verify :only => :guarded_by_xhr, :xhr => true,
:redirect_to => { :action => "unguarded" }
-
+
verify :only => :guarded_by_not_xhr, :xhr => false,
:redirect_to => { :action => "unguarded" }
@@ -39,10 +39,13 @@ class VerificationTest < Test::Unit::TestCase
verify :only => :no_default_action, :params => "santa"
+ verify :only => :guarded_with_back, :method => :post,
+ :redirect_to => :back
+
def guarded_one
render :text => "#{params[:one]}"
end
-
+
def guarded_one_for_named_route_test
render :text => "#{params[:one]}"
end
@@ -70,11 +73,11 @@ class VerificationTest < Test::Unit::TestCase
def guarded_by_method
render :text => "#{request.method}"
end
-
+
def guarded_by_xhr
render :text => "#{request.xhr?}"
end
-
+
def guarded_by_not_xhr
render :text => "#{request.xhr?}"
end
@@ -86,15 +89,19 @@ class VerificationTest < Test::Unit::TestCase
def two_redirects
render :nothing => true
end
-
+
def must_be_post
render :text => "Was a post!"
end
-
+
+ def guarded_with_back
+ render :text => "#{params[:one]}"
+ end
+
def no_default_action
# Will never run
end
-
+
protected
def rescue_action(e) raise end
@@ -109,7 +116,17 @@ class VerificationTest < Test::Unit::TestCase
@response = ActionController::TestResponse.new
ActionController::Routing::Routes.add_named_route :foo, '/foo', :controller => 'test', :action => 'foo'
end
-
+
+ def test_using_symbol_back_with_no_referrer
+ assert_raise(ActionController::RedirectBackError) { get :guarded_with_back }
+ end
+
+ def test_using_symbol_back_redirects_to_referrer
+ @request.env["HTTP_REFERER"] = "/foo"
+ get :guarded_with_back
+ assert_redirected_to '/foo'
+ end
+
def test_no_deprecation_warning_for_named_route
assert_not_deprecated do
get :guarded_one_for_named_route_test, :two => "not one"
@@ -209,44 +226,44 @@ class VerificationTest < Test::Unit::TestCase
get :guarded_by_method
assert_redirected_to :action => "unguarded"
end
-
+
def test_guarded_by_xhr_with_prereqs
xhr :post, :guarded_by_xhr
assert_equal "true", @response.body
end
-
+
def test_guarded_by_xhr_without_prereqs
get :guarded_by_xhr
assert_redirected_to :action => "unguarded"
end
-
+
def test_guarded_by_not_xhr_with_prereqs
get :guarded_by_not_xhr
assert_equal "false", @response.body
end
-
+
def test_guarded_by_not_xhr_without_prereqs
xhr :post, :guarded_by_not_xhr
assert_redirected_to :action => "unguarded"
end
-
+
def test_guarded_post_and_calls_render_succeeds
post :must_be_post
assert_equal "Was a post!", @response.body
end
-
+
def test_default_failure_should_be_a_bad_request
post :no_default_action
assert_response :bad_request
end
-
+
def test_guarded_post_and_calls_render_fails_and_sets_allow_header
get :must_be_post
assert_response 405
assert_equal "Must be post", @response.body
assert_equal "POST", @response.headers["Allow"]
end
-
+
def test_second_redirect
assert_nothing_raised { get :two_redirects }
end
diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb
index 0516da32d8..1b4c1fae2f 100644
--- a/actionpack/test/controller/view_paths_test.rb
+++ b/actionpack/test/controller/view_paths_test.rb
@@ -1,30 +1,30 @@
require 'abstract_unit'
class ViewLoadPathsTest < Test::Unit::TestCase
-
LOAD_PATH_ROOT = File.join(File.dirname(__FILE__), '..', 'fixtures')
- ActionController::Base.view_paths = [ LOAD_PATH_ROOT ]
+ ActionController::Base.view_paths = [LOAD_PATH_ROOT]
class TestController < ActionController::Base
def self.controller_path() "test" end
def rescue_action(e) raise end
-
+
before_filter :add_view_path, :only => :hello_world_at_request_time
-
+
def hello_world() end
def hello_world_at_request_time() render(:action => 'hello_world') end
+
private
- def add_view_path
- prepend_view_path "#{LOAD_PATH_ROOT}/override"
- end
+ def add_view_path
+ prepend_view_path "#{LOAD_PATH_ROOT}/override"
+ end
end
-
+
class Test::SubController < ActionController::Base
layout 'test/sub'
def hello_world; render(:template => 'test/hello_world'); end
end
-
+
def setup
TestController.view_paths = nil
@@ -41,68 +41,80 @@ class ViewLoadPathsTest < Test::Unit::TestCase
@last_message = nil
ActiveSupport::Deprecation.behavior = Proc.new { |message, callback| @last_message = message }
end
-
+
def teardown
ActiveSupport::Deprecation.behavior = @old_behavior
end
-
+
def test_template_load_path_was_set_correctly
- assert_equal [ LOAD_PATH_ROOT ], @controller.view_paths
+ assert_equal [ LOAD_PATH_ROOT ], @controller.view_paths.map(&:to_s)
end
-
+
def test_controller_appends_view_path_correctly
@controller.append_view_path 'foo'
- assert_equal [LOAD_PATH_ROOT, 'foo'], @controller.view_paths
-
+ assert_equal [LOAD_PATH_ROOT, 'foo'], @controller.view_paths.map(&:to_s)
+
@controller.append_view_path(%w(bar baz))
- assert_equal [LOAD_PATH_ROOT, 'foo', 'bar', 'baz'], @controller.view_paths
+ assert_equal [LOAD_PATH_ROOT, 'foo', 'bar', 'baz'], @controller.view_paths.map(&:to_s)
+
+ @controller.append_view_path(LOAD_PATH_ROOT)
+ assert_equal ['foo', 'bar', 'baz', LOAD_PATH_ROOT], @controller.view_paths.map(&:to_s)
+
+ @controller.append_view_path([LOAD_PATH_ROOT])
+ assert_equal ['foo', 'bar', 'baz', LOAD_PATH_ROOT], @controller.view_paths.map(&:to_s)
end
-
+
def test_controller_prepends_view_path_correctly
@controller.prepend_view_path 'baz'
- assert_equal ['baz', LOAD_PATH_ROOT], @controller.view_paths
-
+ assert_equal ['baz', LOAD_PATH_ROOT], @controller.view_paths.map(&:to_s)
+
@controller.prepend_view_path(%w(foo bar))
- assert_equal ['foo', 'bar', 'baz', LOAD_PATH_ROOT], @controller.view_paths
+ assert_equal ['foo', 'bar', 'baz', LOAD_PATH_ROOT], @controller.view_paths.map(&:to_s)
+
+ @controller.prepend_view_path(LOAD_PATH_ROOT)
+ assert_equal [LOAD_PATH_ROOT, 'foo', 'bar', 'baz'], @controller.view_paths.map(&:to_s)
+
+ @controller.prepend_view_path([LOAD_PATH_ROOT])
+ assert_equal [LOAD_PATH_ROOT, 'foo', 'bar', 'baz'], @controller.view_paths.map(&:to_s)
end
-
+
def test_template_appends_view_path_correctly
@controller.instance_variable_set :@template, ActionView::Base.new(TestController.view_paths, {}, @controller)
class_view_paths = TestController.view_paths
@controller.append_view_path 'foo'
- assert_equal [LOAD_PATH_ROOT, 'foo'], @controller.view_paths
-
+ assert_equal [LOAD_PATH_ROOT, 'foo'], @controller.view_paths.map(&:to_s)
+
@controller.append_view_path(%w(bar baz))
- assert_equal [LOAD_PATH_ROOT, 'foo', 'bar', 'baz'], @controller.view_paths
+ assert_equal [LOAD_PATH_ROOT, 'foo', 'bar', 'baz'], @controller.view_paths.map(&:to_s)
assert_equal class_view_paths, TestController.view_paths
end
-
+
def test_template_prepends_view_path_correctly
@controller.instance_variable_set :@template, ActionView::Base.new(TestController.view_paths, {}, @controller)
class_view_paths = TestController.view_paths
-
+
@controller.prepend_view_path 'baz'
- assert_equal ['baz', LOAD_PATH_ROOT], @controller.view_paths
-
+ assert_equal ['baz', LOAD_PATH_ROOT], @controller.view_paths.map(&:to_s)
+
@controller.prepend_view_path(%w(foo bar))
- assert_equal ['foo', 'bar', 'baz', LOAD_PATH_ROOT], @controller.view_paths
+ assert_equal ['foo', 'bar', 'baz', LOAD_PATH_ROOT], @controller.view_paths.map(&:to_s)
assert_equal class_view_paths, TestController.view_paths
end
-
+
def test_view_paths
get :hello_world
assert_response :success
assert_equal "Hello world!", @response.body
end
-
+
def test_view_paths_override
TestController.prepend_view_path "#{LOAD_PATH_ROOT}/override"
get :hello_world
assert_response :success
assert_equal "Hello overridden world!", @response.body
end
-
+
def test_view_paths_override_for_layouts_in_controllers_with_a_module
@controller = Test::SubController.new
Test::SubController.view_paths = [ "#{LOAD_PATH_ROOT}/override", LOAD_PATH_ROOT, "#{LOAD_PATH_ROOT}/override2" ]
@@ -110,31 +122,44 @@ class ViewLoadPathsTest < Test::Unit::TestCase
assert_response :success
assert_equal "layout: Hello overridden world!", @response.body
end
-
+
def test_view_paths_override_at_request_time
get :hello_world_at_request_time
assert_response :success
assert_equal "Hello overridden world!", @response.body
end
-
+
def test_inheritance
original_load_paths = ActionController::Base.view_paths
-
+
self.class.class_eval %{
class A < ActionController::Base; end
class B < A; end
class C < ActionController::Base; end
}
-
- A.view_paths = [ 'a/path' ]
-
- assert_equal [ 'a/path' ], A.view_paths
- assert_equal A.view_paths, B.view_paths
+
+ A.view_paths = ['a/path']
+
+ assert_equal ['a/path'], A.view_paths.map(&:to_s)
+ assert_equal A.view_paths, B.view_paths
assert_equal original_load_paths, C.view_paths
-
+
C.view_paths = []
assert_nothing_raised { C.view_paths << 'c/path' }
- assert_equal ['c/path'], C.view_paths
+ assert_equal ['c/path'], C.view_paths.map(&:to_s)
+ end
+
+ def test_find_template_file_for_path
+ assert_equal "test/hello_world.erb", @controller.view_paths.find_template_file_for_path("test/hello_world.erb").to_s
+ assert_equal "test/hello.builder", @controller.view_paths.find_template_file_for_path("test/hello.builder").to_s
+ assert_equal nil, @controller.view_paths.find_template_file_for_path("test/missing.erb")
+ end
+
+ def test_view_paths_find_template_file_for_path
+ assert_equal "test/formatted_html_erb.html.erb", @controller.view_paths.find_template_file_for_path("test/formatted_html_erb.html").to_s
+ assert_equal "test/formatted_xml_erb.xml.erb", @controller.view_paths.find_template_file_for_path("test/formatted_xml_erb.xml").to_s
+ assert_equal "test/hello_world.erb", @controller.view_paths.find_template_file_for_path("test/hello_world.html").to_s
+ assert_equal "test/hello_world.erb", @controller.view_paths.find_template_file_for_path("test/hello_world.xml").to_s
+ assert_equal nil, @controller.view_paths.find_template_file_for_path("test/missing.html")
end
-
end
diff --git a/actionpack/test/fixtures/test/block_content_for.erb b/actionpack/test/fixtures/test/block_content_for.erb
deleted file mode 100644
index 9510337365..0000000000
--- a/actionpack/test/fixtures/test/block_content_for.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-<% block_content_for :title do 'Putting stuff in the title!' end %>
-Great stuff! \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/erb_content_for.erb b/actionpack/test/fixtures/test/erb_content_for.erb
deleted file mode 100644
index c3bdd13643..0000000000
--- a/actionpack/test/fixtures/test/erb_content_for.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-<% erb_content_for :title do %>Putting stuff in the title!<% end %>
-Great stuff! \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/non_erb_block_content_for.builder b/actionpack/test/fixtures/test/non_erb_block_content_for.builder
index 6ff6db0f95..a94643561c 100644
--- a/actionpack/test/fixtures/test/non_erb_block_content_for.builder
+++ b/actionpack/test/fixtures/test/non_erb_block_content_for.builder
@@ -1,4 +1,4 @@
content_for :title do
'Putting stuff in the title!'
end
-xml << "\nGreat stuff!" \ No newline at end of file
+xml << "\nGreat stuff!"
diff --git a/actionpack/test/fixtures/test/render_file_from_template.html.erb b/actionpack/test/fixtures/test/render_file_from_template.html.erb
new file mode 100644
index 0000000000..fde9f4bb64
--- /dev/null
+++ b/actionpack/test/fixtures/test/render_file_from_template.html.erb
@@ -0,0 +1 @@
+<%= render :file => @path %> \ No newline at end of file
diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb
index 0a7b19ba96..11b3bdb3fa 100755
--- a/actionpack/test/template/date_helper_test.rb
+++ b/actionpack/test/template/date_helper_test.rb
@@ -1002,17 +1002,15 @@ class DateHelperTest < ActionView::TestCase
@post = Post.new
@post.written_on = Date.new(2004, 6, 15)
- _erbout = ''
-
fields_for :post, @post do |f|
- _erbout.concat f.date_select(:written_on)
+ concat f.date_select(:written_on)
end
expected = "<select id='post_written_on_1i' name='post[written_on(1i)]'>\n<option value='1999'>1999</option>\n<option value='2000'>2000</option>\n<option value='2001'>2001</option>\n<option value='2002'>2002</option>\n<option value='2003'>2003</option>\n<option selected='selected' value='2004'>2004</option>\n<option value='2005'>2005</option>\n<option value='2006'>2006</option>\n<option value='2007'>2007</option>\n<option value='2008'>2008</option>\n<option value='2009'>2009</option>\n</select>\n"
expected << "<select id='post_written_on_2i' name='post[written_on(2i)]'>\n<option value='1'>January</option>\n<option value='2'>February</option>\n<option value='3'>March</option>\n<option value='4'>April</option>\n<option value='5'>May</option>\n<option selected='selected' value='6'>June</option>\n<option value='7'>July</option>\n<option value='8'>August</option>\n<option value='9'>September</option>\n<option value='10'>October</option>\n<option value='11'>November</option>\n<option value='12'>December</option>\n</select>\n"
expected << "<select id='post_written_on_3i' name='post[written_on(3i)]'>\n<option value='1'>1</option>\n<option value='2'>2</option>\n<option value='3'>3</option>\n<option value='4'>4</option>\n<option value='5'>5</option>\n<option value='6'>6</option>\n<option value='7'>7</option>\n<option value='8'>8</option>\n<option value='9'>9</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option selected='selected' value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n</select>\n"
- assert_dom_equal(expected, _erbout)
+ assert_dom_equal(expected, output_buffer)
end
def test_date_select_with_index
@@ -1287,10 +1285,8 @@ class DateHelperTest < ActionView::TestCase
@post = Post.new
@post.updated_at = Time.local(2004, 6, 15, 16, 35)
- _erbout = ''
-
fields_for :post, @post do |f|
- _erbout.concat f.datetime_select(:updated_at)
+ concat f.datetime_select(:updated_at)
end
expected = "<select id='post_updated_at_1i' name='post[updated_at(1i)]'>\n<option value='1999'>1999</option>\n<option value='2000'>2000</option>\n<option value='2001'>2001</option>\n<option value='2002'>2002</option>\n<option value='2003'>2003</option>\n<option selected='selected' value='2004'>2004</option>\n<option value='2005'>2005</option>\n<option value='2006'>2006</option>\n<option value='2007'>2007</option>\n<option value='2008'>2008</option>\n<option value='2009'>2009</option>\n</select>\n"
@@ -1299,7 +1295,7 @@ class DateHelperTest < ActionView::TestCase
expected << " &mdash; <select id='post_updated_at_4i' name='post[updated_at(4i)]'>\n<option value='00'>00</option>\n<option value='01'>01</option>\n<option value='02'>02</option>\n<option value='03'>03</option>\n<option value='04'>04</option>\n<option value='05'>05</option>\n<option value='06'>06</option>\n<option value='07'>07</option>\n<option value='08'>08</option>\n<option value='09'>09</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option value='15'>15</option>\n<option selected='selected' value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n</select>\n"
expected << " : <select id='post_updated_at_5i' name='post[updated_at(5i)]'>\n<option value='00'>00</option>\n<option value='01'>01</option>\n<option value='02'>02</option>\n<option value='03'>03</option>\n<option value='04'>04</option>\n<option value='05'>05</option>\n<option value='06'>06</option>\n<option value='07'>07</option>\n<option value='08'>08</option>\n<option value='09'>09</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n<option value='32'>32</option>\n<option value='33'>33</option>\n<option value='34'>34</option>\n<option selected='selected' value='35'>35</option>\n<option value='36'>36</option>\n<option value='37'>37</option>\n<option value='38'>38</option>\n<option value='39'>39</option>\n<option value='40'>40</option>\n<option value='41'>41</option>\n<option value='42'>42</option>\n<option value='43'>43</option>\n<option value='44'>44</option>\n<option value='45'>45</option>\n<option value='46'>46</option>\n<option value='47'>47</option>\n<option value='48'>48</option>\n<option value='49'>49</option>\n<option value='50'>50</option>\n<option value='51'>51</option>\n<option value='52'>52</option>\n<option value='53'>53</option>\n<option value='54'>54</option>\n<option value='55'>55</option>\n<option value='56'>56</option>\n<option value='57'>57</option>\n<option value='58'>58</option>\n<option value='59'>59</option>\n</select>\n"
- assert_dom_equal(expected, _erbout)
+ assert_dom_equal(expected, output_buffer)
end
def test_date_select_with_zero_value_and_no_start_year
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index af99e6243d..39649c3622 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -337,14 +337,12 @@ class FormHelperTest < ActionView::TestCase
end
def test_form_for
- _erbout = ''
-
form_for(:post, @post, :html => { :id => 'create-post' }) do |f|
- _erbout.concat f.label(:title)
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
- _erbout.concat f.submit('Create post')
+ concat f.label(:title)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
+ concat f.submit('Create post')
end
expected =
@@ -357,16 +355,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='commit' id='post_submit' type='submit' value='Create post' />" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_method
- _erbout = ''
-
form_for(:post, @post, :html => { :id => 'create-post', :method => :put }) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -378,16 +374,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[secret]' type='hidden' value='0' />" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_without_object
- _erbout = ''
-
form_for(:post, :html => { :id => 'create-post' }) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -398,17 +392,15 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[secret]' type='hidden' value='0' />" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_index
- _erbout = ''
-
form_for("post[]", @post) do |f|
- _erbout.concat f.label(:title)
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.label(:title)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -420,16 +412,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[123][secret]' type='hidden' value='0' />" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_nil_index_option_override
- _erbout = ''
-
form_for("post[]", @post, :index => nil) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -440,14 +430,13 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[][secret]' type='hidden' value='0' />" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_nested_fields_for
- _erbout = ''
form_for(:post, @post) do |f|
f.fields_for(:comment, @post) do |c|
- _erbout.concat c.text_field(:title)
+ concat c.text_field(:title)
end
end
@@ -455,16 +444,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[comment][title]' size='30' type='text' id='post_comment_title' value='Hello World' />" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_fields_for
- _erbout = ''
-
fields_for(:post, @post) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -473,16 +460,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
"<input name='post[secret]' type='hidden' value='0' />"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_fields_for_with_index
- _erbout = ''
-
fields_for("post[]", @post) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -491,16 +476,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[123][secret]' checked='checked' type='checkbox' id='post_123_secret' value='1' />" +
"<input name='post[123][secret]' type='hidden' value='0' />"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_fields_for_with_nil_index_option_override
- _erbout = ''
-
fields_for("post[]", @post, :index => nil) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -509,16 +492,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[][secret]' checked='checked' type='checkbox' id='post__secret' value='1' />" +
"<input name='post[][secret]' type='hidden' value='0' />"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_fields_for_with_index_option_override
- _erbout = ''
-
fields_for("post[]", @post, :index => "abc") do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -527,15 +508,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[abc][secret]' checked='checked' type='checkbox' id='post_abc_secret' value='1' />" +
"<input name='post[abc][secret]' type='hidden' value='0' />"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_fields_for_without_object
- _erbout = ''
fields_for(:post) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -544,15 +524,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
"<input name='post[secret]' type='hidden' value='0' />"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_fields_for_with_only_object
- _erbout = ''
fields_for(@post) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -561,31 +540,29 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
"<input name='post[secret]' type='hidden' value='0' />"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_fields_for_object_with_bracketed_name
- _erbout = ''
fields_for("author[post]", @post) do |f|
- _erbout.concat f.label(:title)
- _erbout.concat f.text_field(:title)
+ concat f.label(:title)
+ concat f.text_field(:title)
end
assert_dom_equal "<label for=\"author_post_title\">Title</label>" +
"<input name='author[post][title]' size='30' type='text' id='author_post_title' value='Hello World' />",
- _erbout
+ output_buffer
end
def test_fields_for_object_with_bracketed_name_and_index
- _erbout = ''
fields_for("author[post]", @post, :index => 1) do |f|
- _erbout.concat f.label(:title)
- _erbout.concat f.text_field(:title)
+ concat f.label(:title)
+ concat f.text_field(:title)
end
assert_dom_equal "<label for=\"author_post_1_title\">Title</label>" +
"<input name='author[post][1][title]' size='30' type='text' id='author_post_1_title' value='Hello World' />",
- _erbout
+ output_buffer
end
def test_form_builder_does_not_have_form_for_method
@@ -593,14 +570,12 @@ class FormHelperTest < ActionView::TestCase
end
def test_form_for_and_fields_for
- _erbout = ''
-
form_for(:post, @post, :html => { :id => 'create-post' }) do |post_form|
- _erbout.concat post_form.text_field(:title)
- _erbout.concat post_form.text_area(:body)
+ concat post_form.text_field(:title)
+ concat post_form.text_area(:body)
fields_for(:parent_post, @post) do |parent_fields|
- _erbout.concat parent_fields.check_box(:secret)
+ concat parent_fields.check_box(:secret)
end
end
@@ -612,18 +587,16 @@ class FormHelperTest < ActionView::TestCase
"<input name='parent_post[secret]' type='hidden' value='0' />" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_and_fields_for_with_object
- _erbout = ''
-
form_for(:post, @post, :html => { :id => 'create-post' }) do |post_form|
- _erbout.concat post_form.text_field(:title)
- _erbout.concat post_form.text_area(:body)
+ concat post_form.text_field(:title)
+ concat post_form.text_area(:body)
post_form.fields_for(@comment) do |comment_fields|
- _erbout.concat comment_fields.text_field(:name)
+ concat comment_fields.text_field(:name)
end
end
@@ -634,7 +607,7 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[comment][name]' type='text' id='post_comment_name' value='new comment' size='30' />" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
class LabelledFormBuilder < ActionView::Helpers::FormBuilder
@@ -649,12 +622,10 @@ class FormHelperTest < ActionView::TestCase
end
def test_form_for_with_labelled_builder
- _erbout = ''
-
form_for(:post, @post, :builder => LabelledFormBuilder) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -665,18 +636,17 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[secret]' type='hidden' value='0' /><br/>" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_default_form_builder
old_default_form_builder, ActionView::Base.default_form_builder =
ActionView::Base.default_form_builder, LabelledFormBuilder
- _erbout = ''
form_for(:post, @post) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -687,17 +657,15 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[secret]' type='hidden' value='0' /><br/>" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
ensure
ActionView::Base.default_form_builder = old_default_form_builder
end
def test_default_form_builder_with_active_record_helpers
-
- _erbout = ''
form_for(:post, @post) do |f|
- _erbout.concat f.error_message_on('author_name')
- _erbout.concat f.error_messages
+ concat f.error_message_on('author_name')
+ concat f.error_messages
end
expected = %(<form action='http://www.example.com' method='post'>) +
@@ -705,7 +673,7 @@ class FormHelperTest < ActionView::TestCase
%(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>) +
%(</form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
@@ -713,10 +681,9 @@ class FormHelperTest < ActionView::TestCase
post = @post
@post = nil
- _erbout = ''
form_for(:post, post) do |f|
- _erbout.concat f.error_message_on('author_name')
- _erbout.concat f.error_messages
+ concat f.error_message_on('author_name')
+ concat f.error_messages
end
expected = %(<form action='http://www.example.com' method='post'>) +
@@ -724,19 +691,18 @@ class FormHelperTest < ActionView::TestCase
%(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>) +
%(</form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
# Perhaps this test should be moved to prototype helper tests.
def test_remote_form_for_with_labelled_builder
self.extend ActionView::Helpers::PrototypeHelper
- _erbout = ''
remote_form_for(:post, @post, :builder => LabelledFormBuilder) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -747,16 +713,14 @@ class FormHelperTest < ActionView::TestCase
"<input name='post[secret]' type='hidden' value='0' /><br/>" +
"</form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_fields_for_with_labelled_builder
- _erbout = ''
-
fields_for(:post, @post, :builder => LabelledFormBuilder) do |f|
- _erbout.concat f.text_field(:title)
- _erbout.concat f.text_area(:body)
- _erbout.concat f.check_box(:secret)
+ concat f.text_field(:title)
+ concat f.text_area(:body)
+ concat f.check_box(:secret)
end
expected =
@@ -765,29 +729,23 @@ class FormHelperTest < ActionView::TestCase
"<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
"<input name='post[secret]' type='hidden' value='0' /><br/>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_html_options_adds_options_to_form_tag
- _erbout = ''
-
form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end
expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\"></form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_string_url_option
- _erbout = ''
-
form_for(:post, @post, :url => 'http://www.otherdomain.com') do |f| end
- assert_equal '<form action="http://www.otherdomain.com" method="post"></form>', _erbout
+ assert_equal '<form action="http://www.otherdomain.com" method="post"></form>', output_buffer
end
def test_form_for_with_hash_url_option
- _erbout = ''
-
form_for(:post, @post, :url => {:controller => 'controller', :action => 'action'}) do |f| end
assert_equal 'controller', @controller.url_for_options[:controller]
@@ -795,26 +753,20 @@ class FormHelperTest < ActionView::TestCase
end
def test_form_for_with_record_url_option
- _erbout = ''
-
form_for(:post, @post, :url => @post) do |f| end
expected = "<form action=\"/posts/123\" method=\"post\"></form>"
- assert_equal expected, _erbout
+ assert_equal expected, output_buffer
end
def test_form_for_with_existing_object
- _erbout = ''
-
form_for(@post) do |f| end
expected = "<form action=\"/posts/123\" class=\"edit_post\" id=\"edit_post_123\" method=\"post\"><div style=\"margin:0;padding:0\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>"
- assert_equal expected, _erbout
+ assert_equal expected, output_buffer
end
def test_form_for_with_new_object
- _erbout = ''
-
post = Post.new
post.new_record = true
def post.id() nil end
@@ -822,64 +774,61 @@ class FormHelperTest < ActionView::TestCase
form_for(post) do |f| end
expected = "<form action=\"/posts\" class=\"new_post\" id=\"new_post\" method=\"post\"></form>"
- assert_equal expected, _erbout
+ assert_equal expected, output_buffer
end
def test_form_for_with_existing_object_in_list
@post.new_record = false
@comment.save
- _erbout = ''
+
form_for([@post, @comment]) {}
expected = %(<form action="#{comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_new_object_in_list
@post.new_record = false
- _erbout = ''
+
form_for([@post, @comment]) {}
expected = %(<form action="#{comments_path(@post)}" class="new_comment" id="new_comment" method="post"></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_existing_object_and_namespace_in_list
@post.new_record = false
@comment.save
- _erbout = ''
+
form_for([:admin, @post, @comment]) {}
expected = %(<form action="#{admin_comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_new_object_and_namespace_in_list
@post.new_record = false
- _erbout = ''
+
form_for([:admin, @post, @comment]) {}
expected = %(<form action="#{admin_comments_path(@post)}" class="new_comment" id="new_comment" method="post"></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_existing_object_and_custom_url
- _erbout = ''
-
form_for(@post, :url => "/super_posts") do |f| end
expected = "<form action=\"/super_posts\" class=\"edit_post\" id=\"edit_post_123\" method=\"post\"><div style=\"margin:0;padding:0\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>"
- assert_equal expected, _erbout
+ assert_equal expected, output_buffer
end
def test_remote_form_for_with_html_options_adds_options_to_form_tag
self.extend ActionView::Helpers::PrototypeHelper
- _erbout = ''
remote_form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end
expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\" onsubmit=\"new Ajax.Request('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\"></form>"
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb
index 48a26deea9..3f89a5e426 100644
--- a/actionpack/test/template/form_options_helper_test.rb
+++ b/actionpack/test/template/form_options_helper_test.rb
@@ -20,8 +20,6 @@ class MockTimeZone
end
end
-ActionView::Helpers::FormOptionsHelper::TimeZone = MockTimeZone
-
class FormOptionsHelperTest < ActionView::TestCase
tests ActionView::Helpers::FormOptionsHelper
@@ -31,6 +29,8 @@ class FormOptionsHelperTest < ActionView::TestCase
Country = Struct.new('Country', :country_id, :country_name)
Firm = Struct.new('Firm', :time_zone)
Album = Struct.new('Album', :id, :title, :genre)
+
+ ActiveSupport::TimeZone = MockTimeZone
end
def test_collection_options
@@ -183,7 +183,7 @@ class FormOptionsHelperTest < ActionView::TestCase
end
def test_time_zone_options_with_priority_zones
- zones = [ TimeZone.new( "B" ), TimeZone.new( "E" ) ]
+ zones = [ ActiveSupport::TimeZone.new( "B" ), ActiveSupport::TimeZone.new( "E" ) ]
opts = time_zone_options_for_select( nil, zones )
assert_dom_equal "<option value=\"B\">B</option>\n" +
"<option value=\"E\">E</option>" +
@@ -195,7 +195,7 @@ class FormOptionsHelperTest < ActionView::TestCase
end
def test_time_zone_options_with_selected_priority_zones
- zones = [ TimeZone.new( "B" ), TimeZone.new( "E" ) ]
+ zones = [ ActiveSupport::TimeZone.new( "B" ), ActiveSupport::TimeZone.new( "E" ) ]
opts = time_zone_options_for_select( "E", zones )
assert_dom_equal "<option value=\"B\">B</option>\n" +
"<option value=\"E\" selected=\"selected\">E</option>" +
@@ -207,7 +207,7 @@ class FormOptionsHelperTest < ActionView::TestCase
end
def test_time_zone_options_with_unselected_priority_zones
- zones = [ TimeZone.new( "B" ), TimeZone.new( "E" ) ]
+ zones = [ ActiveSupport::TimeZone.new( "B" ), ActiveSupport::TimeZone.new( "E" ) ]
opts = time_zone_options_for_select( "C", zones )
assert_dom_equal "<option value=\"B\">B</option>\n" +
"<option value=\"E\">E</option>" +
@@ -230,16 +230,14 @@ class FormOptionsHelperTest < ActionView::TestCase
def test_select_under_fields_for
@post = Post.new
@post.category = "<mus>"
-
- _erbout = ''
-
+
fields_for :post, @post do |f|
- _erbout.concat f.select(:category, %w( abe <mus> hest))
+ concat f.select(:category, %w( abe <mus> hest))
end
assert_dom_equal(
"<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"&lt;mus&gt;\" selected=\"selected\">&lt;mus&gt;</option>\n<option value=\"hest\">hest</option></select>",
- _erbout
+ output_buffer
)
end
@@ -352,16 +350,14 @@ class FormOptionsHelperTest < ActionView::TestCase
@post = Post.new
@post.author_name = "Babe"
-
- _erbout = ''
-
+
fields_for :post, @post do |f|
- _erbout.concat f.collection_select(:author_name, @posts, :author_name, :author_name)
+ concat f.collection_select(:author_name, @posts, :author_name, :author_name)
end
assert_dom_equal(
"<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"&lt;Abe&gt;\">&lt;Abe&gt;</option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\">Cabe</option></select>",
- _erbout
+ output_buffer
)
end
@@ -1194,11 +1190,9 @@ COUNTRIES
def test_time_zone_select_under_fields_for
@firm = Firm.new("D")
-
- _erbout = ''
-
+
fields_for :firm, @firm do |f|
- _erbout.concat f.time_zone_select(:time_zone)
+ concat f.time_zone_select(:time_zone)
end
assert_dom_equal(
@@ -1209,7 +1203,7 @@ COUNTRIES
"<option value=\"D\" selected=\"selected\">D</option>\n" +
"<option value=\"E\">E</option>" +
"</select>",
- _erbout
+ output_buffer
)
end
@@ -1293,7 +1287,7 @@ COUNTRIES
def test_time_zone_select_with_priority_zones
@firm = Firm.new("D")
- zones = [ TimeZone.new("A"), TimeZone.new("D") ]
+ zones = [ ActiveSupport::TimeZone.new("A"), ActiveSupport::TimeZone.new("D") ]
html = time_zone_select("firm", "time_zone", zones )
assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" +
"<option value=\"A\">A</option>\n" +
diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb
index 73a8bd4d87..eabbe9c8a0 100644
--- a/actionpack/test/template/form_tag_helper_test.rb
+++ b/actionpack/test/template/form_tag_helper_test.rb
@@ -35,27 +35,27 @@ class FormTagHelperTest < ActionView::TestCase
expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0'><input type="hidden" name="_method" value="put" /></div>)
assert_dom_equal expected, actual
end
-
+
def test_form_tag_with_method_delete
actual = form_tag({}, { :method => :delete })
expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0'><input type="hidden" name="_method" value="delete" /></div>)
assert_dom_equal expected, actual
end
- def test_form_tag_with_block
- _erbout = ''
- form_tag("http://example.com") { _erbout.concat "Hello world!" }
+ def test_form_tag_with_block_in_erb
+ __in_erb_template = ''
+ form_tag("http://example.com") { concat "Hello world!" }
expected = %(<form action="http://example.com" method="post">Hello world!</form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
- def test_form_tag_with_block_and_method
- _erbout = ''
- form_tag("http://example.com", :method => :put) { _erbout.concat "Hello world!" }
+ def test_form_tag_with_block_and_method_in_erb
+ __in_erb_template = ''
+ form_tag("http://example.com", :method => :put) { concat "Hello world!" }
expected = %(<form action="http://example.com" method="post"><div style='margin:0;padding:0'><input type="hidden" name="_method" value="put" /></div>Hello world!</form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_hidden_field_tag
@@ -90,11 +90,11 @@ class FormTagHelperTest < ActionView::TestCase
actual = radio_button_tag("gender", "m") + radio_button_tag("gender", "f")
expected = %(<input id="gender_m" name="gender" type="radio" value="m" /><input id="gender_f" name="gender" type="radio" value="f" />)
assert_dom_equal expected, actual
-
+
actual = radio_button_tag("opinion", "-1") + radio_button_tag("opinion", "1")
expected = %(<input id="opinion_-1" name="opinion" type="radio" value="-1" /><input id="opinion_1" name="opinion" type="radio" value="1" />)
assert_dom_equal expected, actual
-
+
actual = radio_button_tag("person[gender]", "m")
expected = %(<input id="person_gender_m" name="person[gender]" type="radio" value="m" />)
assert_dom_equal expected, actual
@@ -105,13 +105,13 @@ class FormTagHelperTest < ActionView::TestCase
expected = %(<select id="people" name="people"><option>david</option></select>)
assert_dom_equal expected, actual
end
-
+
def test_select_tag_with_multiple
actual = select_tag "colors", "<option>Red</option><option>Blue</option><option>Green</option>", :multiple => :true
expected = %(<select id="colors" multiple="multiple" name="colors"><option>Red</option><option>Blue</option><option>Green</option></select>)
assert_dom_equal expected, actual
end
-
+
def test_select_tag_disabled
actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>", :disabled => :true
expected = %(<select id="places" disabled="disabled" name="places"><option>Home</option><option>Work</option><option>Pub</option></select>)
@@ -147,37 +147,37 @@ class FormTagHelperTest < ActionView::TestCase
expected = %(<input class="admin" id="title" name="title" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
-
+
def test_text_field_tag_size_symbol
actual = text_field_tag "title", "Hello!", :size => 75
expected = %(<input id="title" name="title" size="75" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
-
+
def test_text_field_tag_size_string
actual = text_field_tag "title", "Hello!", "size" => "75"
expected = %(<input id="title" name="title" size="75" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
-
+
def test_text_field_tag_maxlength_symbol
actual = text_field_tag "title", "Hello!", :maxlength => 75
expected = %(<input id="title" name="title" maxlength="75" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
-
+
def test_text_field_tag_maxlength_string
actual = text_field_tag "title", "Hello!", "maxlength" => "75"
expected = %(<input id="title" name="title" maxlength="75" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
-
+
def test_text_field_disabled
actual = text_field_tag "title", "Hello!", :disabled => :true
expected = %(<input id="title" name="title" disabled="disabled" type="text" value="Hello!" />)
assert_dom_equal expected, actual
end
-
+
def test_text_field_tag_with_multiple_options
actual = text_field_tag "title", "Hello!", :size => 70, :maxlength => 80
expected = %(<input id="title" name="title" size="70" maxlength="80" type="text" value="Hello!" />)
@@ -228,29 +228,29 @@ class FormTagHelperTest < ActionView::TestCase
submit_tag("Save", :confirm => "Are you sure?")
)
end
-
+
def test_pass
assert_equal 1, 1
end
- def test_field_set_tag
- _erbout = ''
- field_set_tag("Your details") { _erbout.concat "Hello world!" }
+ def test_field_set_tag_in_erb
+ __in_erb_template = ''
+ field_set_tag("Your details") { concat "Hello world!" }
expected = %(<fieldset><legend>Your details</legend>Hello world!</fieldset>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
- _erbout = ''
- field_set_tag { _erbout.concat "Hello world!" }
+ self.output_buffer = ''
+ field_set_tag { concat "Hello world!" }
expected = %(<fieldset>Hello world!</fieldset>)
- assert_dom_equal expected, _erbout
-
- _erbout = ''
- field_set_tag('') { _erbout.concat "Hello world!" }
+ assert_dom_equal expected, output_buffer
+
+ self.output_buffer = ''
+ field_set_tag('') { concat "Hello world!" }
expected = %(<fieldset>Hello world!</fieldset>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def protect_against_forgery?
diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb
index f18adb990c..d6d398d224 100644
--- a/actionpack/test/template/javascript_helper_test.rb
+++ b/actionpack/test/template/javascript_helper_test.rb
@@ -48,7 +48,7 @@ class JavaScriptHelperTest < ActionView::TestCase
end
def test_link_to_function_with_href
- assert_dom_equal %(<a href="http://example.com/" onclick="alert('Hello world!'); return false;">Greeting</a>),
+ assert_dom_equal %(<a href="http://example.com/" onclick="alert('Hello world!'); return false;">Greeting</a>),
link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/')
end
@@ -82,8 +82,12 @@ class JavaScriptHelperTest < ActionView::TestCase
end
def test_javascript_tag
+ self.output_buffer = 'foo'
+
assert_dom_equal "<script type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>",
javascript_tag("alert('hello')")
+
+ assert_equal 'foo', output_buffer, 'javascript_tag without a block should not concat to output_buffer'
end
def test_javascript_tag_with_options
@@ -91,16 +95,16 @@ class JavaScriptHelperTest < ActionView::TestCase
javascript_tag("alert('hello')", :id => "the_js_tag")
end
- def test_javascript_tag_with_block
- _erbout = ''
- javascript_tag { _erbout.concat "alert('hello')" }
- assert_dom_equal "<script type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", _erbout
+ def test_javascript_tag_with_block_in_erb
+ __in_erb_template = ''
+ javascript_tag { concat "alert('hello')" }
+ assert_dom_equal "<script type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", output_buffer
end
- def test_javascript_tag_with_block_and_options
- _erbout = ''
- javascript_tag(:id => "the_js_tag") { _erbout.concat "alert('hello')" }
- assert_dom_equal "<script id=\"the_js_tag\" type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", _erbout
+ def test_javascript_tag_with_block_and_options_in_erb
+ __in_erb_template = ''
+ javascript_tag(:id => "the_js_tag") { concat "alert('hello')" }
+ assert_dom_equal "<script id=\"the_js_tag\" type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", output_buffer
end
def test_javascript_cdata_section
diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb
index 53a250f9d5..60b83b476d 100644
--- a/actionpack/test/template/prototype_helper_test.rb
+++ b/actionpack/test/template/prototype_helper_test.rb
@@ -54,7 +54,7 @@ class PrototypeHelperBaseTest < ActionView::TestCase
end
def create_generator
- block = Proc.new { |*args| yield *args if block_given? }
+ block = Proc.new { |*args| yield *args if block_given? }
JavaScriptGenerator.new self, &block
end
end
@@ -70,7 +70,7 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outauthor</a>),
link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }}, { :class => "fine" })
assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
- link_to_remote("Remote outauthor", :complete => "alert(request.responseText)", :url => { :action => "whatnot" })
+ link_to_remote("Remote outauthor", :complete => "alert(request.responseText)", :url => { :action => "whatnot" })
assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
link_to_remote("Remote outauthor", :success => "alert(request.responseText)", :url => { :action => "whatnot" })
assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
@@ -78,12 +78,12 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&amp;b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.responseText)}}); return false;\">Remote outauthor</a>),
link_to_remote("Remote outauthor", :failure => "alert(request.responseText)", :url => { :action => "whatnot", :a => '10', :b => '20' })
end
-
+
def test_link_to_remote_html_options
assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outauthor</a>),
link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }, :html => { :class => "fine" } })
end
-
+
def test_link_to_remote_url_quote_escaping
assert_dom_equal %(<a href="#" onclick="new Ajax.Request('http://www.example.com/whatnot\\\'s', {asynchronous:true, evalScripts:true}); return false;">Remote</a>),
link_to_remote("Remote", { :url => { :action => "whatnot's" } })
@@ -93,14 +93,14 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
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" })
end
-
+
def test_periodically_call_remote_with_frequency
assert_dom_equal(
"<script type=\"text/javascript\">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true})}, 2)\n//]]>\n</script>",
periodically_call_remote(:frequency => 2)
)
end
-
+
def test_form_remote_tag
assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">),
form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast })
@@ -117,53 +117,48 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, :html => { :method => :put })
end
- def test_form_remote_tag_with_block
- _erbout = ''
- form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }) { _erbout.concat "Hello world!" }
- assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">Hello world!</form>), _erbout
+ def test_form_remote_tag_with_block_in_erb
+ __in_erb_template = ''
+ form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }) { concat "Hello world!" }
+ assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">Hello world!</form>), output_buffer
end
def test_remote_form_for_with_record_identification_with_new_record
- _erbout = ''
remote_form_for(@record, {:html => { :id => 'create-author' }}) {}
-
+
expected = %(<form action='#{authors_path}' onsubmit="new Ajax.Request('#{authors_path}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_author' id='create-author' method='post'></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_remote_form_for_with_record_identification_without_html_options
- _erbout = ''
remote_form_for(@record) {}
-
+
expected = %(<form action='#{authors_path}' onsubmit="new Ajax.Request('#{authors_path}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_author' method='post' id='new_author'></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_remote_form_for_with_record_identification_with_existing_record
@record.save
- _erbout = ''
remote_form_for(@record) {}
-
+
expected = %(<form action='#{author_path(@record)}' id='edit_author_1' method='post' onsubmit="new Ajax.Request('#{author_path(@record)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='edit_author'><div style='margin:0;padding:0'><input name='_method' type='hidden' value='put' /></div></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_remote_form_for_with_new_object_in_list
- _erbout = ''
remote_form_for([@author, @article]) {}
-
+
expected = %(<form action='#{author_articles_path(@author)}' onsubmit="new Ajax.Request('#{author_articles_path(@author)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='new_article' method='post' id='new_article'></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
-
+
def test_remote_form_for_with_existing_object_in_list
@author.save
@article.save
- _erbout = ''
remote_form_for([@author, @article]) {}
-
+
expected = %(<form action='#{author_article_path(@author, @article)}' id='edit_article_1' method='post' onsubmit="new Ajax.Request('#{author_article_path(@author, @article)}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" class='edit_article'><div style='margin:0;padding:0'><input name='_method' type='hidden' value='put' /></div></form>)
- assert_dom_equal expected, _erbout
+ assert_dom_equal expected, output_buffer
end
def test_on_callbacks
@@ -178,18 +173,18 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
form_remote_tag(:update => { :success => "glass_of_beer", :failure => "glass_of_water" }, :url => { :action => :fast }, callback=>"monkeys();")
end
-
+
#HTTP status codes 200 up to 599 have callbacks
#these should work
100.upto(599) do |callback|
assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">),
form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
end
-
+
#test 200 and 404
assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, parameters:Form.serialize(this)}); return false;">),
form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, 200=>"monkeys();", 404=>"bananas();")
-
+
#these shouldn't
1.upto(99) do |callback|
assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">),
@@ -199,44 +194,44 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">),
form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();")
end
-
+
#test ultimate combo
assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, onComplete:function(request){c();}, onFailure:function(request){f();}, onLoading:function(request){c1()}, onSuccess:function(request){s()}, parameters:Form.serialize(this)}); return false;\">),
form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, :loading => "c1()", :success => "s()", :failure => "f();", :complete => "c();", 200=>"monkeys();", 404=>"bananas();")
-
+
end
-
+
def test_submit_to_remote
assert_dom_equal %(<input name=\"More beer!\" onclick=\"new Ajax.Updater('empty_bottle', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)}); return false;\" type=\"button\" value=\"1000000\" />),
submit_to_remote("More beer!", 1_000_000, :update => "empty_bottle")
end
-
+
def test_observe_field
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/reorder_if_empty', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" })
end
-
+
def test_observe_field_using_with_option
expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(value)})})\n//]]>\n</script>)
assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => 'id')
assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + encodeURIComponent(value)")
end
-
+
def test_observe_field_using_json_in_with_option
expected = %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/check_value', {asynchronous:true, evalScripts:true, parameters:{'id':value}})})\n//]]>\n</script>)
- assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "{'id':value}")
+ assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "{'id':value}")
end
-
+
def test_observe_field_using_function_for_callback
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {alert('Element changed')})\n//]]>\n</script>),
observe_field("glass", :frequency => 5.minutes, :function => "alert('Element changed')")
end
-
+
def test_observe_form
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {new Ajax.Request('http://www.example.com/cart_changed', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>),
observe_form("cart", :frequency => 2, :url => { :action => "cart_changed" })
end
-
+
def test_observe_form_using_function_for_callback
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {alert('Form changed')})\n//]]>\n</script>),
observe_form("cart", :frequency => 2, :function => "alert('Form changed')")
@@ -251,7 +246,7 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
block = Proc.new { |page| page.replace_html('foo', 'bar') }
assert_equal create_generator(&block).to_s, update_page(&block)
end
-
+
def test_update_page_tag
block = Proc.new { |page| page.replace_html('foo', 'bar') }
assert_equal javascript_tag(create_generator(&block).to_s), update_page_tag(&block)
@@ -267,15 +262,15 @@ class PrototypeHelperTest < PrototypeHelperBaseTest
def author_path(record)
"/authors/#{record.id}"
end
-
+
def authors_path
"/authors"
end
-
+
def author_articles_path(author)
"/authors/#{author.id}/articles"
end
-
+
def author_article_path(author, article)
"/authors/#{author.id}/articles/#{article.id}"
end
@@ -286,7 +281,7 @@ class JavaScriptGeneratorTest < PrototypeHelperBaseTest
super
@generator = create_generator
end
-
+
def test_insert_html_with_string
assert_equal 'new Insertion.Top("element", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");',
@generator.insert_html(:top, 'element', '<p>This is a test</p>')
@@ -297,70 +292,75 @@ class JavaScriptGeneratorTest < PrototypeHelperBaseTest
assert_equal 'new Insertion.After("element", "\\u003Cp\u003EThis is a test\\u003C/p\u003E");',
@generator.insert_html(:after, 'element', '<p>This is a test</p>')
end
-
+
def test_replace_html_with_string
assert_equal 'Element.update("element", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");',
@generator.replace_html('element', '<p>This is a test</p>')
end
-
+
def test_replace_element_with_string
assert_equal 'Element.replace("element", "\\u003Cdiv id=\"element\"\\u003E\\u003Cp\\u003EThis is a test\\u003C/p\\u003E\\u003C/div\\u003E");',
@generator.replace('element', '<div id="element"><p>This is a test</p></div>')
end
-
+
def test_remove
assert_equal 'Element.remove("foo");',
@generator.remove('foo')
assert_equal '["foo", "bar", "baz"].each(Element.remove);',
@generator.remove('foo', 'bar', 'baz')
end
-
+
def test_show
assert_equal 'Element.show("foo");',
@generator.show('foo')
assert_equal '["foo", "bar", "baz"].each(Element.show);',
- @generator.show('foo', 'bar', 'baz')
+ @generator.show('foo', 'bar', 'baz')
end
-
+
def test_hide
assert_equal 'Element.hide("foo");',
@generator.hide('foo')
assert_equal '["foo", "bar", "baz"].each(Element.hide);',
- @generator.hide('foo', 'bar', 'baz')
+ @generator.hide('foo', 'bar', 'baz')
end
-
+
def test_toggle
assert_equal 'Element.toggle("foo");',
@generator.toggle('foo')
assert_equal '["foo", "bar", "baz"].each(Element.toggle);',
- @generator.toggle('foo', 'bar', 'baz')
+ @generator.toggle('foo', 'bar', 'baz')
end
-
+
def test_alert
assert_equal 'alert("hello");', @generator.alert('hello')
end
-
+
def test_redirect_to
assert_equal 'window.location.href = "http://www.example.com/welcome";',
@generator.redirect_to(:action => 'welcome')
assert_equal 'window.location.href = "http://www.example.com/welcome?a=b&c=d";',
@generator.redirect_to("http://www.example.com/welcome?a=b&c=d")
end
-
+
+ def test_reload
+ assert_equal 'window.location.reload();',
+ @generator.reload
+ end
+
def test_delay
@generator.delay(20) do
@generator.hide('foo')
end
-
+
assert_equal "setTimeout(function() {\n;\nElement.hide(\"foo\");\n}, 20000);", @generator.to_s
end
-
+
def test_to_s
@generator.insert_html(:top, 'element', '<p>This is a test</p>')
@generator.insert_html(:bottom, 'element', '<p>This is a test</p>')
@generator.remove('foo', 'bar')
@generator.replace_html('baz', '<p>This is a test</p>')
-
+
assert_equal <<-EOS.chomp, @generator.to_s
new Insertion.Top("element", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");
new Insertion.Bottom("element", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");
@@ -382,12 +382,12 @@ Element.update("baz", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");
@generator['hello'].hide
assert_equal %($("hello").hide();), @generator.to_s
end
-
+
def test_element_proxy_variable_access
@generator['hello']['style']
assert_equal %($("hello").style;), @generator.to_s
end
-
+
def test_element_proxy_variable_access_with_assignment
@generator['hello']['style']['color'] = 'red'
assert_equal %($("hello").style.color = "red";), @generator.to_s
@@ -402,7 +402,7 @@ Element.update("baz", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");
@generator['hello'].hide("first").clean_whitespace
assert_equal %($("hello").hide("first").cleanWhitespace();), @generator.to_s
end
-
+
def test_select_access
assert_equal %($$("div.hello");), @generator.select('div.hello')
end
@@ -411,29 +411,29 @@ Element.update("baz", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");
@generator.select('p.welcome b').first.hide
assert_equal %($$("p.welcome b").first().hide();), @generator.to_s
end
-
+
def test_visual_effect
- assert_equal %(new Effect.Puff("blah",{});),
+ assert_equal %(new Effect.Puff("blah",{});),
@generator.visual_effect(:puff,'blah')
- end
-
+ end
+
def test_visual_effect_toggle
- assert_equal %(Effect.toggle("blah",'appear',{});),
+ assert_equal %(Effect.toggle("blah",'appear',{});),
@generator.visual_effect(:toggle_appear,'blah')
end
-
+
def test_sortable
- assert_equal %(Sortable.create("blah", {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("blah")})}});),
+ assert_equal %(Sortable.create("blah", {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("blah")})}});),
@generator.sortable('blah', :url => { :action => "order" })
end
-
+
def test_draggable
- assert_equal %(new Draggable("blah", {});),
+ assert_equal %(new Draggable("blah", {});),
@generator.draggable('blah')
end
-
+
def test_drop_receiving
- assert_equal %(Droppables.add("blah", {onDrop:function(element){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}});),
+ assert_equal %(Droppables.add("blah", {onDrop:function(element){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}});),
@generator.drop_receiving('blah', :url => { :action => "order" })
end
@@ -535,7 +535,7 @@ return array.reverse();
});
EOS
end
-
+
def test_collection_proxy_with_find_all
@generator.select('p').find_all 'a' do |value, index|
@generator << '(value.className == "welcome")'
@@ -547,7 +547,7 @@ return (value.className == "welcome");
});
EOS
end
-
+
def test_collection_proxy_with_in_groups_of
@generator.select('p').in_groups_of('a', 3)
@generator.select('p').in_groups_of('a', 3, 'x')
@@ -556,13 +556,13 @@ var a = $$("p").inGroupsOf(3);
var a = $$("p").inGroupsOf(3, "x");
EOS
end
-
+
def test_collection_proxy_with_each_slice
@generator.select('p').each_slice('a', 3)
@generator.select('p').each_slice('a', 3) do |group, index|
group.reverse
end
-
+
assert_equal <<-EOS.strip, @generator.to_s
var a = $$("p").eachSlice(3);
var a = $$("p").eachSlice(3, function(value, index) {
@@ -570,7 +570,7 @@ return value.reverse();
});
EOS
end
-
+
def test_debug_rjs
ActionView::Base.debug_rjs = true
@generator['welcome'].replace_html 'Welcome'
@@ -578,7 +578,7 @@ return value.reverse();
ensure
ActionView::Base.debug_rjs = false
end
-
+
def test_literal
literal = @generator.literal("function() {}")
assert_equal "function() {}", literal.to_json
@@ -589,7 +589,7 @@ return value.reverse();
@generator.form.focus('my_field')
assert_equal "Form.focus(\"my_field\");", @generator.to_s
end
-
+
def test_call_with_block
@generator.call(:before)
@generator.call(:my_method) do |p|
@@ -602,7 +602,7 @@ return value.reverse();
end
assert_equal "before();\nmy_method(function() { $(\"one\").show();\n$(\"two\").hide(); });\nin_between();\nmy_method_with_arguments(true, \"hello\", function() { $(\"three\").visualEffect(\"highlight\"); });", @generator.to_s
end
-
+
def test_class_proxy_call_with_block
@generator.my_object.my_method do |p|
p[:one].show
diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb
index 0afbb54f57..34a200b933 100644
--- a/actionpack/test/template/record_tag_helper_test.rb
+++ b/actionpack/test/template/record_tag_helper_test.rb
@@ -2,7 +2,7 @@ require 'abstract_unit'
class Post
def id
- 45
+ 45
end
def body
"What a wonderful world!"
@@ -15,40 +15,36 @@ class RecordTagHelperTest < ActionView::TestCase
def setup
@post = Post.new
end
-
+
def test_content_tag_for
- _erbout = ''
expected = %(<li class="post bar" id="post_45"></li>)
actual = content_tag_for(:li, @post, :class => 'bar') { }
assert_dom_equal expected, actual
end
-
+
def test_content_tag_for_prefix
- _erbout = ''
expected = %(<ul class="post" id="archived_post_45"></ul>)
actual = content_tag_for(:ul, @post, :archived) { }
- assert_dom_equal expected, actual
+ assert_dom_equal expected, actual
end
-
+
def test_content_tag_for_with_extra_html_tags
- _erbout = ''
expected = %(<tr class="post bar" id="post_45" style='background-color: #f0f0f0'></tr>)
actual = content_tag_for(:tr, @post, {:class => "bar", :style => "background-color: #f0f0f0"}) { }
- assert_dom_equal expected, actual
+ assert_dom_equal expected, actual
end
-
- def test_block_works_with_content_tag_for
- _erbout = ''
+
+ def test_block_works_with_content_tag_for_in_erb
+ __in_erb_template = ''
expected = %(<tr class="post" id="post_45">#{@post.body}</tr>)
- actual = content_tag_for(:tr, @post) { _erbout.concat @post.body }
- assert_dom_equal expected, actual
+ actual = content_tag_for(:tr, @post) { concat @post.body }
+ assert_dom_equal expected, actual
end
-
- def test_div_for
- _erbout = ''
+
+ def test_div_for_in_erb
+ __in_erb_template = ''
expected = %(<div class="post bar" id="post_45">#{@post.body}</div>)
- actual = div_for(@post, :class => "bar") { _erbout.concat @post.body }
+ actual = div_for(@post, :class => "bar") { concat @post.body }
assert_dom_equal expected, actual
- end
-
+ end
end
diff --git a/actionpack/test/template/tag_helper_test.rb b/actionpack/test/template/tag_helper_test.rb
index 4da6116095..fc49d340ef 100644
--- a/actionpack/test/template/tag_helper_test.rb
+++ b/actionpack/test/template/tag_helper_test.rb
@@ -33,24 +33,40 @@ class TagHelperTest < ActionView::TestCase
assert_equal content_tag("a", "Create", "href" => "create"),
content_tag("a", "Create", :href => "create")
end
-
- def test_content_tag_with_block
- _erbout = ''
- content_tag(:div) { _erbout.concat "Hello world!" }
- assert_dom_equal "<div>Hello world!</div>", _erbout
+
+ def test_content_tag_with_block_in_erb
+ __in_erb_template = ''
+ content_tag(:div) { concat "Hello world!" }
+ assert_dom_equal "<div>Hello world!</div>", output_buffer
end
-
- def test_content_tag_with_block_and_options
- _erbout = ''
- content_tag(:div, :class => "green") { _erbout.concat "Hello world!" }
- assert_dom_equal %(<div class="green">Hello world!</div>), _erbout
+
+ def test_content_tag_with_block_and_options_in_erb
+ __in_erb_template = ''
+ content_tag(:div, :class => "green") { concat "Hello world!" }
+ assert_dom_equal %(<div class="green">Hello world!</div>), output_buffer
end
-
- def test_content_tag_with_block_and_options_outside_of_action_view
+
+ def test_content_tag_with_block_and_options_out_of_erb
+ assert_dom_equal %(<div class="green">Hello world!</div>), content_tag(:div, :class => "green") { "Hello world!" }
+ end
+
+ def test_content_tag_with_block_and_options_outside_out_of_erb
assert_equal content_tag("a", "Create", :href => "create"),
- content_tag("a", "href" => "create") { "Create" }
+ content_tag("a", "href" => "create") { "Create" }
end
-
+
+ def test_content_tag_nested_in_content_tag_out_of_erb
+ assert_equal content_tag("p", content_tag("b", "Hello")),
+ content_tag("p") { content_tag("b", "Hello") },
+ output_buffer
+ end
+
+ def test_content_tag_nested_in_content_tag_in_erb
+ __in_erb_template = true
+ content_tag("p") { concat content_tag("b", "Hello") }
+ assert_equal '<p><b>Hello</b></p>', output_buffer
+ end
+
def test_cdata_section
assert_equal "<![CDATA[<hello world>]]>", cdata_section("<hello world>")
end
diff --git a/actionpack/test/template/template_file_test.rb b/actionpack/test/template/template_file_test.rb
new file mode 100644
index 0000000000..d14a966c1c
--- /dev/null
+++ b/actionpack/test/template/template_file_test.rb
@@ -0,0 +1,95 @@
+require 'abstract_unit'
+
+class TemplateFileTest < Test::Unit::TestCase
+ LOAD_PATH_ROOT = File.join(File.dirname(__FILE__), '..', 'fixtures')
+
+ def setup
+ @template = ActionView::TemplateFile.new("test/hello_world.html.erb")
+ @another_template = ActionView::TemplateFile.new("test/hello_world.erb")
+ @file_only = ActionView::TemplateFile.new("hello_world.erb")
+ @full_path = ActionView::TemplateFile.new("/u/app/scales/config/../app/views/test/hello_world.erb", true)
+ @layout = ActionView::TemplateFile.new("layouts/hello")
+ @multipart = ActionView::TemplateFile.new("test_mailer/implicitly_multipart_example.text.html.erb")
+ end
+
+ def test_path
+ assert_equal "test/hello_world.html.erb", @template.path
+ assert_equal "test/hello_world.erb", @another_template.path
+ assert_equal "hello_world.erb", @file_only.path
+ assert_equal "/u/app/scales/config/../app/views/test/hello_world.erb", @full_path.path
+ assert_equal "layouts/hello", @layout.path
+ assert_equal "test_mailer/implicitly_multipart_example.text.html.erb", @multipart.path
+ end
+
+ def test_path_without_extension
+ assert_equal "test/hello_world.html", @template.path_without_extension
+ assert_equal "test/hello_world", @another_template.path_without_extension
+ assert_equal "hello_world", @file_only.path_without_extension
+ assert_equal "layouts/hello", @layout.path_without_extension
+ assert_equal "test_mailer/implicitly_multipart_example.text.html", @multipart.path_without_extension
+ end
+
+ def test_path_without_format_and_extension
+ assert_equal "test/hello_world", @template.path_without_format_and_extension
+ assert_equal "test/hello_world", @another_template.path_without_format_and_extension
+ assert_equal "hello_world", @file_only.path_without_format_and_extension
+ assert_equal "layouts/hello", @layout.path_without_format_and_extension
+ assert_equal "test_mailer/implicitly_multipart_example", @multipart.path_without_format_and_extension
+ end
+
+ def test_name
+ assert_equal "hello_world", @template.name
+ assert_equal "hello_world", @another_template.name
+ assert_equal "hello_world", @file_only.name
+ assert_equal "hello_world", @full_path.name
+ assert_equal "hello", @layout.name
+ assert_equal "implicitly_multipart_example", @multipart.name
+ end
+
+ def test_format
+ assert_equal "html", @template.format
+ assert_equal nil, @another_template.format
+ assert_equal nil, @layout.format
+ assert_equal "text.html", @multipart.format
+ end
+
+ def test_extension
+ assert_equal "erb", @template.extension
+ assert_equal "erb", @another_template.extension
+ assert_equal nil, @layout.extension
+ assert_equal "erb", @multipart.extension
+ end
+
+ def test_format_and_extension
+ assert_equal "html.erb", @template.format_and_extension
+ assert_equal "erb", @another_template.format_and_extension
+ assert_equal nil, @layout.format_and_extension
+ assert_equal "text.html.erb", @multipart.format_and_extension
+ end
+
+ def test_new_file_with_extension
+ file = @template.dup_with_extension(:haml)
+ assert_equal "test/hello_world.html", file.path_without_extension
+ assert_equal "haml", file.extension
+ assert_equal "test/hello_world.html.haml", file.path
+
+ file = @another_template.dup_with_extension(:haml)
+ assert_equal "test/hello_world", file.path_without_extension
+ assert_equal "haml", file.extension
+ assert_equal "test/hello_world.haml", file.path
+
+ file = @another_template.dup_with_extension(nil)
+ assert_equal "test/hello_world", file.path_without_extension
+ assert_equal nil, file.extension
+ assert_equal "test/hello_world", file.path
+ end
+
+ def test_freezes_entire_contents
+ @template.freeze
+ assert @template.frozen?
+ assert @template.base_path.frozen?
+ assert @template.name.frozen?
+ assert @template.format.frozen?
+ assert @template.extension.frozen?
+ end
+end
diff --git a/actionpack/test/template/template_finder_test.rb b/actionpack/test/template/template_finder_test.rb
deleted file mode 100644
index 3d6baff5fb..0000000000
--- a/actionpack/test/template/template_finder_test.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'abstract_unit'
-
-class TemplateFinderTest < Test::Unit::TestCase
-
- LOAD_PATH_ROOT = File.join(File.dirname(__FILE__), '..', 'fixtures')
-
- def setup
- ActionView::TemplateFinder.process_view_paths(LOAD_PATH_ROOT)
- ActionView::Template::register_template_handler :mab, Class.new(ActionView::TemplateHandler)
- @template = ActionView::Base.new
- @finder = ActionView::TemplateFinder.new(@template, LOAD_PATH_ROOT)
- end
-
- def test_should_raise_exception_for_unprocessed_view_path
- assert_raises ActionView::TemplateFinder::InvalidViewPath do
- ActionView::TemplateFinder.new(@template, File.dirname(__FILE__))
- end
- end
-
- def test_should_cache_file_extension_properly
- assert_equal ["builder", "erb", "rhtml", "rjs", "rxml", "mab"].sort,
- ActionView::TemplateFinder.file_extension_cache[LOAD_PATH_ROOT].values.flatten.uniq.sort
-
- assert_equal (Dir.glob("#{LOAD_PATH_ROOT}/**/*/*.{erb,rjs,rhtml,builder,rxml,mab}") |
- Dir.glob("#{LOAD_PATH_ROOT}/**.{erb,rjs,rhtml,builder,rxml,mab}")).size,
- ActionView::TemplateFinder.file_extension_cache[LOAD_PATH_ROOT].keys.size
- end
-
- def test_should_cache_dir_content_properly
- assert ActionView::TemplateFinder.processed_view_paths[LOAD_PATH_ROOT]
- assert_equal (Dir.glob("#{LOAD_PATH_ROOT}/**/*/**") | Dir.glob("#{LOAD_PATH_ROOT}/**")).find_all {|f| !File.directory?(f) }.size,
- ActionView::TemplateFinder.processed_view_paths[LOAD_PATH_ROOT].size
- end
-
- def test_find_template_extension_from_first_render
- assert_nil @finder.send(:find_template_extension_from_first_render)
-
- {
- nil => nil,
- '' => nil,
- 'foo' => nil,
- '/foo' => nil,
- 'foo.rb' => 'rb',
- 'foo.bar.rb' => 'bar.rb',
- 'baz/foo.rb' => 'rb',
- 'baz/foo.bar.rb' => 'bar.rb',
- 'baz/foo.o/foo.rb' => 'rb',
- 'baz/foo.o/foo.bar.rb' => 'bar.rb',
- }.each do |input,expectation|
- @template.instance_variable_set('@first_render', input)
- assert_equal expectation, @finder.send(:find_template_extension_from_first_render)
- end
- end
-
- def test_should_report_file_exists_correctly
- assert_nil @finder.send(:find_template_extension_from_first_render)
- assert_equal false, @finder.send(:file_exists?, 'test.rhtml')
- assert_equal false, @finder.send(:file_exists?, 'test.rb')
-
- @template.instance_variable_set('@first_render', 'foo.rb')
-
- assert_equal 'rb', @finder.send(:find_template_extension_from_first_render)
- assert_equal false, @finder.send(:file_exists?, 'baz')
- assert_equal false, @finder.send(:file_exists?, 'baz.rb')
- end
-
- uses_mocha 'Template finder tests' do
- def test_should_update_extension_cache_when_template_handler_is_registered
- ActionView::TemplateFinder.expects(:update_extension_cache_for).with("funky")
- ActionView::Template::register_template_handler :funky, Class.new(ActionView::TemplateHandler)
- end
- end
-end
diff --git a/actionpack/test/template/template_object_test.rb b/actionpack/test/template/template_object_test.rb
index afb5c5cc16..2cfc4523c6 100644
--- a/actionpack/test/template/template_object_test.rb
+++ b/actionpack/test/template/template_object_test.rb
@@ -2,60 +2,57 @@ require 'abstract_unit'
class TemplateObjectTest < Test::Unit::TestCase
LOAD_PATH_ROOT = File.join(File.dirname(__FILE__), '..', 'fixtures')
- ActionView::TemplateFinder.process_view_paths(LOAD_PATH_ROOT)
-
+
class TemplateTest < Test::Unit::TestCase
def setup
@view = ActionView::Base.new(LOAD_PATH_ROOT)
@path = "test/hello_world.erb"
end
-
+
def test_should_create_valid_template
template = ActionView::Template.new(@view, @path, true)
-
+
assert_kind_of ActionView::TemplateHandlers::ERB, template.handler
- assert_equal "test/hello_world.erb", template.path
+ assert_equal "test/hello_world.erb", template.path.to_s
assert_nil template.instance_variable_get(:"@source")
assert_equal "erb", template.extension
end
-
+
uses_mocha 'Template preparation tests' do
-
def test_should_prepare_template_properly
template = ActionView::Template.new(@view, @path, true)
view = template.instance_variable_get(:"@view")
-
+
view.expects(:evaluate_assigns)
template.handler.expects(:compile_template).with(template)
view.expects(:method_names).returns({})
-
+
template.prepare!
end
-
end
end
-
+
class PartialTemplateTest < Test::Unit::TestCase
def setup
@view = ActionView::Base.new(LOAD_PATH_ROOT)
@path = "test/partial_only"
end
-
+
def test_should_create_valid_partial_template
template = ActionView::PartialTemplate.new(@view, @path, nil)
-
- assert_equal "test/_partial_only", template.path
+
+ assert_equal "test/_partial_only", template.path.path_without_format_and_extension
assert_equal :partial_only, template.variable_name
-
+
assert template.locals.has_key?(:object)
assert template.locals.has_key?(:partial_only)
end
-
+
def test_partial_with_errors
template = ActionView::PartialTemplate.new(@view, 'test/raise', nil)
assert_raise(ActionView::TemplateError) { template.render_template }
end
-
+
uses_mocha 'Partial template preparation tests' do
def test_should_prepare_on_initialization
ActionView::PartialTemplate.any_instance.expects(:prepare!)
@@ -63,7 +60,7 @@ class TemplateObjectTest < Test::Unit::TestCase
end
end
end
-
+
class PartialTemplateFallbackTest < Test::Unit::TestCase
def setup
@view = ActionView::Base.new(LOAD_PATH_ROOT)
@@ -72,7 +69,7 @@ class TemplateObjectTest < Test::Unit::TestCase
def test_default
template = ActionView::PartialTemplate.new(@view, @path, nil)
- assert_equal 'test/_layout_for_partial', template.path
+ assert_equal 'test/_layout_for_partial', template.path.path_without_format_and_extension
assert_equal 'erb', template.extension
assert_equal :html, @view.template_format
end
@@ -80,7 +77,7 @@ class TemplateObjectTest < Test::Unit::TestCase
def test_js
@view.template_format = :js
template = ActionView::PartialTemplate.new(@view, @path, nil)
- assert_equal 'test/_layout_for_partial', template.path
+ assert_equal 'test/_layout_for_partial', template.path.path_without_format_and_extension
assert_equal 'erb', template.extension
assert_equal :html, @view.template_format
end
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index 62cdca03d1..df6be3bb13 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -11,6 +11,12 @@ class TextHelperTest < ActionView::TestCase
@_cycles = nil if (defined? @_cycles)
end
+ def test_concat
+ self.output_buffer = 'foo'
+ assert_equal 'foobar', concat('bar')
+ assert_equal 'foobar', output_buffer
+ end
+
def test_simple_format
assert_equal "<p></p>", simple_format(nil)
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index d45ea08a6f..44ceed6661 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -80,7 +80,7 @@ class UrlHelperTest < ActionView::TestCase
def test_link_tag_with_straight_url
assert_dom_equal "<a href=\"http://www.example.com\">Hello</a>", link_to("Hello", "http://www.example.com")
end
-
+
def test_link_tag_without_host_option
ActionController::Base.class_eval { attr_accessor :url }
url = {:controller => 'weblog', :action => 'show'}
@@ -121,7 +121,7 @@ class UrlHelperTest < ActionView::TestCase
@controller.request = RequestMock.new("http://www.example.com/weblog/show", nil, nil, {'HTTP_REFERER' => 'http://www.example.com/referer'})
assert_dom_equal "<a href=\"http://www.example.com/referer\">go back</a>", link_to('go back', :back)
end
-
+
def test_link_tag_with_back_and_no_referer
@controller.request = RequestMock.new("http://www.example.com/weblog/show", nil, nil, {})
assert_dom_equal "<a href=\"javascript:history.back()\">go back</a>", link_to('go back', :back)
@@ -211,7 +211,15 @@ class UrlHelperTest < ActionView::TestCase
def test_link_tag_using_post_javascript_and_popup
assert_raises(ActionView::ActionViewError) { link_to("Hello", "http://www.example.com", :popup => true, :method => :post, :confirm => "Are you serious?") }
end
-
+
+ def test_link_tag_using_block_in_erb
+ __in_erb_template = ''
+
+ link_to("http://example.com") { concat("Example site") }
+
+ assert_equal '<a href="http://example.com">Example site</a>', output_buffer
+ end
+
def test_link_to_unless
assert_equal "Showing", link_to_unless(true, "Showing", :action => "show", :controller => "weblog")
assert_dom_equal "<a href=\"http://www.example.com\">Listing</a>", link_to_unless(false, "Listing", :action => "list", :controller => "weblog")
@@ -285,7 +293,7 @@ class UrlHelperTest < ActionView::TestCase
assert_dom_equal "<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">&#109;&#101;&#40;&#97;&#116;&#41;&#100;&#111;&#109;&#97;&#105;&#110;&#40;&#100;&#111;&#116;&#41;&#99;&#111;&#109;</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)", :replace_dot => "(dot)")
assert_dom_equal "<script type=\"text/javascript\">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)")
end
-
+
def protect_against_forgery?
false
end
@@ -412,11 +420,11 @@ class Workshop
def initialize(id, new_record)
@id, @new_record = id, new_record
end
-
+
def new_record?
@new_record
end
-
+
def to_s
id.to_s
end