mirror of
https://github.com/TracksApp/tracks.git
synced 2026-02-24 16:14:07 +01:00
Upgraded to Rails 1.2.5. Added classic_pagination plugin since Rails paginantion is deprecated and was giving a warning. Got all the tests passing except a couple of selenium ones related to trying to edit a project twice.
git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@645 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
parent
ae95f03c5b
commit
c2a547e6de
117 changed files with 2418 additions and 583 deletions
|
|
@ -1,15 +1,6 @@
|
||||||
# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb
|
# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb
|
||||||
|
|
||||||
unless defined?(RAILS_ROOT)
|
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
||||||
root_path = File.join(File.dirname(__FILE__), '..')
|
|
||||||
|
|
||||||
unless RUBY_PLATFORM =~ /mswin32/
|
|
||||||
require 'pathname'
|
|
||||||
root_path = Pathname.new(root_path).cleanpath(true).to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
RAILS_ROOT = root_path
|
|
||||||
end
|
|
||||||
|
|
||||||
unless defined?(Rails::Initializer)
|
unless defined?(Rails::Initializer)
|
||||||
if File.directory?("#{RAILS_ROOT}/vendor/rails")
|
if File.directory?("#{RAILS_ROOT}/vendor/rails")
|
||||||
|
|
@ -17,29 +8,32 @@ unless defined?(Rails::Initializer)
|
||||||
else
|
else
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
|
|
||||||
environment_without_comments = IO.readlines(File.dirname(__FILE__) + '/environment.rb').reject { |l| l =~ /^#/ }.join
|
rails_gem_version =
|
||||||
environment_without_comments =~ /[^#]RAILS_GEM_VERSION = '([\d.]+)'/
|
if defined? RAILS_GEM_VERSION
|
||||||
rails_gem_version = $1
|
RAILS_GEM_VERSION
|
||||||
|
else
|
||||||
|
File.read("#{File.dirname(__FILE__)}/environment.rb") =~ /^[^#]*RAILS_GEM_VERSION\s+=\s+'([\d.]+)'/
|
||||||
|
$1
|
||||||
|
end
|
||||||
|
|
||||||
if version = defined?(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : rails_gem_version
|
if rails_gem_version
|
||||||
# Asking for 1.1.6 will give you 1.1.6.5206, if available -- makes it easier to use beta gems
|
rails_gem = Gem.cache.search('rails', "=#{rails_gem_version}.0").sort_by { |g| g.version.version }.last
|
||||||
rails_gem = Gem.cache.search('rails', "~>#{version}.0").sort_by { |g| g.version.version }.last
|
|
||||||
|
|
||||||
if rails_gem
|
if rails_gem
|
||||||
require_gem "rails", "=#{rails_gem.version.version}"
|
gem "rails", "=#{rails_gem.version.version}"
|
||||||
require rails_gem.full_gem_path + '/lib/initializer'
|
require rails_gem.full_gem_path + '/lib/initializer'
|
||||||
else
|
else
|
||||||
STDERR.puts %(Cannot find gem for Rails ~>#{version}.0:
|
STDERR.puts %(Cannot find gem for Rails =#{rails_gem_version}.0:
|
||||||
Install the missing gem with 'gem install -v=#{version} rails', or
|
Install the missing gem with 'gem install -v=#{rails_gem_version} rails', or
|
||||||
change environment.rb to define RAILS_GEM_VERSION with your desired version.
|
change environment.rb to define RAILS_GEM_VERSION with your desired version.
|
||||||
)
|
)
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
require_gem "rails"
|
gem "rails"
|
||||||
require 'initializer'
|
require 'initializer'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Rails::Initializer.run(:set_load_path)
|
Rails::Initializer.run(:set_load_path)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ click "css=#context_3 .buttons img.edit_item"
|
||||||
wait_for_visible "edit_context_3"
|
wait_for_visible "edit_context_3"
|
||||||
wait_for_not_visible "context_3"
|
wait_for_not_visible "context_3"
|
||||||
type "//div[@id='edit_context_3'] //input[@name='context[name]']", "telegraph"
|
type "//div[@id='edit_context_3'] //input[@name='context[name]']", "telegraph"
|
||||||
click "//div[@id='edit_context_3'] //input[@value='Update']"
|
click "//div[@id='edit_context_3'] //button"
|
||||||
wait_for_not_visible "edit_context_3"
|
wait_for_not_visible "edit_context_3"
|
||||||
wait_for_visible "context_3"
|
wait_for_visible "context_3"
|
||||||
click "css=#context_3 .buttons img.delete_item"
|
click "css=#context_3 .buttons img.delete_item"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ click "css=#context_3 .buttons img.edit_item"
|
||||||
wait_for_visible "edit_context_3"
|
wait_for_visible "edit_context_3"
|
||||||
wait_for_not_visible "context_3"
|
wait_for_not_visible "context_3"
|
||||||
type "//div[@id='edit_context_3'] //input[@name='context[name]']", "telegraph"
|
type "//div[@id='edit_context_3'] //input[@name='context[name]']", "telegraph"
|
||||||
click "//div[@id='edit_context_3'] //input[@value='Update']"
|
click "//div[@id='edit_context_3'] //button"
|
||||||
wait_for_not_visible "edit_context_3"
|
wait_for_not_visible "edit_context_3"
|
||||||
wait_for_visible "context_3"
|
wait_for_visible "context_3"
|
||||||
assert_text 'css=#context_3 .data a', 'telegraph'
|
assert_text 'css=#context_3 .data a', 'telegraph'
|
||||||
|
|
@ -13,7 +13,7 @@ click "css=#context_3 .buttons img.edit_item"
|
||||||
wait_for_visible "edit_context_3"
|
wait_for_visible "edit_context_3"
|
||||||
wait_for_not_visible "context_3"
|
wait_for_not_visible "context_3"
|
||||||
type "//div[@id='edit_context_3'] //input[@name='context[name]']", "email"
|
type "//div[@id='edit_context_3'] //input[@name='context[name]']", "email"
|
||||||
click "//div[@id='edit_context_3'] //input[@value='Update']"
|
click "//div[@id='edit_context_3'] //button"
|
||||||
wait_for_not_visible "edit_context_3"
|
wait_for_not_visible "edit_context_3"
|
||||||
wait_for_visible "context_3"
|
wait_for_visible "context_3"
|
||||||
assert_text 'css=#context_3 .data a', 'email'
|
assert_text 'css=#context_3 .data a', 'email'
|
||||||
|
|
@ -5,7 +5,7 @@ click "css=#project_2 .buttons img.edit_item"
|
||||||
wait_for_visible "edit_project_2"
|
wait_for_visible "edit_project_2"
|
||||||
wait_for_not_visible "project_2"
|
wait_for_not_visible "project_2"
|
||||||
type "//div[@id='edit_project_2'] //input[@name='project[name]']", "become a billionaire"
|
type "//div[@id='edit_project_2'] //input[@name='project[name]']", "become a billionaire"
|
||||||
click "//div[@id='edit_project_2'] //input[@value='Update']"
|
click "//div[@id='edit_project_2'] //button"
|
||||||
wait_for_not_visible "edit_project_2"
|
wait_for_not_visible "edit_project_2"
|
||||||
wait_for_visible "project_2"
|
wait_for_visible "project_2"
|
||||||
wait_for_visible "flash"
|
wait_for_visible "flash"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ click "css=#project_2 .buttons img.edit_item"
|
||||||
wait_for_visible "edit_project_2"
|
wait_for_visible "edit_project_2"
|
||||||
wait_for_not_visible "project_2"
|
wait_for_not_visible "project_2"
|
||||||
type "//div[@id='edit_project_2'] //input[@name='project[name]']", "become a billionaire"
|
type "//div[@id='edit_project_2'] //input[@name='project[name]']", "become a billionaire"
|
||||||
click "//div[@id='edit_project_2'] //input[@value='Update']"
|
click "//div[@id='edit_project_2'] //button"
|
||||||
wait_for_not_visible "edit_project_2"
|
wait_for_not_visible "edit_project_2"
|
||||||
wait_for_visible "project_2"
|
wait_for_visible "project_2"
|
||||||
assert_text 'css=#project_2 .data a', 'become a billionaire'
|
assert_text 'css=#project_2 .data a', 'become a billionaire'
|
||||||
|
|
@ -13,7 +13,7 @@ click "css=#project_2 .buttons img.edit_item"
|
||||||
wait_for_visible "edit_project_2"
|
wait_for_visible "edit_project_2"
|
||||||
wait_for_not_visible "project_2"
|
wait_for_not_visible "project_2"
|
||||||
type "//div[@id='edit_project_2'] //input[@name='project[name]']", "become a multi-millionaire"
|
type "//div[@id='edit_project_2'] //input[@name='project[name]']", "become a multi-millionaire"
|
||||||
click "//div[@id='edit_project_2'] //input[@value='Update']"
|
click "//div[@id='edit_project_2'] //button"
|
||||||
wait_for_not_visible "edit_project_2"
|
wait_for_not_visible "edit_project_2"
|
||||||
wait_for_visible "project_2"
|
wait_for_visible "project_2"
|
||||||
assert_text 'css=#project_2 .data a', 'become a multi-millionaire'
|
assert_text 'css=#project_2 .data a', 'become a multi-millionaire'
|
||||||
|
|
@ -53,13 +53,13 @@ class TodosHelperTest < Test::Rails::HelperTestCase
|
||||||
|
|
||||||
def test_remote_star_icon_unstarred
|
def test_remote_star_icon_unstarred
|
||||||
@todo = flexmock(:id => 1, :to_param => 1, :description => 'Get gas', :starred? => false)
|
@todo = flexmock(:id => 1, :to_param => 1, :description => 'Get gas', :starred? => false)
|
||||||
assert_remote_star_icon_helper_matches %r{<a href="/todos/1;toggle_star" class="icon star_item" title="star the action 'Get gas'"><img alt="Blank" class="unstarred_todo" src="/images/blank.png[?0-9]*" title="Star action" /></a>}
|
assert_remote_star_icon_helper_matches %r{<a href="/todos/1/toggle_star" class="icon star_item" title="star the action 'Get gas'"><img alt="Blank" class="unstarred_todo" src="/images/blank.png[?0-9]*" title="Star action" /></a>}
|
||||||
assert_behavior_registered
|
assert_behavior_registered
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_remote_star_icon_starred
|
def test_remote_star_icon_starred
|
||||||
@todo = flexmock(:id => 1, :to_param => 1, :description => 'Get gas', :starred? => true)
|
@todo = flexmock(:id => 1, :to_param => 1, :description => 'Get gas', :starred? => true)
|
||||||
assert_remote_star_icon_helper_matches %r{<a href="/todos/1;toggle_star" class="icon star_item" title="star the action 'Get gas'"><img alt="Blank" class="starred_todo" src="/images/blank.png[?0-9]*" title="Star action" /></a>}
|
assert_remote_star_icon_helper_matches %r{<a href="/todos/1/toggle_star" class="icon star_item" title="star the action 'Get gas'"><img alt="Blank" class="starred_todo" src="/images/blank.png[?0-9]*" title="Star action" /></a>}
|
||||||
assert_behavior_registered
|
assert_behavior_registered
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
10
tracks/vendor/rails/actionmailer/CHANGELOG
vendored
10
tracks/vendor/rails/actionmailer/CHANGELOG
vendored
|
|
@ -1,3 +1,13 @@
|
||||||
|
*1.3.5* (October 12th, 2007)
|
||||||
|
|
||||||
|
* Depend on Action Pack 1.13.5
|
||||||
|
|
||||||
|
|
||||||
|
*1.3.4* (October 4th, 2007)
|
||||||
|
|
||||||
|
* Depend on Action Pack 1.13.4
|
||||||
|
|
||||||
|
|
||||||
*1.3.3* (March 12th, 2007)
|
*1.3.3* (March 12th, 2007)
|
||||||
|
|
||||||
* Depend on Action Pack 1.13.3
|
* Depend on Action Pack 1.13.3
|
||||||
|
|
|
||||||
2
tracks/vendor/rails/actionmailer/Rakefile
vendored
2
tracks/vendor/rails/actionmailer/Rakefile
vendored
|
|
@ -54,7 +54,7 @@ spec = Gem::Specification.new do |s|
|
||||||
s.rubyforge_project = "actionmailer"
|
s.rubyforge_project = "actionmailer"
|
||||||
s.homepage = "http://www.rubyonrails.org"
|
s.homepage = "http://www.rubyonrails.org"
|
||||||
|
|
||||||
s.add_dependency('actionpack', '= 1.13.3' + PKG_BUILD)
|
s.add_dependency('actionpack', '= 1.13.5' + PKG_BUILD)
|
||||||
|
|
||||||
s.has_rdoc = true
|
s.has_rdoc = true
|
||||||
s.requirements << 'none'
|
s.requirements << 'none'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ module ActionMailer
|
||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 1
|
MAJOR = 1
|
||||||
MINOR = 3
|
MINOR = 3
|
||||||
TINY = 3
|
TINY = 5
|
||||||
|
|
||||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||||
end
|
end
|
||||||
|
|
|
||||||
53
tracks/vendor/rails/actionpack/CHANGELOG
vendored
53
tracks/vendor/rails/actionpack/CHANGELOG
vendored
|
|
@ -1,6 +1,55 @@
|
||||||
|
*1.13.5* (October 12th, 2007)
|
||||||
|
|
||||||
|
* Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before. #6765, #7047, #7462 [bgipsy, Jeremy McAnally, Dan Kubb, brendan, Diego Algorta Casamayou]
|
||||||
|
|
||||||
|
* Fix in place editor's setter action with non-string fields. #7418 [Andreas]
|
||||||
|
|
||||||
|
|
||||||
|
*1.13.4* (October 4th, 2007)
|
||||||
|
|
||||||
|
* Only accept session ids from cookies, prevents session fixation attacks. [bradediger]
|
||||||
|
|
||||||
|
* Change the resource seperator from ; to / change the generated routes to use the new-style named routes. e.g. new_group_user_path(@group) instead of group_new_user_path(@group). [pixeltrix]
|
||||||
|
|
||||||
|
* Integration tests: introduce methods for other HTTP methods. #6353 [caboose]
|
||||||
|
|
||||||
|
* Improve performance of action caching. Closes #8231 [skaes]
|
||||||
|
|
||||||
|
* Fix errors with around_filters which do not yield, restore 1.1 behaviour with after filters. Closes #8891 [skaes]
|
||||||
|
|
||||||
|
After filters will *no longer* be run if an around_filter fails to yield, users relying on
|
||||||
|
this behaviour are advised to put the code in question after a yield statement in an around filter.
|
||||||
|
|
||||||
|
* Allow you to delete cookies with options. Closes #3685 [josh, Chris Wanstrath]
|
||||||
|
|
||||||
|
* Deprecate pagination. Install the classic_pagination plugin for forward compatibility, or move to the superior will_paginate plugin. #8157 [Mislav Marohnic]
|
||||||
|
|
||||||
|
* Fix filtered parameter logging with nil parameter values. #8422 [choonkeat]
|
||||||
|
|
||||||
|
* Integration tests: alias xhr to xml_http_request and add a request_method argument instead of always using POST. #7124 [Nik Wakelin, Francois Beausoleil, Wizard]
|
||||||
|
|
||||||
|
* Document caches_action. #5419 [Jarkko Laine]
|
||||||
|
|
||||||
|
* observe_form always sends the serialized form. #5271 [manfred, normelton@gmail.com]
|
||||||
|
|
||||||
|
* Update UrlWriter to accept :anchor parameter. Closes #6771. [octopod]
|
||||||
|
|
||||||
|
* Replace the current block/continuation filter chain handling by an implementation based on a simple loop. Closes #8226 [Stefan Kaes]
|
||||||
|
|
||||||
|
* Return the string representation from an Xml Builder when rendering a partial. #5044 [tpope]
|
||||||
|
|
||||||
|
* Cleaned up, corrected, and mildly expanded ActionPack documentation. Closes #7190 [jeremymcanally]
|
||||||
|
|
||||||
|
* Small collection of ActionController documentation cleanups. Closes #7319 [jeremymcanally]
|
||||||
|
|
||||||
|
* Performance: patch cgi/session/pstore to require digest/md5 once rather than per #initialize. #7583 [Stefan Kaes]
|
||||||
|
|
||||||
|
* Deprecation: verification with :redirect_to => :named_route shouldn't be deprecated. #7525 [Justin French]
|
||||||
|
|
||||||
|
|
||||||
*1.13.3* (March 12th, 2007)
|
*1.13.3* (March 12th, 2007)
|
||||||
|
|
||||||
* Apply [5709] to stable.
|
* Fix a bug in Routing where a parameter taken from the path of the current request could not be used as a query parameter for the next. #6752 [Nicholas Seckar]
|
||||||
|
|
||||||
* session_enabled? works with session :off. #6680 [Catfish]
|
* session_enabled? works with session :off. #6680 [Catfish]
|
||||||
|
|
||||||
|
|
@ -440,7 +489,7 @@
|
||||||
|
|
||||||
* Avoid naming collision among compiled view methods. [Jeremy Kemper]
|
* Avoid naming collision among compiled view methods. [Jeremy Kemper]
|
||||||
|
|
||||||
* Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [mislav@nippur.irb.hr]
|
* Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [Mislav Marohnic]
|
||||||
|
|
||||||
* Determine the correct template_root for deeply nested components. #2841 [s.brink@web.de]
|
* Determine the correct template_root for deeply nested components. #2841 [s.brink@web.de]
|
||||||
|
|
||||||
|
|
|
||||||
2
tracks/vendor/rails/actionpack/Rakefile
vendored
2
tracks/vendor/rails/actionpack/Rakefile
vendored
|
|
@ -75,7 +75,7 @@ spec = Gem::Specification.new do |s|
|
||||||
s.has_rdoc = true
|
s.has_rdoc = true
|
||||||
s.requirements << 'none'
|
s.requirements << 'none'
|
||||||
|
|
||||||
s.add_dependency('activesupport', '= 1.4.2' + PKG_BUILD)
|
s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD)
|
||||||
|
|
||||||
s.require_path = 'lib'
|
s.require_path = 'lib'
|
||||||
s.autorequire = 'action_controller'
|
s.autorequire = 'action_controller'
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
module ActionController
|
module ActionController
|
||||||
module Assertions
|
module Assertions
|
||||||
module DomAssertions
|
module DomAssertions
|
||||||
# test 2 html strings to be equivalent, i.e. identical up to reordering of attributes
|
# Test two HTML strings for equivalency (e.g., identical up to reordering of attributes)
|
||||||
def assert_dom_equal(expected, actual, message="")
|
def assert_dom_equal(expected, actual, message="")
|
||||||
clean_backtrace do
|
clean_backtrace do
|
||||||
expected_dom = HTML::Document.new(expected).root
|
expected_dom = HTML::Document.new(expected).root
|
||||||
|
|
@ -11,7 +11,7 @@ module ActionController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# negated form of +assert_dom_equivalent+
|
# The negated form of +assert_dom_equivalent+.
|
||||||
def assert_dom_not_equal(expected, actual, message="")
|
def assert_dom_not_equal(expected, actual, message="")
|
||||||
clean_backtrace do
|
clean_backtrace do
|
||||||
expected_dom = HTML::Document.new(expected).root
|
expected_dom = HTML::Document.new(expected).root
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
module ActionController
|
module ActionController
|
||||||
module Assertions
|
module Assertions
|
||||||
module ModelAssertions
|
module ModelAssertions
|
||||||
# ensures that the passed record is valid by active record standards. returns the error messages if not
|
# Ensures that the passed record is valid by ActiveRecord standards and returns any error messages if it is not.
|
||||||
def assert_valid(record)
|
def assert_valid(record)
|
||||||
clean_backtrace do
|
clean_backtrace do
|
||||||
assert record.valid?, record.errors.full_messages.join("\n")
|
assert record.valid?, record.errors.full_messages.join("\n")
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
if value.respond_to?(:[]) && value['controller']
|
if value.respond_to?(:[]) && value['controller']
|
||||||
|
value['controller'] = value['controller'].to_s
|
||||||
if key == :actual && value['controller'].first != '/' && !value['controller'].include?('/')
|
if key == :actual && value['controller'].first != '/' && !value['controller'].include?('/')
|
||||||
new_controller_path = ActionController::Routing.controller_relative_to(value['controller'], @controller.class.controller_path)
|
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)
|
||||||
|
|
@ -120,6 +121,7 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
# Recognizes the route for a given path.
|
||||||
def recognized_request_for(path, request_method = nil)
|
def recognized_request_for(path, request_method = nil)
|
||||||
path = "/#{path}" unless path.first == '/'
|
path = "/#{path}" unless path.first == '/'
|
||||||
|
|
||||||
|
|
@ -132,6 +134,7 @@ module ActionController
|
||||||
request
|
request
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Proxy to to_param if the object will respond to it.
|
||||||
def parameterize(value)
|
def parameterize(value)
|
||||||
value.respond_to?(:to_param) ? value.to_param : value
|
value.respond_to?(:to_param) ? value.to_param : value
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
# Recognizes the route for a given path.
|
||||||
def recognized_request_for(path, request_method = nil)
|
def recognized_request_for(path, request_method = nil)
|
||||||
path = "/#{path}" unless path.first == '/'
|
path = "/#{path}" unless path.first == '/'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -561,6 +561,8 @@ module ActionController
|
||||||
# RJS encodes double quotes and line breaks.
|
# RJS encodes double quotes and line breaks.
|
||||||
unescaped= rjs_string.gsub('\"', '"')
|
unescaped= rjs_string.gsub('\"', '"')
|
||||||
unescaped.gsub!('\n', "\n")
|
unescaped.gsub!('\n', "\n")
|
||||||
|
unescaped.gsub!('\076', '>')
|
||||||
|
unescaped.gsub!('\074', '<')
|
||||||
# RJS encodes non-ascii characters.
|
# RJS encodes non-ascii characters.
|
||||||
unescaped.gsub!(RJS_PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')}
|
unescaped.gsub!(RJS_PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')}
|
||||||
unescaped
|
unescaped
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,10 @@ module ActionController #:nodoc:
|
||||||
# Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates.
|
# Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates.
|
||||||
cattr_accessor :ignore_missing_templates
|
cattr_accessor :ignore_missing_templates
|
||||||
|
|
||||||
|
# Controls the resource action separator
|
||||||
|
@@resource_action_separator = "/"
|
||||||
|
cattr_accessor :resource_action_separator
|
||||||
|
|
||||||
# Holds the request object that's primarily used to get environment variables through access like
|
# Holds the request object that's primarily used to get environment variables through access like
|
||||||
# <tt>request.env["REQUEST_URI"]</tt>.
|
# <tt>request.env["REQUEST_URI"]</tt>.
|
||||||
attr_internal :request
|
attr_internal :request
|
||||||
|
|
@ -393,7 +397,8 @@ module ActionController #:nodoc:
|
||||||
elsif value.is_a?(Hash)
|
elsif value.is_a?(Hash)
|
||||||
filtered_parameters[key] = filter_parameters(value)
|
filtered_parameters[key] = filter_parameters(value)
|
||||||
elsif block_given?
|
elsif block_given?
|
||||||
key, value = key.dup, value.dup
|
key = key.dup
|
||||||
|
value = value.dup if value
|
||||||
yield key, value
|
yield key, value
|
||||||
filtered_parameters[key] = value
|
filtered_parameters[key] = value
|
||||||
else
|
else
|
||||||
|
|
@ -538,6 +543,7 @@ module ActionController #:nodoc:
|
||||||
self.class.controller_path
|
self.class.controller_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Test whether the session is enabled for this request.
|
||||||
def session_enabled?
|
def session_enabled?
|
||||||
request.session_options && request.session_options[:disabled] != false
|
request.session_options && request.session_options[:disabled] != false
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'uri'
|
require 'uri'
|
||||||
|
require 'set'
|
||||||
|
|
||||||
module ActionController #:nodoc:
|
module ActionController #:nodoc:
|
||||||
# Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls
|
# Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls
|
||||||
|
|
@ -163,13 +164,24 @@ module ActionController #:nodoc:
|
||||||
module Actions
|
module Actions
|
||||||
def self.included(base) #:nodoc:
|
def self.included(base) #:nodoc:
|
||||||
base.extend(ClassMethods)
|
base.extend(ClassMethods)
|
||||||
base.send(:attr_accessor, :rendered_action_cache)
|
base.class_eval do
|
||||||
|
attr_accessor :rendered_action_cache, :action_cache_path
|
||||||
|
alias_method_chain :protected_instance_variables, :action_caching
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module ClassMethods #:nodoc:
|
def protected_instance_variables_with_action_caching
|
||||||
|
protected_instance_variables_without_action_caching + %w(@action_cache_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
# Declares that +actions+ should be cached.
|
||||||
|
# See ActionController::Caching::Actions for details.
|
||||||
def caches_action(*actions)
|
def caches_action(*actions)
|
||||||
return unless perform_caching
|
return unless perform_caching
|
||||||
around_filter(ActionCacheFilter.new(*actions))
|
action_cache_filter = ActionCacheFilter.new(*actions)
|
||||||
|
before_filter action_cache_filter
|
||||||
|
after_filter action_cache_filter
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -185,70 +197,59 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
class ActionCacheFilter #:nodoc:
|
class ActionCacheFilter #:nodoc:
|
||||||
def initialize(*actions, &block)
|
def initialize(*actions)
|
||||||
@actions = actions
|
@actions = Set.new actions
|
||||||
end
|
end
|
||||||
|
|
||||||
def before(controller)
|
def before(controller)
|
||||||
return unless @actions.include?(controller.action_name.intern)
|
return unless @actions.include?(controller.action_name.to_sym)
|
||||||
action_cache_path = ActionCachePath.new(controller)
|
cache_path = ActionCachePath.new(controller, {})
|
||||||
if cache = controller.read_fragment(action_cache_path.path)
|
if cache = controller.read_fragment(cache_path.path)
|
||||||
controller.rendered_action_cache = true
|
controller.rendered_action_cache = true
|
||||||
set_content_type!(action_cache_path)
|
set_content_type!(controller, cache_path.extension)
|
||||||
controller.send(:render_text, cache)
|
controller.send(:render_text, cache)
|
||||||
false
|
false
|
||||||
|
else
|
||||||
|
controller.action_cache_path = cache_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def after(controller)
|
def after(controller)
|
||||||
return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache
|
return if !@actions.include?(controller.action_name.to_sym) || controller.rendered_action_cache
|
||||||
controller.write_fragment(ActionCachePath.path_for(controller), controller.response.body)
|
controller.write_fragment(controller.action_cache_path.path, controller.response.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
def set_content_type!(controller, extension)
|
||||||
def set_content_type!(action_cache_path)
|
controller.response.content_type = Mime::EXTENSION_LOOKUP[extension].to_s if extension
|
||||||
if extention = action_cache_path.extension
|
|
||||||
content_type = Mime::EXTENSION_LOOKUP[extention]
|
|
||||||
action_cache_path.controller.response.content_type = content_type.to_s
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class ActionCachePath
|
class ActionCachePath
|
||||||
attr_reader :controller, :options
|
attr_reader :path, :extension
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def path_for(*args, &block)
|
def path_for(controller, options)
|
||||||
new(*args).path
|
new(controller, options).path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(controller, options = {})
|
def initialize(controller, options = {})
|
||||||
@controller = controller
|
@extension = extract_extension(controller.request.path)
|
||||||
@options = options
|
path = controller.url_for(options).split('://').last
|
||||||
end
|
normalize!(path)
|
||||||
|
add_extension!(path, @extension)
|
||||||
def path
|
@path = URI.unescape(path)
|
||||||
return @path if @path
|
|
||||||
@path = controller.url_for(options).split('://').last
|
|
||||||
normalize!
|
|
||||||
add_extension!
|
|
||||||
URI.unescape(@path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def extension
|
|
||||||
@extension ||= extract_extension(controller.request.path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def normalize!
|
def normalize!(path)
|
||||||
@path << 'index' if @path.last == '/'
|
path << 'index' if path[-1] == ?/
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_extension!
|
def add_extension!(path, extension)
|
||||||
@path << ".#{extension}" if extension
|
path << ".#{extension}" if extension
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_extension(file_path)
|
def extract_extension(file_path)
|
||||||
|
|
|
||||||
30
tracks/vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb
vendored
Normal file
30
tracks/vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
# CGI::Session::PStore.initialize requires 'digest/md5' on every call.
|
||||||
|
# This makes sense when spawning processes per request, but is
|
||||||
|
# unnecessarily expensive when serving requests from a long-lived
|
||||||
|
# process.
|
||||||
|
require 'cgi/session'
|
||||||
|
require 'cgi/session/pstore'
|
||||||
|
require 'digest/md5'
|
||||||
|
|
||||||
|
class CGI::Session::PStore #:nodoc:
|
||||||
|
def initialize(session, option={})
|
||||||
|
dir = option['tmpdir'] || Dir::tmpdir
|
||||||
|
prefix = option['prefix'] || ''
|
||||||
|
id = session.session_id
|
||||||
|
md5 = Digest::MD5.hexdigest(id)[0,16]
|
||||||
|
path = dir+"/"+prefix+md5
|
||||||
|
path.untaint
|
||||||
|
if File::exist?(path)
|
||||||
|
@hash = nil
|
||||||
|
else
|
||||||
|
unless session.new_session
|
||||||
|
raise CGI::Session::NoSession, "uninitialized session"
|
||||||
|
end
|
||||||
|
@hash = {}
|
||||||
|
end
|
||||||
|
@p = ::PStore.new(path)
|
||||||
|
@p.transaction do |p|
|
||||||
|
File.chmod(0600, p.path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -65,7 +65,7 @@ class CGI #:nodoc:
|
||||||
if env_qs.blank? && !(uri = env_table['REQUEST_URI']).blank?
|
if env_qs.blank? && !(uri = env_table['REQUEST_URI']).blank?
|
||||||
uri.split('?', 2)[1] || ''
|
uri.split('?', 2)[1] || ''
|
||||||
else
|
else
|
||||||
env_qs
|
env_qs || ''
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ require 'action_controller/cgi_ext/cgi_ext'
|
||||||
require 'action_controller/cgi_ext/cookie_performance_fix'
|
require 'action_controller/cgi_ext/cookie_performance_fix'
|
||||||
require 'action_controller/cgi_ext/raw_post_data_fix'
|
require 'action_controller/cgi_ext/raw_post_data_fix'
|
||||||
require 'action_controller/cgi_ext/session_performance_fix'
|
require 'action_controller/cgi_ext/session_performance_fix'
|
||||||
|
require 'action_controller/cgi_ext/pstore_performance_fix'
|
||||||
|
|
||||||
module ActionController #:nodoc:
|
module ActionController #:nodoc:
|
||||||
class Base
|
class Base
|
||||||
|
|
@ -12,8 +13,8 @@ module ActionController #:nodoc:
|
||||||
# (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in
|
# (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in
|
||||||
# lib/action_controller/session.
|
# lib/action_controller/session.
|
||||||
# * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'.
|
# * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'.
|
||||||
# * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ parameter
|
# * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ cookie, or
|
||||||
# of the request, or automatically generated for a new session.
|
# automatically generated for a new session.
|
||||||
# * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
|
# * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently
|
||||||
# exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
|
# exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set,
|
||||||
# an ArgumentError is raised.
|
# an ArgumentError is raised.
|
||||||
|
|
@ -23,6 +24,8 @@ module ActionController #:nodoc:
|
||||||
# server.
|
# server.
|
||||||
# * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS.
|
# * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS.
|
||||||
# * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script.
|
# * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script.
|
||||||
|
# * <tt>:cookie_only</tt> - if +true+ (the default), session IDs will only be accepted from cookies and not from
|
||||||
|
# the query string or POST parameters. This protects against session fixation attacks.
|
||||||
def self.process_cgi(cgi = CGI.new, session_options = {})
|
def self.process_cgi(cgi = CGI.new, session_options = {})
|
||||||
new.process_cgi(cgi, session_options)
|
new.process_cgi(cgi, session_options)
|
||||||
end
|
end
|
||||||
|
|
@ -33,18 +36,21 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
class CgiRequest < AbstractRequest #:nodoc:
|
class CgiRequest < AbstractRequest #:nodoc:
|
||||||
attr_accessor :cgi, :session_options
|
attr_accessor :cgi, :session_options, :cookie_only
|
||||||
|
class SessionFixationAttempt < StandardError; end #:nodoc:
|
||||||
|
|
||||||
DEFAULT_SESSION_OPTIONS = {
|
DEFAULT_SESSION_OPTIONS = {
|
||||||
:database_manager => CGI::Session::PStore,
|
:database_manager => CGI::Session::PStore,
|
||||||
:prefix => "ruby_sess.",
|
:prefix => "ruby_sess.",
|
||||||
:session_path => "/"
|
:session_path => "/",
|
||||||
|
:cookie_only => true
|
||||||
} unless const_defined?(:DEFAULT_SESSION_OPTIONS)
|
} unless const_defined?(:DEFAULT_SESSION_OPTIONS)
|
||||||
|
|
||||||
def initialize(cgi, session_options = {})
|
def initialize(cgi, session_options = {})
|
||||||
@cgi = cgi
|
@cgi = cgi
|
||||||
@session_options = session_options
|
@session_options = session_options
|
||||||
@env = @cgi.send(:env_table)
|
@env = @cgi.send(:env_table)
|
||||||
|
@cookie_only = session_options.delete :cookie_only
|
||||||
super()
|
super()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -108,6 +114,9 @@ module ActionController #:nodoc:
|
||||||
@session = Hash.new
|
@session = Hash.new
|
||||||
else
|
else
|
||||||
stale_session_check! do
|
stale_session_check! do
|
||||||
|
if @cookie_only && request_parameters[session_options_with_string_keys['session_key']]
|
||||||
|
raise SessionFixationAttempt
|
||||||
|
end
|
||||||
case value = session_options_with_string_keys['new_session']
|
case value = session_options_with_string_keys['new_session']
|
||||||
when true
|
when true
|
||||||
@session = new_session
|
@session = new_session
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,11 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
# Removes the cookie on the client machine by setting the value to an empty string
|
# Removes the cookie on the client machine by setting the value to an empty string
|
||||||
# and setting its expiration date into the past
|
# and setting its expiration date into the past. Like []=, you can pass in an options
|
||||||
def delete(name)
|
# hash to delete cookies with extra data such as a +path+.
|
||||||
set_cookie("name" => name.to_s, "value" => "", "expires" => Time.at(0))
|
def delete(name, options = {})
|
||||||
|
options.stringify_keys!
|
||||||
|
set_cookie(options.merge("name" => name.to_s, "value" => "", "expires" => Time.at(0)))
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
||||||
|
|
@ -214,9 +214,10 @@ module ActionController #:nodoc:
|
||||||
# == Filter Chain Halting
|
# == Filter Chain Halting
|
||||||
#
|
#
|
||||||
# <tt>before_filter</tt> and <tt>around_filter</tt> may halt the request
|
# <tt>before_filter</tt> and <tt>around_filter</tt> may halt the request
|
||||||
# before controller action is run. This is useful, for example, to deny
|
# before a controller action is run. This is useful, for example, to deny
|
||||||
# access to unauthenticated users or to redirect from http to https.
|
# access to unauthenticated users or to redirect from http to https.
|
||||||
# Simply return false from the filter or call render or redirect.
|
# Simply return false from the filter or call render or redirect.
|
||||||
|
# After filters will not be executed if the filter chain is halted.
|
||||||
#
|
#
|
||||||
# Around filters halt the request unless the action block is called.
|
# Around filters halt the request unless the action block is called.
|
||||||
# Given these filters
|
# Given these filters
|
||||||
|
|
@ -238,12 +239,12 @@ module ActionController #:nodoc:
|
||||||
# . . /
|
# . . /
|
||||||
# . #around (code after yield)
|
# . #around (code after yield)
|
||||||
# . /
|
# . /
|
||||||
# #after (actual filter code is run)
|
# #after (actual filter code is run, unless the around filter does not yield)
|
||||||
#
|
#
|
||||||
# If #around returns before yielding, only #after will be run. The #before
|
# If #around returns before yielding, #after will still not be run. The #before
|
||||||
# filter and controller action will not be run. If #before returns false,
|
# filter and controller action will not be run. If #before returns false,
|
||||||
# the second half of #around and all of #after will still run but the
|
# the second half of #around and will still run but #after and the
|
||||||
# action will not.
|
# action will not. If #around does not yield, #after will not be run.
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
# The passed <tt>filters</tt> will be appended to the filter_chain and
|
# The passed <tt>filters</tt> will be appended to the filter_chain and
|
||||||
# will execute before the action on this controller is performed.
|
# will execute before the action on this controller is performed.
|
||||||
|
|
@ -263,13 +264,13 @@ module ActionController #:nodoc:
|
||||||
# The passed <tt>filters</tt> will be appended to the array of filters
|
# The passed <tt>filters</tt> will be appended to the array of filters
|
||||||
# that run _after_ actions on this controller are performed.
|
# that run _after_ actions on this controller are performed.
|
||||||
def append_after_filter(*filters, &block)
|
def append_after_filter(*filters, &block)
|
||||||
prepend_filter_to_chain(filters, :after, &block)
|
append_filter_to_chain(filters, :after, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# The passed <tt>filters</tt> will be prepended to the array of filters
|
# The passed <tt>filters</tt> will be prepended to the array of filters
|
||||||
# that run _after_ actions on this controller are performed.
|
# that run _after_ actions on this controller are performed.
|
||||||
def prepend_after_filter(*filters, &block)
|
def prepend_after_filter(*filters, &block)
|
||||||
append_filter_to_chain(filters, :after, &block)
|
prepend_filter_to_chain(filters, :after, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Shorthand for append_after_filter since it's the most common.
|
# Shorthand for append_after_filter since it's the most common.
|
||||||
|
|
@ -362,12 +363,12 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
# Returns a mapping between filters and the actions that may run them.
|
# Returns a mapping between filters and the actions that may run them.
|
||||||
def included_actions #:nodoc:
|
def included_actions #:nodoc:
|
||||||
read_inheritable_attribute("included_actions") || {}
|
@included_actions ||= read_inheritable_attribute("included_actions") || {}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a mapping between filters and actions that may not run them.
|
# Returns a mapping between filters and actions that may not run them.
|
||||||
def excluded_actions #:nodoc:
|
def excluded_actions #:nodoc:
|
||||||
read_inheritable_attribute("excluded_actions") || {}
|
@excluded_actions ||= read_inheritable_attribute("excluded_actions") || {}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Find a filter in the filter_chain where the filter method matches the _filter_ param
|
# Find a filter in the filter_chain where the filter method matches the _filter_ param
|
||||||
|
|
@ -381,10 +382,11 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
# Returns true if the filter is excluded from the given action
|
# Returns true if the filter is excluded from the given action
|
||||||
def filter_excluded_from_action?(filter,action) #:nodoc:
|
def filter_excluded_from_action?(filter,action) #:nodoc:
|
||||||
if (ia = included_actions[filter]) && !ia.empty?
|
case
|
||||||
|
when ia = included_actions[filter]
|
||||||
!ia.include?(action)
|
!ia.include?(action)
|
||||||
else
|
when ea = excluded_actions[filter]
|
||||||
(excluded_actions[filter] || []).include?(action)
|
ea.include?(action)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -397,20 +399,28 @@ module ActionController #:nodoc:
|
||||||
@filter = filter
|
@filter = filter
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def type
|
||||||
|
:around
|
||||||
|
end
|
||||||
|
|
||||||
def before?
|
def before?
|
||||||
false
|
type == :before
|
||||||
end
|
end
|
||||||
|
|
||||||
def after?
|
def after?
|
||||||
false
|
type == :after
|
||||||
end
|
end
|
||||||
|
|
||||||
def around?
|
def around?
|
||||||
true
|
type == :around
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(controller)
|
||||||
|
raise ActionControllerError, 'No filter type: Nothing to do here.'
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(controller, &block)
|
def call(controller, &block)
|
||||||
raise(ActionControllerError, 'No filter type: Nothing to do here.')
|
run(controller)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -420,35 +430,38 @@ module ActionController #:nodoc:
|
||||||
def filter
|
def filter
|
||||||
@filter.filter
|
@filter.filter
|
||||||
end
|
end
|
||||||
|
|
||||||
def around?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class BeforeFilterProxy < FilterProxy #:nodoc:
|
class BeforeFilterProxy < FilterProxy #:nodoc:
|
||||||
def before?
|
def type
|
||||||
true
|
:before
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(controller, &block)
|
def run(controller)
|
||||||
if false == @filter.call(controller) # must only stop if equal to false. only filters returning false are halted.
|
# only filters returning false are halted.
|
||||||
controller.halt_filter_chain(@filter, :returned_false)
|
if false == @filter.call(controller)
|
||||||
else
|
controller.send :halt_filter_chain, @filter, :returned_false
|
||||||
yield
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def call(controller)
|
||||||
|
yield unless run(controller)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AfterFilterProxy < FilterProxy #:nodoc:
|
class AfterFilterProxy < FilterProxy #:nodoc:
|
||||||
def after?
|
def type
|
||||||
true
|
:after
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(controller, &block)
|
def run(controller)
|
||||||
yield
|
|
||||||
@filter.call(controller)
|
@filter.call(controller)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def call(controller)
|
||||||
|
yield
|
||||||
|
run(controller)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class SymbolFilter < Filter #:nodoc:
|
class SymbolFilter < Filter #:nodoc:
|
||||||
|
|
@ -485,29 +498,72 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class ClassBeforeFilter < Filter #:nodoc:
|
||||||
|
def call(controller, &block)
|
||||||
|
@filter.before(controller)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ClassAfterFilter < Filter #:nodoc:
|
||||||
|
def call(controller, &block)
|
||||||
|
@filter.after(controller)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def append_filter_to_chain(filters, position = :around, &block)
|
def append_filter_to_chain(filters, filter_type = :around, &block)
|
||||||
write_inheritable_array('filter_chain', create_filters(filters, position, &block) )
|
pos = find_filter_append_position(filters, filter_type)
|
||||||
|
update_filter_chain(filters, filter_type, pos, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepend_filter_to_chain(filters, position = :around, &block)
|
def prepend_filter_to_chain(filters, filter_type = :around, &block)
|
||||||
write_inheritable_attribute('filter_chain', create_filters(filters, position, &block) + filter_chain)
|
pos = find_filter_prepend_position(filters, filter_type)
|
||||||
|
update_filter_chain(filters, filter_type, pos, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_filters(filters, position, &block) #:nodoc:
|
def update_filter_chain(filters, filter_type, pos, &block)
|
||||||
|
new_filters = create_filters(filters, filter_type, &block)
|
||||||
|
new_chain = filter_chain.insert(pos, new_filters).flatten
|
||||||
|
write_inheritable_attribute('filter_chain', new_chain)
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_filter_append_position(filters, filter_type)
|
||||||
|
# appending an after filter puts it at the end of the call chain
|
||||||
|
# before and around filters go before the first after filter in the chain
|
||||||
|
unless filter_type == :after
|
||||||
|
filter_chain.each_with_index do |f,i|
|
||||||
|
return i if f.after?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_filter_prepend_position(filters, filter_type)
|
||||||
|
# prepending a before or around filter puts it at the front of the call chain
|
||||||
|
# after filters go before the first after filter in the chain
|
||||||
|
if filter_type == :after
|
||||||
|
filter_chain.each_with_index do |f,i|
|
||||||
|
return i if f.after?
|
||||||
|
end
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_filters(filters, filter_type, &block) #:nodoc:
|
||||||
filters, conditions = extract_conditions(filters, &block)
|
filters, conditions = extract_conditions(filters, &block)
|
||||||
filters.map! { |filter| find_or_create_filter(filter,position) }
|
filters.map! { |filter| find_or_create_filter(filter, filter_type) }
|
||||||
update_conditions(filters, conditions)
|
update_conditions(filters, conditions)
|
||||||
filters
|
filters
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_or_create_filter(filter,position)
|
def find_or_create_filter(filter, filter_type)
|
||||||
if found_filter = find_filter(filter) { |f| f.send("#{position}?") }
|
if found_filter = find_filter(filter) { |f| f.type == filter_type }
|
||||||
found_filter
|
found_filter
|
||||||
else
|
else
|
||||||
f = class_for_filter(filter).new(filter)
|
f = class_for_filter(filter, filter_type).new(filter)
|
||||||
# apply proxy to filter if necessary
|
# apply proxy to filter if necessary
|
||||||
case position
|
case filter_type
|
||||||
when :before
|
when :before
|
||||||
BeforeFilterProxy.new(f)
|
BeforeFilterProxy.new(f)
|
||||||
when :after
|
when :after
|
||||||
|
|
@ -520,7 +576,7 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
# The determination of the filter type was once done at run time.
|
# The determination of the filter type was once done at run time.
|
||||||
# This method is here to extract as much logic from the filter run time as possible
|
# This method is here to extract as much logic from the filter run time as possible
|
||||||
def class_for_filter(filter) #:nodoc:
|
def class_for_filter(filter, filter_type) #:nodoc:
|
||||||
case
|
case
|
||||||
when filter.is_a?(Symbol)
|
when filter.is_a?(Symbol)
|
||||||
SymbolFilter
|
SymbolFilter
|
||||||
|
|
@ -534,8 +590,12 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
when filter.respond_to?(:filter)
|
when filter.respond_to?(:filter)
|
||||||
ClassFilter
|
ClassFilter
|
||||||
|
when filter.respond_to?(:before) && filter_type == :before
|
||||||
|
ClassBeforeFilter
|
||||||
|
when filter.respond_to?(:after) && filter_type == :after
|
||||||
|
ClassAfterFilter
|
||||||
else
|
else
|
||||||
raise(ActionControllerError, 'A filters must be a Symbol, Proc, Method, or object responding to filter.')
|
raise(ActionControllerError, 'A filter must be a Symbol, Proc, Method, or object responding to filter, after or before.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -550,8 +610,8 @@ module ActionController #:nodoc:
|
||||||
return if conditions.empty?
|
return if conditions.empty?
|
||||||
if conditions[:only]
|
if conditions[:only]
|
||||||
write_inheritable_hash('included_actions', condition_hash(filters, conditions[:only]))
|
write_inheritable_hash('included_actions', condition_hash(filters, conditions[:only]))
|
||||||
else
|
elsif conditions[:except]
|
||||||
write_inheritable_hash('excluded_actions', condition_hash(filters, conditions[:except])) if conditions[:except]
|
write_inheritable_hash('excluded_actions', condition_hash(filters, conditions[:except]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -576,9 +636,9 @@ module ActionController #:nodoc:
|
||||||
|
|
||||||
def remove_actions_from_included_actions!(filters,*actions)
|
def remove_actions_from_included_actions!(filters,*actions)
|
||||||
actions = actions.flatten.map(&:to_s)
|
actions = actions.flatten.map(&:to_s)
|
||||||
updated_hash = filters.inject(included_actions) do |hash,filter|
|
updated_hash = filters.inject(read_inheritable_attribute('included_actions')||{}) do |hash,filter|
|
||||||
ia = (hash[filter] || []) - actions
|
ia = (hash[filter] || []) - actions
|
||||||
ia.blank? ? hash.delete(filter) : hash[filter] = ia
|
ia.empty? ? hash.delete(filter) : hash[filter] = ia
|
||||||
hash
|
hash
|
||||||
end
|
end
|
||||||
write_inheritable_attribute('included_actions', updated_hash)
|
write_inheritable_attribute('included_actions', updated_hash)
|
||||||
|
|
@ -595,7 +655,9 @@ module ActionController #:nodoc:
|
||||||
def proxy_before_and_after_filter(filter) #:nodoc:
|
def proxy_before_and_after_filter(filter) #:nodoc:
|
||||||
return filter unless filter_responds_to_before_and_after(filter)
|
return filter unless filter_responds_to_before_and_after(filter)
|
||||||
Proc.new do |controller, action|
|
Proc.new do |controller, action|
|
||||||
unless filter.before(controller) == false
|
if filter.before(controller) == false
|
||||||
|
controller.send :halt_filter_chain, filter, :returned_false
|
||||||
|
else
|
||||||
begin
|
begin
|
||||||
action.call
|
action.call
|
||||||
ensure
|
ensure
|
||||||
|
|
@ -615,53 +677,90 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_action_with_filters
|
protected
|
||||||
call_filter(self.class.filter_chain, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_with_filters(request, response, method = :perform_action, *arguments) #:nodoc:
|
def process_with_filters(request, response, method = :perform_action, *arguments) #:nodoc:
|
||||||
@before_filter_chain_aborted = false
|
@before_filter_chain_aborted = false
|
||||||
process_without_filters(request, response, method, *arguments)
|
process_without_filters(request, response, method, *arguments)
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_chain
|
def perform_action_with_filters
|
||||||
self.class.filter_chain
|
call_filters(self.class.filter_chain, 0, 0)
|
||||||
end
|
|
||||||
|
|
||||||
def call_filter(chain, index)
|
|
||||||
return (performed? || perform_action_without_filters) if index >= chain.size
|
|
||||||
filter = chain[index]
|
|
||||||
return call_filter(chain, index.next) if self.class.filter_excluded_from_action?(filter,action_name)
|
|
||||||
|
|
||||||
halted = false
|
|
||||||
filter.call(self) do
|
|
||||||
halted = call_filter(chain, index.next)
|
|
||||||
end
|
|
||||||
halt_filter_chain(filter.filter, :no_yield) if halted == false unless @before_filter_chain_aborted
|
|
||||||
halted
|
|
||||||
end
|
|
||||||
|
|
||||||
def halt_filter_chain(filter, reason)
|
|
||||||
if logger
|
|
||||||
case reason
|
|
||||||
when :no_yield
|
|
||||||
logger.info "Filter chain halted as [#{filter.inspect}] did not yield."
|
|
||||||
when :returned_false
|
|
||||||
logger.info "Filter chain halted as [#{filter.inspect}] returned false."
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@before_filter_chain_aborted = true
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def process_cleanup_with_filters
|
|
||||||
if @before_filter_chain_aborted
|
def call_filters(chain, index, nesting)
|
||||||
close_session
|
index = run_before_filters(chain, index, nesting)
|
||||||
|
aborted = @before_filter_chain_aborted
|
||||||
|
perform_action_without_filters unless performed? || aborted
|
||||||
|
return index if nesting != 0 || aborted
|
||||||
|
run_after_filters(chain, index)
|
||||||
|
end
|
||||||
|
|
||||||
|
def skip_excluded_filters(chain, index)
|
||||||
|
while (filter = chain[index]) && self.class.filter_excluded_from_action?(filter, action_name)
|
||||||
|
index = index.next
|
||||||
|
end
|
||||||
|
[filter, index]
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_before_filters(chain, index, nesting)
|
||||||
|
while chain[index]
|
||||||
|
filter, index = skip_excluded_filters(chain, index)
|
||||||
|
break unless filter # end of call chain reached
|
||||||
|
case filter.type
|
||||||
|
when :before
|
||||||
|
filter.run(self) # invoke before filter
|
||||||
|
index = index.next
|
||||||
|
break if @before_filter_chain_aborted
|
||||||
|
when :around
|
||||||
|
yielded = false
|
||||||
|
filter.call(self) do
|
||||||
|
yielded = true
|
||||||
|
# all remaining before and around filters will be run in this call
|
||||||
|
index = call_filters(chain, index.next, nesting.next)
|
||||||
|
end
|
||||||
|
halt_filter_chain(filter, :did_not_yield) unless yielded
|
||||||
|
break
|
||||||
else
|
else
|
||||||
process_cleanup_without_filters
|
break # no before or around filters left
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
index
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_after_filters(chain, index)
|
||||||
|
seen_after_filter = false
|
||||||
|
while chain[index]
|
||||||
|
filter, index = skip_excluded_filters(chain, index)
|
||||||
|
break unless filter # end of call chain reached
|
||||||
|
case filter.type
|
||||||
|
when :after
|
||||||
|
seen_after_filter = true
|
||||||
|
filter.run(self) # invoke after filter
|
||||||
|
else
|
||||||
|
# implementation error or someone has mucked with the filter chain
|
||||||
|
raise ActionControllerError, "filter #{filter.inspect} was in the wrong place!" if seen_after_filter
|
||||||
|
end
|
||||||
|
index = index.next
|
||||||
|
end
|
||||||
|
index.next
|
||||||
|
end
|
||||||
|
|
||||||
|
def halt_filter_chain(filter, reason)
|
||||||
|
@before_filter_chain_aborted = true
|
||||||
|
logger.info "Filter chain halted as [#{filter.inspect}] #{reason}." if logger
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_cleanup_with_filters
|
||||||
|
if @before_filter_chain_aborted
|
||||||
|
close_session
|
||||||
|
else
|
||||||
|
process_cleanup_without_filters
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ module ActionController
|
||||||
@https = false
|
@https = false
|
||||||
@cookies = {}
|
@cookies = {}
|
||||||
@controller = @request = @response = nil
|
@controller = @request = @response = nil
|
||||||
|
|
||||||
self.host = "www.example.com"
|
self.host = "www.example.com"
|
||||||
self.remote_addr = "127.0.0.1"
|
self.remote_addr = "127.0.0.1"
|
||||||
self.accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
|
self.accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
|
||||||
|
|
@ -89,7 +89,7 @@ module ActionController
|
||||||
# session.https!
|
# session.https!
|
||||||
# session.https!(false)
|
# session.https!(false)
|
||||||
def https!(flag=true)
|
def https!(flag=true)
|
||||||
@https = flag
|
@https = flag
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return +true+ if the session is mimicing a secure HTTPS request.
|
# Return +true+ if the session is mimicing a secure HTTPS request.
|
||||||
|
|
@ -143,10 +143,10 @@ module ActionController
|
||||||
# Performs a GET request with the given parameters. The parameters may
|
# Performs a GET request with the given parameters. The parameters may
|
||||||
# be +nil+, a Hash, or a string that is appropriately encoded
|
# be +nil+, a Hash, or a string that is appropriately encoded
|
||||||
# (application/x-www-form-urlencoded or multipart/form-data). The headers
|
# (application/x-www-form-urlencoded or multipart/form-data). The headers
|
||||||
# should be a hash. The keys will automatically be upcased, with the
|
# should be a hash. The keys will automatically be upcased, with the
|
||||||
# prefix 'HTTP_' added if needed.
|
# prefix 'HTTP_' added if needed.
|
||||||
#
|
#
|
||||||
# You can also perform POST, PUT, DELETE, and HEAD requests with #post,
|
# You can also perform POST, PUT, DELETE, and HEAD requests with #post,
|
||||||
# #put, #delete, and #head.
|
# #put, #delete, and #head.
|
||||||
def get(path, parameters=nil, headers=nil)
|
def get(path, parameters=nil, headers=nil)
|
||||||
process :get, path, parameters, headers
|
process :get, path, parameters, headers
|
||||||
|
|
@ -161,31 +161,41 @@ module ActionController
|
||||||
def put(path, parameters=nil, headers=nil)
|
def put(path, parameters=nil, headers=nil)
|
||||||
process :put, path, parameters, headers
|
process :put, path, parameters, headers
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performs a DELETE request with the given parameters. See get() for more details.
|
# Performs a DELETE request with the given parameters. See get() for more details.
|
||||||
def delete(path, parameters=nil, headers=nil)
|
def delete(path, parameters=nil, headers=nil)
|
||||||
process :delete, path, parameters, headers
|
process :delete, path, parameters, headers
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performs a HEAD request with the given parameters. See get() for more details.
|
# Performs a HEAD request with the given parameters. See get() for more details.
|
||||||
def head(path, parameters=nil, headers=nil)
|
def head(path, parameters=nil, headers=nil)
|
||||||
process :head, path, parameters, headers
|
process :head, path, parameters, headers
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performs an XMLHttpRequest request with the given parameters, mimicing
|
# Performs an XMLHttpRequest request with the given parameters, mirroring
|
||||||
# the request environment created by the Prototype library. The parameters
|
# a request from the Prototype library.
|
||||||
# may be +nil+, a Hash, or a string that is appropriately encoded
|
#
|
||||||
# (application/x-www-form-urlencoded or multipart/form-data). The headers
|
# The request_method is :get, :post, :put, :delete or :head; the
|
||||||
# should be a hash. The keys will automatically be upcased, with the
|
# parameters are +nil+, a hash, or a url-encoded or multipart string;
|
||||||
# prefix 'HTTP_' added if needed.
|
# the headers are a hash. Keys are automatically upcased and prefixed
|
||||||
def xml_http_request(path, parameters=nil, headers=nil)
|
# with 'HTTP_' if not already.
|
||||||
headers = (headers || {}).merge(
|
#
|
||||||
"X-Requested-With" => "XMLHttpRequest",
|
# This method used to omit the request_method parameter, assuming it
|
||||||
"Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
|
# was :post. This was deprecated in Rails 1.2.4. Always pass the request
|
||||||
)
|
# method as the first argument.
|
||||||
|
def xml_http_request(request_method, path, parameters = nil, headers = nil)
|
||||||
|
unless request_method.is_a?(Symbol)
|
||||||
|
ActiveSupport::Deprecation.warn 'xml_http_request now takes the request_method (:get, :post, etc.) as the first argument. It used to assume :post, so add the :post argument to your existing method calls to silence this warning.'
|
||||||
|
request_method, path, parameters, headers = :post, request_method, path, parameters
|
||||||
|
end
|
||||||
|
|
||||||
post(path, parameters, headers)
|
headers ||= {}
|
||||||
|
headers['X-Requested-With'] = 'XMLHttpRequest'
|
||||||
|
headers['Accept'] = 'text/javascript, text/html, application/xml, text/xml, */*'
|
||||||
|
|
||||||
|
process(request_method, path, parameters, headers)
|
||||||
end
|
end
|
||||||
|
alias xhr :xml_http_request
|
||||||
|
|
||||||
# Returns the URL for the given options, according to the rules specified
|
# Returns the URL for the given options, according to the rules specified
|
||||||
# in the application's routes.
|
# in the application's routes.
|
||||||
|
|
@ -292,7 +302,7 @@ module ActionController
|
||||||
@status = @status.to_i
|
@status = @status.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
# Encode the cookies hash in a format suitable for passing to a
|
# Encode the cookies hash in a format suitable for passing to a
|
||||||
# request.
|
# request.
|
||||||
def encode_cookies
|
def encode_cookies
|
||||||
cookies.inject("") do |string, (name, value)|
|
cookies.inject("") do |string, (name, value)|
|
||||||
|
|
@ -450,7 +460,7 @@ module ActionController
|
||||||
# without any test methods.
|
# without any test methods.
|
||||||
def run(*args) #:nodoc:
|
def run(*args) #:nodoc:
|
||||||
return if @method_name == "default_test"
|
return if @method_name == "default_test"
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
# Because of how use_instantiated_fixtures and use_transactional_fixtures
|
# Because of how use_instantiated_fixtures and use_transactional_fixtures
|
||||||
|
|
@ -490,7 +500,7 @@ module ActionController
|
||||||
@integration_session = open_session
|
@integration_session = open_session
|
||||||
end
|
end
|
||||||
|
|
||||||
%w(get post cookies assigns xml_http_request).each do |method|
|
%w(get post put head delete cookies assigns xml_http_request).each do |method|
|
||||||
define_method(method) do |*args|
|
define_method(method) do |*args|
|
||||||
reset! unless @integration_session
|
reset! unless @integration_session
|
||||||
# reset the html_document variable, but only for new get/post calls
|
# reset the html_document variable, but only for new get/post calls
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ module ActionController
|
||||||
define_method("set_#{object}_#{attribute}") do
|
define_method("set_#{object}_#{attribute}") do
|
||||||
@item = object.to_s.camelize.constantize.find(params[:id])
|
@item = object.to_s.camelize.constantize.find(params[:id])
|
||||||
@item.update_attribute(attribute, params[:value])
|
@item.update_attribute(attribute, params[:value])
|
||||||
render :text => @item.send(attribute)
|
render :text => @item.send(attribute).to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
module ActionController
|
module ActionController
|
||||||
# === Action Pack pagination for Active Record collections
|
# === Action Pack pagination for Active Record collections
|
||||||
#
|
#
|
||||||
# DEPRECATION WARNING: Pagination will be separated into its own plugin with Rails 2.0.
|
# DEPRECATION WARNING: Pagination will be moved to a plugin in Rails 2.0.
|
||||||
|
# Install the classic_pagination plugin for forward compatibility:
|
||||||
|
# script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination
|
||||||
#
|
#
|
||||||
# The Pagination module aids in the process of paging large collections of
|
# The Pagination module aids in the process of paging large collections of
|
||||||
# Active Record objects. It offers macro-style automatic fetching of your
|
# Active Record objects. It offers macro-style automatic fetching of your
|
||||||
|
|
@ -130,6 +132,8 @@ module ActionController
|
||||||
paginator_and_collection_for(collection_id, options)
|
paginator_and_collection_for(collection_id, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
deprecate :paginate => 'Pagination is moving to a plugin in Rails 2.0: script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination'
|
||||||
|
|
||||||
# These methods become class methods on any controller
|
# These methods become class methods on any controller
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
# Creates a +before_filter+ which automatically paginates an Active
|
# Creates a +before_filter+ which automatically paginates an Active
|
||||||
|
|
@ -148,6 +152,8 @@ module ActionController
|
||||||
OPTIONS[self][collection_id] = options
|
OPTIONS[self][collection_id] = options
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
deprecate :paginate => 'Pagination is moving to a plugin in Rails 2.0: script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination'
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_paginators_and_retrieve_collections #:nodoc:
|
def create_paginators_and_retrieve_collections #:nodoc:
|
||||||
|
|
|
||||||
|
|
@ -2,48 +2,68 @@ module ActionController
|
||||||
module Resources
|
module Resources
|
||||||
class Resource #:nodoc:
|
class Resource #:nodoc:
|
||||||
attr_reader :collection_methods, :member_methods, :new_methods
|
attr_reader :collection_methods, :member_methods, :new_methods
|
||||||
attr_reader :path_prefix, :name_prefix
|
attr_reader :path_prefix, :new_name_prefix
|
||||||
attr_reader :plural, :singular
|
attr_reader :plural, :singular
|
||||||
attr_reader :options
|
attr_reader :options
|
||||||
|
|
||||||
def initialize(entities, options)
|
def initialize(entities, options)
|
||||||
@plural = entities
|
@plural = entities
|
||||||
@singular = options[:singular] || plural.to_s.singularize
|
@singular = options[:singular] || plural.to_s.singularize
|
||||||
|
|
||||||
@options = options
|
@options = options
|
||||||
|
|
||||||
arrange_actions
|
arrange_actions
|
||||||
add_default_actions
|
add_default_actions
|
||||||
set_prefixes
|
set_prefixes
|
||||||
end
|
end
|
||||||
|
|
||||||
def controller
|
def controller
|
||||||
@controller ||= (options[:controller] || plural).to_s
|
@controller ||= (options[:controller] || plural).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def path
|
def path
|
||||||
@path ||= "#{path_prefix}/#{plural}"
|
@path ||= "#{path_prefix}/#{plural}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_path
|
def new_path
|
||||||
@new_path ||= "#{path}/new"
|
@new_path ||= "#{path}/new"
|
||||||
end
|
end
|
||||||
|
|
||||||
def member_path
|
def member_path
|
||||||
@member_path ||= "#{path}/:id"
|
@member_path ||= "#{path}/:id"
|
||||||
end
|
end
|
||||||
|
|
||||||
def nesting_path_prefix
|
def nesting_path_prefix
|
||||||
@nesting_path_prefix ||= "#{path}/:#{singular}_id"
|
@nesting_path_prefix ||= "#{path}/:#{singular}_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def deprecate_name_prefix?
|
||||||
|
@name_prefix.blank? && !@new_name_prefix.blank?
|
||||||
|
end
|
||||||
|
|
||||||
|
def name_prefix
|
||||||
|
deprecate_name_prefix? ? @new_name_prefix : @name_prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
def old_name_prefix
|
||||||
|
@name_prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
def nesting_name_prefix
|
||||||
|
"#{new_name_prefix}#{singular}_"
|
||||||
|
end
|
||||||
|
|
||||||
|
def action_separator
|
||||||
|
@action_separator ||= Base.resource_action_separator
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def arrange_actions
|
def arrange_actions
|
||||||
@collection_methods = arrange_actions_by_methods(options.delete(:collection))
|
@collection_methods = arrange_actions_by_methods(options.delete(:collection))
|
||||||
@member_methods = arrange_actions_by_methods(options.delete(:member))
|
@member_methods = arrange_actions_by_methods(options.delete(:member))
|
||||||
@new_methods = arrange_actions_by_methods(options.delete(:new))
|
@new_methods = arrange_actions_by_methods(options.delete(:new))
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_default_actions
|
def add_default_actions
|
||||||
add_default_action(member_methods, :get, :edit)
|
add_default_action(member_methods, :get, :edit)
|
||||||
add_default_action(new_methods, :get, :new)
|
add_default_action(new_methods, :get, :new)
|
||||||
|
|
@ -52,6 +72,7 @@ module ActionController
|
||||||
def set_prefixes
|
def set_prefixes
|
||||||
@path_prefix = options.delete(:path_prefix)
|
@path_prefix = options.delete(:path_prefix)
|
||||||
@name_prefix = options.delete(:name_prefix)
|
@name_prefix = options.delete(:name_prefix)
|
||||||
|
@new_name_prefix = options.delete(:new_name_prefix)
|
||||||
end
|
end
|
||||||
|
|
||||||
def arrange_actions_by_methods(actions)
|
def arrange_actions_by_methods(actions)
|
||||||
|
|
@ -60,7 +81,7 @@ module ActionController
|
||||||
flipped_hash
|
flipped_hash
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_default_action(collection, method, action)
|
def add_default_action(collection, method, action)
|
||||||
(collection[method] ||= []).unshift(action)
|
(collection[method] ||= []).unshift(action)
|
||||||
end
|
end
|
||||||
|
|
@ -178,11 +199,11 @@ module ActionController
|
||||||
#
|
#
|
||||||
# The comment resources work the same, but must now include a value for :article_id.
|
# The comment resources work the same, but must now include a value for :article_id.
|
||||||
#
|
#
|
||||||
# comments_url(@article)
|
# article_comments_url(@article)
|
||||||
# comment_url(@article, @comment)
|
# article_comment_url(@article, @comment)
|
||||||
#
|
#
|
||||||
# comments_url(:article_id => @article)
|
# article_comments_url(:article_id => @article)
|
||||||
# comment_url(:article_id => @article, :id => @comment)
|
# article_comment_url(:article_id => @article, :id => @comment)
|
||||||
#
|
#
|
||||||
# * <tt>:name_prefix</tt> -- define a prefix for all generated routes, usually ending in an underscore.
|
# * <tt>:name_prefix</tt> -- define a prefix for all generated routes, usually ending in an underscore.
|
||||||
# Use this if you have named routes that may clash.
|
# Use this if you have named routes that may clash.
|
||||||
|
|
@ -192,7 +213,7 @@ module ActionController
|
||||||
#
|
#
|
||||||
# * <tt>:collection</tt> -- add named routes for other actions that operate on the collection.
|
# * <tt>:collection</tt> -- add named routes for other actions that operate on the collection.
|
||||||
# Takes a hash of <tt>#{action} => #{method}</tt>, where method is <tt>:get</tt>/<tt>:post</tt>/<tt>:put</tt>/<tt>:delete</tt>
|
# Takes a hash of <tt>#{action} => #{method}</tt>, where method is <tt>:get</tt>/<tt>:post</tt>/<tt>:put</tt>/<tt>:delete</tt>
|
||||||
# or <tt>:any</tt> if the method does not matter. These routes map to a URL like /messages;rss, with a route of rss_messages_url.
|
# or <tt>:any</tt> if the method does not matter. These routes map to a URL like /messages/rss, with a route of rss_messages_url.
|
||||||
# * <tt>:member</tt> -- same as :collection, but for actions that operate on a specific member.
|
# * <tt>:member</tt> -- same as :collection, but for actions that operate on a specific member.
|
||||||
# * <tt>:new</tt> -- same as :collection, but for actions that operate on the new resource action.
|
# * <tt>:new</tt> -- same as :collection, but for actions that operate on the new resource action.
|
||||||
#
|
#
|
||||||
|
|
@ -204,19 +225,19 @@ module ActionController
|
||||||
# # --> GET /thread/7/messages/1
|
# # --> GET /thread/7/messages/1
|
||||||
#
|
#
|
||||||
# map.resources :messages, :collection => { :rss => :get }
|
# map.resources :messages, :collection => { :rss => :get }
|
||||||
# # --> GET /messages;rss (maps to the #rss action)
|
# # --> GET /messages/rss (maps to the #rss action)
|
||||||
# # also adds a named route called "rss_messages"
|
# # also adds a named route called "rss_messages"
|
||||||
#
|
#
|
||||||
# map.resources :messages, :member => { :mark => :post }
|
# map.resources :messages, :member => { :mark => :post }
|
||||||
# # --> POST /messages/1;mark (maps to the #mark action)
|
# # --> POST /messages/1/mark (maps to the #mark action)
|
||||||
# # also adds a named route called "mark_message"
|
# # also adds a named route called "mark_message"
|
||||||
#
|
#
|
||||||
# map.resources :messages, :new => { :preview => :post }
|
# map.resources :messages, :new => { :preview => :post }
|
||||||
# # --> POST /messages/new;preview (maps to the #preview action)
|
# # --> POST /messages/new/preview (maps to the #preview action)
|
||||||
# # also adds a named route called "preview_new_message"
|
# # also adds a named route called "preview_new_message"
|
||||||
#
|
#
|
||||||
# map.resources :messages, :new => { :new => :any, :preview => :post }
|
# map.resources :messages, :new => { :new => :any, :preview => :post }
|
||||||
# # --> POST /messages/new;preview (maps to the #preview action)
|
# # --> POST /messages/new/preview (maps to the #preview action)
|
||||||
# # also adds a named route called "preview_new_message"
|
# # also adds a named route called "preview_new_message"
|
||||||
# # --> /messages/new can be invoked via any request method
|
# # --> /messages/new can be invoked via any request method
|
||||||
#
|
#
|
||||||
|
|
@ -235,9 +256,10 @@ module ActionController
|
||||||
# /account profile.
|
# /account profile.
|
||||||
#
|
#
|
||||||
# See map.resources for general conventions. These are the main differences:
|
# See map.resources for general conventions. These are the main differences:
|
||||||
# - a singular name is given to map.resource. The default controller name is taken from the singular name.
|
# - A singular name is given to map.resource. The default controller name is taken from the singular name.
|
||||||
# - To specify a custom plural name, use the :plural option. There is no :singular option
|
# - There is no <tt>:collection</tt> option as there is only the singleton resource.
|
||||||
# - No default index, new, or create routes are created for the singleton resource controller.
|
# - There is no <tt>:singular</tt> option as the singular name is passed to map.resource.
|
||||||
|
# - No default index route is created for the singleton resource controller.
|
||||||
# - When nesting singleton resources, only the singular name is used as the path prefix (example: 'account/messages/1')
|
# - When nesting singleton resources, only the singular name is used as the path prefix (example: 'account/messages/1')
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
|
@ -300,7 +322,7 @@ module ActionController
|
||||||
map_member_actions(map, resource)
|
map_member_actions(map, resource)
|
||||||
|
|
||||||
if block_given?
|
if block_given?
|
||||||
with_options(:path_prefix => resource.nesting_path_prefix, &block)
|
with_options(:path_prefix => resource.nesting_path_prefix, :new_name_prefix => resource.nesting_name_prefix, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -315,7 +337,7 @@ module ActionController
|
||||||
map_member_actions(map, resource)
|
map_member_actions(map, resource)
|
||||||
|
|
||||||
if block_given?
|
if block_given?
|
||||||
with_options(:path_prefix => resource.nesting_path_prefix, &block)
|
with_options(:path_prefix => resource.nesting_path_prefix, :new_name_prefix => resource.nesting_name_prefix, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -324,8 +346,21 @@ module ActionController
|
||||||
resource.collection_methods.each do |method, actions|
|
resource.collection_methods.each do |method, actions|
|
||||||
actions.each do |action|
|
actions.each do |action|
|
||||||
action_options = action_options_for(action, resource, method)
|
action_options = action_options_for(action, resource, method)
|
||||||
map.named_route("#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path};#{action}", action_options)
|
|
||||||
map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path}.:format;#{action}", action_options)
|
unless resource.old_name_prefix.blank?
|
||||||
|
map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.old_name_prefix}#{action}_#{resource.plural}")
|
||||||
|
map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "formatted_#{resource.old_name_prefix}#{action}_#{resource.plural}")
|
||||||
|
end
|
||||||
|
|
||||||
|
if resource.deprecate_name_prefix?
|
||||||
|
map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{action}_#{resource.plural}")
|
||||||
|
map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "formatted_#{action}_#{resource.plural}")
|
||||||
|
end
|
||||||
|
|
||||||
|
map.named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}", action_options)
|
||||||
|
map.connect("#{resource.path};#{action}", action_options)
|
||||||
|
map.connect("#{resource.path}.:format;#{action}", action_options)
|
||||||
|
map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}.:format", action_options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -335,6 +370,11 @@ module ActionController
|
||||||
map.named_route("#{resource.name_prefix}#{resource.plural}", resource.path, index_action_options)
|
map.named_route("#{resource.name_prefix}#{resource.plural}", resource.path, index_action_options)
|
||||||
map.named_route("formatted_#{resource.name_prefix}#{resource.plural}", "#{resource.path}.:format", index_action_options)
|
map.named_route("formatted_#{resource.name_prefix}#{resource.plural}", "#{resource.path}.:format", index_action_options)
|
||||||
|
|
||||||
|
if resource.deprecate_name_prefix?
|
||||||
|
map.deprecated_named_route("#{resource.name_prefix}#{resource.plural}", "#{resource.plural}")
|
||||||
|
map.deprecated_named_route("formatted_#{resource.name_prefix}#{resource.plural}", "formatted_#{resource.plural}")
|
||||||
|
end
|
||||||
|
|
||||||
create_action_options = action_options_for("create", resource)
|
create_action_options = action_options_for("create", resource)
|
||||||
map.connect(resource.path, create_action_options)
|
map.connect(resource.path, create_action_options)
|
||||||
map.connect("#{resource.path}.:format", create_action_options)
|
map.connect("#{resource.path}.:format", create_action_options)
|
||||||
|
|
@ -351,11 +391,37 @@ module ActionController
|
||||||
actions.each do |action|
|
actions.each do |action|
|
||||||
action_options = action_options_for(action, resource, method)
|
action_options = action_options_for(action, resource, method)
|
||||||
if action == :new
|
if action == :new
|
||||||
map.named_route("#{resource.name_prefix}new_#{resource.singular}", resource.new_path, action_options)
|
|
||||||
map.named_route("formatted_#{resource.name_prefix}new_#{resource.singular}", "#{resource.new_path}.:format", action_options)
|
unless resource.old_name_prefix.blank?
|
||||||
|
map.deprecated_named_route("new_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}new_#{resource.singular}")
|
||||||
|
map.deprecated_named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}new_#{resource.singular}")
|
||||||
|
end
|
||||||
|
|
||||||
|
if resource.deprecate_name_prefix?
|
||||||
|
map.deprecated_named_route("new_#{resource.name_prefix}#{resource.singular}", "new_#{resource.singular}")
|
||||||
|
map.deprecated_named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "formatted_new_#{resource.singular}")
|
||||||
|
end
|
||||||
|
|
||||||
|
map.named_route("new_#{resource.name_prefix}#{resource.singular}", resource.new_path, action_options)
|
||||||
|
map.named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}.:format", action_options)
|
||||||
|
|
||||||
else
|
else
|
||||||
map.named_route("#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path};#{action}", action_options)
|
|
||||||
map.named_route("formatted_#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path}.:format;#{action}", action_options)
|
unless resource.old_name_prefix.blank?
|
||||||
|
map.deprecated_named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}#{action}_new_#{resource.singular}")
|
||||||
|
map.deprecated_named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}#{action}_new_#{resource.singular}")
|
||||||
|
end
|
||||||
|
|
||||||
|
if resource.deprecate_name_prefix?
|
||||||
|
map.deprecated_named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{action}_new_#{resource.singular}")
|
||||||
|
map.deprecated_named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{action}_new_#{resource.singular}")
|
||||||
|
end
|
||||||
|
|
||||||
|
map.named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}#{resource.action_separator}#{action}", action_options)
|
||||||
|
map.connect("#{resource.new_path};#{action}", action_options)
|
||||||
|
map.connect("#{resource.new_path}.:format;#{action}", action_options)
|
||||||
|
map.named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}#{resource.action_separator}#{action}.:format", action_options)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -365,8 +431,22 @@ module ActionController
|
||||||
resource.member_methods.each do |method, actions|
|
resource.member_methods.each do |method, actions|
|
||||||
actions.each do |action|
|
actions.each do |action|
|
||||||
action_options = action_options_for(action, resource, method)
|
action_options = action_options_for(action, resource, method)
|
||||||
map.named_route("#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path};#{action}", action_options)
|
|
||||||
map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path}.:format;#{action}",action_options)
|
unless resource.old_name_prefix.blank?
|
||||||
|
map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}#{action}_#{resource.singular}")
|
||||||
|
map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}#{action}_#{resource.singular}")
|
||||||
|
end
|
||||||
|
|
||||||
|
if resource.deprecate_name_prefix?
|
||||||
|
map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{action}_#{resource.singular}")
|
||||||
|
map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "formatted_#{action}_#{resource.singular}")
|
||||||
|
end
|
||||||
|
|
||||||
|
map.named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}", action_options)
|
||||||
|
map.connect("#{resource.member_path};#{action}", action_options)
|
||||||
|
map.connect("#{resource.member_path}.:format;#{action}", action_options)
|
||||||
|
map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}.:format", action_options)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -374,6 +454,11 @@ module ActionController
|
||||||
map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options)
|
map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options)
|
||||||
map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options)
|
map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options)
|
||||||
|
|
||||||
|
if resource.deprecate_name_prefix?
|
||||||
|
map.deprecated_named_route("#{resource.name_prefix}#{resource.singular}", "#{resource.singular}")
|
||||||
|
map.deprecated_named_route("formatted_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.singular}")
|
||||||
|
end
|
||||||
|
|
||||||
update_action_options = action_options_for("update", resource)
|
update_action_options = action_options_for("update", resource)
|
||||||
map.connect(resource.member_path, update_action_options)
|
map.connect(resource.member_path, update_action_options)
|
||||||
map.connect("#{resource.member_path}.:format", update_action_options)
|
map.connect("#{resource.member_path}.:format", update_action_options)
|
||||||
|
|
|
||||||
|
|
@ -451,26 +451,17 @@ module ActionController
|
||||||
# is given (as an array), only the keys indicated will be used to build
|
# is given (as an array), only the keys indicated will be used to build
|
||||||
# the query string. The query string will correctly build array parameter
|
# the query string. The query string will correctly build array parameter
|
||||||
# values.
|
# values.
|
||||||
def build_query_string(hash, only_keys=nil)
|
def build_query_string(hash, only_keys = nil)
|
||||||
elements = []
|
elements = []
|
||||||
|
|
||||||
only_keys ||= hash.keys
|
|
||||||
|
|
||||||
only_keys.each do |key|
|
(only_keys || hash.keys).each do |key|
|
||||||
value = hash[key] or next
|
if value = hash[key]
|
||||||
key = CGI.escape key.to_s
|
elements << value.to_query(key)
|
||||||
if value.class == Array
|
end
|
||||||
key << '[]'
|
end
|
||||||
else
|
elements.empty? ? '' : "?#{elements.sort * '&'}"
|
||||||
value = [ value ]
|
|
||||||
end
|
|
||||||
value.each { |val| elements << "#{key}=#{CGI.escape(val.to_param.to_s)}" }
|
|
||||||
end
|
|
||||||
|
|
||||||
query_string = "?#{elements.join("&")}" unless elements.empty?
|
|
||||||
query_string || ""
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Write the real recognition implementation and then resend the message.
|
# Write the real recognition implementation and then resend the message.
|
||||||
def recognize(path, environment={})
|
def recognize(path, environment={})
|
||||||
write_recognition
|
write_recognition
|
||||||
|
|
@ -668,7 +659,7 @@ module ActionController
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract_value
|
def extract_value
|
||||||
"#{local_name} = hash[:#{key}] #{"|| #{default.inspect}" if default}"
|
"#{local_name} = hash[:#{key}] && hash[:#{key}].to_param #{"|| #{default.inspect}" if default}"
|
||||||
end
|
end
|
||||||
def value_check
|
def value_check
|
||||||
if default # Then we know it won't be nil
|
if default # Then we know it won't be nil
|
||||||
|
|
@ -989,6 +980,10 @@ module ActionController
|
||||||
def named_route(name, path, options = {})
|
def named_route(name, path, options = {})
|
||||||
@set.add_named_route(name, path, options)
|
@set.add_named_route(name, path, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def deprecated_named_route(name, deprecated_name, options = {})
|
||||||
|
@set.add_deprecated_named_route(name, deprecated_name)
|
||||||
|
end
|
||||||
|
|
||||||
# Added deprecation notice for anyone who already added a named route called "root".
|
# Added deprecation notice for anyone who already added a named route called "root".
|
||||||
# It'll be used as a shortcut for map.connect '' in Rails 2.0.
|
# It'll be used as a shortcut for map.connect '' in Rails 2.0.
|
||||||
|
|
@ -1019,7 +1014,7 @@ module ActionController
|
||||||
def clear!
|
def clear!
|
||||||
@routes = {}
|
@routes = {}
|
||||||
@helpers = []
|
@helpers = []
|
||||||
|
|
||||||
@module ||= Module.new
|
@module ||= Module.new
|
||||||
@module.instance_methods.each do |selector|
|
@module.instance_methods.each do |selector|
|
||||||
@module.send :remove_method, selector
|
@module.send :remove_method, selector
|
||||||
|
|
@ -1055,6 +1050,38 @@ module ActionController
|
||||||
def install(destinations = [ActionController::Base, ActionView::Base])
|
def install(destinations = [ActionController::Base, ActionView::Base])
|
||||||
Array(destinations).each { |dest| dest.send :include, @module }
|
Array(destinations).each { |dest| dest.send :include, @module }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def define_deprecated_named_route_methods(name, deprecated_name)
|
||||||
|
|
||||||
|
[:url, :path].each do |kind|
|
||||||
|
@module.send :module_eval, <<-end_eval # We use module_eval to avoid leaks
|
||||||
|
|
||||||
|
def #{url_helper_name(deprecated_name, kind)}(*args)
|
||||||
|
|
||||||
|
ActiveSupport::Deprecation.warn(
|
||||||
|
'The named route "#{url_helper_name(deprecated_name, kind)}" uses a format that has been deprecated. ' +
|
||||||
|
'You should use "#{url_helper_name(name, kind)}" instead.', caller
|
||||||
|
)
|
||||||
|
|
||||||
|
send :#{url_helper_name(name, kind)}, *args
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def #{hash_access_name(deprecated_name, kind)}(*args)
|
||||||
|
|
||||||
|
ActiveSupport::Deprecation.warn(
|
||||||
|
'The named route "#{hash_access_name(deprecated_name, kind)}" uses a format that has been deprecated. ' +
|
||||||
|
'You should use "#{hash_access_name(name, kind)}" instead.', caller
|
||||||
|
)
|
||||||
|
|
||||||
|
send :#{hash_access_name(name, kind)}, *args
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end_eval
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def url_helper_name(name, kind = :url)
|
def url_helper_name(name, kind = :url)
|
||||||
|
|
@ -1177,6 +1204,10 @@ module ActionController
|
||||||
def add_named_route(name, path, options = {})
|
def add_named_route(name, path, options = {})
|
||||||
named_routes[name] = add_route(path, options)
|
named_routes[name] = add_route(path, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_deprecated_named_route(name, deprecated_name)
|
||||||
|
named_routes.define_deprecated_named_route_methods(name, deprecated_name)
|
||||||
|
end
|
||||||
|
|
||||||
def options_as_params(options)
|
def options_as_params(options)
|
||||||
# If an explicit :controller was given, always make :action explicit
|
# If an explicit :controller was given, always make :action explicit
|
||||||
|
|
@ -1190,10 +1221,9 @@ module ActionController
|
||||||
#
|
#
|
||||||
# great fun, eh?
|
# great fun, eh?
|
||||||
|
|
||||||
options_as_params = options[:controller] ? { :action => "index" } : {}
|
options_as_params = options.clone
|
||||||
options.each do |k, value|
|
options_as_params[:action] ||= 'index' if options[:controller]
|
||||||
options_as_params[k] = value.to_param
|
options_as_params[:action] = options_as_params[:action].to_s if options_as_params[:action]
|
||||||
end
|
|
||||||
options_as_params
|
options_as_params
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -1224,6 +1254,9 @@ module ActionController
|
||||||
options = options_as_params(options)
|
options = options_as_params(options)
|
||||||
expire_on = build_expiry(options, recall)
|
expire_on = build_expiry(options, recall)
|
||||||
|
|
||||||
|
if options[:controller]
|
||||||
|
options[:controller] = options[:controller].to_s
|
||||||
|
end
|
||||||
# if the controller has changed, make sure it changes relative to the
|
# if the controller has changed, make sure it changes relative to the
|
||||||
# current controller module, if any. In other words, if we're currently
|
# current controller module, if any. In other words, if we're currently
|
||||||
# on admin/get, and the new controller is 'set', the new controller
|
# on admin/get, and the new controller is 'set', the new controller
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ module ActionController #:nodoc:
|
||||||
attr_accessor :cookies, :session_options
|
attr_accessor :cookies, :session_options
|
||||||
attr_accessor :query_parameters, :request_parameters, :path, :session, :env
|
attr_accessor :query_parameters, :request_parameters, :path, :session, :env
|
||||||
attr_accessor :host
|
attr_accessor :host
|
||||||
|
attr_reader :request_uri_overridden
|
||||||
|
|
||||||
def initialize(query_parameters = nil, request_parameters = nil, session = nil)
|
def initialize(query_parameters = nil, request_parameters = nil, session = nil)
|
||||||
@query_parameters = query_parameters || {}
|
@query_parameters = query_parameters || {}
|
||||||
|
|
@ -67,12 +68,14 @@ module ActionController #:nodoc:
|
||||||
# Used to check AbstractRequest's request_uri functionality.
|
# Used to check AbstractRequest's request_uri functionality.
|
||||||
# Disables the use of @path and @request_uri so superclass can handle those.
|
# Disables the use of @path and @request_uri so superclass can handle those.
|
||||||
def set_REQUEST_URI(value)
|
def set_REQUEST_URI(value)
|
||||||
|
@request_uri_overridden = true
|
||||||
@env["REQUEST_URI"] = value
|
@env["REQUEST_URI"] = value
|
||||||
@request_uri = nil
|
@request_uri = nil
|
||||||
@path = nil
|
@path = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_uri=(uri)
|
def request_uri=(uri)
|
||||||
|
@env["REQUEST_URI"] = uri
|
||||||
@request_uri = uri
|
@request_uri = uri
|
||||||
@path = uri.split("?").first
|
@path = uri.split("?").first
|
||||||
end
|
end
|
||||||
|
|
@ -426,12 +429,12 @@ module ActionController #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_request_uri(action, parameters)
|
def build_request_uri(action, parameters)
|
||||||
unless @request.env['REQUEST_URI']
|
unless @request.request_uri_overridden
|
||||||
options = @controller.send(:rewrite_options, parameters)
|
options = @controller.send(:rewrite_options, parameters)
|
||||||
options.update(:only_path => true, :action => action)
|
options.update(:only_path => true, :action => action)
|
||||||
|
|
||||||
url = ActionController::UrlRewriter.new(@request, parameters)
|
url = ActionController::UrlRewriter.new(@request, parameters)
|
||||||
@request.set_REQUEST_URI(url.rewrite(options))
|
@request.request_uri = url.rewrite(options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,9 @@ module ActionController
|
||||||
# Delete the unused options to prevent their appearance in the query string
|
# Delete the unused options to prevent their appearance in the query string
|
||||||
[:protocol, :host, :port].each { |k| options.delete k }
|
[:protocol, :host, :port].each { |k| options.delete k }
|
||||||
end
|
end
|
||||||
|
anchor = "##{options.delete(:anchor)}" if options.key?(:anchor)
|
||||||
url << Routing::Routes.generate(options, {})
|
url << Routing::Routes.generate(options, {})
|
||||||
return url
|
return "#{url}#{anchor}"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -76,6 +77,7 @@ module ActionController
|
||||||
alias_method :to_s, :to_str
|
alias_method :to_s, :to_str
|
||||||
|
|
||||||
private
|
private
|
||||||
|
# Given a path and options, returns a rewritten URL string
|
||||||
def rewrite_url(path, options)
|
def rewrite_url(path, options)
|
||||||
rewritten_url = ""
|
rewritten_url = ""
|
||||||
unless options[:only_path]
|
unless options[:only_path]
|
||||||
|
|
@ -91,6 +93,7 @@ module ActionController
|
||||||
rewritten_url
|
rewritten_url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Given a Hash of options, generates a route
|
||||||
def rewrite_path(options)
|
def rewrite_path(options)
|
||||||
options = options.symbolize_keys
|
options = options.symbolize_keys
|
||||||
options.update(options[:params].symbolize_keys) if options[:params]
|
options.update(options[:params].symbolize_keys) if options[:params]
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ module ActionController #:nodoc:
|
||||||
response.headers.update(options[:add_headers]) if options[:add_headers]
|
response.headers.update(options[:add_headers]) if options[:add_headers]
|
||||||
unless performed?
|
unless performed?
|
||||||
render(options[:render]) if options[:render]
|
render(options[:render]) if options[:render]
|
||||||
|
options[:redirect_to] = self.send(options[:redirect_to]) if options[:redirect_to].is_a? Symbol
|
||||||
redirect_to(options[:redirect_to]) if options[:redirect_to]
|
redirect_to(options[:redirect_to]) if options[:redirect_to]
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ module ActionPack #:nodoc:
|
||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 1
|
MAJOR = 1
|
||||||
MINOR = 13
|
MINOR = 13
|
||||||
TINY = 3
|
TINY = 5
|
||||||
|
|
||||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ module ActionView #:nodoc:
|
||||||
#
|
#
|
||||||
# This refreshes the sidebar, removes a person element and highlights the user list.
|
# This refreshes the sidebar, removes a person element and highlights the user list.
|
||||||
#
|
#
|
||||||
# See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation for more details.
|
# See the ActionView::Helpers::PrototypeHelper::GeneratorMethods documentation for more details.
|
||||||
class Base
|
class Base
|
||||||
include ERB::Util
|
include ERB::Util
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ module ActionView #:nodoc:
|
||||||
attr_internal *ActionController::Base::DEPRECATED_INSTANCE_VARIABLES
|
attr_internal *ActionController::Base::DEPRECATED_INSTANCE_VARIABLES
|
||||||
|
|
||||||
# Specify trim mode for the ERB compiler. Defaults to '-'.
|
# Specify trim mode for the ERB compiler. Defaults to '-'.
|
||||||
# See ERB documentation for suitable values.
|
# See ERb documentation for suitable values.
|
||||||
@@erb_trim_mode = '-'
|
@@erb_trim_mode = '-'
|
||||||
cattr_accessor :erb_trim_mode
|
cattr_accessor :erb_trim_mode
|
||||||
|
|
||||||
|
|
@ -191,17 +191,17 @@ module ActionView #:nodoc:
|
||||||
end
|
end
|
||||||
include CompiledTemplates
|
include CompiledTemplates
|
||||||
|
|
||||||
# maps inline templates to their method names
|
# Maps inline templates to their method names
|
||||||
@@method_names = {}
|
@@method_names = {}
|
||||||
# map method names to their compile time
|
# Map method names to their compile time
|
||||||
@@compile_time = {}
|
@@compile_time = {}
|
||||||
# map method names to the names passed in local assigns so far
|
# Map method names to the names passed in local assigns so far
|
||||||
@@template_args = {}
|
@@template_args = {}
|
||||||
# count the number of inline templates
|
# Count the number of inline templates
|
||||||
@@inline_template_count = 0
|
@@inline_template_count = 0
|
||||||
# maps template paths without extension to their file extension returned by pick_template_extension.
|
# Maps template paths without extension to their file extension returned by pick_template_extension.
|
||||||
# if for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions
|
# If for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions
|
||||||
# used by pick_template_extension determines whether ext1 or ext2 will be stored
|
# used by pick_template_extension determines whether ext1 or ext2 will be stored.
|
||||||
@@cached_template_extension = {}
|
@@cached_template_extension = {}
|
||||||
|
|
||||||
class ObjectWrapper < Struct.new(:value) #:nodoc:
|
class ObjectWrapper < Struct.new(:value) #:nodoc:
|
||||||
|
|
@ -305,7 +305,6 @@ module ActionView #:nodoc:
|
||||||
# Render the provided template with the given local assigns. If the template has not been rendered with the provided
|
# Render the provided template with the given local assigns. If the template has not been rendered with the provided
|
||||||
# local assigns yet, or if the template has been updated on disk, then the template will be compiled to a method.
|
# local assigns yet, or if the template has been updated on disk, then the template will be compiled to a method.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Either, but not both, of template and file_path may be nil. If file_path is given, the template
|
# Either, but not both, of template and file_path may be nil. If file_path is given, the template
|
||||||
# will only be read if it has to be compiled.
|
# will only be read if it has to be compiled.
|
||||||
#
|
#
|
||||||
|
|
@ -371,10 +370,12 @@ module ActionView #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
# Builds a string holding the full path of the template including extension
|
||||||
def full_template_path(template_path, extension)
|
def full_template_path(template_path, extension)
|
||||||
"#{@base_path}/#{template_path}.#{extension}"
|
"#{@base_path}/#{template_path}.#{extension}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Asserts the existence of a template.
|
||||||
def template_exists?(template_path, extension)
|
def template_exists?(template_path, extension)
|
||||||
file_path = full_template_path(template_path, extension)
|
file_path = full_template_path(template_path, extension)
|
||||||
@@method_names.has_key?(file_path) || FileTest.exists?(file_path)
|
@@method_names.has_key?(file_path) || FileTest.exists?(file_path)
|
||||||
|
|
@ -389,6 +390,7 @@ module ActionView #:nodoc:
|
||||||
@@cache_template_extensions && @@cached_template_extension[template_path]
|
@@cache_template_extensions && @@cached_template_extension[template_path]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Determines the template's file extension, such as rhtml, rxml, or rjs.
|
||||||
def find_template_extension_for(template_path)
|
def find_template_extension_for(template_path)
|
||||||
if match = delegate_template_exists?(template_path)
|
if match = delegate_template_exists?(template_path)
|
||||||
match.first.to_sym
|
match.first.to_sym
|
||||||
|
|
@ -405,6 +407,7 @@ module ActionView #:nodoc:
|
||||||
File.read(template_path)
|
File.read(template_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Evaluate the local assigns and pushes them to the view.
|
||||||
def evaluate_assigns
|
def evaluate_assigns
|
||||||
unless @assigns_added
|
unless @assigns_added
|
||||||
assign_variables_from_controller
|
assign_variables_from_controller
|
||||||
|
|
@ -416,6 +419,7 @@ module ActionView #:nodoc:
|
||||||
handler.new(self).render(template, local_assigns)
|
handler.new(self).render(template, local_assigns)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Assigns instance variables from the controller to the view.
|
||||||
def assign_variables_from_controller
|
def assign_variables_from_controller
|
||||||
@assigns.each { |key, value| instance_variable_set("@#{key}", value) }
|
@assigns.each { |key, value| instance_variable_set("@#{key}", value) }
|
||||||
end
|
end
|
||||||
|
|
@ -427,10 +431,10 @@ module ActionView #:nodoc:
|
||||||
((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) })
|
((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) })
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check whether compilation is necessary.
|
# Method to check whether template compilation is necessary.
|
||||||
# Compile if the inline template or file has not been compiled yet.
|
# The template will be compiled if the inline template or file has not been compiled yet,
|
||||||
# Or if local_assigns has a new key, which isn't supported by the compiled code yet.
|
# if local_assigns has a new key, which isn't supported by the compiled code yet,
|
||||||
# Or if the file has changed on disk and checking file mods hasn't been disabled.
|
# or if the file has changed on disk and checking file mods hasn't been disabled.
|
||||||
def compile_template?(template, file_name, local_assigns)
|
def compile_template?(template, file_name, local_assigns)
|
||||||
method_key = file_name || template
|
method_key = file_name || template
|
||||||
render_symbol = @@method_names[method_key]
|
render_symbol = @@method_names[method_key]
|
||||||
|
|
@ -445,14 +449,15 @@ module ActionView #:nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create source code for given template
|
# Method to create the source code for a given template.
|
||||||
def create_template_source(extension, template, render_symbol, locals)
|
def create_template_source(extension, template, render_symbol, locals)
|
||||||
if template_requires_setup?(extension)
|
if template_requires_setup?(extension)
|
||||||
body = case extension.to_sym
|
body = case extension.to_sym
|
||||||
when :rxml
|
when :rxml
|
||||||
"controller.response.content_type ||= 'application/xml'\n" +
|
"controller.response.content_type ||= 'application/xml'\n" +
|
||||||
"xml = Builder::XmlMarkup.new(:indent => 2)\n" +
|
"xml ||= Builder::XmlMarkup.new(:indent => 2)\n" +
|
||||||
template
|
template +
|
||||||
|
"\nxml.target!\n"
|
||||||
when :rjs
|
when :rjs
|
||||||
"controller.response.content_type ||= 'text/javascript'\n" +
|
"controller.response.content_type ||= 'text/javascript'\n" +
|
||||||
"update_page do |page|\n#{template}\nend"
|
"update_page do |page|\n#{template}\nend"
|
||||||
|
|
@ -473,11 +478,11 @@ module ActionView #:nodoc:
|
||||||
"def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend"
|
"def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend"
|
||||||
end
|
end
|
||||||
|
|
||||||
def template_requires_setup?(extension)
|
def template_requires_setup?(extension) #:nodoc:
|
||||||
templates_requiring_setup.include? extension.to_s
|
templates_requiring_setup.include? extension.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def templates_requiring_setup
|
def templates_requiring_setup #:nodoc:
|
||||||
%w(rxml rjs)
|
%w(rxml rjs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -501,6 +506,7 @@ module ActionView #:nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Compile and evaluate the template's code
|
||||||
def compile_template(extension, template, file_name, local_assigns)
|
def compile_template(extension, template, file_name, local_assigns)
|
||||||
render_symbol = assign_method_name(extension, template, file_name)
|
render_symbol = assign_method_name(extension, template, file_name)
|
||||||
render_source = create_template_source(extension, template, render_symbol, local_assigns.keys)
|
render_source = create_template_source(extension, template, render_symbol, local_assigns.keys)
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@ module ActionView
|
||||||
|
|
||||||
# CompiledTemplates modules hold methods that have been compiled.
|
# CompiledTemplates modules hold methods that have been compiled.
|
||||||
# Templates are compiled into these methods so that they do not need to be
|
# Templates are compiled into these methods so that they do not need to be
|
||||||
# re-read and re-parsed each request.
|
# read and parsed for each request.
|
||||||
#
|
#
|
||||||
# Each template may be compiled into one or more methods. Each method accepts a given
|
# Each template may be compiled into one or more methods. Each method accepts a given
|
||||||
# set of parameters which is used to implement local assigns passing.
|
# set of parameters which is used to implement local assigns passing.
|
||||||
#
|
#
|
||||||
# To use a compiled template module, create a new instance and include it into the class
|
# To use a compiled template module, create a new instance and include it into the class
|
||||||
# in which you want the template to be rendered.
|
# in which you want the template to be rendered.
|
||||||
class CompiledTemplates < Module #:nodoc:
|
class CompiledTemplates < Module
|
||||||
attr_reader :method_names
|
attr_reader :method_names
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,18 @@ module ActionView
|
||||||
# is a great of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form.
|
# is a great of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form.
|
||||||
# In that case, it's better to use the input method and the specialized form methods in link:classes/ActionView/Helpers/FormHelper.html
|
# In that case, it's better to use the input method and the specialized form methods in link:classes/ActionView/Helpers/FormHelper.html
|
||||||
module ActiveRecordHelper
|
module ActiveRecordHelper
|
||||||
# Returns a default input tag for the type of object returned by the method. Example
|
# Returns a default input tag for the type of object returned by the method. For example, let's say you have a model
|
||||||
# (title is a VARCHAR column and holds "Hello World"):
|
# that has an attribute +title+ of type VARCHAR column, and this instance holds "Hello World":
|
||||||
# input("post", "title") =>
|
# input("post", "title") =>
|
||||||
# <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />
|
# <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />
|
||||||
def input(record_name, method, options = {})
|
def input(record_name, method, options = {})
|
||||||
InstanceTag.new(record_name, method, self).to_tag(options)
|
InstanceTag.new(record_name, method, self).to_tag(options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an entire form with input tags and everything for a specified Active Record object. Example
|
# Returns an entire form with all needed input tags for a specified Active Record object. For example, let's say you
|
||||||
# (post is a new record that has a title using VARCHAR and a body using TEXT):
|
# have a table model <tt>Post</tt> with attributes named <tt>title</tt> of type <tt>VARCHAR</tt> and <tt>body</tt> of type <tt>TEXT</tt>:
|
||||||
# form("post") =>
|
# form("post")
|
||||||
|
# That line would yield a form like the following:
|
||||||
# <form action='/post/create' method='post'>
|
# <form action='/post/create' method='post'>
|
||||||
# <p>
|
# <p>
|
||||||
# <label for="post_title">Title</label><br />
|
# <label for="post_title">Title</label><br />
|
||||||
|
|
@ -32,14 +33,13 @@ module ActionView
|
||||||
# <p>
|
# <p>
|
||||||
# <label for="post_body">Body</label><br />
|
# <label for="post_body">Body</label><br />
|
||||||
# <textarea cols="40" id="post_body" name="post[body]" rows="20">
|
# <textarea cols="40" id="post_body" name="post[body]" rows="20">
|
||||||
# Back to the hill and over it again!
|
|
||||||
# </textarea>
|
# </textarea>
|
||||||
# </p>
|
# </p>
|
||||||
# <input type='submit' value='Create' />
|
# <input type='submit' value='Create' />
|
||||||
# </form>
|
# </form>
|
||||||
#
|
#
|
||||||
# It's possible to specialize the form builder by using a different action name and by supplying another
|
# It's possible to specialize the form builder by using a different action name and by supplying another
|
||||||
# block renderer. Example (entry is a new record that has a message attribute using VARCHAR):
|
# block renderer. For example, let's say you have a model <tt>Entry</tt> with an attribute <tt>message</tt> of type <tt>VARCHAR</tt>:
|
||||||
#
|
#
|
||||||
# form("entry", :action => "sign", :input_block =>
|
# form("entry", :action => "sign", :input_block =>
|
||||||
# Proc.new { |record, column| "#{column.human_name}: #{input(record, column.name)}<br />" }) =>
|
# Proc.new { |record, column| "#{column.human_name}: #{input(record, column.name)}<br />" }) =>
|
||||||
|
|
@ -74,16 +74,16 @@ module ActionView
|
||||||
content_tag('form', contents, :action => action, :method => 'post', :enctype => options[:multipart] ? 'multipart/form-data': nil)
|
content_tag('form', contents, :action => action, :method => 'post', :enctype => options[:multipart] ? 'multipart/form-data': nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a string containing the error message attached to the +method+ on the +object+, if one exists.
|
# Returns a string containing the error message attached to the +method+ on the +object+ if one exists.
|
||||||
# This error message is wrapped in a DIV tag, which can be specialized to include both a +prepend_text+ and +append_text+
|
# This error message is wrapped in a <tt>DIV</tt> tag, which can be extended to include a +prepend_text+ and/or +append_text+
|
||||||
# to properly introduce the error and a +css_class+ to style it accordingly. Examples (post has an error message
|
# (to properly explain the error), and a +css_class+ to style it accordingly. As an example, let's say you have a model
|
||||||
# "can't be empty" on the title attribute):
|
# +post+ that has an error message on the +title+ attribute:
|
||||||
#
|
#
|
||||||
# <%= error_message_on "post", "title" %> =>
|
# <%= error_message_on "post", "title" %> =>
|
||||||
# <div class="formError">can't be empty</div>
|
# <div class="formError">can't be empty</div>
|
||||||
#
|
#
|
||||||
# <%= error_message_on "post", "title", "Title simply ", " (or it won't work)", "inputError" %> =>
|
# <%= error_message_on "post", "title", "Title simply ", " (or it won't work).", "inputError" %> =>
|
||||||
# <div class="inputError">Title simply can't be empty (or it won't work)</div>
|
# <div class="inputError">Title simply can't be empty (or it won't work).</div>
|
||||||
def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError")
|
def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError")
|
||||||
if (obj = instance_variable_get("@#{object}")) && (errors = obj.errors.on(method))
|
if (obj = instance_variable_get("@#{object}")) && (errors = obj.errors.on(method))
|
||||||
content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class)
|
content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class)
|
||||||
|
|
@ -92,11 +92,11 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a string with a div containing all of the error messages for the objects located as instance variables by the names
|
# Returns a string with a <tt>DIV</tt> containing all of the error messages for the objects located as instance variables by the names
|
||||||
# given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are
|
# given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are
|
||||||
# provided.
|
# provided.
|
||||||
#
|
#
|
||||||
# This div can be tailored by the following options:
|
# This <tt>DIV</tt> can be tailored by the following options:
|
||||||
#
|
#
|
||||||
# * <tt>header_tag</tt> - Used for the header of the error div (default: h2)
|
# * <tt>header_tag</tt> - Used for the header of the error div (default: h2)
|
||||||
# * <tt>id</tt> - The id of the error div (default: errorExplanation)
|
# * <tt>id</tt> - The id of the error div (default: errorExplanation)
|
||||||
|
|
@ -105,12 +105,12 @@ module ActionView
|
||||||
# any text that you prefer. If <tt>object_name</tt> is not set, the name of
|
# any text that you prefer. If <tt>object_name</tt> is not set, the name of
|
||||||
# the first object will be used.
|
# the first object will be used.
|
||||||
#
|
#
|
||||||
# Specifying one object:
|
# To specify the display for one object, you simply provide its name as a parameter. For example, for the +User+ model:
|
||||||
#
|
#
|
||||||
# error_messages_for 'user'
|
# error_messages_for 'user'
|
||||||
#
|
#
|
||||||
# Specifying more than one object (and using the name 'user' in the
|
# To specify more than one object, you simply list them; optionally, you can add an extra +object_name+ parameter, which
|
||||||
# header as the <tt>object_name</tt> instead of 'user_common'):
|
# be the name in the header.
|
||||||
#
|
#
|
||||||
# error_messages_for 'user_common', 'user', :object_name => 'user'
|
# error_messages_for 'user_common', 'user', :object_name => 'user'
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,16 @@ module ActionView
|
||||||
# Provides a set of methods for making it easier to locate problems.
|
# Provides a set of methods for making it easier to locate problems.
|
||||||
module DebugHelper
|
module DebugHelper
|
||||||
# Returns a <pre>-tag set with the +object+ dumped by YAML. Very readable way to inspect an object.
|
# Returns a <pre>-tag set with the +object+ dumped by YAML. Very readable way to inspect an object.
|
||||||
|
# my_hash = {'first' => 1, 'second' => 'two', 'third' => [1,2,3]}
|
||||||
|
# debug(my_hash)
|
||||||
|
# => <pre class='debug_dump'>---
|
||||||
|
# first: 1
|
||||||
|
# second: two
|
||||||
|
# third:
|
||||||
|
# - 1
|
||||||
|
# - 2
|
||||||
|
# - 3
|
||||||
|
# </pre>
|
||||||
def debug(object)
|
def debug(object)
|
||||||
begin
|
begin
|
||||||
Marshal::dump(object)
|
Marshal::dump(object)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@ module ActionView
|
||||||
module Helpers
|
module Helpers
|
||||||
module PrototypeHelper
|
module PrototypeHelper
|
||||||
|
|
||||||
|
# Method to execute an element update using Prototype.
|
||||||
|
# DEPRECATION WARNING: This helper has been depercated; use RJS instead.
|
||||||
|
# See ActionView::Helpers::PrototypeHelper::JavaScriptGenerator::GeneratorMethods for more information.
|
||||||
def update_element_function(element_id, options = {}, &block)
|
def update_element_function(element_id, options = {}, &block)
|
||||||
content = escape_javascript(options[:content] || '')
|
content = escape_javascript(options[:content] || '')
|
||||||
content = escape_javascript(capture(&block)) if block
|
content = escape_javascript(capture(&block)) if block
|
||||||
|
|
|
||||||
|
|
@ -250,8 +250,10 @@ module ActionView
|
||||||
return function
|
return function
|
||||||
end
|
end
|
||||||
|
|
||||||
# Observes the field with the DOM ID specified by +field_id+ and makes
|
# Observes the field with the DOM ID specified by +field_id+ and calls a
|
||||||
# an Ajax call when its contents have changed.
|
# callback when its contents have changed. The default callback is an
|
||||||
|
# Ajax call. By default the value of the observed field is sent as a
|
||||||
|
# parameter with the Ajax call.
|
||||||
#
|
#
|
||||||
# Required +options+ are either of:
|
# Required +options+ are either of:
|
||||||
# <tt>:url</tt>:: +url_for+-style options for the action to call
|
# <tt>:url</tt>:: +url_for+-style options for the action to call
|
||||||
|
|
@ -268,14 +270,24 @@ module ActionView
|
||||||
# <tt>:update</tt>:: Specifies the DOM ID of the element whose
|
# <tt>:update</tt>:: Specifies the DOM ID of the element whose
|
||||||
# innerHTML should be updated with the
|
# innerHTML should be updated with the
|
||||||
# XMLHttpRequest response text.
|
# XMLHttpRequest response text.
|
||||||
# <tt>:with</tt>:: A JavaScript expression specifying the
|
# <tt>:with</tt>:: A JavaScript expression specifying the parameters
|
||||||
# parameters for the XMLHttpRequest. This defaults
|
# for the XMLHttpRequest. The default is to send the
|
||||||
# to 'value', which in the evaluated context
|
# key and value of the observed field. Any custom
|
||||||
# refers to the new field value. If you specify a
|
# expressions should return a valid URL query string.
|
||||||
# string without a "=", it'll be extended to mean
|
# The value of the field is stored in the JavaScript
|
||||||
# the form key that the value should be assigned to.
|
# variable +value+.
|
||||||
# So :with => "term" gives "'term'=value". If a "=" is
|
#
|
||||||
# present, no extension will happen.
|
# Examples
|
||||||
|
#
|
||||||
|
# :with => "'my_custom_key=' + value"
|
||||||
|
# :with => "'person[name]=' + prompt('New name')"
|
||||||
|
# :with => "Form.Element.serialize('other-field')"
|
||||||
|
#
|
||||||
|
# Finally
|
||||||
|
# :with => 'name'
|
||||||
|
# is shorthand for
|
||||||
|
# :with => "'name=' + value"
|
||||||
|
# This essentially just changes the key of the parameter.
|
||||||
# <tt>:on</tt>:: Specifies which event handler to observe. By default,
|
# <tt>:on</tt>:: Specifies which event handler to observe. By default,
|
||||||
# it's set to "changed" for text fields and areas and
|
# it's set to "changed" for text fields and areas and
|
||||||
# "click" for radio buttons and checkboxes. With this,
|
# "click" for radio buttons and checkboxes. With this,
|
||||||
|
|
@ -291,11 +303,15 @@ module ActionView
|
||||||
build_observer('Form.Element.EventObserver', field_id, options)
|
build_observer('Form.Element.EventObserver', field_id, options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Like +observe_field+, but operates on an entire form identified by the
|
# Observes the form with the DOM ID specified by +form_id+ and calls a
|
||||||
# DOM ID +form_id+. +options+ are the same as +observe_field+, except
|
# callback when its contents have changed. The default callback is an
|
||||||
# the default value of the <tt>:with</tt> option evaluates to the
|
# Ajax call. By default all fields of the observed field are sent as
|
||||||
# serialized (request string) value of the form.
|
# parameters with the Ajax call.
|
||||||
|
#
|
||||||
|
# The +options+ for +observe_form+ are the same as the options for
|
||||||
|
# +observe_field+. The JavaScript variable +value+ available to the
|
||||||
|
# <tt>:with</tt> option is set to the serialized form by default.
|
||||||
def observe_form(form_id, options = {})
|
def observe_form(form_id, options = {})
|
||||||
if options[:frequency]
|
if options[:frequency]
|
||||||
build_observer('Form.Observer', form_id, options)
|
build_observer('Form.Observer', form_id, options)
|
||||||
|
|
@ -660,10 +676,10 @@ module ActionView
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_observer(klass, name, options = {})
|
def build_observer(klass, name, options = {})
|
||||||
if options[:with] && !options[:with].include?("=")
|
if options[:with] && (options[:with] !~ /[=(.]/)
|
||||||
options[:with] = "'#{options[:with]}=' + value"
|
options[:with] = "'#{options[:with]}=' + value"
|
||||||
else
|
else
|
||||||
options[:with] ||= 'value' if options[:update]
|
options[:with] ||= 'value' unless options[:function]
|
||||||
end
|
end
|
||||||
|
|
||||||
callback = options[:function] || remote_function(options)
|
callback = options[:function] || remote_function(options)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ class PaginationTest < ActiveRecordTestCase
|
||||||
|
|
||||||
class PaginationController < ActionController::Base
|
class PaginationController < ActionController::Base
|
||||||
self.template_root = "#{File.dirname(__FILE__)}/../fixtures/"
|
self.template_root = "#{File.dirname(__FILE__)}/../fixtures/"
|
||||||
|
|
||||||
|
around_filter :silence_deprecation_warnings
|
||||||
|
|
||||||
def simple_paginate
|
def simple_paginate
|
||||||
@topic_pages, @topics = paginate(:topics)
|
@topic_pages, @topics = paginate(:topics)
|
||||||
|
|
@ -67,6 +69,13 @@ class PaginationTest < ActiveRecordTestCase
|
||||||
:count => "d.id")
|
:count => "d.id")
|
||||||
render :nothing => true
|
render :nothing => true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def silence_deprecation_warnings
|
||||||
|
ActiveSupport::Deprecation.silence do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def rescue_errors(e) raise e end
|
def rescue_errors(e) raise e end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ class ActionPackAssertionsController < ActionController::Base
|
||||||
|
|
||||||
def redirect_to_controller() redirect_to :controller => "elsewhere", :action => "flash_me"; end
|
def redirect_to_controller() redirect_to :controller => "elsewhere", :action => "flash_me"; end
|
||||||
|
|
||||||
|
def redirect_to_controller_with_symbol() redirect_to :controller => :elsewhere, :action => :flash_me; end
|
||||||
|
|
||||||
def redirect_to_path() redirect_to '/some/path' end
|
def redirect_to_path() redirect_to '/some/path' end
|
||||||
|
|
||||||
def redirect_to_named_route() redirect_to route_one_url end
|
def redirect_to_named_route() redirect_to route_one_url end
|
||||||
|
|
@ -555,6 +557,17 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
||||||
assert_redirected_to 'http://test.host/some/path'
|
assert_redirected_to 'http://test.host/some/path'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_assert_redirection_with_symbol
|
||||||
|
process :redirect_to_controller_with_symbol
|
||||||
|
assert_nothing_raised {
|
||||||
|
assert_redirected_to :controller => "elsewhere", :action => "flash_me"
|
||||||
|
}
|
||||||
|
process :redirect_to_controller_with_symbol
|
||||||
|
assert_nothing_raised {
|
||||||
|
assert_redirected_to :controller => :elsewhere, :action => :flash_me
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def test_redirected_to_with_nested_controller
|
def test_redirected_to_with_nested_controller
|
||||||
@controller = Admin::InnerModuleController.new
|
@controller = Admin::InnerModuleController.new
|
||||||
get :redirect_to_absolute_controller
|
get :redirect_to_absolute_controller
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,10 @@ class AddressesTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_list
|
def test_list
|
||||||
get :list
|
# because pagination is deprecated
|
||||||
|
ActiveSupport::Deprecation.silence do
|
||||||
|
get :list
|
||||||
|
end
|
||||||
assert_equal "We only need to get this far!", @response.body.chomp
|
assert_equal "We only need to get this far!", @response.body.chomp
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ class ControllerInstanceTests < Test::Unit::TestCase
|
||||||
# Mocha adds methods to Object which are then included in the public_instance_methods
|
# Mocha adds methods to Object which are then included in the public_instance_methods
|
||||||
# This method hides those from the controller so the above tests won't know the difference
|
# This method hides those from the controller so the above tests won't know the difference
|
||||||
def hide_mocha_methods_from_controller(controller)
|
def hide_mocha_methods_from_controller(controller)
|
||||||
mocha_methods = [:expects, :metaclass, :mocha, :mocha_inspect, :reset_mocha, :stubba_object, :stubba_method, :stubs, :verify]
|
mocha_methods = [:expects, :metaclass, :mocha, :mocha_inspect, :reset_mocha, :stubba_object, :stubba_method, :stubs, :verify, :__is_a__, :__metaclass__]
|
||||||
controller.class.send(:hide_action, *mocha_methods)
|
controller.class.send(:hide_action, *mocha_methods)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ class ActionCachingTestController < ActionController::Base
|
||||||
caches_action :index
|
caches_action :index
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
sleep 0.01
|
||||||
@cache_this = Time.now.to_f.to_s
|
@cache_this = Time.now.to_f.to_s
|
||||||
render :text => @cache_this
|
render :text => @cache_this
|
||||||
end
|
end
|
||||||
|
|
@ -195,7 +196,7 @@ class ActionCacheTest < Test::Unit::TestCase
|
||||||
def test_xml_version_of_resource_is_treated_as_different_cache
|
def test_xml_version_of_resource_is_treated_as_different_cache
|
||||||
@mock_controller.mock_url_for = 'http://example.org/posts/'
|
@mock_controller.mock_url_for = 'http://example.org/posts/'
|
||||||
@mock_controller.mock_path = '/posts/index.xml'
|
@mock_controller.mock_path = '/posts/index.xml'
|
||||||
path_object = @path_class.new(@mock_controller)
|
path_object = @path_class.new(@mock_controller, {})
|
||||||
assert_equal 'xml', path_object.extension
|
assert_equal 'xml', path_object.extension
|
||||||
assert_equal 'example.org/posts/index.xml', path_object.path
|
assert_equal 'example.org/posts/index.xml', path_object.path
|
||||||
end
|
end
|
||||||
|
|
@ -204,7 +205,7 @@ class ActionCacheTest < Test::Unit::TestCase
|
||||||
@mock_controller.mock_url_for = 'http://example.org/'
|
@mock_controller.mock_url_for = 'http://example.org/'
|
||||||
@mock_controller.mock_path = '/'
|
@mock_controller.mock_path = '/'
|
||||||
|
|
||||||
assert_equal 'example.org/index', @path_class.path_for(@mock_controller)
|
assert_equal 'example.org/index', @path_class.path_for(@mock_controller, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_file_extensions
|
def test_file_extensions
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,11 @@ class CookieTest < Test::Unit::TestCase
|
||||||
cookies.delete("user_name")
|
cookies.delete("user_name")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def delete_cookie_with_path
|
||||||
|
cookies.delete("user_name", :path => '/beaten')
|
||||||
|
render_text "hello world"
|
||||||
|
end
|
||||||
|
|
||||||
def rescue_action(e)
|
def rescue_action(e)
|
||||||
raise unless ActionController::MissingTemplate # No templates here, and we don't care about the output
|
raise unless ActionController::MissingTemplate # No templates here, and we don't care about the output
|
||||||
end
|
end
|
||||||
|
|
@ -85,4 +90,10 @@ class CookieTest < Test::Unit::TestCase
|
||||||
assert_equal "david", jar["user_name"]
|
assert_equal "david", jar["user_name"]
|
||||||
assert_equal nil, jar["something_else"]
|
assert_equal nil, jar["something_else"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_delete_cookie_with_path
|
||||||
|
get :delete_cookie_with_path
|
||||||
|
assert_equal "/beaten", @response.headers["cookie"].first.path
|
||||||
|
assert_not_equal "/", @response.headers["cookie"].first.path
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
require File.dirname(__FILE__) + '/../../abstract_unit'
|
require File.dirname(__FILE__) + '/../../abstract_unit'
|
||||||
|
|
||||||
class DeprecatedBaseMethodsTest < Test::Unit::TestCase
|
class DeprecatedBaseMethodsTest < Test::Unit::TestCase
|
||||||
|
# ActiveRecord model mock to test pagination deprecation
|
||||||
|
class DummyModel
|
||||||
|
def self.find(*args) [] end
|
||||||
|
def self.count(*args) 0 end
|
||||||
|
end
|
||||||
|
|
||||||
class Target < ActionController::Base
|
class Target < ActionController::Base
|
||||||
def deprecated_symbol_parameter_to_url_for
|
def deprecated_symbol_parameter_to_url_for
|
||||||
redirect_to(url_for(:home_url, "superstars"))
|
redirect_to(url_for(:home_url, "superstars"))
|
||||||
|
|
@ -18,6 +24,11 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase
|
||||||
this_method_doesnt_exist
|
this_method_doesnt_exist
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pagination
|
||||||
|
paginate :dummy_models, :class_name => 'DeprecatedBaseMethodsTest::DummyModel'
|
||||||
|
render :nothing => true
|
||||||
|
end
|
||||||
|
|
||||||
def rescue_action(e) raise e end
|
def rescue_action(e) raise e end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -27,6 +38,7 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase
|
||||||
@request = ActionController::TestRequest.new
|
@request = ActionController::TestRequest.new
|
||||||
@response = ActionController::TestResponse.new
|
@response = ActionController::TestResponse.new
|
||||||
@controller = Target.new
|
@controller = Target.new
|
||||||
|
@controller.logger = Logger.new(nil) unless @controller.logger
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_deprecated_symbol_parameter_to_url_for
|
def test_deprecated_symbol_parameter_to_url_for
|
||||||
|
|
@ -57,4 +69,10 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase
|
||||||
error = Test::Unit::Error.new('testing ur doodz', e)
|
error = Test::Unit::Error.new('testing ur doodz', e)
|
||||||
assert_not_deprecated { error.message }
|
assert_not_deprecated { error.message }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_pagination_deprecation
|
||||||
|
assert_deprecated('svn://errtheblog.com/svn/plugins/classic_pagination') do
|
||||||
|
get :pagination
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class FilterParamTest < Test::Unit::TestCase
|
||||||
assert @controller.respond_to?(:filter_parameters)
|
assert @controller.respond_to?(:filter_parameters)
|
||||||
|
|
||||||
test_hashes = [[{},{},[]],
|
test_hashes = [[{},{},[]],
|
||||||
|
[{'foo'=>nil},{'foo'=>nil},[]],
|
||||||
[{'foo'=>'bar'},{'foo'=>'bar'},[]],
|
[{'foo'=>'bar'},{'foo'=>'bar'},[]],
|
||||||
[{'foo'=>'bar'},{'foo'=>'bar'},%w'food'],
|
[{'foo'=>'bar'},{'foo'=>'bar'},%w'food'],
|
||||||
[{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'],
|
[{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'],
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
@ran_filter ||= []
|
@ran_filter ||= []
|
||||||
@ran_filter << "ensure_login"
|
@ran_filter << "ensure_login"
|
||||||
end
|
end
|
||||||
|
|
||||||
def clean_up
|
def clean_up
|
||||||
@ran_after_filter ||= []
|
@ran_after_filter ||= []
|
||||||
@ran_after_filter << "clean_up"
|
@ran_after_filter << "clean_up"
|
||||||
|
|
@ -62,7 +62,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
render :inline => "something else"
|
render :inline => "something else"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ConditionalFilterController < ActionController::Base
|
class ConditionalFilterController < ActionController::Base
|
||||||
def show
|
def show
|
||||||
render :inline => "ran action"
|
render :inline => "ran action"
|
||||||
|
|
@ -86,7 +86,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
@ran_filter ||= []
|
@ran_filter ||= []
|
||||||
@ran_filter << "clean_up_tmp"
|
@ran_filter << "clean_up_tmp"
|
||||||
end
|
end
|
||||||
|
|
||||||
def rescue_action(e) raise(e) end
|
def rescue_action(e) raise(e) end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
before_filter :ensure_login, :except => [ :show_without_filter, :another_action ]
|
before_filter :ensure_login, :except => [ :show_without_filter, :another_action ]
|
||||||
end
|
end
|
||||||
|
|
||||||
class OnlyConditionSymController < ConditionalFilterController
|
class OnlyConditionSymController < ConditionalFilterController
|
||||||
before_filter :ensure_login, :only => :show
|
before_filter :ensure_login, :only => :show
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -104,10 +104,10 @@ class FilterTest < Test::Unit::TestCase
|
||||||
|
|
||||||
class BeforeAndAfterConditionController < ConditionalFilterController
|
class BeforeAndAfterConditionController < ConditionalFilterController
|
||||||
before_filter :ensure_login, :only => :show
|
before_filter :ensure_login, :only => :show
|
||||||
after_filter :clean_up_tmp, :only => :show
|
after_filter :clean_up_tmp, :only => :show
|
||||||
end
|
end
|
||||||
|
|
||||||
class OnlyConditionProcController < ConditionalFilterController
|
class OnlyConditionProcController < ConditionalFilterController
|
||||||
before_filter(:only => :show) {|c| c.assigns["ran_proc_filter"] = true }
|
before_filter(:only => :show) {|c| c.assigns["ran_proc_filter"] = true }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -131,6 +131,14 @@ class FilterTest < Test::Unit::TestCase
|
||||||
before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.assigns["ran_proc_filter1"] = true }, :except => :show_without_filter) { |c| c.assigns["ran_proc_filter2"] = true}
|
before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.assigns["ran_proc_filter1"] = true }, :except => :show_without_filter) { |c| c.assigns["ran_proc_filter2"] = true}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class EmptyFilterChainController < TestController
|
||||||
|
self.filter_chain.clear
|
||||||
|
def show
|
||||||
|
@action_executed = true
|
||||||
|
render :text => "yawp!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class PrependingController < TestController
|
class PrependingController < TestController
|
||||||
prepend_before_filter :wonderful_life
|
prepend_before_filter :wonderful_life
|
||||||
# skip_before_filter :fire_flash
|
# skip_before_filter :fire_flash
|
||||||
|
|
@ -145,7 +153,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
class ConditionalSkippingController < TestController
|
class ConditionalSkippingController < TestController
|
||||||
skip_before_filter :ensure_login, :only => [ :login ]
|
skip_before_filter :ensure_login, :only => [ :login ]
|
||||||
skip_after_filter :clean_up, :only => [ :login ]
|
skip_after_filter :clean_up, :only => [ :login ]
|
||||||
|
|
||||||
before_filter :find_user, :only => [ :change_password ]
|
before_filter :find_user, :only => [ :change_password ]
|
||||||
|
|
||||||
def login
|
def login
|
||||||
|
|
@ -155,7 +163,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
def change_password
|
def change_password
|
||||||
render :inline => "ran action"
|
render :inline => "ran action"
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def find_user
|
def find_user
|
||||||
@ran_filter ||= []
|
@ran_filter ||= []
|
||||||
|
|
@ -166,15 +174,15 @@ class FilterTest < Test::Unit::TestCase
|
||||||
class ConditionalParentOfConditionalSkippingController < ConditionalFilterController
|
class ConditionalParentOfConditionalSkippingController < ConditionalFilterController
|
||||||
before_filter :conditional_in_parent, :only => [:show, :another_action]
|
before_filter :conditional_in_parent, :only => [:show, :another_action]
|
||||||
after_filter :conditional_in_parent, :only => [:show, :another_action]
|
after_filter :conditional_in_parent, :only => [:show, :another_action]
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def conditional_in_parent
|
def conditional_in_parent
|
||||||
@ran_filter ||= []
|
@ran_filter ||= []
|
||||||
@ran_filter << 'conditional_in_parent'
|
@ran_filter << 'conditional_in_parent'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController
|
class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController
|
||||||
skip_before_filter :conditional_in_parent, :only => :another_action
|
skip_before_filter :conditional_in_parent, :only => :another_action
|
||||||
skip_after_filter :conditional_in_parent, :only => :another_action
|
skip_after_filter :conditional_in_parent, :only => :another_action
|
||||||
|
|
@ -197,7 +205,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
controller.assigns["was_audited"] = true
|
controller.assigns["was_audited"] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AroundFilter
|
class AroundFilter
|
||||||
def before(controller)
|
def before(controller)
|
||||||
@execution_log = "before"
|
@execution_log = "before"
|
||||||
|
|
@ -209,7 +217,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
controller.assigns["execution_log"] = @execution_log + " and after"
|
controller.assigns["execution_log"] = @execution_log + " and after"
|
||||||
controller.assigns["after_ran"] = true
|
controller.assigns["after_ran"] = true
|
||||||
controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log
|
controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AppendedAroundFilter
|
class AppendedAroundFilter
|
||||||
|
|
@ -219,12 +227,12 @@ class FilterTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def after(controller)
|
def after(controller)
|
||||||
controller.class.execution_log << " after appended aroundfilter "
|
controller.class.execution_log << " after appended aroundfilter "
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AuditController < ActionController::Base
|
class AuditController < ActionController::Base
|
||||||
before_filter(AuditFilter)
|
before_filter(AuditFilter)
|
||||||
|
|
||||||
def show
|
def show
|
||||||
render_text "hello"
|
render_text "hello"
|
||||||
end
|
end
|
||||||
|
|
@ -234,6 +242,14 @@ class FilterTest < Test::Unit::TestCase
|
||||||
around_filter AroundFilter.new
|
around_filter AroundFilter.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class BeforeAfterClassFilterController < PrependingController
|
||||||
|
begin
|
||||||
|
filter = AroundFilter.new
|
||||||
|
before_filter filter
|
||||||
|
after_filter filter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class MixedFilterController < PrependingController
|
class MixedFilterController < PrependingController
|
||||||
cattr_accessor :execution_log
|
cattr_accessor :execution_log
|
||||||
|
|
||||||
|
|
@ -247,7 +263,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
after_filter { |c| c.class.execution_log << " after procfilter " }
|
after_filter { |c| c.class.execution_log << " after procfilter " }
|
||||||
append_around_filter AppendedAroundFilter.new
|
append_around_filter AppendedAroundFilter.new
|
||||||
end
|
end
|
||||||
|
|
||||||
class MixedSpecializationController < ActionController::Base
|
class MixedSpecializationController < ActionController::Base
|
||||||
class OutOfOrder < StandardError; end
|
class OutOfOrder < StandardError; end
|
||||||
|
|
||||||
|
|
@ -285,6 +301,101 @@ class FilterTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class PrependingBeforeAndAfterController < ActionController::Base
|
||||||
|
prepend_before_filter :before_all
|
||||||
|
prepend_after_filter :after_all
|
||||||
|
before_filter :between_before_all_and_after_all
|
||||||
|
|
||||||
|
def before_all
|
||||||
|
@ran_filter ||= []
|
||||||
|
@ran_filter << 'before_all'
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_all
|
||||||
|
@ran_filter ||= []
|
||||||
|
@ran_filter << 'after_all'
|
||||||
|
end
|
||||||
|
|
||||||
|
def between_before_all_and_after_all
|
||||||
|
@ran_filter ||= []
|
||||||
|
@ran_filter << 'between_before_all_and_after_all'
|
||||||
|
end
|
||||||
|
def show
|
||||||
|
render :text => 'hello'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class NonYieldingAroundFilterController < ActionController::Base
|
||||||
|
|
||||||
|
before_filter :filter_one
|
||||||
|
around_filter :non_yielding_filter
|
||||||
|
before_filter :filter_two
|
||||||
|
after_filter :filter_three
|
||||||
|
|
||||||
|
def index
|
||||||
|
render :inline => "index"
|
||||||
|
end
|
||||||
|
|
||||||
|
#make sure the controller complains
|
||||||
|
def rescue_action(e); raise e; end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def filter_one
|
||||||
|
@filters ||= []
|
||||||
|
@filters << "filter_one"
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_two
|
||||||
|
@filters << "filter_two"
|
||||||
|
end
|
||||||
|
|
||||||
|
def non_yielding_filter
|
||||||
|
@filters << "zomg it didn't yield"
|
||||||
|
@filter_return_value
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_three
|
||||||
|
@filters << "filter_three"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_yielding_around_filters_not_returning_false_do_not_raise
|
||||||
|
controller = NonYieldingAroundFilterController.new
|
||||||
|
controller.instance_variable_set "@filter_return_value", true
|
||||||
|
assert_nothing_raised do
|
||||||
|
test_process(controller, "index")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_yielding_around_filters_returning_false_do_not_raise
|
||||||
|
controller = NonYieldingAroundFilterController.new
|
||||||
|
controller.instance_variable_set "@filter_return_value", false
|
||||||
|
assert_nothing_raised do
|
||||||
|
test_process(controller, "index")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_after_filters_are_not_run_if_around_filter_returns_false
|
||||||
|
controller = NonYieldingAroundFilterController.new
|
||||||
|
controller.instance_variable_set "@filter_return_value", false
|
||||||
|
test_process(controller, "index")
|
||||||
|
assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters']
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_after_filters_are_not_run_if_around_filter_does_not_yield
|
||||||
|
controller = NonYieldingAroundFilterController.new
|
||||||
|
controller.instance_variable_set "@filter_return_value", true
|
||||||
|
test_process(controller, "index")
|
||||||
|
assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters']
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_empty_filter_chain
|
||||||
|
assert_equal 0, EmptyFilterChainController.filter_chain.size
|
||||||
|
assert test_process(EmptyFilterChainController).template.assigns['action_executed']
|
||||||
|
end
|
||||||
|
|
||||||
def test_added_filter_to_inheritance_graph
|
def test_added_filter_to_inheritance_graph
|
||||||
assert_equal [ :ensure_login ], TestController.before_filters
|
assert_equal [ :ensure_login ], TestController.before_filters
|
||||||
end
|
end
|
||||||
|
|
@ -292,11 +403,11 @@ class FilterTest < Test::Unit::TestCase
|
||||||
def test_base_class_in_isolation
|
def test_base_class_in_isolation
|
||||||
assert_equal [ ], ActionController::Base.before_filters
|
assert_equal [ ], ActionController::Base.before_filters
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_prepending_filter
|
def test_prepending_filter
|
||||||
assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_filters
|
assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_filters
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_running_filters
|
def test_running_filters
|
||||||
assert_equal %w( wonderful_life ensure_login ), test_process(PrependingController).template.assigns["ran_filter"]
|
assert_equal %w( wonderful_life ensure_login ), test_process(PrependingController).template.assigns["ran_filter"]
|
||||||
end
|
end
|
||||||
|
|
@ -304,11 +415,11 @@ class FilterTest < Test::Unit::TestCase
|
||||||
def test_running_filters_with_proc
|
def test_running_filters_with_proc
|
||||||
assert test_process(ProcController).template.assigns["ran_proc_filter"]
|
assert test_process(ProcController).template.assigns["ran_proc_filter"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_running_filters_with_implicit_proc
|
def test_running_filters_with_implicit_proc
|
||||||
assert test_process(ImplicitProcController).template.assigns["ran_proc_filter"]
|
assert test_process(ImplicitProcController).template.assigns["ran_proc_filter"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_running_filters_with_class
|
def test_running_filters_with_class
|
||||||
assert test_process(AuditController).template.assigns["was_audited"]
|
assert test_process(AuditController).template.assigns["was_audited"]
|
||||||
end
|
end
|
||||||
|
|
@ -319,7 +430,7 @@ class FilterTest < Test::Unit::TestCase
|
||||||
assert response.template.assigns["ran_class_filter"]
|
assert response.template.assigns["ran_class_filter"]
|
||||||
assert response.template.assigns["ran_proc_filter1"]
|
assert response.template.assigns["ran_proc_filter1"]
|
||||||
assert response.template.assigns["ran_proc_filter2"]
|
assert response.template.assigns["ran_proc_filter2"]
|
||||||
|
|
||||||
response = test_process(AnomolousYetValidConditionController, "show_without_filter")
|
response = test_process(AnomolousYetValidConditionController, "show_without_filter")
|
||||||
assert_equal nil, response.template.assigns["ran_filter"]
|
assert_equal nil, response.template.assigns["ran_filter"]
|
||||||
assert !response.template.assigns["ran_class_filter"]
|
assert !response.template.assigns["ran_class_filter"]
|
||||||
|
|
@ -373,6 +484,12 @@ class FilterTest < Test::Unit::TestCase
|
||||||
assert controller.template.assigns["after_ran"]
|
assert controller.template.assigns["after_ran"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_before_after_class_filter
|
||||||
|
controller = test_process(BeforeAfterClassFilterController)
|
||||||
|
assert controller.template.assigns["before_ran"]
|
||||||
|
assert controller.template.assigns["after_ran"]
|
||||||
|
end
|
||||||
|
|
||||||
def test_having_properties_in_around_filter
|
def test_having_properties_in_around_filter
|
||||||
controller = test_process(AroundFilterController)
|
controller = test_process(AroundFilterController)
|
||||||
assert_equal "before and after", controller.template.assigns["execution_log"]
|
assert_equal "before and after", controller.template.assigns["execution_log"]
|
||||||
|
|
@ -381,10 +498,10 @@ class FilterTest < Test::Unit::TestCase
|
||||||
def test_prepending_and_appending_around_filter
|
def test_prepending_and_appending_around_filter
|
||||||
controller = test_process(MixedFilterController)
|
controller = test_process(MixedFilterController)
|
||||||
assert_equal " before aroundfilter before procfilter before appended aroundfilter " +
|
assert_equal " before aroundfilter before procfilter before appended aroundfilter " +
|
||||||
" after appended aroundfilter after aroundfilter after procfilter ",
|
" after appended aroundfilter after aroundfilter after procfilter ",
|
||||||
MixedFilterController.execution_log
|
MixedFilterController.execution_log
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_rendering_breaks_filtering_chain
|
def test_rendering_breaks_filtering_chain
|
||||||
response = test_process(RenderingController)
|
response = test_process(RenderingController)
|
||||||
assert_equal "something else", response.body
|
assert_equal "something else", response.body
|
||||||
|
|
@ -412,6 +529,12 @@ class FilterTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_running_prepended_before_and_after_filter
|
||||||
|
assert_equal 3, PrependingBeforeAndAfterController.filter_chain.length
|
||||||
|
response = test_process(PrependingBeforeAndAfterController)
|
||||||
|
assert_equal %w( before_all between_before_all_and_after_all after_all ), response.template.assigns["ran_filter"]
|
||||||
|
end
|
||||||
|
|
||||||
def test_conditional_skipping_of_filters
|
def test_conditional_skipping_of_filters
|
||||||
assert_nil test_process(ConditionalSkippingController, "login").template.assigns["ran_filter"]
|
assert_nil test_process(ConditionalSkippingController, "login").template.assigns["ran_filter"]
|
||||||
assert_equal %w( ensure_login find_user ), test_process(ConditionalSkippingController, "change_password").template.assigns["ran_filter"]
|
assert_equal %w( ensure_login find_user ), test_process(ConditionalSkippingController, "change_password").template.assigns["ran_filter"]
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ require 'stubba'
|
||||||
module ActionController
|
module ActionController
|
||||||
module Integration
|
module Integration
|
||||||
class Session
|
class Session
|
||||||
def process
|
def process(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def generic_url_rewriter
|
def generic_url_rewriter
|
||||||
|
|
@ -56,8 +56,7 @@ class SessionTest < Test::Unit::TestCase
|
||||||
|
|
||||||
@session.expects(:get).with(path,args)
|
@session.expects(:get).with(path,args)
|
||||||
|
|
||||||
redirects = [true, true, false]
|
@session.stubs(:redirect?).returns(true).then.returns(true).then.returns(false)
|
||||||
@session.stubs(:redirect?).returns(lambda { redirects.shift })
|
|
||||||
@session.expects(:follow_redirect!).times(2)
|
@session.expects(:follow_redirect!).times(2)
|
||||||
|
|
||||||
@session.stubs(:status).returns(200)
|
@session.stubs(:status).returns(200)
|
||||||
|
|
@ -69,8 +68,7 @@ class SessionTest < Test::Unit::TestCase
|
||||||
|
|
||||||
@session.expects(:post).with(path,args)
|
@session.expects(:post).with(path,args)
|
||||||
|
|
||||||
redirects = [true, true, false]
|
@session.stubs(:redirect?).returns(true).then.returns(true).then.returns(false)
|
||||||
@session.stubs(:redirect?).returns(lambda { redirects.shift })
|
|
||||||
@session.expects(:follow_redirect!).times(2)
|
@session.expects(:follow_redirect!).times(2)
|
||||||
|
|
||||||
@session.stubs(:status).returns(200)
|
@session.stubs(:status).returns(200)
|
||||||
|
|
@ -134,15 +132,102 @@ class SessionTest < Test::Unit::TestCase
|
||||||
@session.head(path,params,headers)
|
@session.head(path,params,headers)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_xml_http_request
|
def test_xml_http_request_deprecated_call
|
||||||
path = "/index"; params = "blah"; headers = {:location => 'blah'}
|
path = "/index"; params = "blah"; headers = {:location => 'blah'}
|
||||||
headers_after_xhr = headers.merge(
|
headers_after_xhr = headers.merge(
|
||||||
"X-Requested-With" => "XMLHttpRequest",
|
"X-Requested-With" => "XMLHttpRequest",
|
||||||
"Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
|
"Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
|
||||||
)
|
)
|
||||||
@session.expects(:post).with(path,params,headers_after_xhr)
|
@session.expects(:process).with(:post,path,params,headers_after_xhr)
|
||||||
@session.xml_http_request(path,params,headers)
|
assert_deprecated { @session.xml_http_request(path,params,headers) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_xml_http_request_get
|
||||||
|
path = "/index"; params = "blah"; headers = {:location => 'blah'}
|
||||||
|
headers_after_xhr = headers.merge(
|
||||||
|
"X-Requested-With" => "XMLHttpRequest",
|
||||||
|
"Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
|
||||||
|
)
|
||||||
|
@session.expects(:process).with(:get,path,params,headers_after_xhr)
|
||||||
|
@session.xml_http_request(:get,path,params,headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_xml_http_request_post
|
||||||
|
path = "/index"; params = "blah"; headers = {:location => 'blah'}
|
||||||
|
headers_after_xhr = headers.merge(
|
||||||
|
"X-Requested-With" => "XMLHttpRequest",
|
||||||
|
"Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
|
||||||
|
)
|
||||||
|
@session.expects(:process).with(:post,path,params,headers_after_xhr)
|
||||||
|
@session.xml_http_request(:post,path,params,headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_xml_http_request_put
|
||||||
|
path = "/index"; params = "blah"; headers = {:location => 'blah'}
|
||||||
|
headers_after_xhr = headers.merge(
|
||||||
|
"X-Requested-With" => "XMLHttpRequest",
|
||||||
|
"Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
|
||||||
|
)
|
||||||
|
@session.expects(:process).with(:put,path,params,headers_after_xhr)
|
||||||
|
@session.xml_http_request(:put,path,params,headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_xml_http_request_delete
|
||||||
|
path = "/index"; params = "blah"; headers = {:location => 'blah'}
|
||||||
|
headers_after_xhr = headers.merge(
|
||||||
|
"X-Requested-With" => "XMLHttpRequest",
|
||||||
|
"Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
|
||||||
|
)
|
||||||
|
@session.expects(:process).with(:delete,path,params,headers_after_xhr)
|
||||||
|
@session.xml_http_request(:delete,path,params,headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_xml_http_request_head
|
||||||
|
path = "/index"; params = "blah"; headers = {:location => 'blah'}
|
||||||
|
headers_after_xhr = headers.merge(
|
||||||
|
"X-Requested-With" => "XMLHttpRequest",
|
||||||
|
"Accept" => "text/javascript, text/html, application/xml, text/xml, */*"
|
||||||
|
)
|
||||||
|
@session.expects(:process).with(:head,path,params,headers_after_xhr)
|
||||||
|
@session.xml_http_request(:head,path,params,headers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class IntegrationTestTest < Test::Unit::TestCase
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@test = ::ActionController::IntegrationTest.new(:default_test)
|
||||||
|
@test.class.stubs(:fixture_table_names).returns([])
|
||||||
|
@session = @test.open_session
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_opens_new_session
|
||||||
|
@test.class.expects(:fixture_table_names).times(2).returns(['foo'])
|
||||||
|
|
||||||
|
session1 = @test.open_session { |sess| }
|
||||||
|
session2 = @test.open_session # implicit session
|
||||||
|
|
||||||
|
assert_equal ::ActionController::Integration::Session, session1.class
|
||||||
|
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.
|
||||||
|
# Integration tests have their own setup and teardown.
|
||||||
|
class IntegrationTestUsesCorrectClass < ActionController::IntegrationTest
|
||||||
|
|
||||||
|
def self.fixture_table_names
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_integration_methods_called
|
||||||
|
%w( get post head put delete ).each do |verb|
|
||||||
|
assert_nothing_raised("'#{verb}' should use integration test methods") { send(verb, '/') }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ class ThreadsController < ResourcesController; end
|
||||||
class MessagesController < ResourcesController; end
|
class MessagesController < ResourcesController; end
|
||||||
class CommentsController < ResourcesController; end
|
class CommentsController < ResourcesController; end
|
||||||
|
|
||||||
class AccountController < ResourcesController; end
|
class AccountController < ResourcesController; end
|
||||||
class AdminController < ResourcesController; end
|
class AdminController < ResourcesController; end
|
||||||
|
class ProductsController < ResourcesController; end
|
||||||
|
|
||||||
class ResourcesTest < Test::Unit::TestCase
|
class ResourcesTest < Test::Unit::TestCase
|
||||||
def test_should_arrange_actions
|
def test_should_arrange_actions
|
||||||
|
|
@ -63,13 +64,13 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_multile_with_path_prefix
|
def test_multiple_with_path_prefix
|
||||||
with_restful_routing :messages, :comments, :path_prefix => '/thread/:thread_id' do
|
with_restful_routing :messages, :comments, :path_prefix => '/thread/:thread_id' do
|
||||||
assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
|
assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
|
||||||
assert_simply_restful_for :comments, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
|
assert_simply_restful_for :comments, :path_prefix => 'thread/5/', :options => { :thread_id => '5' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_with_name_prefix
|
def test_with_name_prefix
|
||||||
with_restful_routing :messages, :name_prefix => 'post_' do
|
with_restful_routing :messages, :name_prefix => 'post_' do
|
||||||
assert_simply_restful_for :messages, :name_prefix => 'post_'
|
assert_simply_restful_for :messages, :name_prefix => 'post_'
|
||||||
|
|
@ -78,7 +79,7 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def test_with_collection_action
|
def test_with_collection_action
|
||||||
rss_options = {:action => 'rss'}
|
rss_options = {:action => 'rss'}
|
||||||
rss_path = "/messages;rss"
|
rss_path = "/messages/rss"
|
||||||
actions = { 'a' => :put, 'b' => :post, 'c' => :delete }
|
actions = { 'a' => :put, 'b' => :post, 'c' => :delete }
|
||||||
|
|
||||||
with_restful_routing :messages, :collection => { :rss => :get }.merge(actions) do
|
with_restful_routing :messages, :collection => { :rss => :get }.merge(actions) do
|
||||||
|
|
@ -86,14 +87,14 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
assert_routing rss_path, options.merge(rss_options)
|
assert_routing rss_path, options.merge(rss_options)
|
||||||
|
|
||||||
actions.each do |action, method|
|
actions.each do |action, method|
|
||||||
assert_recognizes(options.merge(:action => action), :path => "/messages;#{action}", :method => method)
|
assert_recognizes(options.merge(:action => action), :path => "/messages/#{action}", :method => method)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_restful_named_routes_for :messages do |options|
|
assert_restful_named_routes_for :messages do |options|
|
||||||
assert_named_route rss_path, :rss_messages_path, rss_options
|
assert_named_route rss_path, :rss_messages_path, rss_options
|
||||||
actions.keys.each do |action|
|
actions.keys.each do |action|
|
||||||
assert_named_route "/messages;#{action}", "#{action}_messages_path", :action => action
|
assert_named_route "/messages/#{action}", "#{action}_messages_path", :action => action
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -103,7 +104,7 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
[:put, :post].each do |method|
|
[:put, :post].each do |method|
|
||||||
with_restful_routing :messages, :member => { :mark => method } do
|
with_restful_routing :messages, :member => { :mark => method } do
|
||||||
mark_options = {:action => 'mark', :id => '1'}
|
mark_options = {:action => 'mark', :id => '1'}
|
||||||
mark_path = "/messages/1;mark"
|
mark_path = "/messages/1/mark"
|
||||||
assert_restful_routes_for :messages do |options|
|
assert_restful_routes_for :messages do |options|
|
||||||
assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method)
|
assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method)
|
||||||
end
|
end
|
||||||
|
|
@ -120,7 +121,7 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
with_restful_routing :messages, :member => { :mark => method, :unmark => method } do
|
with_restful_routing :messages, :member => { :mark => method, :unmark => method } do
|
||||||
%w(mark unmark).each do |action|
|
%w(mark unmark).each do |action|
|
||||||
action_options = {:action => action, :id => '1'}
|
action_options = {:action => action, :id => '1'}
|
||||||
action_path = "/messages/1;#{action}"
|
action_path = "/messages/1/#{action}"
|
||||||
assert_restful_routes_for :messages do |options|
|
assert_restful_routes_for :messages do |options|
|
||||||
assert_recognizes(options.merge(action_options), :path => action_path, :method => method)
|
assert_recognizes(options.merge(action_options), :path => action_path, :method => method)
|
||||||
end
|
end
|
||||||
|
|
@ -136,7 +137,7 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
def test_with_new_action
|
def test_with_new_action
|
||||||
with_restful_routing :messages, :new => { :preview => :post } do
|
with_restful_routing :messages, :new => { :preview => :post } do
|
||||||
preview_options = {:action => 'preview'}
|
preview_options = {:action => 'preview'}
|
||||||
preview_path = "/messages/new;preview"
|
preview_path = "/messages/new/preview"
|
||||||
assert_restful_routes_for :messages do |options|
|
assert_restful_routes_for :messages do |options|
|
||||||
assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post)
|
assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post)
|
||||||
end
|
end
|
||||||
|
|
@ -178,9 +179,11 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
assert_simply_restful_for :threads
|
assert_simply_restful_for :threads
|
||||||
assert_simply_restful_for :messages,
|
assert_simply_restful_for :messages,
|
||||||
:path_prefix => 'threads/1/',
|
:path_prefix => 'threads/1/',
|
||||||
|
:name_prefix => 'thread_',
|
||||||
:options => { :thread_id => '1' }
|
:options => { :thread_id => '1' }
|
||||||
assert_simply_restful_for :comments,
|
assert_simply_restful_for :comments,
|
||||||
:path_prefix => 'threads/1/messages/2/',
|
:path_prefix => 'threads/1/messages/2/',
|
||||||
|
:name_prefix => 'thread_message_',
|
||||||
:options => { :thread_id => '1', :message_id => '2' }
|
:options => { :thread_id => '1', :message_id => '2' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -217,9 +220,9 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
admin.resource :account
|
admin.resource :account
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_singleton_restful_for :admin
|
assert_singleton_restful_for :admin
|
||||||
assert_singleton_restful_for :account, :path_prefix => 'admin/'
|
assert_singleton_restful_for :account, :path_prefix => 'admin/', :name_prefix => 'admin_'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -227,7 +230,7 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
[:put, :post].each do |method|
|
[:put, :post].each do |method|
|
||||||
with_singleton_resources :account, :member => { :reset => method } do
|
with_singleton_resources :account, :member => { :reset => method } do
|
||||||
reset_options = {:action => 'reset'}
|
reset_options = {:action => 'reset'}
|
||||||
reset_path = "/account;reset"
|
reset_path = "/account/reset"
|
||||||
assert_singleton_routes_for :account do |options|
|
assert_singleton_routes_for :account do |options|
|
||||||
assert_recognizes(options.merge(reset_options), :path => reset_path, :method => method)
|
assert_recognizes(options.merge(reset_options), :path => reset_path, :method => method)
|
||||||
end
|
end
|
||||||
|
|
@ -244,7 +247,7 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
with_singleton_resources :account, :member => { :reset => method, :disable => method } do
|
with_singleton_resources :account, :member => { :reset => method, :disable => method } do
|
||||||
%w(reset disable).each do |action|
|
%w(reset disable).each do |action|
|
||||||
action_options = {:action => action}
|
action_options = {:action => action}
|
||||||
action_path = "/account;#{action}"
|
action_path = "/account/#{action}"
|
||||||
assert_singleton_routes_for :account do |options|
|
assert_singleton_routes_for :account do |options|
|
||||||
assert_recognizes(options.merge(action_options), :path => action_path, :method => method)
|
assert_recognizes(options.merge(action_options), :path => action_path, :method => method)
|
||||||
end
|
end
|
||||||
|
|
@ -264,9 +267,9 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
account.resources :messages
|
account.resources :messages
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_singleton_restful_for :account
|
assert_singleton_restful_for :account
|
||||||
assert_simply_restful_for :messages, :path_prefix => 'account/'
|
assert_simply_restful_for :messages, :path_prefix => 'account/', :name_prefix => 'account_'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -279,10 +282,10 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_singleton_restful_for :account, :path_prefix => '7/', :options => { :site_id => '7' }
|
assert_singleton_restful_for :account, :path_prefix => '7/', :options => { :site_id => '7' }
|
||||||
assert_simply_restful_for :messages, :path_prefix => '7/account/', :options => { :site_id => '7' }
|
assert_simply_restful_for :messages, :path_prefix => '7/account/', :name_prefix => 'account_', :options => { :site_id => '7' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_should_nest_singleton_resource_in_resources
|
def test_should_nest_singleton_resource_in_resources
|
||||||
with_routing do |set|
|
with_routing do |set|
|
||||||
set.draw do |map|
|
set.draw do |map|
|
||||||
|
|
@ -290,9 +293,9 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
thread.resource :admin
|
thread.resource :admin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_simply_restful_for :threads
|
assert_simply_restful_for :threads
|
||||||
assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :options => { :thread_id => '5' }
|
assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :name_prefix => 'thread_', :options => { :thread_id => '5' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -312,6 +315,181 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_resource_action_separator
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id'
|
||||||
|
map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin'
|
||||||
|
end
|
||||||
|
|
||||||
|
action_separator = ActionController::Base.resource_action_separator
|
||||||
|
|
||||||
|
assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' }
|
||||||
|
assert_named_route "/threads/1/messages#{action_separator}search", "search_thread_messages_path", {}
|
||||||
|
assert_named_route "/threads/1/messages/new", "new_thread_message_path", {}
|
||||||
|
assert_named_route "/threads/1/messages/new#{action_separator}preview", "preview_new_thread_message_path", {}
|
||||||
|
assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/'
|
||||||
|
assert_named_route "/admin/account#{action_separator}login", "login_admin_account_path", {}
|
||||||
|
assert_named_route "/admin/account/new", "new_admin_account_path", {}
|
||||||
|
assert_named_route "/admin/account/new#{action_separator}preview", "preview_new_admin_account_path", {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_new_style_named_routes_for_resource
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id'
|
||||||
|
end
|
||||||
|
assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' }
|
||||||
|
assert_named_route "/threads/1/messages/search", "search_thread_messages_path", {}
|
||||||
|
assert_named_route "/threads/1/messages/new", "new_thread_message_path", {}
|
||||||
|
assert_named_route "/threads/1/messages/new/preview", "preview_new_thread_message_path", {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_new_style_named_routes_for_singleton_resource
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin'
|
||||||
|
end
|
||||||
|
assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/'
|
||||||
|
assert_named_route "/admin/account/login", "login_admin_account_path", {}
|
||||||
|
assert_named_route "/admin/account/new", "new_admin_account_path", {}
|
||||||
|
assert_named_route "/admin/account/new/preview", "preview_new_admin_account_path", {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_add_deprecated_named_routes_for_resource
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id'
|
||||||
|
end
|
||||||
|
assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' }
|
||||||
|
assert_deprecated do
|
||||||
|
assert_named_route "/threads/1/messages/search", "thread_search_messages_path", {}
|
||||||
|
assert_named_route "/threads/1/messages/new", "thread_new_message_path", {}
|
||||||
|
assert_named_route "/threads/1/messages/new/preview", "thread_preview_new_message_path", {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_add_deprecated_named_routes_for_singleton_resource
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin'
|
||||||
|
end
|
||||||
|
assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/'
|
||||||
|
assert_deprecated do
|
||||||
|
assert_named_route "/admin/account/login", "admin_login_account_path", {}
|
||||||
|
assert_named_route "/admin/account/new", "admin_new_account_path", {}
|
||||||
|
assert_named_route "/admin/account/new/preview", "admin_preview_new_account_path", {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_add_deprecated_named_routes_for_nested_resources
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resources :threads do |map|
|
||||||
|
map.resources :messages do |map|
|
||||||
|
map.resources :comments
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_simply_restful_for :threads
|
||||||
|
assert_simply_restful_for :messages,
|
||||||
|
:path_prefix => 'threads/1/',
|
||||||
|
:name_prefix => 'thread_',
|
||||||
|
:options => { :thread_id => '1' }
|
||||||
|
assert_simply_restful_for :comments,
|
||||||
|
:path_prefix => 'threads/1/messages/2/',
|
||||||
|
:name_prefix => 'thread_message_',
|
||||||
|
:options => { :thread_id => '1', :message_id => '2' }
|
||||||
|
|
||||||
|
assert_deprecated do
|
||||||
|
assert_named_route "/threads/1/messages", "messages_path", {}
|
||||||
|
assert_named_route "/threads/1/messages/1", "message_path", {:thread_id => '1', :id => '1'}
|
||||||
|
assert_named_route "/threads/1/messages/new", "new_message_path", {:thread_id => '1'}
|
||||||
|
assert_named_route "/threads/1/messages/1/edit", "edit_message_path", {:thread_id => '1', :id => '1'}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_add_deprecated_named_routes_for_nested_singleton_resources
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resource :admin do |admin|
|
||||||
|
admin.resource :account
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_singleton_restful_for :admin
|
||||||
|
assert_singleton_restful_for :account, :path_prefix => 'admin/', :name_prefix => 'admin_'
|
||||||
|
|
||||||
|
assert_deprecated do
|
||||||
|
assert_named_route "/admin/account", "account_path", {}
|
||||||
|
assert_named_route "/admin/account/new", "new_account_path", {}
|
||||||
|
assert_named_route "/admin/account/edit", "edit_account_path", {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_add_deprecated_named_routes_for_nested_resources_in_singleton_resource
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resource :account do |account|
|
||||||
|
account.resources :messages
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_singleton_restful_for :account
|
||||||
|
assert_simply_restful_for :messages, :path_prefix => 'account/', :name_prefix => 'account_'
|
||||||
|
|
||||||
|
assert_deprecated do
|
||||||
|
assert_named_route "/account/messages", "messages_path", {}
|
||||||
|
assert_named_route "/account/messages/1", "message_path", {:id => '1'}
|
||||||
|
assert_named_route "/account/messages/new", "new_message_path", {}
|
||||||
|
assert_named_route "/account/messages/1/edit", "edit_message_path", {:id => '1'}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_add_deprecated_named_routes_for_nested_singleton_resource_in_resources
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resources :threads do |thread|
|
||||||
|
thread.resource :admin
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_simply_restful_for :threads
|
||||||
|
assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :name_prefix => 'thread_', :options => { :thread_id => '5' }
|
||||||
|
|
||||||
|
assert_deprecated do
|
||||||
|
assert_named_route "/threads/5/admin", "admin_path", {}
|
||||||
|
assert_named_route "/threads/5/admin/new", "new_admin_path", {}
|
||||||
|
assert_named_route "/threads/5/admin/edit", "edit_admin_path", {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_add_deprecated_formatted_routes
|
||||||
|
with_routing do |set|
|
||||||
|
set.draw do |map|
|
||||||
|
map.resources :products, :collection => { :specials => :get }, :member => { :thumbnail => :get }
|
||||||
|
map.resource :account, :member => { :icon => :get }
|
||||||
|
end
|
||||||
|
assert_restful_routes_for :products do |options|
|
||||||
|
assert_recognizes options.merge({ :action => 'specials', :format => 'xml' }), :path => '/products.xml;specials', :method => :get
|
||||||
|
assert_recognizes options.merge({ :action => 'thumbnail', :format => 'jpg', :id => '1' }), :path => '/products/1.jpg;thumbnail', :method => :get
|
||||||
|
end
|
||||||
|
assert_singleton_restful_for :account do |options|
|
||||||
|
assert_recognizes options.merge({ :action => 'icon', :format => 'jpg' }), :path => '/account.jpg;icon', :method => :get
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def with_restful_routing(*args)
|
def with_restful_routing(*args)
|
||||||
with_routing do |set|
|
with_routing do |set|
|
||||||
|
|
@ -319,7 +497,7 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_singleton_resources(*args)
|
def with_singleton_resources(*args)
|
||||||
with_routing do |set|
|
with_routing do |set|
|
||||||
set.draw { |map| map.resource(*args) }
|
set.draw { |map| map.resource(*args) }
|
||||||
|
|
@ -344,8 +522,8 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
collection_path = "/#{options[:path_prefix]}#{controller_name}"
|
collection_path = "/#{options[:path_prefix]}#{controller_name}"
|
||||||
member_path = "#{collection_path}/1"
|
member_path = "#{collection_path}/1"
|
||||||
new_path = "#{collection_path}/new"
|
new_path = "#{collection_path}/new"
|
||||||
edit_member_path = "#{member_path};edit"
|
edit_member_path = "#{member_path}/edit"
|
||||||
formatted_edit_member_path = "#{member_path}.xml;edit"
|
formatted_edit_member_path = "#{member_path}/edit.xml"
|
||||||
|
|
||||||
with_options(options[:options]) do |controller|
|
with_options(options[:options]) do |controller|
|
||||||
controller.assert_routing collection_path, :action => 'index'
|
controller.assert_routing collection_path, :action => 'index'
|
||||||
|
|
@ -395,13 +573,13 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
name_prefix = options[:name_prefix]
|
name_prefix = options[:name_prefix]
|
||||||
|
|
||||||
assert_named_route "#{full_prefix}", "#{name_prefix}#{controller_name}_path", options[:options]
|
assert_named_route "#{full_prefix}", "#{name_prefix}#{controller_name}_path", options[:options]
|
||||||
assert_named_route "#{full_prefix}/new", "#{name_prefix}new_#{singular_name}_path", options[:options]
|
assert_named_route "#{full_prefix}/new", "new_#{name_prefix}#{singular_name}_path", options[:options]
|
||||||
assert_named_route "#{full_prefix}/1", "#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1')
|
assert_named_route "#{full_prefix}/1", "#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1')
|
||||||
assert_named_route "#{full_prefix}/1;edit", "#{name_prefix}edit_#{singular_name}_path", options[:options].merge(:id => '1')
|
assert_named_route "#{full_prefix}/1/edit", "edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1')
|
||||||
assert_named_route "#{full_prefix}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge( :format => 'xml')
|
assert_named_route "#{full_prefix}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge( :format => 'xml')
|
||||||
assert_named_route "#{full_prefix}/new.xml", "formatted_#{name_prefix}new_#{singular_name}_path", options[:options].merge( :format => 'xml')
|
assert_named_route "#{full_prefix}/new.xml", "formatted_new_#{name_prefix}#{singular_name}_path", options[:options].merge( :format => 'xml')
|
||||||
assert_named_route "#{full_prefix}/1.xml", "formatted_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml')
|
assert_named_route "#{full_prefix}/1.xml", "formatted_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml')
|
||||||
assert_named_route "#{full_prefix}/1.xml;edit", "formatted_#{name_prefix}edit_#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml')
|
assert_named_route "#{full_prefix}/1/edit.xml", "formatted_edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml')
|
||||||
yield options[:options] if block_given?
|
yield options[:options] if block_given?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -410,8 +588,8 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
|
|
||||||
full_path = "/#{options[:path_prefix]}#{singleton_name}"
|
full_path = "/#{options[:path_prefix]}#{singleton_name}"
|
||||||
new_path = "#{full_path}/new"
|
new_path = "#{full_path}/new"
|
||||||
edit_path = "#{full_path};edit"
|
edit_path = "#{full_path}/edit"
|
||||||
formatted_edit_path = "#{full_path}.xml;edit"
|
formatted_edit_path = "#{full_path}/edit.xml"
|
||||||
|
|
||||||
with_options options[:options] do |controller|
|
with_options options[:options] do |controller|
|
||||||
controller.assert_routing full_path, :action => 'show'
|
controller.assert_routing full_path, :action => 'show'
|
||||||
|
|
@ -448,13 +626,14 @@ class ResourcesTest < Test::Unit::TestCase
|
||||||
options[:options].delete :action
|
options[:options].delete :action
|
||||||
|
|
||||||
full_path = "/#{options[:path_prefix]}#{singleton_name}"
|
full_path = "/#{options[:path_prefix]}#{singleton_name}"
|
||||||
|
full_name = "#{options[:name_prefix]}#{singleton_name}"
|
||||||
|
|
||||||
assert_named_route "#{full_path}", "#{singleton_name}_path", options[:options]
|
assert_named_route "#{full_path}", "#{full_name}_path", options[:options]
|
||||||
assert_named_route "#{full_path}/new", "new_#{singleton_name}_path", options[:options]
|
assert_named_route "#{full_path}/new", "new_#{full_name}_path", options[:options]
|
||||||
assert_named_route "#{full_path};edit", "edit_#{singleton_name}_path", options[:options]
|
assert_named_route "#{full_path}/edit", "edit_#{full_name}_path", options[:options]
|
||||||
assert_named_route "#{full_path}.xml", "formatted_#{singleton_name}_path", options[:options].merge(:format => 'xml')
|
assert_named_route "#{full_path}.xml", "formatted_#{full_name}_path", options[:options].merge(:format => 'xml')
|
||||||
assert_named_route "#{full_path}/new.xml", "formatted_new_#{singleton_name}_path", options[:options].merge(:format => 'xml')
|
assert_named_route "#{full_path}/new.xml", "formatted_new_#{full_name}_path", options[:options].merge(:format => 'xml')
|
||||||
assert_named_route "#{full_path}.xml;edit", "formatted_edit_#{singleton_name}_path", options[:options].merge(:format => 'xml')
|
assert_named_route "#{full_path}/edit.xml", "formatted_edit_#{full_name}_path", options[:options].merge(:format => 'xml')
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_named_route(expected, route, options)
|
def assert_named_route(expected, route, options)
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase
|
||||||
map.content '/content/:query', :controller => 'content', :action => 'show'
|
map.content '/content/:query', :controller => 'content', :action => 'show'
|
||||||
end
|
end
|
||||||
exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") }
|
exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") }
|
||||||
expected_message = %[content_url failed to generate from {:action=>"show", :controller=>"content"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: ["content", :query] - are they all satisifed?]
|
expected_message = "content_url failed to generate from #{{:action=>"show", :controller=>"content"}.inspect} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: [\"content\", :query] - are they all satisifed?"
|
||||||
assert_equal expected_message, exception.message
|
assert_equal expected_message, exception.message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -946,7 +946,7 @@ class RouteTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_expand_array_build_query_string
|
def test_expand_array_build_query_string
|
||||||
assert_equal '?x[]=1&x[]=2', order_query_string(@route.build_query_string(:x => [1, 2]))
|
assert_equal '?x%5B%5D=1&x%5B%5D=2', order_query_string(@route.build_query_string(:x => [1, 2]))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_escape_spaces_build_query_string_selected_keys
|
def test_escape_spaces_build_query_string_selected_keys
|
||||||
|
|
|
||||||
|
|
@ -482,6 +482,22 @@ HTML
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_request_uri_updates
|
||||||
|
get :test_params
|
||||||
|
uri = @request.request_uri
|
||||||
|
assert_equal @request.env['REQUEST_URI'], uri
|
||||||
|
|
||||||
|
get :test_uri
|
||||||
|
assert_not_equal uri, @request.request_uri
|
||||||
|
uri = @request.request_uri
|
||||||
|
assert_equal @request.env['REQUEST_URI'], uri
|
||||||
|
|
||||||
|
get :test_uri, :testing => true
|
||||||
|
assert_not_equal uri, @request.request_uri
|
||||||
|
uri = @request.request_uri
|
||||||
|
assert_equal @request.env['REQUEST_URI'], uri
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def with_foo_routing
|
def with_foo_routing
|
||||||
with_routing do |set|
|
with_routing do |set|
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,12 @@ class UrlRewriterTests < Test::Unit::TestCase
|
||||||
assert_match %r(/hi/hi/2$), u
|
assert_match %r(/hi/hi/2$), u
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_anchor
|
||||||
private
|
assert_equal(
|
||||||
def split_query_string(str)
|
'http://test.host/c/a/i#anchor',
|
||||||
[str[0].chr] + str[1..-1].split(/&/).sort
|
@rewriter.rewrite(:controller => 'c', :action => 'a', :id => 'i', :anchor => 'anchor')
|
||||||
end
|
)
|
||||||
|
end
|
||||||
def assert_query_equal(q1, q2)
|
|
||||||
assert_equal(split_query_string(q1), split_query_string(q2))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class UrlWriterTests < Test::Unit::TestCase
|
class UrlWriterTests < Test::Unit::TestCase
|
||||||
|
|
@ -75,6 +72,12 @@ class UrlWriterTests < Test::Unit::TestCase
|
||||||
W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https')
|
W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https')
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_anchor
|
||||||
|
assert_equal('/c/a#anchor',
|
||||||
|
W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :anchor => 'anchor')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def test_named_route
|
def test_named_route
|
||||||
ActionController::Routing::Routes.draw do |map|
|
ActionController::Routing::Routes.draw do |map|
|
||||||
|
|
@ -111,5 +114,58 @@ class UrlWriterTests < Test::Unit::TestCase
|
||||||
ensure
|
ensure
|
||||||
ActionController::Routing::Routes.load!
|
ActionController::Routing::Routes.load!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_one_parameter
|
||||||
|
assert_equal('/c/a?param=val',
|
||||||
|
W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :param => 'val')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_two_parameters
|
||||||
|
url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :p1 => 'X1', :p2 => 'Y2')
|
||||||
|
params = extract_params(url)
|
||||||
|
assert_equal params[0], { :p1 => 'X1' }.to_query
|
||||||
|
assert_equal params[1], { :p2 => 'Y2' }.to_query
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hash_parameter
|
||||||
|
url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:name => 'Bob', :category => 'prof'})
|
||||||
|
params = extract_params(url)
|
||||||
|
assert_equal params[0], { 'query[category]' => 'prof' }.to_query
|
||||||
|
assert_equal params[1], { 'query[name]' => 'Bob' }.to_query
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_array_parameter
|
||||||
|
url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => ['Bob', 'prof'])
|
||||||
|
params = extract_params(url)
|
||||||
|
assert_equal params[0], { 'query[]' => 'Bob' }.to_query
|
||||||
|
assert_equal params[1], { 'query[]' => 'prof' }.to_query
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hash_recursive_parameters
|
||||||
|
url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:person => {:name => 'Bob', :position => 'prof'}, :hobby => 'piercing'})
|
||||||
|
params = extract_params(url)
|
||||||
|
assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query
|
||||||
|
assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query
|
||||||
|
assert_equal params[2], { 'query[person][position]' => 'prof' }.to_query
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hash_recursive_and_array_parameters
|
||||||
|
url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :id => 101, :query => {:person => {:name => 'Bob', :position => ['prof', 'art director']}, :hobby => 'piercing'})
|
||||||
|
assert_match %r(^/c/a/101), url
|
||||||
|
params = extract_params(url)
|
||||||
|
assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query
|
||||||
|
assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query
|
||||||
|
assert_equal params[2], { 'query[person][position][]' => 'art director' }.to_query
|
||||||
|
assert_equal params[3], { 'query[person][position][]' => 'prof' }.to_query
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_path_generation_for_symbol_parameter_keys
|
||||||
|
assert_generates("/image", :controller=> :image)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def extract_params(url)
|
||||||
|
url.split('?', 2).last.split('&')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,16 @@ class VerificationTest < Test::Unit::TestCase
|
||||||
|
|
||||||
verify :only => :must_be_post, :method => :post, :render => { :status => 405, :text => "Must be post" }, :add_headers => { "Allow" => "POST" }
|
verify :only => :must_be_post, :method => :post, :render => { :status => 405, :text => "Must be post" }, :add_headers => { "Allow" => "POST" }
|
||||||
|
|
||||||
|
verify :only => :guarded_one_for_named_route_test, :params => "one",
|
||||||
|
:redirect_to => :foo_url
|
||||||
|
|
||||||
def guarded_one
|
def guarded_one
|
||||||
render :text => "#{params[:one]}"
|
render :text => "#{params[:one]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def guarded_one_for_named_route_test
|
||||||
|
render :text => "#{params[:one]}"
|
||||||
|
end
|
||||||
|
|
||||||
def guarded_with_flash
|
def guarded_with_flash
|
||||||
render :text => "#{params[:one]}"
|
render :text => "#{params[:one]}"
|
||||||
|
|
@ -94,6 +101,14 @@ class VerificationTest < Test::Unit::TestCase
|
||||||
@controller = TestController.new
|
@controller = TestController.new
|
||||||
@request = ActionController::TestRequest.new
|
@request = ActionController::TestRequest.new
|
||||||
@response = ActionController::TestResponse.new
|
@response = ActionController::TestResponse.new
|
||||||
|
ActionController::Routing::Routes.add_named_route :foo, '/foo', :controller => 'test', :action => 'foo'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_no_deprecation_warning_for_named_route
|
||||||
|
assert_not_deprecated do
|
||||||
|
get :guarded_one_for_named_route_test, :two => "not one"
|
||||||
|
assert_redirected_to '/foo'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_guarded_one_with_prereqs
|
def test_guarded_one_with_prereqs
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
xml.html do
|
xml.html do
|
||||||
xml.p "Hello"
|
xml.p "Hello"
|
||||||
end
|
end
|
||||||
|
"String return value"
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,12 @@ class AssetTagHelperTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def test_preset_empty_asset_id
|
def test_preset_empty_asset_id
|
||||||
Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/")
|
Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/")
|
||||||
|
# on windows, setting ENV["XXX"] to "" makes ENV["XXX"] return nil
|
||||||
|
if RUBY_PLATFORM =~ /win32/
|
||||||
|
ENV["RAILS_ASSET_ID"] = " "
|
||||||
|
else
|
||||||
ENV["RAILS_ASSET_ID"] = ""
|
ENV["RAILS_ASSET_ID"] = ""
|
||||||
|
end
|
||||||
assert_equal %(<img alt="Rails" src="/images/rails.png" />), image_tag("rails.png")
|
assert_equal %(<img alt="Rails" src="/images/rails.png" />), image_tag("rails.png")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,12 @@ class CompiledTemplateTests < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_compile_time
|
def test_compile_time
|
||||||
`echo '#{@a}' > #{@a}; echo '#{@b}' > #{@b}; ln -s #{@a} #{@s}`
|
File.open(@a, "w"){|f| f.puts @a}
|
||||||
|
File.open(@b, "w"){|f| f.puts @b}
|
||||||
|
|
||||||
|
# windows doesn't support symlinks (even under cygwin)
|
||||||
|
windows = (RUBY_PLATFORM =~ /win32/)
|
||||||
|
`ln -s #{@a} #{@s}` unless windows
|
||||||
|
|
||||||
v = ActionView::Base.new
|
v = ActionView::Base.new
|
||||||
v.base_path = '.'
|
v.base_path = '.'
|
||||||
|
|
@ -79,47 +84,54 @@ class CompiledTemplateTests < Test::Unit::TestCase
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
t = Time.now
|
t = Time.now
|
||||||
|
sleep 1
|
||||||
|
|
||||||
v.compile_and_render_template(:rhtml, '', @a)
|
v.compile_and_render_template(:rhtml, '', @a)
|
||||||
v.compile_and_render_template(:rhtml, '', @b)
|
v.compile_and_render_template(:rhtml, '', @b)
|
||||||
v.compile_and_render_template(:rhtml, '', @s)
|
v.compile_and_render_template(:rhtml, '', @s) unless windows
|
||||||
|
|
||||||
a_n = v.method_names[@a]
|
a_n = v.method_names[@a]
|
||||||
b_n = v.method_names[@b]
|
b_n = v.method_names[@b]
|
||||||
s_n = v.method_names[@s]
|
s_n = v.method_names[@s] unless windows
|
||||||
|
ct_a = v.compile_time[a_n]
|
||||||
|
ct_b = v.compile_time[b_n]
|
||||||
|
ct_s = v.compile_time[s_n] unless windows
|
||||||
# all of the files have changed since last compile
|
# all of the files have changed since last compile
|
||||||
assert v.compile_time[a_n] > t
|
assert v.compile_time[a_n] > t
|
||||||
assert v.compile_time[b_n] > t
|
assert v.compile_time[b_n] > t
|
||||||
assert v.compile_time[s_n] > t
|
assert v.compile_time[s_n] > t unless windows
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
t = Time.now
|
|
||||||
v.compile_and_render_template(:rhtml, '', @a)
|
v.compile_and_render_template(:rhtml, '', @a)
|
||||||
v.compile_and_render_template(:rhtml, '', @b)
|
v.compile_and_render_template(:rhtml, '', @b)
|
||||||
v.compile_and_render_template(:rhtml, '', @s)
|
v.compile_and_render_template(:rhtml, '', @s) unless windows
|
||||||
# none of the files have changed since last compile
|
# none of the files have changed since last compile
|
||||||
assert v.compile_time[a_n] < t
|
# so they should not have been recmpiled
|
||||||
assert v.compile_time[b_n] < t
|
assert_equal ct_a, v.compile_time[a_n]
|
||||||
assert v.compile_time[s_n] < t
|
assert_equal ct_b, v.compile_time[b_n]
|
||||||
|
assert_equal ct_s, v.compile_time[s_n] unless windows
|
||||||
|
|
||||||
`rm #{@s}; ln -s #{@b} #{@s}`
|
`rm #{@s}; ln -s #{@b} #{@s}` unless windows
|
||||||
v.compile_and_render_template(:rhtml, '', @a)
|
v.compile_and_render_template(:rhtml, '', @a)
|
||||||
v.compile_and_render_template(:rhtml, '', @b)
|
v.compile_and_render_template(:rhtml, '', @b)
|
||||||
v.compile_and_render_template(:rhtml, '', @s)
|
v.compile_and_render_template(:rhtml, '', @s) unless windows
|
||||||
# the symlink has changed since last compile
|
# the symlink has changed since last compile
|
||||||
assert v.compile_time[a_n] < t
|
assert_equal ct_a, v.compile_time[a_n]
|
||||||
assert v.compile_time[b_n] < t
|
assert_equal ct_b, v.compile_time[b_n]
|
||||||
assert v.compile_time[s_n] > t
|
assert v.compile_time[s_n] > t unless windows
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
`touch #{@b}`
|
FileUtils.touch @b
|
||||||
t = Time.now
|
t = Time.now
|
||||||
|
sleep 1
|
||||||
v.compile_and_render_template(:rhtml, '', @a)
|
v.compile_and_render_template(:rhtml, '', @a)
|
||||||
v.compile_and_render_template(:rhtml, '', @b)
|
v.compile_and_render_template(:rhtml, '', @b)
|
||||||
v.compile_and_render_template(:rhtml, '', @s)
|
v.compile_and_render_template(:rhtml, '', @s) unless windows
|
||||||
# the file at the end of the symlink has changed since last compile
|
# the file at the end of the symlink has changed since last compile
|
||||||
# both the symlink and the file at the end of it should be recompiled
|
# both the symlink and the file at the end of it should be recompiled
|
||||||
assert v.compile_time[a_n] < t
|
assert v.compile_time[a_n] < t
|
||||||
assert v.compile_time[b_n] > t
|
assert v.compile_time[b_n] > t
|
||||||
assert v.compile_time[s_n] > t
|
assert v.compile_time[s_n] > t unless windows
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,14 @@ class JavaScriptHelperTest < Test::Unit::TestCase
|
||||||
html = link_to_function( "Greet me!" ) do |page|
|
html = link_to_function( "Greet me!" ) do |page|
|
||||||
page.replace_html 'header', "<h1>Greetings</h1>"
|
page.replace_html 'header', "<h1>Greetings</h1>"
|
||||||
end
|
end
|
||||||
assert_dom_equal %(<a href="#" onclick="Element.update("header", "<h1>Greetings</h1>");; return false;">Greet me!</a>), html
|
assert_dom_equal %q(<a href="#" onclick="Element.update("header", "\074h1\076Greetings\074/h1\076");; return false;">Greet me!</a>), html
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_link_to_function_with_rjs_block_and_options
|
def test_link_to_function_with_rjs_block_and_options
|
||||||
html = link_to_function( "Greet me!", :class => "updater" ) do |page|
|
html = link_to_function( "Greet me!", :class => "updater" ) do |page|
|
||||||
page.replace_html 'header', "<h1>Greetings</h1>"
|
page.replace_html 'header', "<h1>Greetings</h1>"
|
||||||
end
|
end
|
||||||
assert_dom_equal %(<a href="#" class="updater" onclick="Element.update("header", "<h1>Greetings</h1>");; return false;">Greet me!</a>), html
|
assert_dom_equal %q(<a href="#" class="updater" onclick="Element.update("header", "\074h1\076Greetings\074/h1\076");; return false;">Greet me!</a>), html
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_button_to_function
|
def test_button_to_function
|
||||||
|
|
@ -55,13 +55,13 @@ class JavaScriptHelperTest < Test::Unit::TestCase
|
||||||
html = button_to_function( "Greet me!" ) do |page|
|
html = button_to_function( "Greet me!" ) do |page|
|
||||||
page.replace_html 'header', "<h1>Greetings</h1>"
|
page.replace_html 'header', "<h1>Greetings</h1>"
|
||||||
end
|
end
|
||||||
assert_dom_equal %(<input type="button" onclick="Element.update("header", "<h1>Greetings</h1>");;" value="Greet me!" />), html
|
assert_dom_equal %q(<input type="button" onclick="Element.update("header", "\074h1\076Greetings\074/h1\076");;" value="Greet me!" />), html
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_button_to_function_with_rjs_block_and_options
|
def test_button_to_function_with_rjs_block_and_options
|
||||||
html = button_to_function( "Greet me!", :class => "greeter" ) do |page|
|
html = button_to_function( "Greet me!", :class => "greeter" ) do |page|
|
||||||
page.replace_html 'header', "<h1>Greetings</h1>"
|
page.replace_html 'header', "<h1>Greetings</h1>"
|
||||||
end
|
end
|
||||||
assert_dom_equal %(<input type="button" class="greeter" onclick="Element.update("header", "<h1>Greetings</h1>");;" value="Greet me!" />), html
|
assert_dom_equal %q(<input type="button" class="greeter" onclick="Element.update("header", "\074h1\076Greetings\074/h1\076");;" value="Greet me!" />), html
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class NumberHelperTest < Test::Unit::TestCase
|
||||||
def test_number_to_currency
|
def test_number_to_currency
|
||||||
assert_equal("$1,234,567,890.50", number_to_currency(1234567890.50))
|
assert_equal("$1,234,567,890.50", number_to_currency(1234567890.50))
|
||||||
assert_equal("$1,234,567,890.51", number_to_currency(1234567890.506))
|
assert_equal("$1,234,567,890.51", number_to_currency(1234567890.506))
|
||||||
assert_equal("$1,234,567,890", number_to_currency(1234567890.50, {:precision => 0}))
|
assert_equal("$1,234,567,891", number_to_currency(1234567890.51, {:precision => 0}))
|
||||||
assert_equal("$1,234,567,890.5", number_to_currency(1234567890.50, {:precision => 1}))
|
assert_equal("$1,234,567,890.5", number_to_currency(1234567890.50, {:precision => 1}))
|
||||||
assert_equal("£1234567890,50", number_to_currency(1234567890.50, {:unit => "£", :separator => ",", :delimiter => ""}))
|
assert_equal("£1234567890,50", number_to_currency(1234567890.50, {:unit => "£", :separator => ",", :delimiter => ""}))
|
||||||
assert_equal("$1,234,567,890.50", number_to_currency("1234567890.50"))
|
assert_equal("$1,234,567,890.50", number_to_currency("1234567890.50"))
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ class PrototypeHelperTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_observe_field
|
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})})\n//]]>\n</script>),
|
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" })
|
observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -135,7 +135,7 @@ class PrototypeHelperTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_observe_form
|
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})})\n//]]>\n</script>),
|
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" })
|
observe_form("cart", :frequency => 2, :url => { :action => "cart_changed" })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -170,23 +170,23 @@ class JavaScriptGeneratorTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_insert_html_with_string
|
def test_insert_html_with_string
|
||||||
assert_equal 'new Insertion.Top("element", "<p>This is a test</p>");',
|
assert_equal 'new Insertion.Top("element", "\074p\076This is a test\074/p\076");',
|
||||||
@generator.insert_html(:top, 'element', '<p>This is a test</p>')
|
@generator.insert_html(:top, 'element', '<p>This is a test</p>')
|
||||||
assert_equal 'new Insertion.Bottom("element", "<p>This is a test</p>");',
|
assert_equal 'new Insertion.Bottom("element", "\074p\076This is a test\074/p\076");',
|
||||||
@generator.insert_html(:bottom, 'element', '<p>This is a test</p>')
|
@generator.insert_html(:bottom, 'element', '<p>This is a test</p>')
|
||||||
assert_equal 'new Insertion.Before("element", "<p>This is a test</p>");',
|
assert_equal 'new Insertion.Before("element", "\074p\076This is a test\074/p\076");',
|
||||||
@generator.insert_html(:before, 'element', '<p>This is a test</p>')
|
@generator.insert_html(:before, 'element', '<p>This is a test</p>')
|
||||||
assert_equal 'new Insertion.After("element", "<p>This is a test</p>");',
|
assert_equal 'new Insertion.After("element", "\074p\076This is a test\074/p\076");',
|
||||||
@generator.insert_html(:after, 'element', '<p>This is a test</p>')
|
@generator.insert_html(:after, 'element', '<p>This is a test</p>')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_replace_html_with_string
|
def test_replace_html_with_string
|
||||||
assert_equal 'Element.update("element", "<p>This is a test</p>");',
|
assert_equal 'Element.update("element", "\074p\076This is a test\074/p\076");',
|
||||||
@generator.replace_html('element', '<p>This is a test</p>')
|
@generator.replace_html('element', '<p>This is a test</p>')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_replace_element_with_string
|
def test_replace_element_with_string
|
||||||
assert_equal 'Element.replace("element", "<div id=\"element\"><p>This is a test</p></div>");',
|
assert_equal 'Element.replace("element", "\074div id=\"element\"\076\074p\076This is a test\074/p\076\074/div\076");',
|
||||||
@generator.replace('element', '<div id="element"><p>This is a test</p></div>')
|
@generator.replace('element', '<div id="element"><p>This is a test</p></div>')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -241,12 +241,12 @@ class JavaScriptGeneratorTest < Test::Unit::TestCase
|
||||||
@generator.remove('foo', 'bar')
|
@generator.remove('foo', 'bar')
|
||||||
@generator.replace_html('baz', '<p>This is a test</p>')
|
@generator.replace_html('baz', '<p>This is a test</p>')
|
||||||
|
|
||||||
assert_equal <<-EOS.chomp, @generator.to_s
|
expected = %q(new Insertion.Top("element", "\074p\076This is a test\074/p\076");
|
||||||
new Insertion.Top("element", "<p>This is a test</p>");
|
new Insertion.Bottom("element", "\074p\076This is a test\074/p\076");
|
||||||
new Insertion.Bottom("element", "<p>This is a test</p>");
|
|
||||||
["foo", "bar"].each(Element.remove);
|
["foo", "bar"].each(Element.remove);
|
||||||
Element.update("baz", "<p>This is a test</p>");
|
Element.update("baz", "\074p\076This is a test\074/p\076");)
|
||||||
EOS
|
|
||||||
|
assert_equal expected, @generator.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_element_access
|
def test_element_access
|
||||||
|
|
|
||||||
14
tracks/vendor/rails/actionwebservice/CHANGELOG
vendored
14
tracks/vendor/rails/actionwebservice/CHANGELOG
vendored
|
|
@ -1,3 +1,17 @@
|
||||||
|
*1.2.5* (October 12th, 2007)
|
||||||
|
|
||||||
|
* Depend on Action Pack 1.13.5
|
||||||
|
|
||||||
|
* Depend on Active Record 1.15.5
|
||||||
|
|
||||||
|
|
||||||
|
*1.2.4* (October 4th, 2007)
|
||||||
|
|
||||||
|
* Depend on Action Pack 1.13.4
|
||||||
|
|
||||||
|
* Depend on Active Record 1.15.4
|
||||||
|
|
||||||
|
|
||||||
*1.2.3* (March 12th, 2007)
|
*1.2.3* (March 12th, 2007)
|
||||||
|
|
||||||
* Depend on Action Pack 1.13.3
|
* Depend on Action Pack 1.13.3
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ spec = Gem::Specification.new do |s|
|
||||||
s.rubyforge_project = "aws"
|
s.rubyforge_project = "aws"
|
||||||
s.homepage = "http://www.rubyonrails.org"
|
s.homepage = "http://www.rubyonrails.org"
|
||||||
|
|
||||||
s.add_dependency('actionpack', '= 1.13.3' + PKG_BUILD)
|
s.add_dependency('actionpack', '= 1.13.5' + PKG_BUILD)
|
||||||
s.add_dependency('activerecord', '= 1.15.3' + PKG_BUILD)
|
s.add_dependency('activerecord', '= 1.15.5' + PKG_BUILD)
|
||||||
|
|
||||||
s.has_rdoc = true
|
s.has_rdoc = true
|
||||||
s.requirements << 'none'
|
s.requirements << 'none'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ module ActionWebService
|
||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 1
|
MAJOR = 1
|
||||||
MINOR = 2
|
MINOR = 2
|
||||||
TINY = 3
|
TINY = 5
|
||||||
|
|
||||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||||
end
|
end
|
||||||
|
|
|
||||||
34
tracks/vendor/rails/activerecord/CHANGELOG
vendored
34
tracks/vendor/rails/activerecord/CHANGELOG
vendored
|
|
@ -1,3 +1,37 @@
|
||||||
|
*1.15.5* (October 12th, 2007)
|
||||||
|
|
||||||
|
* Depend on Action Pack 1.4.4
|
||||||
|
|
||||||
|
|
||||||
|
*1.15.4* (October 4th, 2007)
|
||||||
|
|
||||||
|
* Fix #count on a has_many :through association so that it recognizes the :uniq option. Closes #8801 [lifofifo]
|
||||||
|
|
||||||
|
* Don't clobber includes passed to has_many.count [danger]
|
||||||
|
|
||||||
|
* Make sure has_many uses :include when counting [danger]
|
||||||
|
|
||||||
|
* Save associated records only if the association is already loaded. #8713 [blaine]
|
||||||
|
|
||||||
|
* Changing the :default Date format doesn't break date quoting. #6312 [bshand, Elias]
|
||||||
|
|
||||||
|
* Allow nil serialized attributes with a set class constraint. #7293 [sandofsky]
|
||||||
|
|
||||||
|
* belongs_to assignment creates a new proxy rather than modifying its target in-place. #8412 [mmangino@elevatedrails.com]
|
||||||
|
|
||||||
|
* Fix column type detection while loading fixtures. Closes #7987 [roderickvd]
|
||||||
|
|
||||||
|
* Document deep eager includes. #6267 [Josh Susser, Dan Manges]
|
||||||
|
|
||||||
|
* Oracle: extract column length for CHAR also. #7866 [ymendel]
|
||||||
|
|
||||||
|
* Small additions and fixes for ActiveRecord documentation. Closes #7342 [jeremymcanally]
|
||||||
|
|
||||||
|
* SQLite: binary escaping works with $KCODE='u'. #7862 [tsuka]
|
||||||
|
|
||||||
|
* Improved cloning performance by relying less on exception raising #8159 [Blaine]
|
||||||
|
|
||||||
|
|
||||||
*1.15.3* (March 12th, 2007)
|
*1.15.3* (March 12th, 2007)
|
||||||
|
|
||||||
* Allow a polymorphic :source for has_many :through associations. Closes #7143 [protocool]
|
* Allow a polymorphic :source for has_many :through associations. Closes #7143 [protocool]
|
||||||
|
|
|
||||||
2
tracks/vendor/rails/activerecord/Rakefile
vendored
2
tracks/vendor/rails/activerecord/Rakefile
vendored
|
|
@ -151,7 +151,7 @@ spec = Gem::Specification.new do |s|
|
||||||
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
||||||
end
|
end
|
||||||
|
|
||||||
s.add_dependency('activesupport', '= 1.4.2' + PKG_BUILD)
|
s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD)
|
||||||
|
|
||||||
s.files.delete "test/fixtures/fixture_database.sqlite"
|
s.files.delete "test/fixtures/fixture_database.sqlite"
|
||||||
s.files.delete "test/fixtures/fixture_database_2.sqlite"
|
s.files.delete "test/fixtures/fixture_database_2.sqlite"
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ module ActiveRecord
|
||||||
|
|
||||||
#{scope_condition_method}
|
#{scope_condition_method}
|
||||||
|
|
||||||
after_destroy :remove_from_list
|
before_destroy :remove_from_list
|
||||||
before_create :add_to_list_bottom
|
before_create :add_to_list_bottom
|
||||||
EOV
|
EOV
|
||||||
end
|
end
|
||||||
|
|
@ -74,6 +74,7 @@ module ActiveRecord
|
||||||
# lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return true if that chapter is
|
# lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return true if that chapter is
|
||||||
# the first in the list of all chapters.
|
# the first in the list of all chapters.
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
|
# Insert the item at the given position (defaults to the top position of 1).
|
||||||
def insert_at(position = 1)
|
def insert_at(position = 1)
|
||||||
insert_at_position(position)
|
insert_at_position(position)
|
||||||
end
|
end
|
||||||
|
|
@ -118,8 +119,12 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Removes the item from the list.
|
||||||
def remove_from_list
|
def remove_from_list
|
||||||
decrement_positions_on_lower_items if in_list?
|
if in_list?
|
||||||
|
decrement_positions_on_lower_items
|
||||||
|
update_attribute position_column, nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Increase the position of this item without adjusting the rest of the list.
|
# Increase the position of this item without adjusting the rest of the list.
|
||||||
|
|
@ -162,6 +167,7 @@ module ActiveRecord
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Test if this record is in a list
|
||||||
def in_list?
|
def in_list?
|
||||||
!send(position_column).nil?
|
!send(position_column).nil?
|
||||||
end
|
end
|
||||||
|
|
@ -178,21 +184,26 @@ module ActiveRecord
|
||||||
# Overwrite this method to define the scope of the list changes
|
# Overwrite this method to define the scope of the list changes
|
||||||
def scope_condition() "1" end
|
def scope_condition() "1" end
|
||||||
|
|
||||||
|
# Returns the bottom position number in the list.
|
||||||
|
# bottom_position_in_list # => 2
|
||||||
def bottom_position_in_list(except = nil)
|
def bottom_position_in_list(except = nil)
|
||||||
item = bottom_item(except)
|
item = bottom_item(except)
|
||||||
item ? item.send(position_column) : 0
|
item ? item.send(position_column) : 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the bottom item
|
||||||
def bottom_item(except = nil)
|
def bottom_item(except = nil)
|
||||||
conditions = scope_condition
|
conditions = scope_condition
|
||||||
conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
|
conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
|
||||||
acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
|
acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Forces item to assume the bottom position in the list.
|
||||||
def assume_bottom_position
|
def assume_bottom_position
|
||||||
update_attribute(position_column, bottom_position_in_list(self).to_i + 1)
|
update_attribute(position_column, bottom_position_in_list(self).to_i + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Forces item to assume the top position in the list.
|
||||||
def assume_top_position
|
def assume_top_position
|
||||||
update_attribute(position_column, 1)
|
update_attribute(position_column, 1)
|
||||||
end
|
end
|
||||||
|
|
@ -227,6 +238,7 @@ module ActiveRecord
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Increments position (<tt>position_column</tt>) of all items in the list.
|
||||||
def increment_positions_on_all_items
|
def increment_positions_on_all_items
|
||||||
acts_as_list_class.update_all(
|
acts_as_list_class.update_all(
|
||||||
"#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
|
"#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
|
||||||
|
|
|
||||||
|
|
@ -70,16 +70,23 @@ module ActiveRecord
|
||||||
nodes
|
nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the root node of the tree.
|
||||||
def root
|
def root
|
||||||
node = self
|
node = self
|
||||||
node = node.parent while node.parent
|
node = node.parent while node.parent
|
||||||
node
|
node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns all siblings of the current node.
|
||||||
|
#
|
||||||
|
# subchild1.siblings # => [subchild2]
|
||||||
def siblings
|
def siblings
|
||||||
self_and_siblings - [self]
|
self_and_siblings - [self]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns all siblings and a reference to the current node.
|
||||||
|
#
|
||||||
|
# subchild1.self_and_siblings # => [subchild1, subchild2]
|
||||||
def self_and_siblings
|
def self_and_siblings
|
||||||
parent ? parent.children : self.class.roots
|
parent ? parent.children : self.class.roots
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,15 @@ module ActiveRecord
|
||||||
# for post in Post.find(:all, :include => [ :author, :comments ])
|
# for post in Post.find(:all, :include => [ :author, :comments ])
|
||||||
#
|
#
|
||||||
# That'll add another join along the lines of: LEFT OUTER JOIN comments ON comments.post_id = posts.id. And we'll be down to 1 query.
|
# That'll add another join along the lines of: LEFT OUTER JOIN comments ON comments.post_id = posts.id. And we'll be down to 1 query.
|
||||||
# But that shouldn't fool you to think that you can pull out huge amounts of data with no performance penalty just because you've reduced
|
#
|
||||||
|
# To include a deep hierarchy of associations, using a hash:
|
||||||
|
#
|
||||||
|
# for post in Post.find(:all, :include => [ :author, { :comments => { :author => :gravatar } } ])
|
||||||
|
#
|
||||||
|
# That'll grab not only all the comments but all their authors and gravatar pictures. You can mix and match
|
||||||
|
# symbols, arrays and hashes in any combination to describe the associations you want to load.
|
||||||
|
#
|
||||||
|
# All of this power shouldn't fool you into thinking that you can pull out huge amounts of data with no performance penalty just because you've reduced
|
||||||
# the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it's no
|
# the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it's no
|
||||||
# catch-all for performance problems, but it's a great way to cut down on the number of queries in a situation as the one described above.
|
# catch-all for performance problems, but it's a great way to cut down on the number of queries in a situation as the one described above.
|
||||||
#
|
#
|
||||||
|
|
@ -734,6 +742,7 @@ module ActiveRecord
|
||||||
deprecated_association_comparison_method(reflection.name, reflection.class_name)
|
deprecated_association_comparison_method(reflection.name, reflection.class_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Create the callbacks to update counter cache
|
||||||
if options[:counter_cache]
|
if options[:counter_cache]
|
||||||
cache_column = options[:counter_cache] == true ?
|
cache_column = options[:counter_cache] == true ?
|
||||||
"#{self.to_s.underscore.pluralize}_count" :
|
"#{self.to_s.underscore.pluralize}_count" :
|
||||||
|
|
@ -871,6 +880,12 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
# Generate a join table name from two provided tables names.
|
||||||
|
# The order of names in join name is determined by lexical precedence.
|
||||||
|
# join_table_name("members", "clubs")
|
||||||
|
# => "clubs_members"
|
||||||
|
# join_table_name("members", "special_clubs")
|
||||||
|
# => "members_special_clubs"
|
||||||
def join_table_name(first_table_name, second_table_name)
|
def join_table_name(first_table_name, second_table_name)
|
||||||
if first_table_name < second_table_name
|
if first_table_name < second_table_name
|
||||||
join_table = "#{first_table_name}_#{second_table_name}"
|
join_table = "#{first_table_name}_#{second_table_name}"
|
||||||
|
|
@ -880,7 +895,7 @@ module ActiveRecord
|
||||||
|
|
||||||
table_name_prefix + join_table + table_name_suffix
|
table_name_prefix + join_table + table_name_suffix
|
||||||
end
|
end
|
||||||
|
|
||||||
def association_accessor_methods(reflection, association_proxy_class)
|
def association_accessor_methods(reflection, association_proxy_class)
|
||||||
define_method(reflection.name) do |*params|
|
define_method(reflection.name) do |*params|
|
||||||
force_reload = params.first unless params.empty?
|
force_reload = params.first unless params.empty?
|
||||||
|
|
@ -901,7 +916,7 @@ module ActiveRecord
|
||||||
|
|
||||||
define_method("#{reflection.name}=") do |new_value|
|
define_method("#{reflection.name}=") do |new_value|
|
||||||
association = instance_variable_get("@#{reflection.name}")
|
association = instance_variable_get("@#{reflection.name}")
|
||||||
if association.nil?
|
if association.nil? || association.target != new_value
|
||||||
association = association_proxy_class.new(self, reflection)
|
association = association_proxy_class.new(self, reflection)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -911,10 +926,7 @@ module ActiveRecord
|
||||||
instance_variable_set("@#{reflection.name}", association)
|
instance_variable_set("@#{reflection.name}", association)
|
||||||
else
|
else
|
||||||
instance_variable_set("@#{reflection.name}", nil)
|
instance_variable_set("@#{reflection.name}", nil)
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
association
|
|
||||||
end
|
end
|
||||||
|
|
||||||
define_method("set_#{reflection.name}_target") do |target|
|
define_method("set_#{reflection.name}_target") do |target|
|
||||||
|
|
@ -981,18 +993,21 @@ module ActiveRecord
|
||||||
|
|
||||||
after_callback = <<-end_eval
|
after_callback = <<-end_eval
|
||||||
association = instance_variable_get("@#{association_name}")
|
association = instance_variable_get("@#{association_name}")
|
||||||
|
|
||||||
if association.respond_to?(:loaded?)
|
records_to_save = if @new_record_before_save
|
||||||
if @new_record_before_save
|
association
|
||||||
records_to_save = association
|
elsif association.respond_to?(:loaded?) && association.loaded?
|
||||||
else
|
association.select { |record| record.new_record? }
|
||||||
records_to_save = association.select { |record| record.new_record? }
|
else
|
||||||
end
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
if !records_to_save.blank?
|
||||||
records_to_save.each { |record| association.send(:insert_record, record) }
|
records_to_save.each { |record| association.send(:insert_record, record) }
|
||||||
association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id
|
association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id
|
||||||
end
|
end
|
||||||
end_eval
|
end_eval
|
||||||
|
|
||||||
# Doesn't use after_save as that would save associations added in after_create/after_update twice
|
# Doesn't use after_save as that would save associations added in after_create/after_update twice
|
||||||
after_create(after_callback)
|
after_create(after_callback)
|
||||||
after_update(after_callback)
|
after_update(after_callback)
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,11 @@ module ActiveRecord
|
||||||
attributes.collect { |attr| create(attr) }
|
attributes.collect { |attr| create(attr) }
|
||||||
else
|
else
|
||||||
record = build(attributes)
|
record = build(attributes)
|
||||||
record.save unless @owner.new_record?
|
if @owner.new_record?
|
||||||
|
ActiveSupport::Deprecation.warn("Calling .create on a has_many association without saving its owner will not work in rails 2.0, you probably want .build instead")
|
||||||
|
else
|
||||||
|
record.save
|
||||||
|
end
|
||||||
record
|
record
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ module ActiveRecord
|
||||||
options[:conditions] = options[:conditions].nil? ?
|
options[:conditions] = options[:conditions].nil? ?
|
||||||
@finder_sql :
|
@finder_sql :
|
||||||
@finder_sql + " AND (#{sanitize_sql(options[:conditions])})"
|
@finder_sql + " AND (#{sanitize_sql(options[:conditions])})"
|
||||||
options[:include] = @reflection.options[:include]
|
options[:include] ||= @reflection.options[:include]
|
||||||
|
|
||||||
@reflection.klass.count(column_name, options)
|
@reflection.klass.count(column_name, options)
|
||||||
end
|
end
|
||||||
|
|
@ -138,7 +138,7 @@ module ActiveRecord
|
||||||
elsif @reflection.options[:counter_sql]
|
elsif @reflection.options[:counter_sql]
|
||||||
@reflection.klass.count_by_sql(@counter_sql)
|
@reflection.klass.count_by_sql(@counter_sql)
|
||||||
else
|
else
|
||||||
@reflection.klass.count(:conditions => @counter_sql)
|
@reflection.klass.count(:conditions => @counter_sql, :include => @reflection.options[:include])
|
||||||
end
|
end
|
||||||
|
|
||||||
@target = [] and loaded if count == 0
|
@target = [] and loaded if count == 0
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,16 @@ module ActiveRecord
|
||||||
def sum(*args, &block)
|
def sum(*args, &block)
|
||||||
calculate(:sum, *args, &block)
|
calculate(:sum, *args, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def count(*args)
|
||||||
|
column_name, options = @reflection.klass.send(:construct_count_options_from_legacy_args, *args)
|
||||||
|
if @reflection.options[:uniq]
|
||||||
|
# This is needed becase 'SELECT count(DISTINCT *)..' is not valid sql statement.
|
||||||
|
column_name = "#{@reflection.klass.table_name}.#{@reflection.klass.primary_key}" if column_name == :all
|
||||||
|
options.merge!(:distinct => true)
|
||||||
|
end
|
||||||
|
@reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.count(column_name, options) }
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def method_missing(method, *args, &block)
|
def method_missing(method, *args, &block)
|
||||||
|
|
|
||||||
|
|
@ -575,7 +575,7 @@ module ActiveRecord #:nodoc:
|
||||||
|
|
||||||
# Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized
|
# Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized
|
||||||
# after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized
|
# after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized
|
||||||
# object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised.
|
# object must be of that class on retrieval, or nil. Otherwise, +SerializationTypeMismatch+ will be raised.
|
||||||
def serialize(attr_name, class_name = Object)
|
def serialize(attr_name, class_name = Object)
|
||||||
serialized_attributes[attr_name.to_s] = class_name
|
serialized_attributes[attr_name.to_s] = class_name
|
||||||
end
|
end
|
||||||
|
|
@ -1188,6 +1188,9 @@ module ActiveRecord #:nodoc:
|
||||||
#
|
#
|
||||||
# It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount
|
# It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount
|
||||||
# is actually find_all_by_amount(amount, options).
|
# is actually find_all_by_amount(amount, options).
|
||||||
|
#
|
||||||
|
# This also enables you to initialize a record if it is not found, such as find_or_initialize_by_amount(amount)
|
||||||
|
# or find_or_create_by_user_and_password(user, password).
|
||||||
def method_missing(method_id, *arguments)
|
def method_missing(method_id, *arguments)
|
||||||
if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s)
|
if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s)
|
||||||
finder, deprecated_finder = determine_finder(match), determine_deprecated_finder(match)
|
finder, deprecated_finder = determine_finder(match), determine_deprecated_finder(match)
|
||||||
|
|
@ -1957,7 +1960,7 @@ module ActiveRecord #:nodoc:
|
||||||
def unserialize_attribute(attr_name)
|
def unserialize_attribute(attr_name)
|
||||||
unserialized_object = object_from_yaml(@attributes[attr_name])
|
unserialized_object = object_from_yaml(@attributes[attr_name])
|
||||||
|
|
||||||
if unserialized_object.is_a?(self.class.serialized_attributes[attr_name])
|
if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) || unserialized_object.nil?
|
||||||
@attributes[attr_name] = unserialized_object
|
@attributes[attr_name] = unserialized_object
|
||||||
else
|
else
|
||||||
raise SerializationTypeMismatch,
|
raise SerializationTypeMismatch,
|
||||||
|
|
@ -2156,7 +2159,13 @@ module ActiveRecord #:nodoc:
|
||||||
|
|
||||||
def clone_attribute_value(reader_method, attribute_name)
|
def clone_attribute_value(reader_method, attribute_name)
|
||||||
value = send(reader_method, attribute_name)
|
value = send(reader_method, attribute_name)
|
||||||
value.clone
|
|
||||||
|
case value
|
||||||
|
when nil, Fixnum, true, false
|
||||||
|
value
|
||||||
|
else
|
||||||
|
value.clone
|
||||||
|
end
|
||||||
rescue TypeError, NoMethodError
|
rescue TypeError, NoMethodError
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -242,8 +242,8 @@ module ActiveRecord
|
||||||
options.assert_valid_keys(CALCULATIONS_OPTIONS)
|
options.assert_valid_keys(CALCULATIONS_OPTIONS)
|
||||||
end
|
end
|
||||||
|
|
||||||
# converts a given key to the value that the database adapter returns as
|
# Converts a given key to the value that the database adapter returns as
|
||||||
#
|
# as a usable column name.
|
||||||
# users.id #=> users_id
|
# users.id #=> users_id
|
||||||
# sum(id) #=> sum_id
|
# sum(id) #=> sum_id
|
||||||
# count(distinct users.id) #=> count_distinct_users_id
|
# count(distinct users.id) #=> count_distinct_users_id
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ module ActiveRecord
|
||||||
when Float, Fixnum, Bignum then value.to_s
|
when Float, Fixnum, Bignum then value.to_s
|
||||||
# BigDecimals need to be output in a non-normalized form and quoted.
|
# BigDecimals need to be output in a non-normalized form and quoted.
|
||||||
when BigDecimal then value.to_s('F')
|
when BigDecimal then value.to_s('F')
|
||||||
when Date then "'#{value.to_s}'"
|
when Date then "'#{value.to_s(:db)}'"
|
||||||
when Time, DateTime then "'#{quoted_date(value)}'"
|
when Time, DateTime then "'#{quoted_date(value)}'"
|
||||||
else "'#{quote_string(value.to_yaml)}'"
|
else "'#{quote_string(value.to_yaml)}'"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -320,6 +320,7 @@ begin
|
||||||
decode(data_type, 'NUMBER', data_precision,
|
decode(data_type, 'NUMBER', data_precision,
|
||||||
'FLOAT', data_precision,
|
'FLOAT', data_precision,
|
||||||
'VARCHAR2', data_length,
|
'VARCHAR2', data_length,
|
||||||
|
'CHAR', data_length,
|
||||||
null) as limit,
|
null) as limit,
|
||||||
decode(data_type, 'NUMBER', data_scale, null) as scale
|
decode(data_type, 'NUMBER', data_scale, null) as scale
|
||||||
from all_tab_columns
|
from all_tab_columns
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ module ActiveRecord
|
||||||
class SQLiteColumn < Column #:nodoc:
|
class SQLiteColumn < Column #:nodoc:
|
||||||
class << self
|
class << self
|
||||||
def string_to_binary(value)
|
def string_to_binary(value)
|
||||||
value.gsub(/\0|\%/) do |b|
|
value.gsub(/\0|\%/n) do |b|
|
||||||
case b
|
case b
|
||||||
when "\0" then "%00"
|
when "\0" then "%00"
|
||||||
when "%" then "%25"
|
when "%" then "%25"
|
||||||
|
|
@ -77,7 +77,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def binary_to_string(value)
|
def binary_to_string(value)
|
||||||
value.gsub(/%00|%25/) do |b|
|
value.gsub(/%00|%25/n) do |b|
|
||||||
case b
|
case b
|
||||||
when "%00" then "\0"
|
when "%00" then "\0"
|
||||||
when "%25" then "%"
|
when "%25" then "%"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
class Base
|
class Base
|
||||||
class << self
|
class << self
|
||||||
# This method is deprecated in favor of find with the :conditions option.
|
# DEPRECATION NOTICE: This method is deprecated in favor of find with the :conditions option.
|
||||||
#
|
#
|
||||||
# Works like find, but the record matching +id+ must also meet the +conditions+.
|
# Works like find, but the record matching +id+ must also meet the +conditions+.
|
||||||
# +RecordNotFound+ is raised if no record can be found matching the +id+ or meeting the condition.
|
# +RecordNotFound+ is raised if no record can be found matching the +id+ or meeting the condition.
|
||||||
|
|
@ -12,7 +12,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
deprecate :find_on_conditions => "use find(ids, :conditions => conditions)"
|
deprecate :find_on_conditions => "use find(ids, :conditions => conditions)"
|
||||||
|
|
||||||
# This method is deprecated in favor of find(:first, options).
|
# DEPRECATION NOTICE: This method is deprecated in favor of find(:first, options).
|
||||||
#
|
#
|
||||||
# Returns the object for the first record responding to the conditions in +conditions+,
|
# Returns the object for the first record responding to the conditions in +conditions+,
|
||||||
# such as "group = 'master'". If more than one record is returned from the query, it's the first that'll
|
# such as "group = 'master'". If more than one record is returned from the query, it's the first that'll
|
||||||
|
|
@ -24,7 +24,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
deprecate :find_first => "use find(:first, ...)"
|
deprecate :find_first => "use find(:first, ...)"
|
||||||
|
|
||||||
# This method is deprecated in favor of find(:all, options).
|
# DEPRECATION NOTICE: This method is deprecated in favor of find(:all, options).
|
||||||
#
|
#
|
||||||
# Returns an array of all the objects that could be instantiated from the associated
|
# Returns an array of all the objects that could be instantiated from the associated
|
||||||
# table in the database. The +conditions+ can be used to narrow the selection of objects (WHERE-part),
|
# table in the database. The +conditions+ can be used to narrow the selection of objects (WHERE-part),
|
||||||
|
|
|
||||||
|
|
@ -412,7 +412,7 @@ class Fixture #:nodoc:
|
||||||
klass = @class_name.constantize rescue nil
|
klass = @class_name.constantize rescue nil
|
||||||
|
|
||||||
list = @fixture.inject([]) do |fixtures, (key, value)|
|
list = @fixture.inject([]) do |fixtures, (key, value)|
|
||||||
col = klass.columns_hash[key] if klass.kind_of?(ActiveRecord::Base)
|
col = klass.columns_hash[key] if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base)
|
||||||
fixtures << ActiveRecord::Base.connection.quote(value, col).gsub('[^\]\\n', "\n").gsub('[^\]\\r', "\r")
|
fixtures << ActiveRecord::Base.connection.quote(value, col).gsub('[^\]\\n', "\n").gsub('[^\]\\r', "\r")
|
||||||
end
|
end
|
||||||
list * ', '
|
list * ', '
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,6 @@ module ActiveRecord
|
||||||
# Timestamping can be turned off by setting
|
# Timestamping can be turned off by setting
|
||||||
# <tt>ActiveRecord::Base.record_timestamps = false</tt>
|
# <tt>ActiveRecord::Base.record_timestamps = false</tt>
|
||||||
#
|
#
|
||||||
# Keep in mind that, via inheritance, you can turn off timestamps on a per
|
|
||||||
# model basis by setting <tt>record_timestamps</tt> to false in the desired
|
|
||||||
# models.
|
|
||||||
#
|
|
||||||
# class Feed < ActiveRecord::Base
|
|
||||||
# self.record_timestamps = false
|
|
||||||
# # ...
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# Timestamps are in the local timezone by default but can use UTC by setting
|
# Timestamps are in the local timezone by default but can use UTC by setting
|
||||||
# <tt>ActiveRecord::Base.default_timezone = :utc</tt>
|
# <tt>ActiveRecord::Base.default_timezone = :utc</tt>
|
||||||
module Timestamp
|
module Timestamp
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ module ActiveRecord
|
||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 1
|
MAJOR = 1
|
||||||
MINOR = 15
|
MINOR = 15
|
||||||
TINY = 3
|
TINY = 5
|
||||||
|
|
||||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,12 @@ class EagerAssociationTest < Test::Unit::TestCase
|
||||||
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'")
|
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'")
|
||||||
assert_equal 0, posts.size
|
assert_equal 0, posts.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional
|
||||||
|
author = authors(:david)
|
||||||
|
author_posts_without_comments = author.posts.select { |post| post.comments.blank? }
|
||||||
|
assert_equal author_posts_without_comments.size, author.posts.count(:all, :include => :comments, :conditions => 'comments.id is null')
|
||||||
|
end
|
||||||
|
|
||||||
def test_eager_with_has_and_belongs_to_many_and_limit
|
def test_eager_with_has_and_belongs_to_many_and_limit
|
||||||
posts = Post.find(:all, :include => :categories, :order => "posts.id", :limit => 3)
|
posts = Post.find(:all, :include => :categories, :order => "posts.id", :limit => 3)
|
||||||
|
|
@ -271,6 +277,13 @@ class EagerAssociationTest < Test::Unit::TestCase
|
||||||
assert_not_nil f.account
|
assert_not_nil f.account
|
||||||
assert_equal companies(:first_firm, :reload).account, f.account
|
assert_equal companies(:first_firm, :reload).account, f.account
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_eager_with_multi_table_conditional_properly_counts_the_records_when_using_size
|
||||||
|
author = authors(:david)
|
||||||
|
posts_with_no_comments = author.posts.select { |post| post.comments.blank? }
|
||||||
|
assert_equal posts_with_no_comments.size, author.posts_with_no_comments.size
|
||||||
|
assert_equal posts_with_no_comments, author.posts_with_no_comments
|
||||||
|
end
|
||||||
|
|
||||||
def test_eager_with_invalid_association_reference
|
def test_eager_with_invalid_association_reference
|
||||||
assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
|
assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,16 @@ class AssociationsJoinModelTest < Test::Unit::TestCase
|
||||||
assert_equal 2, authors(:mary).categorized_posts.size
|
assert_equal 2, authors(:mary).categorized_posts.size
|
||||||
assert_equal 1, authors(:mary).unique_categorized_posts.size
|
assert_equal 1, authors(:mary).unique_categorized_posts.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_has_many_uniq_through_count
|
||||||
|
author = authors(:mary)
|
||||||
|
assert !authors(:mary).unique_categorized_posts.loaded?
|
||||||
|
assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count }
|
||||||
|
assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title, {}) }
|
||||||
|
assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, { :conditions => "title is NULL" }) }
|
||||||
|
assert !authors(:mary).unique_categorized_posts.loaded?
|
||||||
|
end
|
||||||
|
|
||||||
def test_polymorphic_has_many
|
def test_polymorphic_has_many
|
||||||
assert posts(:welcome).taggings.include?(taggings(:welcome_general))
|
assert posts(:welcome).taggings.include?(taggings(:welcome_general))
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@ class AssociationsTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
class AssociationProxyTest < Test::Unit::TestCase
|
class AssociationProxyTest < Test::Unit::TestCase
|
||||||
fixtures :authors, :posts
|
fixtures :authors, :posts, :developers, :projects, :developers_projects
|
||||||
|
|
||||||
def test_proxy_accessors
|
def test_proxy_accessors
|
||||||
welcome = posts(:welcome)
|
welcome = posts(:welcome)
|
||||||
assert_equal welcome, welcome.author.proxy_owner
|
assert_equal welcome, welcome.author.proxy_owner
|
||||||
|
|
@ -87,6 +87,19 @@ class AssociationProxyTest < Test::Unit::TestCase
|
||||||
david.posts_with_extension.first # force load target
|
david.posts_with_extension.first # force load target
|
||||||
assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target
|
assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_save_on_parent_does_not_load_target
|
||||||
|
david = developers(:david)
|
||||||
|
|
||||||
|
assert !david.projects.loaded?
|
||||||
|
david.update_attribute(:created_at, Time.now)
|
||||||
|
assert !david.projects.loaded?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_save_on_parent_saves_children
|
||||||
|
developer = Developer.create :name => "Bryan", :salary => 50_000
|
||||||
|
assert_equal 1, developer.reload.audit_logs.size
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class HasOneAssociationsTest < Test::Unit::TestCase
|
class HasOneAssociationsTest < Test::Unit::TestCase
|
||||||
|
|
@ -583,6 +596,13 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
||||||
assert_equal 3, first_firm.plain_clients.size
|
assert_equal 3, first_firm.plain_clients.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_regular_create_on_has_many_when_parent_is_new_raises
|
||||||
|
assert_deprecated(/.build instead/) do
|
||||||
|
firm = Firm.new
|
||||||
|
firm.plain_clients.create :name=>"Whoever"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_adding_a_mismatch_class
|
def test_adding_a_mismatch_class
|
||||||
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
|
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
|
||||||
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
|
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
|
||||||
|
|
@ -1007,7 +1027,20 @@ class BelongsToAssociationsTest < Test::Unit::TestCase
|
||||||
citibank.firm = apple
|
citibank.firm = apple
|
||||||
assert_equal apple.id, citibank.firm_id
|
assert_equal apple.id, citibank.firm_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_no_unexpected_aliasing
|
||||||
|
first_firm = companies(:first_firm)
|
||||||
|
another_firm = companies(:another_firm)
|
||||||
|
|
||||||
|
citibank = Account.create("credit_limit" => 10)
|
||||||
|
citibank.firm = first_firm
|
||||||
|
original_proxy = citibank.firm
|
||||||
|
citibank.firm = another_firm
|
||||||
|
|
||||||
|
assert_equal first_firm.object_id, original_proxy.object_id
|
||||||
|
assert_equal another_firm.object_id, citibank.firm.object_id
|
||||||
|
end
|
||||||
|
|
||||||
def test_creating_the_belonging_object
|
def test_creating_the_belonging_object
|
||||||
citibank = Account.create("credit_limit" => 10)
|
citibank = Account.create("credit_limit" => 10)
|
||||||
apple = citibank.create_firm("name" => "Apple")
|
apple = citibank.create_firm("name" => "Apple")
|
||||||
|
|
|
||||||
|
|
@ -1086,16 +1086,29 @@ class BasicsTest < Test::Unit::TestCase
|
||||||
assert_equal(myobj, topic.content)
|
assert_equal(myobj, topic.content)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_serialized_attribute_with_class_constraint
|
def test_nil_serialized_attribute_with_class_constraint
|
||||||
myobj = MyObject.new('value1', 'value2')
|
myobj = MyObject.new('value1', 'value2')
|
||||||
topic = Topic.create("content" => myobj)
|
topic = Topic.new
|
||||||
|
assert_nil topic.content
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_raise_exception_on_serialized_attribute_with_type_mismatch
|
||||||
|
myobj = MyObject.new('value1', 'value2')
|
||||||
|
topic = Topic.new(:content => myobj)
|
||||||
|
assert topic.save
|
||||||
Topic.serialize(:content, Hash)
|
Topic.serialize(:content, Hash)
|
||||||
|
|
||||||
assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content }
|
assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content }
|
||||||
|
ensure
|
||||||
|
Topic.serialize(:content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_serialized_attribute_with_class_constraint
|
||||||
settings = { "color" => "blue" }
|
settings = { "color" => "blue" }
|
||||||
Topic.find(topic.id).update_attribute("content", settings)
|
Topic.serialize(:content, Hash)
|
||||||
|
topic = Topic.new(:content => settings)
|
||||||
|
assert topic.save
|
||||||
assert_equal(settings, Topic.find(topic.id).content)
|
assert_equal(settings, Topic.find(topic.id).content)
|
||||||
|
ensure
|
||||||
Topic.serialize(:content)
|
Topic.serialize(:content)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ class Author < ActiveRecord::Base
|
||||||
|
|
||||||
has_many :hello_posts, :class_name => "Post", :conditions => "posts.body = 'hello'"
|
has_many :hello_posts, :class_name => "Post", :conditions => "posts.body = 'hello'"
|
||||||
has_many :hello_post_comments, :through => :hello_posts, :source => :comments
|
has_many :hello_post_comments, :through => :hello_posts, :source => :comments
|
||||||
|
has_many :posts_with_no_comments, :class_name => 'Post', :conditions => 'comments.id is null', :include => :comments
|
||||||
|
|
||||||
has_many :other_posts, :class_name => "Post"
|
has_many :other_posts, :class_name => "Post"
|
||||||
has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding,
|
has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding,
|
||||||
|
|
|
||||||
437
tracks/vendor/rails/activerecord/test/fixtures/binaries.yml
vendored
Normal file
437
tracks/vendor/rails/activerecord/test/fixtures/binaries.yml
vendored
Normal file
|
|
@ -0,0 +1,437 @@
|
||||||
|
flowers:
|
||||||
|
id: 1
|
||||||
|
data: !binary | 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
|
||||||
|
KKpVChRRRQAUUUUAFFFFABRRRQAUUUUAf//Z
|
||||||
|
|
||||||
|
|
@ -57,4 +57,9 @@ ActiveRecord::Schema.define do
|
||||||
create_table :lock_without_defaults_cust, :force => true do |t|
|
create_table :lock_without_defaults_cust, :force => true do |t|
|
||||||
t.column :custom_lock_version, :integer
|
t.column :custom_lock_version, :integer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table :audit_logs, :force => true do |t|
|
||||||
|
t.column :message, :string, :null=>false
|
||||||
|
t.column :developer_id, :integer, :null=>false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,18 @@ class Developer < ActiveRecord::Base
|
||||||
|
|
||||||
has_and_belongs_to_many :special_projects, :join_table => 'developers_projects', :association_foreign_key => 'project_id'
|
has_and_belongs_to_many :special_projects, :join_table => 'developers_projects', :association_foreign_key => 'project_id'
|
||||||
|
|
||||||
|
has_many :audit_logs
|
||||||
|
|
||||||
validates_inclusion_of :salary, :in => 50000..200000
|
validates_inclusion_of :salary, :in => 50000..200000
|
||||||
validates_length_of :name, :within => 3..20
|
validates_length_of :name, :within => 3..20
|
||||||
|
|
||||||
|
before_create do |developer|
|
||||||
|
developer.audit_logs.build :message => "Computer created"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class AuditLog < ActiveRecord::Base
|
||||||
|
belongs_to :developer
|
||||||
end
|
end
|
||||||
|
|
||||||
DeveloperSalary = Struct.new(:amount)
|
DeveloperSalary = Struct.new(:amount)
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,15 @@ class FixturesTest < Test::Unit::TestCase
|
||||||
self.use_instantiated_fixtures = true
|
self.use_instantiated_fixtures = true
|
||||||
self.use_transactional_fixtures = false
|
self.use_transactional_fixtures = false
|
||||||
|
|
||||||
fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes
|
fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes, :binaries
|
||||||
|
|
||||||
FIXTURES = %w( accounts companies customers
|
FIXTURES = %w( accounts binaries companies customers
|
||||||
developers developers_projects entrants
|
developers developers_projects entrants
|
||||||
movies projects subscribers topics tasks )
|
movies projects subscribers topics tasks )
|
||||||
MATCH_ATTRIBUTE_NAME = /[a-zA-Z][-_\w]*/
|
MATCH_ATTRIBUTE_NAME = /[a-zA-Z][-_\w]*/
|
||||||
|
|
||||||
|
BINARY_FIXTURE_PATH = File.dirname(__FILE__) + '/fixtures/flowers.jpg'
|
||||||
|
|
||||||
def test_clean_fixtures
|
def test_clean_fixtures
|
||||||
FIXTURES.each do |name|
|
FIXTURES.each do |name|
|
||||||
fixtures = nil
|
fixtures = nil
|
||||||
|
|
@ -100,7 +102,6 @@ class FixturesTest < Test::Unit::TestCase
|
||||||
assert first
|
assert first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def test_bad_format
|
def test_bad_format
|
||||||
path = File.join(File.dirname(__FILE__), 'fixtures', 'bad_fixtures')
|
path = File.join(File.dirname(__FILE__), 'fixtures', 'bad_fixtures')
|
||||||
Dir.entries(path).each do |file|
|
Dir.entries(path).each do |file|
|
||||||
|
|
@ -174,7 +175,6 @@ class FixturesTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def test_yml_file_in_subdirectory
|
def test_yml_file_in_subdirectory
|
||||||
assert_equal(categories(:sub_special_1).name, "A special category in a subdir file")
|
assert_equal(categories(:sub_special_1).name, "A special category in a subdir file")
|
||||||
assert_equal(categories(:sub_special_1).class, SpecialCategory)
|
assert_equal(categories(:sub_special_1).class, SpecialCategory)
|
||||||
|
|
@ -185,7 +185,11 @@ class FixturesTest < Test::Unit::TestCase
|
||||||
assert_equal(categories(:sub_special_3).class, SpecialCategory)
|
assert_equal(categories(:sub_special_3).class, SpecialCategory)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_binary_in_fixtures
|
||||||
|
assert_equal 1, @binaries.size
|
||||||
|
data = File.read(BINARY_FIXTURE_PATH).freeze
|
||||||
|
assert_equal data, @flowers.data
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if Account.connection.respond_to?(:reset_pk_sequence!)
|
if Account.connection.respond_to?(:reset_pk_sequence!)
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
||||||
# SQL Server and Sybase will not allow you to add a NOT NULL column
|
# SQL Server and Sybase will not allow you to add a NOT NULL column
|
||||||
# to a table without specifying a default value, so the
|
# to a table without specifying a default value, so the
|
||||||
# following test must be skipped
|
# following test must be skipped
|
||||||
unless current_adapter?(:SQLServerAdapter, :SybaseAdapter)
|
unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :SQLiteAdapter)
|
||||||
def test_add_column_not_null_without_default
|
def test_add_column_not_null_without_default
|
||||||
Person.connection.create_table :testings do |t|
|
Person.connection.create_table :testings do |t|
|
||||||
t.column :foo, :string
|
t.column :foo, :string
|
||||||
|
|
@ -209,7 +209,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
||||||
def test_native_decimal_insert_manual_vs_automatic
|
def test_native_decimal_insert_manual_vs_automatic
|
||||||
# SQLite3 always uses float in violation of SQL
|
# SQLite3 always uses float in violation of SQL
|
||||||
# 16 decimal places
|
# 16 decimal places
|
||||||
correct_value = (current_adapter?(:SQLiteAdapter) ? '0.123456789012346E20' : '0012345678901234567890.0123456789').to_d
|
correct_value = '0012345678901234567890.0123456789'.to_d
|
||||||
|
|
||||||
Person.delete_all
|
Person.delete_all
|
||||||
Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
|
Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
|
||||||
|
|
@ -227,8 +227,9 @@ if ActiveRecord::Base.connection.supports_migrations?
|
||||||
assert_kind_of BigDecimal, row.wealth
|
assert_kind_of BigDecimal, row.wealth
|
||||||
|
|
||||||
# If this assert fails, that means the SELECT is broken!
|
# If this assert fails, that means the SELECT is broken!
|
||||||
assert_equal correct_value, row.wealth
|
unless current_adapter?(:SQLite3Adapter)
|
||||||
|
assert_equal correct_value, row.wealth
|
||||||
|
end
|
||||||
# Reset to old state
|
# Reset to old state
|
||||||
Person.delete_all
|
Person.delete_all
|
||||||
|
|
||||||
|
|
@ -240,8 +241,9 @@ if ActiveRecord::Base.connection.supports_migrations?
|
||||||
assert_kind_of BigDecimal, row.wealth
|
assert_kind_of BigDecimal, row.wealth
|
||||||
|
|
||||||
# If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
|
# If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
|
||||||
assert_equal correct_value, row.wealth
|
unless current_adapter?(:SQLite3Adapter)
|
||||||
|
assert_equal correct_value, row.wealth
|
||||||
|
end
|
||||||
# Reset to old state
|
# Reset to old state
|
||||||
Person.connection.del_column "people", "wealth" rescue nil
|
Person.connection.del_column "people", "wealth" rescue nil
|
||||||
Person.reset_column_information
|
Person.reset_column_information
|
||||||
|
|
@ -267,10 +269,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
||||||
|
|
||||||
# Test for 30 significent digits (beyond the 16 of float), 10 of them
|
# Test for 30 significent digits (beyond the 16 of float), 10 of them
|
||||||
# after the decimal place.
|
# after the decimal place.
|
||||||
if current_adapter?(:SQLiteAdapter)
|
unless current_adapter?(:SQLite3Adapter)
|
||||||
# SQLite3 uses float in violation of SQL. Test for 16 decimal places.
|
|
||||||
assert_equal BigDecimal.new('0.123456789012346E20'), bob.wealth
|
|
||||||
else
|
|
||||||
assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
|
assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,53 @@ class ListTest < Test::Unit::TestCase
|
||||||
assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
|
assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_remove_from_list_should_then_fail_in_list?
|
||||||
|
assert_equal true, mixins(:list_1).in_list?
|
||||||
|
mixins(:list_1).remove_from_list
|
||||||
|
assert_equal false, mixins(:list_1).in_list?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_remove_from_list_should_set_position_to_nil
|
||||||
|
assert_equal [mixins(:list_1),
|
||||||
|
mixins(:list_2),
|
||||||
|
mixins(:list_3),
|
||||||
|
mixins(:list_4)],
|
||||||
|
ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
|
||||||
|
|
||||||
|
mixins(:list_2).remove_from_list
|
||||||
|
|
||||||
|
assert_equal [mixins(:list_2, :reload),
|
||||||
|
mixins(:list_1, :reload),
|
||||||
|
mixins(:list_3, :reload),
|
||||||
|
mixins(:list_4, :reload)],
|
||||||
|
ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
|
||||||
|
|
||||||
|
assert_equal 1, mixins(:list_1).pos
|
||||||
|
assert_equal nil, mixins(:list_2).pos
|
||||||
|
assert_equal 2, mixins(:list_3).pos
|
||||||
|
assert_equal 3, mixins(:list_4).pos
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_remove_before_destroy_does_not_shift_lower_items_twice
|
||||||
|
assert_equal [mixins(:list_1),
|
||||||
|
mixins(:list_2),
|
||||||
|
mixins(:list_3),
|
||||||
|
mixins(:list_4)],
|
||||||
|
ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
|
||||||
|
|
||||||
|
mixins(:list_2).remove_from_list
|
||||||
|
mixins(:list_2).destroy
|
||||||
|
|
||||||
|
assert_equal [mixins(:list_1, :reload),
|
||||||
|
mixins(:list_3, :reload),
|
||||||
|
mixins(:list_4, :reload)],
|
||||||
|
ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
|
||||||
|
|
||||||
|
assert_equal 1, mixins(:list_1).pos
|
||||||
|
assert_equal 2, mixins(:list_3).pos
|
||||||
|
assert_equal 3, mixins(:list_4).pos
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class TreeTest < Test::Unit::TestCase
|
class TreeTest < Test::Unit::TestCase
|
||||||
|
|
|
||||||
|
|
@ -631,7 +631,7 @@ class ValidationsTest < Test::Unit::TestCase
|
||||||
t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
|
t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
|
||||||
assert !t.save
|
assert !t.save
|
||||||
assert t.errors.on(:replies)
|
assert t.errors.on(:replies)
|
||||||
t.replies.create('title' => 'areply', 'content' => 'whateveragain')
|
t.replies.build('title' => 'areply', 'content' => 'whateveragain')
|
||||||
assert t.valid?
|
assert t.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -824,7 +824,7 @@ class ValidationsTest < Test::Unit::TestCase
|
||||||
t = Topic.new('title' => 'あいうえお', 'content' => 'かきくけこ')
|
t = Topic.new('title' => 'あいうえお', 'content' => 'かきくけこ')
|
||||||
assert !t.save
|
assert !t.save
|
||||||
assert t.errors.on(:replies)
|
assert t.errors.on(:replies)
|
||||||
t.replies.create('title' => 'あいうえお', 'content' => 'かきくけこ')
|
t.replies.build('title' => 'あいうえお', 'content' => 'かきくけこ')
|
||||||
assert t.valid?
|
assert t.valid?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
16
tracks/vendor/rails/activesupport/CHANGELOG
vendored
16
tracks/vendor/rails/activesupport/CHANGELOG
vendored
|
|
@ -1,3 +1,19 @@
|
||||||
|
*1.4.4* (October 12th, 2007)
|
||||||
|
|
||||||
|
* Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before. #6765, #7047, #7462 [bgipsy, Jeremy McAnally, Dan Kubb, brendan, Diego Algorta Casamayou]
|
||||||
|
|
||||||
|
|
||||||
|
*1.4.3* (October 4th, 2007)
|
||||||
|
|
||||||
|
* Demote Hash#to_xml to use XmlSimple#xml_in_string so it can't read files or stdin. #8453 [candlerb, Jeremy Kemper]
|
||||||
|
|
||||||
|
* Document Object#blank?. #6491 [Chris Mear]
|
||||||
|
|
||||||
|
* Update Dependencies to ignore constants inherited from ancestors. Closes #6951. [Nicholas Seckar]
|
||||||
|
|
||||||
|
* Improved multibyte performance by relying less on exception raising #8159 [Blaine]
|
||||||
|
|
||||||
|
|
||||||
*1.4.2* (March 12th, 2007)
|
*1.4.2* (March 12th, 2007)
|
||||||
|
|
||||||
* Ruby 1.8.6 and 1.9 define private Time#to_date and #to_datetime; make them
|
* Ruby 1.8.6 and 1.9 define private Time#to_date and #to_datetime; make them
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
class Object #:nodoc:
|
class Object
|
||||||
# "", " ", nil, [], and {} are blank
|
# An object is blank if it's nil, empty, or a whitespace string.
|
||||||
|
# For example, "", " ", nil, [], and {} are blank.
|
||||||
|
#
|
||||||
|
# This simplifies
|
||||||
|
# if !address.nil? && !address.empty?
|
||||||
|
# to
|
||||||
|
# if !address.blank?
|
||||||
def blank?
|
def blank?
|
||||||
if respond_to?(:empty?) && respond_to?(:strip)
|
if respond_to?(:empty?) && respond_to?(:strip)
|
||||||
empty? or strip.empty?
|
empty? or strip.empty?
|
||||||
|
|
@ -47,4 +53,4 @@ class Numeric #:nodoc:
|
||||||
def blank?
|
def blank?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,44 @@
|
||||||
require 'date'
|
require 'date'
|
||||||
require 'xml_simple'
|
require 'xml_simple'
|
||||||
|
require 'cgi'
|
||||||
|
|
||||||
|
# Extensions needed for Hash#to_query
|
||||||
|
class Object
|
||||||
|
def to_param #:nodoc:
|
||||||
|
to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_query(key) #:nodoc:
|
||||||
|
"#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Array
|
||||||
|
def to_query(key) #:nodoc:
|
||||||
|
collect { |value| value.to_query("#{key}[]") }.sort * '&'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Locked down XmlSimple#xml_in_string
|
||||||
|
class XmlSimple
|
||||||
|
# Same as xml_in but doesn't try to smartly shoot itself in the foot.
|
||||||
|
def xml_in_string(string, options = nil)
|
||||||
|
handle_options('in', options)
|
||||||
|
|
||||||
|
@doc = parse(string)
|
||||||
|
result = collapse(@doc.root)
|
||||||
|
|
||||||
|
if @options['keeproot']
|
||||||
|
merge({}, @doc.root.name, result)
|
||||||
|
else
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.xml_in_string(string, options = nil)
|
||||||
|
new.xml_in_string(string, options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module ActiveSupport #:nodoc:
|
module ActiveSupport #:nodoc:
|
||||||
module CoreExtensions #:nodoc:
|
module CoreExtensions #:nodoc:
|
||||||
|
|
@ -27,6 +66,12 @@ module ActiveSupport #:nodoc:
|
||||||
klass.extend(ClassMethods)
|
klass.extend(ClassMethods)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_query(namespace = nil)
|
||||||
|
collect do |key, value|
|
||||||
|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
||||||
|
end.sort * '&'
|
||||||
|
end
|
||||||
|
|
||||||
def to_xml(options = {})
|
def to_xml(options = {})
|
||||||
options[:indent] ||= 2
|
options[:indent] ||= 2
|
||||||
options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]),
|
options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]),
|
||||||
|
|
@ -81,14 +126,14 @@ module ActiveSupport #:nodoc:
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
def from_xml(xml)
|
def from_xml(xml)
|
||||||
# TODO: Refactor this into something much cleaner that doesn't rely on XmlSimple
|
# TODO: Refactor this into something much cleaner that doesn't rely on XmlSimple
|
||||||
undasherize_keys(typecast_xml_value(XmlSimple.xml_in(xml,
|
undasherize_keys(typecast_xml_value(XmlSimple.xml_in_string(xml,
|
||||||
'forcearray' => false,
|
'forcearray' => false,
|
||||||
'forcecontent' => true,
|
'forcecontent' => true,
|
||||||
'keeproot' => true,
|
'keeproot' => true,
|
||||||
'contentkey' => '__content__')
|
'contentkey' => '__content__')
|
||||||
))
|
))
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_from_xml(xml)
|
def create_from_xml(xml)
|
||||||
ActiveSupport::Deprecation.warn("Hash.create_from_xml has been renamed to Hash.from_xml", caller)
|
ActiveSupport::Deprecation.warn("Hash.create_from_xml has been renamed to Hash.from_xml", caller)
|
||||||
from_xml(xml)
|
from_xml(xml)
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,18 @@ class Module
|
||||||
parents << Object unless parents.include? Object
|
parents << Object unless parents.include? Object
|
||||||
parents
|
parents
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return the constants that have been defined locally by this object and not
|
||||||
|
# in an ancestor. This method may miss some constants if their definition in
|
||||||
|
# the ancestor is identical to their definition in the receiver.
|
||||||
|
def local_constants
|
||||||
|
inherited = {}
|
||||||
|
ancestors.each do |anc|
|
||||||
|
next if anc == self
|
||||||
|
anc.constants.each { |const| inherited[const] = anc.const_get(const) }
|
||||||
|
end
|
||||||
|
constants.select do |const|
|
||||||
|
! inherited.key?(const) || inherited[const].object_id != const_get(const).object_id
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -318,13 +318,13 @@ module Dependencies #:nodoc:
|
||||||
watch_frames = descs.collect do |desc|
|
watch_frames = descs.collect do |desc|
|
||||||
if desc.is_a? Module
|
if desc.is_a? Module
|
||||||
mod_name = desc.name
|
mod_name = desc.name
|
||||||
initial_constants = desc.constants
|
initial_constants = desc.local_constants
|
||||||
elsif desc.is_a?(String) || desc.is_a?(Symbol)
|
elsif desc.is_a?(String) || desc.is_a?(Symbol)
|
||||||
mod_name = desc.to_s
|
mod_name = desc.to_s
|
||||||
|
|
||||||
# Handle the case where the module has yet to be defined.
|
# Handle the case where the module has yet to be defined.
|
||||||
initial_constants = if qualified_const_defined?(mod_name)
|
initial_constants = if qualified_const_defined?(mod_name)
|
||||||
mod_name.constantize.constants
|
mod_name.constantize.local_constants
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
@ -349,7 +349,7 @@ module Dependencies #:nodoc:
|
||||||
|
|
||||||
mod = mod_name.constantize
|
mod = mod_name.constantize
|
||||||
next [] unless mod.is_a? Module
|
next [] unless mod.is_a? Module
|
||||||
new_constants = mod.constants - prior_constants
|
new_constants = mod.local_constants - prior_constants
|
||||||
|
|
||||||
# Make sure no other frames takes credit for these constants.
|
# Make sure no other frames takes credit for these constants.
|
||||||
constant_watch_stack.each do |frame_name, constants|
|
constant_watch_stack.each do |frame_name, constants|
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,14 @@ module ActiveSupport
|
||||||
"\n" => '\n',
|
"\n" => '\n',
|
||||||
"\r" => '\r',
|
"\r" => '\r',
|
||||||
"\t" => '\t',
|
"\t" => '\t',
|
||||||
'"' => '\"',
|
'"' => '\"',
|
||||||
'\\' => '\\\\'
|
'\\' => '\\\\',
|
||||||
|
'<' => '\\074',
|
||||||
|
'>' => '\\076'
|
||||||
}
|
}
|
||||||
|
|
||||||
define_encoder String do |string|
|
define_encoder String do |string|
|
||||||
'"' + string.gsub(/[\010\f\n\r\t"\\]/) { |s|
|
'"' + string.gsub(/[\010\f\n\r\t"\\<>]/) { |s|
|
||||||
ESCAPED_CHARS[s]
|
ESCAPED_CHARS[s]
|
||||||
}.gsub(/([\xC0-\xDF][\x80-\xBF]|
|
}.gsub(/([\xC0-\xDF][\x80-\xBF]|
|
||||||
[\xE0-\xEF][\x80-\xBF]{2}|
|
[\xE0-\xEF][\x80-\xBF]{2}|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ module ActiveSupport::Multibyte #:nodoc:
|
||||||
|
|
||||||
# Create a new Chars instance.
|
# Create a new Chars instance.
|
||||||
def initialize(str)
|
def initialize(str)
|
||||||
@string = (str.string rescue str)
|
@string = str.respond_to?(:string) ? str.string : str
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns -1, 0 or +1 depending on whether the Chars object is to be sorted before, equal or after the
|
# Returns -1, 0 or +1 depending on whether the Chars object is to be sorted before, equal or after the
|
||||||
|
|
@ -70,18 +70,18 @@ module ActiveSupport::Multibyte #:nodoc:
|
||||||
def method_missing(m, *a, &b)
|
def method_missing(m, *a, &b)
|
||||||
begin
|
begin
|
||||||
# Simulate methods with a ! at the end because we can't touch the enclosed string from the handlers.
|
# Simulate methods with a ! at the end because we can't touch the enclosed string from the handlers.
|
||||||
if m.to_s =~ /^(.*)\!$/
|
if m.to_s =~ /^(.*)\!$/ && handler.respond_to?($1)
|
||||||
result = handler.send($1, @string, *a, &b)
|
result = handler.send($1, @string, *a, &b)
|
||||||
if result == @string
|
if result == @string
|
||||||
result = nil
|
result = nil
|
||||||
else
|
else
|
||||||
@string.replace result
|
@string.replace result
|
||||||
end
|
end
|
||||||
else
|
elsif handler.respond_to?(m)
|
||||||
result = handler.send(m, @string, *a, &b)
|
result = handler.send(m, @string, *a, &b)
|
||||||
|
else
|
||||||
|
result = @string.send(m, *a, &b)
|
||||||
end
|
end
|
||||||
rescue NoMethodError
|
|
||||||
result = @string.send(m, *a, &b)
|
|
||||||
rescue Handlers::EncodingError
|
rescue Handlers::EncodingError
|
||||||
@string.replace handler.tidy_bytes(@string)
|
@string.replace handler.tidy_bytes(@string)
|
||||||
retry
|
retry
|
||||||
|
|
@ -126,4 +126,4 @@ begin
|
||||||
ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8HandlerProc
|
ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8HandlerProc
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8Handler
|
ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8Handler
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ module ActiveSupport
|
||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 1
|
MAJOR = 1
|
||||||
MINOR = 4
|
MINOR = 4
|
||||||
TINY = 2
|
TINY = 4
|
||||||
|
|
||||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -470,3 +470,40 @@ class HashToXmlTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class QueryTest < Test::Unit::TestCase
|
||||||
|
def test_simple_conversion
|
||||||
|
assert_query_equal 'a=10', :a => 10
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_cgi_escaping
|
||||||
|
assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_nil_parameter_value
|
||||||
|
empty = Object.new
|
||||||
|
def empty.to_param; nil end
|
||||||
|
assert_query_equal 'a=', 'a' => empty
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_nested_conversion
|
||||||
|
assert_query_equal 'person%5Bname%5D=Nicholas&person%5Blogin%5D=seckar',
|
||||||
|
:person => {:name => 'Nicholas', :login => 'seckar'}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_multiple_nested
|
||||||
|
assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10',
|
||||||
|
:person => {:id => 10}, :account => {:person => {:id => 20}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_array_values
|
||||||
|
assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20',
|
||||||
|
:person => {:id => [10, 20]}
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def assert_query_equal(expected, actual, message = nil)
|
||||||
|
assert_equal expected.split('&').sort, actual.to_query.split('&').sort
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue