mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Merge commit 'mainstream/master'
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,16 +1,20 @@
|
||||
.DS_Store
|
||||
debug.log
|
||||
doc/rdoc
|
||||
activemodel/doc
|
||||
activeresource/doc
|
||||
activerecord/doc
|
||||
actionpack/doc
|
||||
actionmailer/doc
|
||||
activesupport/doc
|
||||
activemodel/pkg
|
||||
activeresource/pkg
|
||||
activerecord/pkg
|
||||
actionpack/pkg
|
||||
activemodel/test/fixtures/fixture_database.sqlite3
|
||||
actionmailer/pkg
|
||||
activesupport/pkg
|
||||
actionpack/test/tmp
|
||||
activesupport/test/fixtures/isolation_test
|
||||
railties/pkg
|
||||
railties/test/500.html
|
||||
@@ -23,3 +27,5 @@ railties/guides/output
|
||||
*.rbc
|
||||
*.swp
|
||||
*.swo
|
||||
actionpack/bin
|
||||
*/vendor/gems
|
||||
|
||||
5
Rakefile
5
Rakefile
@@ -3,7 +3,7 @@ require 'rake/rdoctask'
|
||||
|
||||
env = %(PKG_BUILD="#{ENV['PKG_BUILD']}") if ENV['PKG_BUILD']
|
||||
|
||||
PROJECTS = %w(activesupport actionpack actionmailer activeresource activerecord railties)
|
||||
PROJECTS = %w(activesupport actionpack actionmailer activeresource activerecord activemodel railties)
|
||||
|
||||
Dir["#{File.dirname(__FILE__)}/*/lib/*/version.rb"].each do |version_path|
|
||||
require version_path
|
||||
@@ -12,7 +12,7 @@ end
|
||||
desc 'Run all tests by default'
|
||||
task :default => :test
|
||||
|
||||
%w(test isolated_test rdoc pgem package release gem).each do |task_name|
|
||||
%w(test isolated_test rdoc pgem package release gem gemspec).each do |task_name|
|
||||
desc "Run #{task_name} task for all projects"
|
||||
task task_name do
|
||||
errors = []
|
||||
@@ -30,7 +30,6 @@ task :install => :gem do
|
||||
system("gem install railties/pkg/rails-#{ActionPack::VERSION::STRING}.gem --no-ri --no-rdoc")
|
||||
end
|
||||
|
||||
|
||||
desc "Generate documentation for the Rails framework"
|
||||
Rake::RDocTask.new do |rdoc|
|
||||
rdoc.rdoc_dir = 'doc/rdoc'
|
||||
|
||||
@@ -78,6 +78,11 @@ Rake::GemPackageTask.new(spec) do |p|
|
||||
p.need_zip = true
|
||||
end
|
||||
|
||||
task :gemspec do
|
||||
File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file|
|
||||
file.puts spec.to_ruby
|
||||
end
|
||||
end
|
||||
|
||||
desc "Publish the API documentation"
|
||||
task :pgem => [:package] do
|
||||
|
||||
33
actionmailer/actionmailer.gemspec
Normal file
33
actionmailer/actionmailer.gemspec
Normal file
File diff suppressed because one or more lines are too long
@@ -256,6 +256,8 @@ module ActionMailer #:nodoc:
|
||||
# +implicit_parts_order+.
|
||||
class Base
|
||||
include AdvAttrAccessor, PartContainer, Quoting, Utils
|
||||
extend AbstractController::RenderingController
|
||||
|
||||
if Object.const_defined?(:ActionController)
|
||||
include ActionController::UrlWriter
|
||||
include ActionController::Layout
|
||||
@@ -479,58 +481,62 @@ module ActionMailer #:nodoc:
|
||||
# Initialize the mailer via the given +method_name+. The body will be
|
||||
# rendered and a new TMail::Mail object created.
|
||||
def create!(method_name, *parameters) #:nodoc:
|
||||
initialize_defaults(method_name)
|
||||
__send__(method_name, *parameters)
|
||||
|
||||
# If an explicit, textual body has not been set, we check assumptions.
|
||||
unless String === @body
|
||||
# First, we look to see if there are any likely templates that match,
|
||||
# which include the content-type in their file name (i.e.,
|
||||
# "the_template_file.text.html.erb", etc.). Only do this if parts
|
||||
# have not already been specified manually.
|
||||
# if @parts.empty?
|
||||
template_root.find_all_by_parts(@template, {}, template_path).each do |template|
|
||||
@parts << Part.new(
|
||||
:content_type => template.mime_type ? template.mime_type.to_s : "text/plain",
|
||||
:disposition => "inline",
|
||||
:charset => charset,
|
||||
:body => render_template(template, @body)
|
||||
)
|
||||
end
|
||||
|
||||
if @parts.size > 1
|
||||
@content_type = "multipart/alternative" if @content_type !~ /^multipart/
|
||||
@parts = sort_parts(@parts, @implicit_parts_order)
|
||||
end
|
||||
# end
|
||||
|
||||
# Then, if there were such templates, we check to see if we ought to
|
||||
# also render a "normal" template (without the content type). If a
|
||||
# normal template exists (or if there were no implicit parts) we render
|
||||
# it.
|
||||
# ====
|
||||
# TODO: Revisit this
|
||||
# template_exists = @parts.empty?
|
||||
# template_exists ||= template_root.find("#{mailer_name}/#{@template}")
|
||||
# @body = render_message(@template, @body) if template_exists
|
||||
ActiveSupport::Orchestra.instrument(:create_mail, :name => method_name) do
|
||||
initialize_defaults(method_name)
|
||||
__send__(method_name, *parameters)
|
||||
|
||||
# Finally, if there are other message parts and a textual body exists,
|
||||
# we shift it onto the front of the parts and set the body to nil (so
|
||||
# that create_mail doesn't try to render it in addition to the parts).
|
||||
# ====
|
||||
# TODO: Revisit this
|
||||
# if !@parts.empty? && String === @body
|
||||
# @parts.unshift Part.new(:charset => charset, :body => @body)
|
||||
# @body = nil
|
||||
# end
|
||||
# If an explicit, textual body has not been set, we check assumptions.
|
||||
unless String === @body
|
||||
# First, we look to see if there are any likely templates that match,
|
||||
# which include the content-type in their file name (i.e.,
|
||||
# "the_template_file.text.html.erb", etc.). Only do this if parts
|
||||
# have not already been specified manually.
|
||||
# if @parts.empty?
|
||||
template_root.find_all(@template, {}, template_path).each do |template|
|
||||
@parts << Part.new(
|
||||
:content_type => template.mime_type ? template.mime_type.to_s : "text/plain",
|
||||
:disposition => "inline",
|
||||
:charset => charset,
|
||||
:body => render_template(template, @body)
|
||||
)
|
||||
end
|
||||
|
||||
if @parts.size > 1
|
||||
@content_type = "multipart/alternative" if @content_type !~ /^multipart/
|
||||
@parts = sort_parts(@parts, @implicit_parts_order)
|
||||
end
|
||||
# end
|
||||
|
||||
# Then, if there were such templates, we check to see if we ought to
|
||||
# also render a "normal" template (without the content type). If a
|
||||
# normal template exists (or if there were no implicit parts) we render
|
||||
# it.
|
||||
# ====
|
||||
# TODO: Revisit this
|
||||
# template_exists = @parts.empty?
|
||||
# template_exists ||= template_root.find("#{mailer_name}/#{@template}")
|
||||
# @body = render_message(@template, @body) if template_exists
|
||||
|
||||
# Finally, if there are other message parts and a textual body exists,
|
||||
# we shift it onto the front of the parts and set the body to nil (so
|
||||
# that create_mail doesn't try to render it in addition to the parts).
|
||||
# ====
|
||||
# TODO: Revisit this
|
||||
# if !@parts.empty? && String === @body
|
||||
# @parts.unshift Part.new(:charset => charset, :body => @body)
|
||||
# @body = nil
|
||||
# end
|
||||
end
|
||||
|
||||
# If this is a multipart e-mail add the mime_version if it is not
|
||||
# already set.
|
||||
@mime_version ||= "1.0" if !@parts.empty?
|
||||
|
||||
# build the mail object itself
|
||||
@mail = create_mail
|
||||
end
|
||||
|
||||
# If this is a multipart e-mail add the mime_version if it is not
|
||||
# already set.
|
||||
@mime_version ||= "1.0" if !@parts.empty?
|
||||
|
||||
# build the mail object itself
|
||||
@mail = create_mail
|
||||
@mail
|
||||
end
|
||||
|
||||
# Delivers a TMail::Mail object. By default, it delivers the cached mail
|
||||
@@ -538,19 +544,21 @@ module ActionMailer #:nodoc:
|
||||
# no alternate has been given as the parameter, this will fail.
|
||||
def deliver!(mail = @mail)
|
||||
raise "no mail object available for delivery!" unless mail
|
||||
|
||||
|
||||
unless logger.nil?
|
||||
logger.info "Sent mail to #{Array(recipients).join(', ')}"
|
||||
logger.debug "\n#{mail.encoded}"
|
||||
end
|
||||
|
||||
begin
|
||||
__send__("perform_delivery_#{delivery_method}", mail) if perform_deliveries
|
||||
rescue Exception => e # Net::SMTP errors or sendmail pipe errors
|
||||
raise e if raise_delivery_errors
|
||||
ActiveSupport::Orchestra.instrument(:deliver_mail, :mail => @mail) do
|
||||
begin
|
||||
__send__("perform_delivery_#{delivery_method}", mail) if perform_deliveries
|
||||
rescue Exception => e # Net::SMTP errors or sendmail pipe errors
|
||||
raise e if raise_delivery_errors
|
||||
end
|
||||
end
|
||||
|
||||
return mail
|
||||
mail
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
require 'action_mailer'
|
||||
14
actionpack/Gemfile
Normal file
14
actionpack/Gemfile
Normal file
@@ -0,0 +1,14 @@
|
||||
rails_root = Pathname.new(File.dirname(__FILE__)).join("..")
|
||||
|
||||
gem "rack", "~> 1.0.0"
|
||||
gem "rack-test", "~> 0.4.2"
|
||||
gem "activesupport", "3.0.pre", :vendored_at => rails_root.join("activesupport")
|
||||
gem "activemodel", "3.0.pre", :vendored_at => rails_root.join("activemodel")
|
||||
|
||||
only :test do
|
||||
gem "mocha"
|
||||
gem "sqlite3-ruby"
|
||||
gem "RedCloth"
|
||||
end
|
||||
|
||||
disable_system_gems
|
||||
@@ -17,68 +17,48 @@ RUBY_FORGE_PROJECT = "actionpack"
|
||||
RUBY_FORGE_USER = "webster132"
|
||||
|
||||
desc "Default Task"
|
||||
task :default => [ :test ]
|
||||
task :default => :test
|
||||
|
||||
task :bundle do
|
||||
puts "Checking if the bundled testing requirements are up to date..."
|
||||
result = system "gem bundle"
|
||||
unless result
|
||||
puts "The gem bundler is not installed. Installing."
|
||||
system "gem install bundler"
|
||||
system "gem bundle"
|
||||
end
|
||||
end
|
||||
|
||||
# Run the unit tests
|
||||
|
||||
desc "Run all unit tests"
|
||||
task :test => [:test_action_pack, :test_active_record_integration, :test_new_base]
|
||||
task :test => [:test_action_pack, :test_active_record_integration]
|
||||
|
||||
TESTS_GLOB = "test/{abstract,controller,dispatch,new_base,template,html-scanner}/**/*_test.rb"
|
||||
|
||||
test_lib_dirs = ENV["NEW"] ? ["test/new_base"] : []
|
||||
test_lib_dirs.push "test", "test/lib"
|
||||
# test_lib_dirs = [ENV["NEW"] ? "test/new_base" : "test", "test/lib"]
|
||||
Rake::TestTask.new(:test_action_pack) do |t|
|
||||
t.libs.concat test_lib_dirs
|
||||
t.libs << 'test'
|
||||
|
||||
# make sure we include the tests in alphabetical order as on some systems
|
||||
# this will not happen automatically and the tests (as a whole) will error
|
||||
t.test_files = Dir.glob( "test/{controller,dispatch,template,html-scanner}/**/*_test.rb" ).sort
|
||||
t.test_files = Dir.glob(TESTS_GLOB).sort
|
||||
|
||||
t.verbose = true
|
||||
#t.warning = true
|
||||
# t.warning = true
|
||||
end
|
||||
|
||||
task :isolated_test do
|
||||
ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
|
||||
Dir.glob("test/{controller,dispatch,template}/**/*_test.rb").all? do |file|
|
||||
system(ruby, "-Ilib:#{test_lib_dirs * ':'}", file)
|
||||
end or raise "Failures"
|
||||
Dir.glob(TESTS_GLOB).all? { |file| system(ruby, '-Ilib:test', file) } or raise "Failures"
|
||||
end
|
||||
|
||||
desc 'ActiveRecord Integration Tests'
|
||||
Rake::TestTask.new(:test_active_record_integration) do |t|
|
||||
t.libs.concat test_lib_dirs
|
||||
t.libs << 'test'
|
||||
t.test_files = Dir.glob("test/activerecord/*_test.rb")
|
||||
t.verbose = true
|
||||
end
|
||||
|
||||
desc 'New Controller Tests'
|
||||
Rake::TestTask.new(:test_new_base) do |t|
|
||||
t.libs << "test/new_base" << "test/lib"
|
||||
t.test_files = Dir.glob("test/{abstract_controller,new_base}/*_test.rb")
|
||||
t.verbose = true
|
||||
end
|
||||
|
||||
desc 'Old Controller Tests on New Base'
|
||||
Rake::TestTask.new(:test_new_base_on_old_tests) do |t|
|
||||
t.libs << "test/new_base" << "test/lib"
|
||||
|
||||
t.verbose = true
|
||||
# ==== Not ported
|
||||
# * filters
|
||||
|
||||
t.test_files = Dir.glob( "test/{dispatch,template}/**/*_test.rb" ).sort + %w(
|
||||
action_pack_assertions addresses_render assert_select
|
||||
base benchmark caching capture content_type cookie dispatcher
|
||||
filter_params flash helper http_basic_authentication
|
||||
http_digest_authentication integration layout logging mime_responds
|
||||
record_identifier redirect render render_js render_json
|
||||
render_other render_xml request_forgery_protection rescue
|
||||
resources routing selector send_file test url_rewriter
|
||||
verification view_paths webservice
|
||||
).map { |name| "test/controller/#{name}_test.rb" }
|
||||
end
|
||||
|
||||
# Genereate the RDoc documentation
|
||||
|
||||
Rake::RDocTask.new { |rdoc|
|
||||
@@ -116,6 +96,7 @@ spec = Gem::Specification.new do |s|
|
||||
s.requirements << 'none'
|
||||
|
||||
s.add_dependency('activesupport', '= 3.0.pre' + PKG_BUILD)
|
||||
s.add_dependency('activemodel', '= 3.0.pre' + PKG_BUILD)
|
||||
s.add_dependency('rack', '~> 1.0.0')
|
||||
s.add_dependency('rack-test', '~> 0.4.2')
|
||||
|
||||
@@ -134,6 +115,12 @@ Rake::GemPackageTask.new(spec) do |p|
|
||||
p.need_zip = true
|
||||
end
|
||||
|
||||
task :gemspec do
|
||||
File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w") do |file|
|
||||
file.puts spec.to_ruby
|
||||
end
|
||||
end
|
||||
|
||||
task :lines do
|
||||
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
|
||||
|
||||
|
||||
42
actionpack/actionpack.gemspec
Normal file
42
actionpack/actionpack.gemspec
Normal file
File diff suppressed because one or more lines are too long
@@ -3,7 +3,6 @@ require "active_support/core_ext/module/delegation"
|
||||
|
||||
module AbstractController
|
||||
autoload :Base, "abstract_controller/base"
|
||||
autoload :Benchmarker, "abstract_controller/benchmarker"
|
||||
autoload :Callbacks, "abstract_controller/callbacks"
|
||||
autoload :Helpers, "abstract_controller/helpers"
|
||||
autoload :Layouts, "abstract_controller/layouts"
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
module AbstractController
|
||||
module Benchmarker
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include Logger
|
||||
|
||||
module ClassMethods
|
||||
# Execute the passed in block, timing the duration of the block in ms.
|
||||
#
|
||||
# ==== Parameters
|
||||
# title<#to_s>:: The title of block to benchmark
|
||||
# log_level<Integer>:: A valid log level. Defaults to Logger::DEBUG
|
||||
# use_silence<TrueClass, FalseClass>:: Whether or not to silence the
|
||||
# logger for the duration of the block.
|
||||
#
|
||||
# ==== Returns
|
||||
# Object:: The result of the block
|
||||
def benchmark(title, log_level = ::Logger::DEBUG, use_silence = true)
|
||||
if logger && logger.level >= log_level
|
||||
result = nil
|
||||
ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
|
||||
logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)")
|
||||
result
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
# Silences the logger for the duration of the block.
|
||||
def silence
|
||||
old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
|
||||
yield
|
||||
ensure
|
||||
logger.level = old_logger_level if logger
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -10,7 +10,7 @@ module AbstractController
|
||||
include ActiveSupport::NewCallbacks
|
||||
|
||||
included do
|
||||
define_callbacks :process_action, "response_body"
|
||||
define_callbacks :process_action, :terminator => "response_body"
|
||||
end
|
||||
|
||||
# Override AbstractController::Base's process_action to run the
|
||||
|
||||
@@ -119,17 +119,17 @@ module AbstractController
|
||||
when true
|
||||
raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil"
|
||||
when nil
|
||||
self.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
|
||||
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
||||
def _layout(details)
|
||||
self.class.cache_layout(details) do
|
||||
if view_paths.exists?("#{_implied_layout_name}", details, "layouts")
|
||||
if template_exists?("#{_implied_layout_name}", details, :_prefix => "layouts")
|
||||
"#{_implied_layout_name}"
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
ruby_eval
|
||||
RUBY
|
||||
end
|
||||
self.class_eval { private :_layout }
|
||||
end
|
||||
@@ -167,7 +167,7 @@ module AbstractController
|
||||
# details<Hash{Symbol => Object}>:: A list of details to restrict
|
||||
# the lookup to. By default, layout lookup is limited to the
|
||||
# formats specified for the current request.
|
||||
def _layout_for_name(name, details = {:formats => formats})
|
||||
def _layout_for_name(name, details)
|
||||
name && _find_layout(name, details)
|
||||
end
|
||||
|
||||
@@ -183,7 +183,7 @@ module AbstractController
|
||||
def _find_layout(name, details)
|
||||
# TODO: Make prefix actually part of details in ViewPath#find_by_parts
|
||||
prefix = details.key?(:prefix) ? details.delete(:prefix) : "layouts"
|
||||
view_paths.find(name, details, prefix)
|
||||
find_template(name, details, :_prefix => prefix)
|
||||
end
|
||||
|
||||
# Returns the default layout for this controller and a given set of details.
|
||||
|
||||
@@ -4,6 +4,26 @@ module AbstractController
|
||||
module Logger
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
cattr_accessor :logger
|
||||
end
|
||||
|
||||
module ClassMethods #:nodoc:
|
||||
# Logs a message appending the value measured.
|
||||
def log_with_time(message, time, log_level=::Logger::DEBUG)
|
||||
return unless logger && logger.level >= log_level
|
||||
logger.add(log_level, "#{message} (%.1fms)" % time)
|
||||
end
|
||||
|
||||
# Silences the logger for the duration of the block.
|
||||
def silence
|
||||
old_logger_level, logger.level = logger.level, ::Logger::ERROR if logge
|
||||
yield
|
||||
ensure
|
||||
logger.level = old_logger_level if logger
|
||||
end
|
||||
end
|
||||
|
||||
# A class that allows you to defer expensive processing
|
||||
# until the logger actually tries to log. Otherwise, you are
|
||||
# forced to do the processing in advance, and send the
|
||||
@@ -11,43 +31,44 @@ module AbstractController
|
||||
# just discard the String if the log level is too low.
|
||||
#
|
||||
# TODO: Require that Rails loggers accept a block.
|
||||
class DelayedLog
|
||||
def initialize(&blk)
|
||||
@blk = blk
|
||||
class DelayedLog < ActiveSupport::BasicObject
|
||||
def initialize(&block)
|
||||
@str, @block = nil, block
|
||||
end
|
||||
|
||||
def to_s
|
||||
@blk.call
|
||||
def method_missing(*args, &block)
|
||||
unless @str
|
||||
@str, @block = @block.call, nil
|
||||
end
|
||||
@str.send(*args, &block)
|
||||
end
|
||||
alias to_str to_s
|
||||
end
|
||||
|
||||
included do
|
||||
cattr_accessor :logger
|
||||
end
|
||||
|
||||
# Override process_action in the AbstractController::Base
|
||||
# to log details about the method.
|
||||
def process_action(action)
|
||||
retval = super
|
||||
event = ActiveSupport::Orchestra.instrument(:process_action,
|
||||
:controller => self, :action => action) do
|
||||
super
|
||||
end
|
||||
|
||||
if logger
|
||||
log = DelayedLog.new do
|
||||
"\n\nProcessing #{self.class.name}\##{action_name} " \
|
||||
"to #{request.formats} " \
|
||||
"(for #{request_origin}) [#{request.method.to_s.upcase}]"
|
||||
"to #{request.formats} (for #{request_origin}) " \
|
||||
"(%.1fms) [#{request.method.to_s.upcase}]" % event.duration
|
||||
end
|
||||
|
||||
logger.info(log)
|
||||
end
|
||||
|
||||
retval
|
||||
event.result
|
||||
end
|
||||
|
||||
private
|
||||
# Returns the request origin with the IP and time. This needs to be cached,
|
||||
# otherwise we would get different results for each time it calls.
|
||||
def request_origin
|
||||
# this *needs* to be cached!
|
||||
# otherwise you'd get different results if calling it more than once
|
||||
@request_origin ||= "#{request.remote_ip} at #{Time.now.to_s(:db)}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -112,12 +112,18 @@ module AbstractController
|
||||
name = (options[:_template_name] || action_name).to_s
|
||||
|
||||
options[:_template] ||= with_template_cache(name) do
|
||||
view_paths.find(
|
||||
name, { :formats => formats }, options[:_prefix], options[:_partial]
|
||||
)
|
||||
find_template(name, { :formats => formats }, options)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def find_template(name, details, options)
|
||||
view_paths.find(name, details, options[:_prefix], options[:_partial])
|
||||
end
|
||||
|
||||
def template_exists?(name, details, options)
|
||||
view_paths.exists?(name, details, options[:_prefix], options[:_partial])
|
||||
end
|
||||
|
||||
def with_template_cache(name)
|
||||
yield
|
||||
end
|
||||
|
||||
@@ -2,7 +2,6 @@ module ActionController
|
||||
class Base < Metal
|
||||
abstract!
|
||||
|
||||
include AbstractController::Benchmarker
|
||||
include AbstractController::Callbacks
|
||||
include AbstractController::Logger
|
||||
|
||||
@@ -51,7 +50,7 @@ module ActionController
|
||||
|
||||
def method_for_action(action_name)
|
||||
super || begin
|
||||
if view_paths.exists?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
|
||||
if template_exists?(action_name.to_s, {:formats => formats}, :_prefix => controller_path)
|
||||
"default_render"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -53,11 +53,11 @@ module ActionController #:nodoc:
|
||||
return content unless cache_configured?
|
||||
|
||||
key = fragment_cache_key(key)
|
||||
|
||||
self.class.benchmark "Cached fragment miss: #{key}" do
|
||||
event = ActiveSupport::Orchestra.instrument(:write_fragment, :key => key) do
|
||||
cache_store.write(key, content, options)
|
||||
end
|
||||
|
||||
self.class.log_with_time("Cached fragment miss: #{key}", event.duration)
|
||||
content
|
||||
end
|
||||
|
||||
@@ -66,10 +66,12 @@ module ActionController #:nodoc:
|
||||
return unless cache_configured?
|
||||
|
||||
key = fragment_cache_key(key)
|
||||
|
||||
self.class.benchmark "Cached fragment hit: #{key}" do
|
||||
event = ActiveSupport::Orchestra.instrument(:read_fragment, :key => key) do
|
||||
cache_store.read(key, options)
|
||||
end
|
||||
|
||||
self.class.log_with_time("Cached fragment hit: #{key}", event.duration)
|
||||
event.result
|
||||
end
|
||||
|
||||
# Check if a cached fragment from the location signified by <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats)
|
||||
@@ -77,10 +79,12 @@ module ActionController #:nodoc:
|
||||
return unless cache_configured?
|
||||
|
||||
key = fragment_cache_key(key)
|
||||
|
||||
self.class.benchmark "Cached fragment exists?: #{key}" do
|
||||
event = ActiveSupport::Orchestra.instrument(:fragment_exist?, :key => key) do
|
||||
cache_store.exist?(key, options)
|
||||
end
|
||||
|
||||
self.class.log_with_time("Cached fragment exists?: #{key}", event.duration)
|
||||
event.result
|
||||
end
|
||||
|
||||
# Removes fragments from the cache.
|
||||
@@ -103,17 +107,21 @@ module ActionController #:nodoc:
|
||||
def expire_fragment(key, options = nil)
|
||||
return unless cache_configured?
|
||||
|
||||
key = key.is_a?(Regexp) ? key : fragment_cache_key(key)
|
||||
key = fragment_cache_key(key) unless key.is_a?(Regexp)
|
||||
message = nil
|
||||
|
||||
if key.is_a?(Regexp)
|
||||
self.class.benchmark "Expired fragments matching: #{key.source}" do
|
||||
event = ActiveSupport::Orchestra.instrument(:expire_fragment, :key => key) do
|
||||
if key.is_a?(Regexp)
|
||||
message = "Expired fragments matching: #{key.source}"
|
||||
cache_store.delete_matched(key, options)
|
||||
end
|
||||
else
|
||||
self.class.benchmark "Expired fragment: #{key}" do
|
||||
else
|
||||
message = "Expired fragment: #{key}"
|
||||
cache_store.delete(key, options)
|
||||
end
|
||||
end
|
||||
|
||||
self.class.log_with_time(message, event.duration)
|
||||
event.result
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,21 +62,29 @@ module ActionController #:nodoc:
|
||||
# expire_page "/lists/show"
|
||||
def expire_page(path)
|
||||
return unless perform_caching
|
||||
path = page_cache_path(path)
|
||||
|
||||
benchmark "Expired page: #{page_cache_file(path)}" do
|
||||
File.delete(page_cache_path(path)) if File.exist?(page_cache_path(path))
|
||||
event = ActiveSupport::Orchestra.instrument(:expire_page, :path => path) do
|
||||
File.delete(path) if File.exist?(path)
|
||||
end
|
||||
|
||||
log_with_time("Expired page: #{path}", event.duration)
|
||||
event.result
|
||||
end
|
||||
|
||||
# Manually cache the +content+ in the key determined by +path+. Example:
|
||||
# cache_page "I'm the cached content", "/lists/show"
|
||||
def cache_page(content, path)
|
||||
return unless perform_caching
|
||||
path = page_cache_path(path)
|
||||
|
||||
benchmark "Cached page: #{page_cache_file(path)}" do
|
||||
FileUtils.makedirs(File.dirname(page_cache_path(path)))
|
||||
File.open(page_cache_path(path), "wb+") { |f| f.write(content) }
|
||||
event = ActiveSupport::Orchestra.instrument(:cache_page, :path => path) do
|
||||
FileUtils.makedirs(File.dirname(path))
|
||||
File.open(path, "wb+") { |f| f.write(content) }
|
||||
end
|
||||
|
||||
log_with_time("Cached page: #{path}", event.duration)
|
||||
event.result
|
||||
end
|
||||
|
||||
# Caches the +actions+ using the page-caching approach that'll store the cache in a path within the page_cache_directory that
|
||||
@@ -149,4 +157,4 @@ module ActionController #:nodoc:
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -54,7 +54,7 @@ module ActionController
|
||||
end
|
||||
end
|
||||
|
||||
delegate :to_prepare, :prepare_dispatch, :before_dispatch, :after_dispatch,
|
||||
delegate :to_prepare, :before_dispatch, :around_dispatch, :after_dispatch,
|
||||
:to => ActionDispatch::Callbacks
|
||||
|
||||
def new
|
||||
|
||||
@@ -4,15 +4,13 @@ use "Rack::Lock", :if => lambda {
|
||||
|
||||
use "ActionDispatch::ShowExceptions", lambda { ActionController::Base.consider_all_requests_local }
|
||||
use "ActionDispatch::Callbacks", lambda { ActionController::Dispatcher.prepare_each_request }
|
||||
use "ActionDispatch::Rescue", lambda {
|
||||
controller = (::ApplicationController rescue ActionController::Base)
|
||||
# TODO: Replace with controller.action(:_rescue_action)
|
||||
controller.method(:rescue_action)
|
||||
}
|
||||
|
||||
# TODO: Redirect global exceptions somewhere?
|
||||
# use "ActionDispatch::Rescue"
|
||||
|
||||
use lambda { ActionController::Base.session_store },
|
||||
lambda { ActionController::Base.session_options }
|
||||
|
||||
use "ActionDispatch::ParamsParser"
|
||||
use "Rack::MethodOverride"
|
||||
use "Rack::Head"
|
||||
use "Rack::Head"
|
||||
|
||||
@@ -191,7 +191,7 @@ module ActionController #:nodoc:
|
||||
def memoized_find_layout(layout, formats) #:nodoc:
|
||||
return layout if layout.nil? || layout.respond_to?(:render)
|
||||
prefix = layout.to_s =~ /layouts\// ? nil : "layouts"
|
||||
view_paths.find(layout.to_s, {:formats => formats}, prefix)
|
||||
find_template(layout.to_s, {:formats => formats}, :_prefix => prefix)
|
||||
end
|
||||
|
||||
def find_layout(*args)
|
||||
@@ -200,7 +200,7 @@ module ActionController #:nodoc:
|
||||
end
|
||||
|
||||
def layout_list #:nodoc:
|
||||
Array(view_paths).sum([]) { |path| Dir["#{path.to_str}/layouts/**/*"] }
|
||||
Array(view_paths).sum([]) { |path| Dir["#{path}/layouts/**/*"] }
|
||||
end
|
||||
memoize :layout_list
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'active_support/core_ext/class/inheritable_attributes'
|
||||
|
||||
module ActionController
|
||||
# ActionController::Metal provides a way to get a valid Rack application from a controller.
|
||||
#
|
||||
@@ -79,6 +81,15 @@ module ActionController
|
||||
end
|
||||
|
||||
class ActionEndpoint
|
||||
@@endpoints = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = {} } }
|
||||
|
||||
def self.for(controller, action, stack)
|
||||
@@endpoints[controller][action][stack] ||= begin
|
||||
endpoint = new(controller, action)
|
||||
stack.build(endpoint)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(controller, action)
|
||||
@controller, @action = controller, action
|
||||
end
|
||||
@@ -88,6 +99,16 @@ module ActionController
|
||||
end
|
||||
end
|
||||
|
||||
extlib_inheritable_accessor(:middleware_stack) { ActionDispatch::MiddlewareStack.new }
|
||||
|
||||
def self.use(*args)
|
||||
middleware_stack.use(*args)
|
||||
end
|
||||
|
||||
def self.middleware
|
||||
middleware_stack
|
||||
end
|
||||
|
||||
# Return a rack endpoint for the given action. Memoize the endpoint, so
|
||||
# multiple calls into MyController.action will return the same object
|
||||
# for the same action.
|
||||
@@ -98,8 +119,7 @@ module ActionController
|
||||
# ==== Returns
|
||||
# Proc:: A rack application
|
||||
def self.action(name)
|
||||
@actions ||= {}
|
||||
@actions[name.to_s] ||= ActionEndpoint.new(self, name)
|
||||
ActionEndpoint.for(self, name, middleware_stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -49,7 +49,7 @@ module ActionController
|
||||
end
|
||||
elsif block_given?
|
||||
key = key.dup
|
||||
value = value.dup if value
|
||||
value = value.dup if value.duplicable?
|
||||
yield key, value
|
||||
filtered_parameters[key] = value
|
||||
else
|
||||
|
||||
@@ -1,52 +1,13 @@
|
||||
module ActionController #:nodoc:
|
||||
# Actions that fail to perform as expected throw exceptions. These
|
||||
# exceptions can either be rescued for the public view (with a nice
|
||||
# user-friendly explanation) or for the developers view (with tons of
|
||||
# debugging information). The developers view is already implemented by
|
||||
# the Action Controller, but the public view should be tailored to your
|
||||
# specific application.
|
||||
#
|
||||
# The default behavior for public exceptions is to render a static html
|
||||
# file with the name of the error code thrown. If no such file exists, an
|
||||
# empty response is sent with the correct status code.
|
||||
#
|
||||
# You can override what constitutes a local request by overriding the
|
||||
# <tt>local_request?</tt> method in your own controller. Custom rescue
|
||||
# behavior is achieved by overriding the <tt>rescue_action_in_public</tt>
|
||||
# and <tt>rescue_action_locally</tt> methods.
|
||||
module Rescue
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
include ActiveSupport::Rescuable
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# This can be removed once we can move action(:_rescue_action) into middlewares.rb
|
||||
# Currently, it does controller.method(:rescue_action), which is hiding the implementation
|
||||
# difference between the old and new base.
|
||||
def rescue_action(env)
|
||||
action(:_rescue_action).call(env)
|
||||
end
|
||||
end
|
||||
|
||||
attr_internal :rescued_exception
|
||||
include ActiveSupport::Rescuable
|
||||
|
||||
private
|
||||
def method_for_action(action_name)
|
||||
return action_name if self.rescued_exception = request.env.delete("action_dispatch.rescue.exception")
|
||||
super
|
||||
end
|
||||
|
||||
def _rescue_action
|
||||
rescue_with_handler(rescued_exception) || raise(rescued_exception)
|
||||
end
|
||||
|
||||
def process_action(*)
|
||||
def process_action(*args)
|
||||
super
|
||||
rescue Exception => exception
|
||||
self.rescued_exception = exception
|
||||
_rescue_action
|
||||
rescue_with_handler(exception) || raise(exception)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,9 +2,7 @@ require 'stringio'
|
||||
require 'uri'
|
||||
require 'active_support/test_case'
|
||||
require 'active_support/core_ext/object/metaclass'
|
||||
|
||||
require 'rack/mock_session'
|
||||
require 'rack/test/cookie_jar'
|
||||
require 'rack/test'
|
||||
|
||||
module ActionController
|
||||
module Integration #:nodoc:
|
||||
@@ -251,7 +249,7 @@ module ActionController
|
||||
end
|
||||
end
|
||||
|
||||
opts = {
|
||||
env = {
|
||||
:method => method,
|
||||
:params => parameters,
|
||||
|
||||
@@ -261,25 +259,24 @@ module ActionController
|
||||
"rack.url_scheme" => https? ? "https" : "http",
|
||||
|
||||
"REQUEST_URI" => path,
|
||||
"PATH_INFO" => path,
|
||||
"HTTP_HOST" => host,
|
||||
"REMOTE_ADDR" => remote_addr,
|
||||
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
||||
"HTTP_ACCEPT" => accept
|
||||
}
|
||||
|
||||
env = ActionDispatch::TestRequest.env_for(path, opts)
|
||||
|
||||
(rack_environment || {}).each do |key, value|
|
||||
env[key] = value
|
||||
end
|
||||
|
||||
session = Rack::Test::Session.new(@mock_session)
|
||||
|
||||
@controller = ActionController::Base.capture_instantiation do
|
||||
@mock_session.request(URI.parse(path), env)
|
||||
session.request(path, env)
|
||||
end
|
||||
|
||||
@request_count += 1
|
||||
@request = ActionDispatch::Request.new(env)
|
||||
@request = ActionDispatch::Request.new(session.last_request.env)
|
||||
@response = ActionDispatch::TestResponse.from_response(@mock_session.last_response)
|
||||
@html_document = nil
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ module ActionController #:nodoc:
|
||||
#
|
||||
# Pass a true third parameter to ensure the uploaded file is opened in binary mode (only required for Windows):
|
||||
# post :change_avatar, :avatar => ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + '/files/spongebob.png', 'image/png', :binary)
|
||||
TestUploadedFile = ActionDispatch::TestRequest::Multipart::UploadedFile
|
||||
TestUploadedFile = Rack::Test::UploadedFile
|
||||
|
||||
module TestProcess
|
||||
def self.included(base)
|
||||
@@ -133,7 +133,7 @@ module ActionController #:nodoc:
|
||||
@request.env['REQUEST_METHOD'] = http_method
|
||||
|
||||
parameters ||= {}
|
||||
@request.assign_parameters(@controller.class.controller_path, action.to_s, parameters)
|
||||
@request.assign_parameters(@controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters)
|
||||
|
||||
@request.session = ActionController::TestSession.new(session) unless session.nil?
|
||||
@request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#++
|
||||
|
||||
activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
|
||||
$:.unshift activesupport_path if File.directory?(activesupport_path)
|
||||
require 'active_support'
|
||||
|
||||
require 'rack'
|
||||
|
||||
module Rack
|
||||
@@ -59,3 +55,7 @@ module ActionDispatch
|
||||
end
|
||||
|
||||
autoload :Mime, 'action_dispatch/http/mime_type'
|
||||
|
||||
activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
|
||||
$:.unshift activesupport_path if File.directory?(activesupport_path)
|
||||
require 'active_support'
|
||||
|
||||
@@ -1,40 +1,55 @@
|
||||
module ActionDispatch
|
||||
class Callbacks
|
||||
include ActiveSupport::Callbacks
|
||||
define_callbacks :prepare, :before, :after
|
||||
include ActiveSupport::NewCallbacks
|
||||
|
||||
define_callbacks :call, :terminator => "result == false", :scope => :kind
|
||||
define_callbacks :prepare, :scope => :name
|
||||
|
||||
# Add a preparation callback. Preparation callbacks are run before every
|
||||
# request in development mode, and before the first request in production mode.
|
||||
#
|
||||
# If a symbol with a block is given, the symbol is used as an identifier.
|
||||
# That allows to_prepare to be called again with the same identifier to
|
||||
# replace the existing callback. Passing an identifier is a suggested
|
||||
# practice if the code adding a preparation block may be reloaded.
|
||||
def self.to_prepare(*args, &block)
|
||||
if args.first.is_a?(Symbol) && block_given?
|
||||
define_method :"__#{args.first}", &block
|
||||
set_callback(:prepare, :"__#{args.first}")
|
||||
else
|
||||
set_callback(:prepare, *args, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def self.before(*args, &block)
|
||||
set_callback(:call, :before, *args, &block)
|
||||
end
|
||||
|
||||
def self.around(*args, &block)
|
||||
set_callback(:call, :around, *args, &block)
|
||||
end
|
||||
|
||||
def self.after(*args, &block)
|
||||
set_callback(:call, :after, *args, &block)
|
||||
end
|
||||
|
||||
class << self
|
||||
# DEPRECATED
|
||||
alias_method :prepare_dispatch, :prepare
|
||||
alias_method :before_dispatch, :before
|
||||
alias_method :around_dispatch, :around
|
||||
alias_method :after_dispatch, :after
|
||||
end
|
||||
|
||||
# Add a preparation callback. Preparation callbacks are run before every
|
||||
# request in development mode, and before the first request in production
|
||||
# mode.
|
||||
#
|
||||
# An optional identifier may be supplied for the callback. If provided,
|
||||
# to_prepare may be called again with the same identifier to replace the
|
||||
# existing callback. Passing an identifier is a suggested practice if the
|
||||
# code adding a preparation block may be reloaded.
|
||||
def self.to_prepare(identifier = nil, &block)
|
||||
@prepare_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new
|
||||
callback = ActiveSupport::Callbacks::Callback.new(:prepare, block, :identifier => identifier)
|
||||
@prepare_callbacks.replace_or_append!(callback)
|
||||
end
|
||||
|
||||
def initialize(app, prepare_each_request = false)
|
||||
@app, @prepare_each_request = app, prepare_each_request
|
||||
run_callbacks :prepare
|
||||
_run_prepare_callbacks
|
||||
end
|
||||
|
||||
def call(env)
|
||||
run_callbacks :before
|
||||
run_callbacks :prepare if @prepare_each_request
|
||||
@app.call(env)
|
||||
ensure
|
||||
run_callbacks :after, :enumerator => :reverse_each
|
||||
_run_call_callbacks do
|
||||
_run_prepare_callbacks if @prepare_each_request
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
module ActionDispatch
|
||||
class Rescue
|
||||
def initialize(app, rescuer)
|
||||
@app, @rescuer = app, rescuer
|
||||
def initialize(app, rescuers = {}, &block)
|
||||
@app, @rescuers = app, {}
|
||||
rescuers.each { |exception, rescuer| rescue_from(exception, rescuer) }
|
||||
instance_eval(&block) if block_given?
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@app.call(env)
|
||||
rescue Exception => exception
|
||||
env['action_dispatch.rescue.exception'] = exception
|
||||
@rescuer.call(env)
|
||||
if rescuer = @rescuers[exception.class.name]
|
||||
env['action_dispatch.rescue.exception'] = exception
|
||||
rescuer.call(env)
|
||||
else
|
||||
raise exception
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def rescue_from(exception, rescuer)
|
||||
exception = exception.class.name if exception.is_a?(Exception)
|
||||
@rescuers[exception.to_s] = rescuer
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -49,7 +49,18 @@ module ActionDispatch
|
||||
:expire_after => nil,
|
||||
:httponly => true
|
||||
}.freeze
|
||||
|
||||
class OptionsHash < Hash
|
||||
def initialize(by, env, default_options)
|
||||
@session_data = env[CookieStore::ENV_SESSION_KEY]
|
||||
default_options.each { |key, value| self[key] = value }
|
||||
end
|
||||
|
||||
def [](key)
|
||||
key == :id ? @session_data[:session_id] : super(key)
|
||||
end
|
||||
end
|
||||
|
||||
ENV_SESSION_KEY = "rack.session".freeze
|
||||
ENV_SESSION_OPTIONS_KEY = "rack.session.options".freeze
|
||||
HTTP_SET_COOKIE = "Set-Cookie".freeze
|
||||
@@ -90,8 +101,8 @@ module ActionDispatch
|
||||
|
||||
def call(env)
|
||||
env[ENV_SESSION_KEY] = AbstractStore::SessionHash.new(self, env)
|
||||
env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup
|
||||
|
||||
env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options)
|
||||
|
||||
status, headers, body = @app.call(env)
|
||||
|
||||
session_data = env[ENV_SESSION_KEY]
|
||||
|
||||
@@ -1,52 +1,47 @@
|
||||
require "active_support/core_ext/kernel/requires"
|
||||
begin
|
||||
require_library_or_gem 'memcache'
|
||||
module ActionDispatch
|
||||
module Session
|
||||
class MemCacheStore < AbstractStore
|
||||
def initialize(app, options = {})
|
||||
require 'memcache'
|
||||
|
||||
module ActionDispatch
|
||||
module Session
|
||||
class MemCacheStore < AbstractStore
|
||||
def initialize(app, options = {})
|
||||
# Support old :expires option
|
||||
options[:expire_after] ||= options[:expires]
|
||||
# Support old :expires option
|
||||
options[:expire_after] ||= options[:expires]
|
||||
|
||||
super
|
||||
super
|
||||
|
||||
@default_options = {
|
||||
:namespace => 'rack:session',
|
||||
:memcache_server => 'localhost:11211'
|
||||
}.merge(@default_options)
|
||||
@default_options = {
|
||||
:namespace => 'rack:session',
|
||||
:memcache_server => 'localhost:11211'
|
||||
}.merge(@default_options)
|
||||
|
||||
@pool = options[:cache] || MemCache.new(@default_options[:memcache_server], @default_options)
|
||||
unless @pool.servers.any? { |s| s.alive? }
|
||||
raise "#{self} unable to find server during initialization."
|
||||
@pool = options[:cache] || MemCache.new(@default_options[:memcache_server], @default_options)
|
||||
unless @pool.servers.any? { |s| s.alive? }
|
||||
raise "#{self} unable to find server during initialization."
|
||||
end
|
||||
@mutex = Mutex.new
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
def get_session(env, sid)
|
||||
sid ||= generate_sid
|
||||
begin
|
||||
session = @pool.get(sid) || {}
|
||||
rescue MemCache::MemCacheError, Errno::ECONNREFUSED
|
||||
session = {}
|
||||
end
|
||||
@mutex = Mutex.new
|
||||
|
||||
super
|
||||
[sid, session]
|
||||
end
|
||||
|
||||
private
|
||||
def get_session(env, sid)
|
||||
sid ||= generate_sid
|
||||
begin
|
||||
session = @pool.get(sid) || {}
|
||||
rescue MemCache::MemCacheError, Errno::ECONNREFUSED
|
||||
session = {}
|
||||
end
|
||||
[sid, session]
|
||||
end
|
||||
|
||||
def set_session(env, sid, session_data)
|
||||
options = env['rack.session.options']
|
||||
expiry = options[:expire_after] || 0
|
||||
@pool.set(sid, session_data, expiry)
|
||||
return true
|
||||
rescue MemCache::MemCacheError, Errno::ECONNREFUSED
|
||||
return false
|
||||
end
|
||||
end
|
||||
def set_session(env, sid, session_data)
|
||||
options = env['rack.session.options']
|
||||
expiry = options[:expire_after] || 0
|
||||
@pool.set(sid, session_data, expiry)
|
||||
return true
|
||||
rescue MemCache::MemCacheError, Errno::ECONNREFUSED
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue LoadError
|
||||
# MemCache wasn't available so neither can the store be
|
||||
end
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
show = "document.getElementById('#{name.gsub /\s/, '-'}').style.display='block';"
|
||||
hide = (names - [name]).collect {|hide_name| "document.getElementById('#{hide_name.gsub /\s/, '-'}').style.display='none';"}
|
||||
%>
|
||||
<a href="#" onclick="<%= hide %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
|
||||
<a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
|
||||
<% end %>
|
||||
|
||||
<% traces.each do |name, trace| %>
|
||||
<div id="<%= name.gsub /\s/, '-' %>" style="display: <%= name == "Application Trace" ? 'block' : 'none' %>;">
|
||||
<pre><code><%= trace.join "\n" %></code></pre>
|
||||
<pre><code><%=h trace.join "\n" %></code></pre>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,308 +1,13 @@
|
||||
module ActionDispatch
|
||||
class TestRequest < Request
|
||||
# Improve version of Multipart thats in rack/master
|
||||
module Multipart #:nodoc:
|
||||
class UploadedFile
|
||||
# The filename, *not* including the path, of the "uploaded" file
|
||||
attr_reader :original_filename
|
||||
|
||||
# The content type of the "uploaded" file
|
||||
attr_accessor :content_type
|
||||
|
||||
def initialize(path, content_type = "text/plain", binary = false)
|
||||
raise "#{path} file does not exist" unless ::File.exist?(path)
|
||||
@content_type = content_type
|
||||
@original_filename = ::File.basename(path)
|
||||
@tempfile = Tempfile.new(@original_filename)
|
||||
@tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
|
||||
@tempfile.binmode if binary
|
||||
FileUtils.copy_file(path, @tempfile.path)
|
||||
end
|
||||
|
||||
def path
|
||||
@tempfile.path
|
||||
end
|
||||
alias_method :local_path, :path
|
||||
|
||||
def method_missing(method_name, *args, &block) #:nodoc:
|
||||
@tempfile.__send__(method_name, *args, &block)
|
||||
end
|
||||
end
|
||||
|
||||
EOL = "\r\n"
|
||||
MULTIPART_BOUNDARY = "AaB03x"
|
||||
|
||||
def self.parse_multipart(env)
|
||||
unless env['CONTENT_TYPE'] =~
|
||||
%r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|n
|
||||
nil
|
||||
else
|
||||
boundary = "--#{$1}"
|
||||
|
||||
params = {}
|
||||
buf = ""
|
||||
content_length = env['CONTENT_LENGTH'].to_i
|
||||
input = env['rack.input']
|
||||
input.rewind
|
||||
|
||||
boundary_size = Utils.bytesize(boundary) + EOL.size
|
||||
bufsize = 16384
|
||||
|
||||
content_length -= boundary_size
|
||||
|
||||
read_buffer = ''
|
||||
|
||||
status = input.read(boundary_size, read_buffer)
|
||||
raise EOFError, "bad content body" unless status == boundary + EOL
|
||||
|
||||
rx = /(?:#{EOL})?#{Regexp.quote boundary}(#{EOL}|--)/n
|
||||
|
||||
loop {
|
||||
head = nil
|
||||
body = ''
|
||||
filename = content_type = name = nil
|
||||
|
||||
until head && buf =~ rx
|
||||
if !head && i = buf.index(EOL+EOL)
|
||||
head = buf.slice!(0, i+2) # First \r\n
|
||||
buf.slice!(0, 2) # Second \r\n
|
||||
|
||||
filename = head[/Content-Disposition:.* filename="?([^\";]*)"?/ni, 1]
|
||||
content_type = head[/Content-Type: (.*)#{EOL}/ni, 1]
|
||||
name = head[/Content-Disposition:.*\s+name="?([^\";]*)"?/ni, 1] || head[/Content-ID:\s*([^#{EOL}]*)/ni, 1]
|
||||
|
||||
if content_type || filename
|
||||
body = Tempfile.new("RackMultipart")
|
||||
body.binmode if body.respond_to?(:binmode)
|
||||
end
|
||||
|
||||
next
|
||||
end
|
||||
|
||||
# Save the read body part.
|
||||
if head && (boundary_size+4 < buf.size)
|
||||
body << buf.slice!(0, buf.size - (boundary_size+4))
|
||||
end
|
||||
|
||||
c = input.read(bufsize < content_length ? bufsize : content_length, read_buffer)
|
||||
raise EOFError, "bad content body" if c.nil? || c.empty?
|
||||
buf << c
|
||||
content_length -= c.size
|
||||
end
|
||||
|
||||
# Save the rest.
|
||||
if i = buf.index(rx)
|
||||
body << buf.slice!(0, i)
|
||||
buf.slice!(0, boundary_size+2)
|
||||
|
||||
content_length = -1 if $1 == "--"
|
||||
end
|
||||
|
||||
if filename == ""
|
||||
# filename is blank which means no file has been selected
|
||||
data = nil
|
||||
elsif filename
|
||||
body.rewind
|
||||
|
||||
# Take the basename of the upload's original filename.
|
||||
# This handles the full Windows paths given by Internet Explorer
|
||||
# (and perhaps other broken user agents) without affecting
|
||||
# those which give the lone filename.
|
||||
filename =~ /^(?:.*[:\\\/])?(.*)/m
|
||||
filename = $1
|
||||
|
||||
data = {:filename => filename, :type => content_type,
|
||||
:name => name, :tempfile => body, :head => head}
|
||||
elsif !filename && content_type
|
||||
body.rewind
|
||||
|
||||
# Generic multipart cases, not coming from a form
|
||||
data = {:type => content_type,
|
||||
:name => name, :tempfile => body, :head => head}
|
||||
else
|
||||
data = body
|
||||
end
|
||||
|
||||
Utils.normalize_params(params, name, data) unless data.nil?
|
||||
|
||||
break if buf.empty? || content_length == -1
|
||||
}
|
||||
|
||||
input.rewind
|
||||
|
||||
params
|
||||
end
|
||||
end
|
||||
|
||||
def self.build_multipart(params, first = true)
|
||||
if first
|
||||
unless params.is_a?(Hash)
|
||||
raise ArgumentError, "value must be a Hash"
|
||||
end
|
||||
|
||||
multipart = false
|
||||
query = lambda { |value|
|
||||
case value
|
||||
when Array
|
||||
value.each(&query)
|
||||
when Hash
|
||||
value.values.each(&query)
|
||||
when UploadedFile
|
||||
multipart = true
|
||||
end
|
||||
}
|
||||
params.values.each(&query)
|
||||
return nil unless multipart
|
||||
end
|
||||
|
||||
flattened_params = Hash.new
|
||||
|
||||
params.each do |key, value|
|
||||
k = first ? key.to_s : "[#{key}]"
|
||||
|
||||
case value
|
||||
when Array
|
||||
value.map { |v|
|
||||
build_multipart(v, false).each { |subkey, subvalue|
|
||||
flattened_params["#{k}[]#{subkey}"] = subvalue
|
||||
}
|
||||
}
|
||||
when Hash
|
||||
build_multipart(value, false).each { |subkey, subvalue|
|
||||
flattened_params[k + subkey] = subvalue
|
||||
}
|
||||
else
|
||||
flattened_params[k] = value
|
||||
end
|
||||
end
|
||||
|
||||
if first
|
||||
flattened_params.map { |name, file|
|
||||
if file.respond_to?(:original_filename)
|
||||
::File.open(file.path, "rb") do |f|
|
||||
f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
|
||||
<<-EOF
|
||||
--#{MULTIPART_BOUNDARY}\r
|
||||
Content-Disposition: form-data; name="#{name}"; filename="#{Rack::Utils.escape(file.original_filename)}"\r
|
||||
Content-Type: #{file.content_type}\r
|
||||
Content-Length: #{::File.stat(file.path).size}\r
|
||||
\r
|
||||
#{f.read}\r
|
||||
EOF
|
||||
end
|
||||
else
|
||||
<<-EOF
|
||||
--#{MULTIPART_BOUNDARY}\r
|
||||
Content-Disposition: form-data; name="#{name}"\r
|
||||
\r
|
||||
#{file}\r
|
||||
EOF
|
||||
end
|
||||
}.join + "--#{MULTIPART_BOUNDARY}--\r"
|
||||
else
|
||||
flattened_params
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DEFAULT_ENV = {
|
||||
"rack.version" => [1,0],
|
||||
"rack.input" => StringIO.new,
|
||||
"rack.errors" => StringIO.new,
|
||||
"rack.multithread" => true,
|
||||
"rack.multiprocess" => true,
|
||||
"rack.run_once" => false,
|
||||
}
|
||||
|
||||
# Improve version of env_for thats in rack/master
|
||||
def self.env_for(uri="", opts={}) #:nodoc:
|
||||
uri = URI(uri)
|
||||
uri.path = "/#{uri.path}" unless uri.path[0] == ?/
|
||||
|
||||
env = DEFAULT_ENV.dup
|
||||
|
||||
env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "GET"
|
||||
env["SERVER_NAME"] = uri.host || "example.org"
|
||||
env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80"
|
||||
env["QUERY_STRING"] = uri.query.to_s
|
||||
env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path
|
||||
env["rack.url_scheme"] = uri.scheme || "http"
|
||||
env["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off"
|
||||
|
||||
env["SCRIPT_NAME"] = opts[:script_name] || ""
|
||||
|
||||
if opts[:fatal]
|
||||
env["rack.errors"] = FatalWarner.new
|
||||
else
|
||||
env["rack.errors"] = StringIO.new
|
||||
end
|
||||
|
||||
if params = opts[:params]
|
||||
if env["REQUEST_METHOD"] == "GET"
|
||||
params = Rack::Utils.parse_nested_query(params) if params.is_a?(String)
|
||||
params.update(Rack::Utils.parse_nested_query(env["QUERY_STRING"]))
|
||||
env["QUERY_STRING"] = build_nested_query(params)
|
||||
elsif !opts.has_key?(:input)
|
||||
opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
|
||||
if params.is_a?(Hash)
|
||||
if data = Multipart.build_multipart(params)
|
||||
opts[:input] = data
|
||||
opts["CONTENT_LENGTH"] ||= data.length.to_s
|
||||
opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Multipart::MULTIPART_BOUNDARY}"
|
||||
else
|
||||
opts[:input] = build_nested_query(params)
|
||||
end
|
||||
else
|
||||
opts[:input] = params
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
empty_str = ""
|
||||
empty_str.force_encoding("ASCII-8BIT") if empty_str.respond_to? :force_encoding
|
||||
opts[:input] ||= empty_str
|
||||
if String === opts[:input]
|
||||
rack_input = StringIO.new(opts[:input])
|
||||
else
|
||||
rack_input = opts[:input]
|
||||
end
|
||||
|
||||
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
|
||||
env['rack.input'] = rack_input
|
||||
|
||||
env["CONTENT_LENGTH"] ||= env["rack.input"].length.to_s
|
||||
|
||||
opts.each { |field, value|
|
||||
env[field] = value if String === field
|
||||
}
|
||||
|
||||
env
|
||||
end
|
||||
|
||||
def self.build_nested_query(value, prefix = nil)
|
||||
case value
|
||||
when Array
|
||||
value.map { |v|
|
||||
build_nested_query(v, "#{prefix}[]")
|
||||
}.join("&")
|
||||
when Hash
|
||||
value.map { |k, v|
|
||||
build_nested_query(v, prefix ? "#{prefix}[#{Rack::Utils.escape(k)}]" : Rack::Utils.escape(k))
|
||||
}.join("&")
|
||||
when String
|
||||
raise ArgumentError, "value must be a Hash" if prefix.nil?
|
||||
"#{prefix}=#{Rack::Utils.escape(value)}"
|
||||
else
|
||||
prefix
|
||||
end
|
||||
end
|
||||
DEFAULT_ENV = Rack::MockRequest.env_for('/')
|
||||
|
||||
def self.new(env = {})
|
||||
super
|
||||
end
|
||||
|
||||
def initialize(env = {})
|
||||
super(self.class.env_for('/').merge(env))
|
||||
super(DEFAULT_ENV.merge(env))
|
||||
|
||||
self.host = 'test.host'
|
||||
self.remote_addr = '0.0.0.0'
|
||||
|
||||
@@ -21,11 +21,6 @@
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#++
|
||||
|
||||
activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
|
||||
$:.unshift activesupport_path if File.directory?(activesupport_path)
|
||||
require 'active_support'
|
||||
require 'active_support/core_ext/class/attribute_accessors'
|
||||
|
||||
require File.join(File.dirname(__FILE__), "action_pack")
|
||||
|
||||
module ActionView
|
||||
@@ -36,14 +31,12 @@ module ActionView
|
||||
autoload :Base, 'action_view/base'
|
||||
autoload :Context, 'action_view/context'
|
||||
autoload :Helpers, 'action_view/helpers'
|
||||
autoload :InlineTemplate, 'action_view/template/inline'
|
||||
autoload :MissingTemplate, 'action_view/base'
|
||||
autoload :Partials, 'action_view/render/partials'
|
||||
autoload :Resolver, 'action_view/template/resolver'
|
||||
autoload :PathResolver, 'action_view/template/resolver'
|
||||
autoload :PathSet, 'action_view/paths'
|
||||
autoload :Rendering, 'action_view/render/rendering'
|
||||
autoload :Renderable, 'action_view/template/renderable'
|
||||
autoload :RenderablePartial, 'action_view/template/partial'
|
||||
autoload :Template, 'action_view/template/template'
|
||||
autoload :TemplateError, 'action_view/template/error'
|
||||
autoload :TemplateHandler, 'action_view/template/handler'
|
||||
@@ -58,3 +51,8 @@ class ERB
|
||||
end
|
||||
|
||||
I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml"
|
||||
|
||||
activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
|
||||
$:.unshift activesupport_path if File.directory?(activesupport_path)
|
||||
require 'active_support'
|
||||
require 'active_support/core_ext/class/attribute_accessors'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
require 'thread'
|
||||
require 'cgi'
|
||||
require 'action_view/helpers/url_helper'
|
||||
require 'action_view/helpers/tag_helper'
|
||||
@@ -286,7 +287,9 @@ module ActionView
|
||||
end
|
||||
javascript_src_tag(joined_javascript_name, options)
|
||||
else
|
||||
ensure_javascript_sources!(expand_javascript_sources(sources, recursive)).collect { |source| javascript_src_tag(source, options) }.join("\n")
|
||||
sources = expand_javascript_sources(sources, recursive)
|
||||
ensure_javascript_sources!(sources) if cache
|
||||
sources.collect { |source| javascript_src_tag(source, options) }.join("\n")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -435,7 +438,9 @@ module ActionView
|
||||
end
|
||||
stylesheet_tag(joined_stylesheet_name, options)
|
||||
else
|
||||
ensure_stylesheet_sources!(expand_stylesheet_sources(sources, recursive)).collect { |source| stylesheet_tag(source, options) }.join("\n")
|
||||
sources = expand_stylesheet_sources(sources, recursive)
|
||||
ensure_stylesheet_sources!(sources) if cache
|
||||
sources.collect { |source| stylesheet_tag(source, options) }.join("\n")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -449,6 +449,15 @@ module ActionView
|
||||
# <% end %>
|
||||
# <% end %>
|
||||
#
|
||||
# Or a collection to be used:
|
||||
#
|
||||
# <% form_for @person, :url => { :action => "update" } do |person_form| %>
|
||||
# ...
|
||||
# <% person_form.fields_for :projects, @active_projects do |project_fields| %>
|
||||
# Name: <%= project_fields.text_field :name %>
|
||||
# <% end %>
|
||||
# <% end %>
|
||||
#
|
||||
# When projects is already an association on Person you can use
|
||||
# +accepts_nested_attributes_for+ to define the writer method for you:
|
||||
#
|
||||
@@ -1037,18 +1046,21 @@ module ActionView
|
||||
|
||||
def fields_for_with_nested_attributes(association_name, args, block)
|
||||
name = "#{object_name}[#{association_name}_attributes]"
|
||||
association = @object.send(association_name)
|
||||
explicit_object = args.first.to_model if args.first.respond_to?(:to_model)
|
||||
association = args.first.to_model if args.first.respond_to?(:to_model)
|
||||
|
||||
if association.respond_to?(:new_record?)
|
||||
association = [association] if @object.send(association_name).is_a?(Array)
|
||||
elsif !association.is_a?(Array)
|
||||
association = @object.send(association_name)
|
||||
end
|
||||
|
||||
if association.is_a?(Array)
|
||||
children = explicit_object ? [explicit_object] : association
|
||||
explicit_child_index = args.last[:child_index] if args.last.is_a?(Hash)
|
||||
|
||||
children.map do |child|
|
||||
association.map do |child|
|
||||
fields_for_nested_model("#{name}[#{explicit_child_index || nested_child_index(name)}]", child, args, block)
|
||||
end.join
|
||||
else
|
||||
fields_for_nested_model(name, explicit_object || association, args, block)
|
||||
elsif association
|
||||
fields_for_nested_model(name, association, args, block)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ module ActionView
|
||||
# escape_once("<< Accept & Checkout")
|
||||
# # => "<< Accept & Checkout"
|
||||
def escape_once(html)
|
||||
html.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] }
|
||||
ActiveSupport::Multibyte.clean(html.to_s).gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'action_view/helpers/javascript_helper'
|
||||
require 'active_support/core_ext/array/access'
|
||||
require 'active_support/core_ext/hash/keys'
|
||||
|
||||
module ActionView
|
||||
|
||||
@@ -6,7 +6,7 @@ module ActionView
|
||||
self.default_format = Mime::XML
|
||||
|
||||
def compile(template)
|
||||
require 'builder'
|
||||
require 'active_support/vendor/builder'
|
||||
"xml = ::Builder::XmlMarkup.new(:indent => 2);" +
|
||||
"self.output_buffer = xml.target!;" +
|
||||
template.source +
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
module ActionView #:nodoc:
|
||||
class InlineTemplate #:nodoc:
|
||||
include Renderable
|
||||
|
||||
attr_reader :source, :extension, :method_segment
|
||||
|
||||
def initialize(source, type = nil)
|
||||
@source = source
|
||||
@extension = type
|
||||
@method_segment = "inline_#{@source.hash.abs}"
|
||||
end
|
||||
|
||||
private
|
||||
# Always recompile inline templates
|
||||
def recompile?
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,18 +0,0 @@
|
||||
module ActionView
|
||||
# NOTE: The template that this mixin is being included into is frozen
|
||||
# so you cannot set or modify any instance variables
|
||||
module RenderablePartial #:nodoc:
|
||||
extend ActiveSupport::Memoizable
|
||||
|
||||
def variable_name
|
||||
name.sub(/\A_/, '').to_sym
|
||||
end
|
||||
memoize :variable_name
|
||||
|
||||
def counter_name
|
||||
"#{variable_name}_counter".to_sym
|
||||
end
|
||||
memoize :counter_name
|
||||
|
||||
end
|
||||
end
|
||||
@@ -1,93 +0,0 @@
|
||||
# encoding: utf-8
|
||||
|
||||
module ActionView
|
||||
# NOTE: The template that this mixin is being included into is frozen
|
||||
# so you cannot set or modify any instance variables
|
||||
module Renderable #:nodoc:
|
||||
extend ActiveSupport::Memoizable
|
||||
|
||||
def render(view, locals)
|
||||
compile(locals)
|
||||
view.send(method_name(locals), locals) {|*args| yield(*args) }
|
||||
end
|
||||
|
||||
def load!
|
||||
names = CompiledTemplates.instance_methods.grep(/#{method_name_without_locals}/)
|
||||
names.each do |name|
|
||||
CompiledTemplates.class_eval do
|
||||
remove_method(name)
|
||||
end
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filename
|
||||
'compiled-template'
|
||||
end
|
||||
|
||||
def handler
|
||||
Template.handler_class_for_extension(extension)
|
||||
end
|
||||
memoize :handler
|
||||
|
||||
def compiled_source
|
||||
handler.call(self)
|
||||
end
|
||||
memoize :compiled_source
|
||||
|
||||
def method_name_without_locals
|
||||
['_run', extension, method_segment].compact.join('_')
|
||||
end
|
||||
memoize :method_name_without_locals
|
||||
|
||||
def method_name(local_assigns)
|
||||
if local_assigns && local_assigns.any?
|
||||
method_name = method_name_without_locals.dup
|
||||
method_name << "_locals_#{local_assigns.keys.map { |k| k.to_s }.sort.join('_')}"
|
||||
else
|
||||
method_name = method_name_without_locals
|
||||
end
|
||||
method_name.to_sym
|
||||
end
|
||||
|
||||
# Compile and evaluate the template's code (if necessary)
|
||||
def compile(local_assigns)
|
||||
render_symbol = method_name(local_assigns)
|
||||
|
||||
if !CompiledTemplates.method_defined?(render_symbol) || recompile?
|
||||
compile!(render_symbol, local_assigns)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def compile!(render_symbol, local_assigns)
|
||||
locals_code = local_assigns.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join
|
||||
|
||||
source = <<-end_src
|
||||
def #{render_symbol}(local_assigns)
|
||||
old_output_buffer = output_buffer;#{locals_code};#{compiled_source}
|
||||
ensure
|
||||
self.output_buffer = old_output_buffer
|
||||
end
|
||||
end_src
|
||||
|
||||
begin
|
||||
ActionView::CompiledTemplates.module_eval(source, filename.to_s, 0)
|
||||
rescue Exception => e # errors from template code
|
||||
if logger = defined?(ActionController) && Base.logger
|
||||
logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}"
|
||||
logger.debug "Function body: #{source}"
|
||||
logger.debug "Backtrace: #{e.backtrace.join("\n")}"
|
||||
end
|
||||
|
||||
raise ActionView::TemplateError.new(self, {}, e)
|
||||
end
|
||||
end
|
||||
|
||||
def recompile?
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,9 +1,28 @@
|
||||
require "pathname"
|
||||
require "active_support/core_ext/class"
|
||||
require "action_view/template/template"
|
||||
|
||||
module ActionView
|
||||
# Abstract superclass
|
||||
class Resolver
|
||||
|
||||
class_inheritable_accessor(:registered_details)
|
||||
self.registered_details = {}
|
||||
|
||||
def self.register_detail(name, options = {})
|
||||
registered_details[name] = lambda do |val|
|
||||
val ||= yield
|
||||
val |= [nil] unless options[:allow_nil] == false
|
||||
val
|
||||
end
|
||||
end
|
||||
|
||||
register_detail(:locale) { [I18n.locale] }
|
||||
register_detail(:formats) { Mime::SET.symbols }
|
||||
register_detail(:handlers, :allow_nil => false) do
|
||||
TemplateHandlers.extensions
|
||||
end
|
||||
|
||||
def initialize(options = {})
|
||||
@cache = options[:cache]
|
||||
@cached = {}
|
||||
@@ -11,15 +30,18 @@ module ActionView
|
||||
|
||||
# Normalizes the arguments and passes it on to find_template
|
||||
def find(*args)
|
||||
find_all_by_parts(*args).first
|
||||
find_all(*args).first
|
||||
end
|
||||
|
||||
def find_all_by_parts(name, details = {}, prefix = nil, partial = nil)
|
||||
details[:locales] = [I18n.locale]
|
||||
name = name.to_s.gsub(handler_matcher, '').split("/")
|
||||
find_templates(name.pop, details, [prefix, *name].compact.join("/"), partial)
|
||||
|
||||
def find_all(name, details = {}, prefix = nil, partial = nil)
|
||||
details = normalize_details(details)
|
||||
name, prefix = normalize_name(name, prefix)
|
||||
|
||||
cached([name, details, prefix, partial]) do
|
||||
find_templates(name, details, prefix, partial)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
# This is what child classes implement. No defaults are needed
|
||||
@@ -28,29 +50,26 @@ module ActionView
|
||||
def find_templates(name, details, prefix, partial)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def valid_handlers
|
||||
@valid_handlers ||= TemplateHandlers.extensions
|
||||
|
||||
def normalize_details(details)
|
||||
details = details.dup
|
||||
# TODO: Refactor this concern out of the resolver
|
||||
details.delete(:formats) if details[:formats] == [:"*/*"]
|
||||
registered_details.each do |k, v|
|
||||
details[k] = v.call(details[k])
|
||||
end
|
||||
details
|
||||
end
|
||||
|
||||
def handler_matcher
|
||||
@handler_matcher ||= begin
|
||||
e = valid_handlers.join('|')
|
||||
/\.(?:#{e})$/
|
||||
end
|
||||
end
|
||||
# Support legacy foo.erb names even though we now ignore .erb
|
||||
# as well as incorrectly putting part of the path in the template
|
||||
# name instead of the prefix.
|
||||
def normalize_name(name, prefix)
|
||||
handlers = TemplateHandlers.extensions.join('|')
|
||||
name = name.to_s.gsub(/\.(?:#{handlers})$/, '')
|
||||
|
||||
def handler_glob
|
||||
@handler_glob ||= begin
|
||||
e = TemplateHandlers.extensions.map{|h| ".#{h}"}.join(",")
|
||||
"{#{e}}"
|
||||
end
|
||||
end
|
||||
|
||||
def formats_glob
|
||||
@formats_glob ||= begin
|
||||
'{' + Mime::SET.symbols.map { |l| ".#{l}," }.join + '}'
|
||||
end
|
||||
parts = name.split('/')
|
||||
return parts.pop, [prefix, *parts].compact.join("/")
|
||||
end
|
||||
|
||||
def cached(key)
|
||||
@@ -60,80 +79,49 @@ module ActionView
|
||||
end
|
||||
end
|
||||
|
||||
class FileSystemResolver < Resolver
|
||||
class PathResolver < Resolver
|
||||
|
||||
def self.cached_glob
|
||||
@@cached_glob ||= {}
|
||||
end
|
||||
|
||||
def initialize(path, options = {})
|
||||
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
||||
super(options)
|
||||
@path = Pathname.new(path).expand_path
|
||||
end
|
||||
|
||||
# TODO: This is the currently needed API. Make this suck less
|
||||
# ==== <suck>
|
||||
attr_reader :path
|
||||
EXTENSION_ORDER = [:locale, :formats, :handlers]
|
||||
|
||||
def to_s
|
||||
path.to_s
|
||||
@path.to_s
|
||||
end
|
||||
alias to_path to_s
|
||||
|
||||
def find_templates(name, details, prefix, partial)
|
||||
path = build_path(name, details, prefix, partial)
|
||||
query(path, EXTENSION_ORDER.map { |ext| details[ext] })
|
||||
end
|
||||
|
||||
def to_str
|
||||
path.to_s
|
||||
end
|
||||
|
||||
def ==(path)
|
||||
to_str == path.to_str
|
||||
end
|
||||
|
||||
def eql?(path)
|
||||
to_str == path.to_str
|
||||
end
|
||||
# ==== </suck>
|
||||
|
||||
def find_templates(name, details, prefix, partial, root = "#{@path}/")
|
||||
if glob = details_to_glob(name, details, prefix, partial, root)
|
||||
cached(glob) do
|
||||
Dir[glob].map do |path|
|
||||
next if File.directory?(path)
|
||||
source = File.read(path)
|
||||
identifier = Pathname.new(path).expand_path.to_s
|
||||
|
||||
Template.new(source, identifier, *path_to_details(path))
|
||||
end.compact
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# :api: plugin
|
||||
def details_to_glob(name, details, prefix, partial, root)
|
||||
self.class.cached_glob[[name, prefix, partial, details, root]] ||= begin
|
||||
path = ""
|
||||
path << "#{prefix}/" unless prefix.empty?
|
||||
path << (partial ? "_#{name}" : name)
|
||||
|
||||
extensions = ""
|
||||
[:locales, :formats].each do |k|
|
||||
extensions << if exts = details[k]
|
||||
'{' + exts.map {|e| ".#{e},"}.join + '}'
|
||||
else
|
||||
k == :formats ? formats_glob : ''
|
||||
end
|
||||
end
|
||||
|
||||
"#{root}#{path}#{extensions}#{handler_glob}"
|
||||
end
|
||||
def build_path(name, details, prefix, partial)
|
||||
path = ""
|
||||
path << "#{prefix}/" unless prefix.empty?
|
||||
path << (partial ? "_#{name}" : name)
|
||||
path
|
||||
end
|
||||
|
||||
# TODO: fix me
|
||||
# :api: plugin
|
||||
def query(path, exts)
|
||||
query = "#{@path}/#{path}"
|
||||
exts.each do |ext|
|
||||
query << '{' << ext.map {|e| e && ".#{e}" }.join(',') << '}'
|
||||
end
|
||||
|
||||
Dir[query].map do |path|
|
||||
next if File.directory?(path)
|
||||
source = File.read(path)
|
||||
identifier = Pathname.new(path).expand_path.to_s
|
||||
|
||||
Template.new(source, identifier, *path_to_details(path))
|
||||
end.compact
|
||||
end
|
||||
|
||||
# # TODO: fix me
|
||||
# # :api: plugin
|
||||
def path_to_details(path)
|
||||
# [:erb, :format => :html, :locale => :en, :partial => true/false]
|
||||
if m = path.match(%r'/(_)?[\w-]+(\.[\w-]+)*\.(\w+)$')
|
||||
if m = path.match(%r'(?:^|/)(_)?[\w-]+(\.[\w-]+)*\.(\w+)$')
|
||||
partial = m[1] == '_'
|
||||
details = (m[2]||"").split('.').reject { |e| e.empty? }
|
||||
handler = Template.handler_class_for_extension(m[3])
|
||||
@@ -146,13 +134,32 @@ module ActionView
|
||||
end
|
||||
end
|
||||
|
||||
class FileSystemResolverWithFallback < FileSystemResolver
|
||||
class FileSystemResolver < PathResolver
|
||||
def initialize(path, options = {})
|
||||
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
||||
super(options)
|
||||
@path = Pathname.new(path).expand_path
|
||||
end
|
||||
end
|
||||
|
||||
def find_templates(name, details, prefix, partial)
|
||||
templates = super
|
||||
return super(name, details, prefix, partial, '') if templates.empty?
|
||||
templates
|
||||
# OMG HAX
|
||||
# TODO: remove hax
|
||||
class FileSystemResolverWithFallback < Resolver
|
||||
def initialize(path, options = {})
|
||||
super(options)
|
||||
@paths = [FileSystemResolver.new(path, options), FileSystemResolver.new("", options), FileSystemResolver.new("/", options)]
|
||||
end
|
||||
|
||||
def find_templates(*args)
|
||||
@paths.each do |p|
|
||||
template = p.find_templates(*args)
|
||||
return template unless template.empty?
|
||||
end
|
||||
[]
|
||||
end
|
||||
|
||||
def to_s
|
||||
@paths.first.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -27,8 +27,10 @@ module ActionView
|
||||
end
|
||||
|
||||
def render(view, locals, &block)
|
||||
method_name = compile(locals, view)
|
||||
view.send(method_name, locals, &block)
|
||||
ActiveSupport::Orchestra.instrument(:render_template, :identifier => identifier) do
|
||||
method_name = compile(locals, view)
|
||||
view.send(method_name, locals, &block)
|
||||
end.result
|
||||
rescue Exception => e
|
||||
if e.is_a?(TemplateError)
|
||||
e.sub_template_of(self)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
require 'action_pack'
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module AbstractController
|
||||
module Testing
|
||||
@@ -148,10 +148,10 @@ module AbstractController
|
||||
private
|
||||
def self.layout(formats)
|
||||
begin
|
||||
view_paths.find(name.underscore, {:formats => formats}, "layouts")
|
||||
find_template(name.underscore, {:formats => formats}, :_prefix => "layouts")
|
||||
rescue ActionView::MissingTemplate
|
||||
begin
|
||||
view_paths.find("application", {:formats => formats}, "layouts")
|
||||
find_template("application", {:formats => formats}, :_prefix => "layouts")
|
||||
rescue ActionView::MissingTemplate
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module AbstractController
|
||||
module Testing
|
||||
@@ -235,4 +235,4 @@ module AbstractController
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module AbstractController
|
||||
module Testing
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
require 'active_support/core_ext/class/removal'
|
||||
|
||||
module AbstractControllerTests
|
||||
@@ -1,21 +0,0 @@
|
||||
$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
||||
$:.unshift(File.dirname(__FILE__) + '/../../../activesupport/lib')
|
||||
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
||||
|
||||
require 'rubygems'
|
||||
require 'test/unit'
|
||||
require 'active_support'
|
||||
require 'active_support/test_case'
|
||||
require 'abstract_controller'
|
||||
require 'action_view'
|
||||
require 'action_view/base'
|
||||
require 'action_dispatch'
|
||||
require 'fixture_template'
|
||||
|
||||
begin
|
||||
require 'ruby-debug'
|
||||
Debugger.settings[:autoeval] = true
|
||||
Debugger.start
|
||||
rescue LoadError
|
||||
# Debugging disabled. `gem install ruby-debug` to enable.
|
||||
end
|
||||
@@ -1,29 +1,36 @@
|
||||
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
||||
$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
|
||||
$:.unshift(File.dirname(__FILE__) + '/../../activemodel/lib')
|
||||
$:.unshift(File.dirname(__FILE__) + '/lib')
|
||||
|
||||
$:.unshift(File.dirname(__FILE__) + '/lib')
|
||||
$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers')
|
||||
$:.unshift(File.dirname(__FILE__) + '/fixtures/alternate_helpers')
|
||||
|
||||
ENV['TMPDIR'] = File.join(File.dirname(__FILE__), 'tmp')
|
||||
bundler = File.join(File.dirname(__FILE__), '..', 'vendor', 'gems', 'environment')
|
||||
require bundler if File.exist?("#{bundler}.rb")
|
||||
|
||||
ENV['new_base'] = "true"
|
||||
$stderr.puts "Running old tests on new_base"
|
||||
begin
|
||||
%w( rack rack/test sqlite3 ).each { |lib| require lib }
|
||||
rescue LoadError => e
|
||||
abort e.message
|
||||
end
|
||||
|
||||
ENV['TMPDIR'] = File.join(File.dirname(__FILE__), 'tmp')
|
||||
|
||||
require 'test/unit'
|
||||
require 'active_support'
|
||||
|
||||
require 'active_support/test_case'
|
||||
require 'abstract_controller'
|
||||
require 'action_controller'
|
||||
require 'action_view'
|
||||
require 'action_view/base'
|
||||
require 'action_dispatch'
|
||||
require 'active_model'
|
||||
require 'fixture_template'
|
||||
require 'action_controller/testing/process'
|
||||
require 'action_view/test_case'
|
||||
require 'action_controller/testing/integration'
|
||||
require 'action_view/test_case'
|
||||
require 'active_support/dependencies'
|
||||
require 'active_model'
|
||||
|
||||
$tags[:new_base] = true
|
||||
|
||||
begin
|
||||
require 'ruby-debug'
|
||||
@@ -33,6 +40,8 @@ rescue LoadError
|
||||
# Debugging disabled. `gem install ruby-debug` to enable.
|
||||
end
|
||||
|
||||
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
|
||||
|
||||
ActiveSupport::Dependencies.hook!
|
||||
|
||||
# Show backtraces for deprecated behavior for quicker cleanup.
|
||||
@@ -55,6 +64,61 @@ module ActionView
|
||||
end
|
||||
end
|
||||
|
||||
# Temporary base class
|
||||
class Rack::TestCase < ActionController::IntegrationTest
|
||||
setup do
|
||||
ActionController::Base.session_options[:key] = "abc"
|
||||
ActionController::Base.session_options[:secret] = ("*" * 30)
|
||||
end
|
||||
|
||||
def app
|
||||
@app ||= ActionController::Dispatcher.new
|
||||
end
|
||||
|
||||
def self.testing(klass = nil)
|
||||
if klass
|
||||
@testing = "/#{klass.name.underscore}".sub!(/_controller$/, '')
|
||||
else
|
||||
@testing
|
||||
end
|
||||
end
|
||||
|
||||
def get(thing, *args)
|
||||
if thing.is_a?(Symbol)
|
||||
super("#{self.class.testing}/#{thing}", *args)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def assert_body(body)
|
||||
assert_equal body, Array.wrap(response.body).join
|
||||
end
|
||||
|
||||
def assert_status(code)
|
||||
assert_equal code, response.status
|
||||
end
|
||||
|
||||
def assert_response(body, status = 200, headers = {})
|
||||
assert_body body
|
||||
assert_status status
|
||||
headers.each do |header, value|
|
||||
assert_header header, value
|
||||
end
|
||||
end
|
||||
|
||||
def assert_content_type(type)
|
||||
assert_equal type, response.headers["Content-Type"]
|
||||
end
|
||||
|
||||
def assert_header(name, value)
|
||||
assert_equal value, response.headers[name]
|
||||
end
|
||||
end
|
||||
|
||||
class ::ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
module ActionController
|
||||
Base.session = {
|
||||
:key => '_testing_session',
|
||||
@@ -131,3 +195,11 @@ module ActionController
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class SimpleRouteCase < Rack::TestCase
|
||||
setup do
|
||||
ActionController::Routing::Routes.draw do |map|
|
||||
map.connect ':controller/:action/:id'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,7 +16,7 @@ if defined?(ActiveRecord) && defined?(Fixtures)
|
||||
else
|
||||
$stderr.print 'Attempting to load Active Record... '
|
||||
begin
|
||||
PATH_TO_AR = "#{File.dirname(__FILE__)}/../../../activerecord/lib"
|
||||
PATH_TO_AR = "#{File.dirname(__FILE__)}/../../activerecord/lib"
|
||||
raise LoadError, "#{PATH_TO_AR} doesn't exist" unless File.directory?(PATH_TO_AR)
|
||||
$LOAD_PATH.unshift PATH_TO_AR
|
||||
require 'active_record'
|
||||
@@ -72,13 +72,13 @@ class ActiveRecordTestConnector
|
||||
|
||||
# Load actionpack sqlite tables
|
||||
def load_schema
|
||||
File.read(File.dirname(__FILE__) + "/../fixtures/db_definitions/sqlite.sql").split(';').each do |sql|
|
||||
File.read(File.dirname(__FILE__) + "/fixtures/db_definitions/sqlite.sql").split(';').each do |sql|
|
||||
ActiveRecord::Base.connection.execute(sql) unless sql.blank?
|
||||
end
|
||||
end
|
||||
|
||||
def require_fixture_models
|
||||
Dir.glob(File.dirname(__FILE__) + "/../fixtures/*.rb").each {|f| require f}
|
||||
Dir.glob(File.dirname(__FILE__) + "/fixtures/*.rb").each {|f| require f}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -176,6 +176,7 @@ class ActiveRecordStoreTest < ActionController::IntegrationTest
|
||||
c.connect "/:action"
|
||||
end
|
||||
end
|
||||
reset_app!
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
require 'abstract_unit'
|
||||
require 'action_controller/vendor/html-scanner'
|
||||
require 'controller/fake_controllers'
|
||||
|
||||
# a controller class to facilitate the tests
|
||||
class ActionPackAssertionsController < ActionController::Base
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
require 'abstract_unit'
|
||||
require 'logger'
|
||||
require 'controller/fake_controllers'
|
||||
|
||||
class Address
|
||||
def Address.count(conditions = nil, join = nil)
|
||||
@@ -15,13 +16,8 @@ class Address
|
||||
end
|
||||
end
|
||||
|
||||
class AddressesTestController < ActionController::Base
|
||||
def self.controller_name; "addresses"; end
|
||||
def self.controller_path; "addresses"; end
|
||||
end
|
||||
|
||||
class AddressesTest < ActionController::TestCase
|
||||
tests AddressesTestController
|
||||
tests AddressesController
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@@ -441,8 +441,8 @@ class ActionCacheTest < ActionController::TestCase
|
||||
|
||||
def test_correct_content_type_is_returned_for_cache_hit
|
||||
# run it twice to cache it the first time
|
||||
get :index, :id => 'content-type.xml'
|
||||
get :index, :id => 'content-type.xml'
|
||||
get :index, :id => 'content-type', :format => 'xml'
|
||||
get :index, :id => 'content-type', :format => 'xml'
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
end
|
||||
|
||||
@@ -625,15 +625,20 @@ class FragmentCachingTest < ActionController::TestCase
|
||||
def test_fragment_for_logging
|
||||
fragment_computed = false
|
||||
|
||||
@controller.class.expects(:benchmark).with('Cached fragment exists?: views/expensive')
|
||||
@controller.class.expects(:benchmark).with('Cached fragment miss: views/expensive')
|
||||
@controller.class.expects(:benchmark).with('Cached fragment hit: views/expensive').never
|
||||
listener = []
|
||||
ActiveSupport::Orchestra.register listener
|
||||
|
||||
buffer = 'generated till now -> '
|
||||
@controller.fragment_for(buffer, 'expensive') { fragment_computed = true }
|
||||
|
||||
assert_equal 2, listener.size
|
||||
assert_equal :fragment_exist?, listener[0].name
|
||||
assert_equal :write_fragment, listener[1].name
|
||||
|
||||
assert fragment_computed
|
||||
assert_equal 'generated till now -> ', buffer
|
||||
ensure
|
||||
ActiveSupport::Orchestra.unregister listener
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require 'abstract_unit'
|
||||
|
||||
class ContentTypeController < ActionController::Base
|
||||
class OldContentTypeController < ActionController::Base
|
||||
# :ported:
|
||||
def render_content_type_from_body
|
||||
response.content_type = Mime::RSS
|
||||
@@ -56,7 +56,7 @@ class ContentTypeController < ActionController::Base
|
||||
end
|
||||
|
||||
class ContentTypeTest < ActionController::TestCase
|
||||
tests ContentTypeController
|
||||
tests OldContentTypeController
|
||||
|
||||
def setup
|
||||
super
|
||||
@@ -73,11 +73,11 @@ class ContentTypeTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
def test_render_changed_charset_default
|
||||
ContentTypeController.default_charset = "utf-16"
|
||||
OldContentTypeController.default_charset = "utf-16"
|
||||
get :render_defaults
|
||||
assert_equal "utf-16", @response.charset
|
||||
assert_equal Mime::HTML, @response.content_type
|
||||
ContentTypeController.default_charset = "utf-8"
|
||||
OldContentTypeController.default_charset = "utf-8"
|
||||
end
|
||||
|
||||
# :ported:
|
||||
@@ -109,12 +109,12 @@ class ContentTypeTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
def test_nil_default_for_rhtml
|
||||
ContentTypeController.default_charset = nil
|
||||
OldContentTypeController.default_charset = nil
|
||||
get :render_default_for_rhtml
|
||||
assert_equal Mime::HTML, @response.content_type
|
||||
assert_nil @response.charset, @response.headers.inspect
|
||||
ensure
|
||||
ContentTypeController.default_charset = "utf-8"
|
||||
OldContentTypeController.default_charset = "utf-8"
|
||||
end
|
||||
|
||||
def test_default_for_rhtml
|
||||
@@ -143,8 +143,7 @@ class ContentTypeTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
class AcceptBasedContentTypeTest < ActionController::TestCase
|
||||
|
||||
tests ContentTypeController
|
||||
tests OldContentTypeController
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@@ -3,13 +3,16 @@ require 'abstract_unit'
|
||||
class DispatcherTest < Test::Unit::TestCase
|
||||
Dispatcher = ActionController::Dispatcher
|
||||
|
||||
class Foo
|
||||
cattr_accessor :a, :b
|
||||
end
|
||||
|
||||
def setup
|
||||
ENV['REQUEST_METHOD'] = 'GET'
|
||||
|
||||
# Clear callbacks as they are redefined by Dispatcher#define_dispatcher_callbacks
|
||||
ActionDispatch::Callbacks.instance_variable_set("@prepare_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
|
||||
ActionDispatch::Callbacks.instance_variable_set("@before_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
|
||||
ActionDispatch::Callbacks.instance_variable_set("@after_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
|
||||
ActionDispatch::Callbacks.reset_callbacks(:prepare)
|
||||
ActionDispatch::Callbacks.reset_callbacks(:call)
|
||||
|
||||
@old_router, Dispatcher.router = Dispatcher.router, mock()
|
||||
Dispatcher.router.stubs(:call).returns([200, {}, 'response'])
|
||||
@@ -68,13 +71,12 @@ class DispatcherTest < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_to_prepare_with_identifier_replaces
|
||||
a = b = nil
|
||||
Dispatcher.to_prepare(:unique_id) { |*args| a = b = 1 }
|
||||
Dispatcher.to_prepare(:unique_id) { |*args| a = 2 }
|
||||
Dispatcher.to_prepare(:unique_id) { |*args| Foo.a, Foo.b = 1, 1 }
|
||||
Dispatcher.to_prepare(:unique_id) { |*args| Foo.a = 2 }
|
||||
|
||||
dispatch
|
||||
assert_equal 2, a
|
||||
assert_equal nil, b
|
||||
assert_equal 2, Foo.a
|
||||
assert_equal nil, Foo.b
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -35,6 +35,7 @@ class FilterParamTest < ActionController::TestCase
|
||||
test_hashes = [[{},{},[]],
|
||||
[{'foo'=>nil},{'foo'=>nil},[]],
|
||||
[{'foo'=>'bar'},{'foo'=>'bar'},[]],
|
||||
[{'foo'=>1},{'foo'=>1},[]],
|
||||
[{'foo'=>'bar'},{'foo'=>'bar'},%w'food'],
|
||||
[{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'],
|
||||
[{'foo'=>'bar', 'bar'=>'foo'},{'foo'=>'[FILTERED]', 'bar'=>'foo'},%w'foo baz'],
|
||||
|
||||
@@ -371,12 +371,13 @@ class IntegrationProcessTest < ActionController::IntegrationTest
|
||||
c.connect "/:action"
|
||||
end
|
||||
end
|
||||
reset!
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class MetalTest < ActionController::IntegrationTest
|
||||
class MetalIntegrationTest < ActionController::IntegrationTest
|
||||
class Poller
|
||||
def self.call(env)
|
||||
if env["PATH_INFO"] =~ /^\/success/
|
||||
|
||||
@@ -2,23 +2,27 @@ require 'abstract_unit'
|
||||
require 'controller/fake_models'
|
||||
require 'pathname'
|
||||
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
class RenderJSTest < ActionController::TestCase
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
def render_vanilla_js_hello
|
||||
render :js => "alert('hello')"
|
||||
end
|
||||
|
||||
def greeting
|
||||
# let's just rely on the template
|
||||
end
|
||||
|
||||
def show_partial
|
||||
render :partial => 'partial'
|
||||
end
|
||||
end
|
||||
def self.controller_path
|
||||
'test'
|
||||
end
|
||||
|
||||
def render_vanilla_js_hello
|
||||
render :js => "alert('hello')"
|
||||
end
|
||||
|
||||
def greeting
|
||||
# let's just rely on the template
|
||||
end
|
||||
|
||||
def show_partial
|
||||
render :partial => 'partial'
|
||||
end
|
||||
end
|
||||
|
||||
class RenderTest < ActionController::TestCase
|
||||
tests TestController
|
||||
|
||||
def test_render_vanilla_js
|
||||
@@ -26,14 +30,14 @@ class RenderTest < ActionController::TestCase
|
||||
assert_equal "alert('hello')", @response.body
|
||||
assert_equal "text/javascript", @response.content_type
|
||||
end
|
||||
|
||||
|
||||
def test_render_with_default_from_accept_header
|
||||
xhr :get, :greeting
|
||||
assert_equal "$(\"body\").visualEffect(\"highlight\");", @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_should_render_js_partial
|
||||
xhr :get, :show_partial, :format => 'js'
|
||||
assert_equal 'partial js', @response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,35 +2,39 @@ require 'abstract_unit'
|
||||
require 'controller/fake_models'
|
||||
require 'pathname'
|
||||
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
def render_json_nil
|
||||
render :json => nil
|
||||
class RenderJsonTest < ActionController::TestCase
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
def self.controller_path
|
||||
'test'
|
||||
end
|
||||
|
||||
def render_json_nil
|
||||
render :json => nil
|
||||
end
|
||||
|
||||
def render_json_hello_world
|
||||
render :json => ActiveSupport::JSON.encode(:hello => 'world')
|
||||
end
|
||||
|
||||
def render_json_hello_world_with_callback
|
||||
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert'
|
||||
end
|
||||
|
||||
def render_json_with_custom_content_type
|
||||
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript'
|
||||
end
|
||||
|
||||
def render_symbol_json
|
||||
render :json => ActiveSupport::JSON.encode(:hello => 'world')
|
||||
end
|
||||
|
||||
def render_json_with_render_to_string
|
||||
render :json => {:hello => render_to_string(:partial => 'partial')}
|
||||
end
|
||||
end
|
||||
|
||||
def render_json_hello_world
|
||||
render :json => ActiveSupport::JSON.encode(:hello => 'world')
|
||||
end
|
||||
|
||||
def render_json_hello_world_with_callback
|
||||
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert'
|
||||
end
|
||||
|
||||
def render_json_with_custom_content_type
|
||||
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript'
|
||||
end
|
||||
|
||||
def render_symbol_json
|
||||
render :json => ActiveSupport::JSON.encode(:hello => 'world')
|
||||
end
|
||||
|
||||
def render_json_with_render_to_string
|
||||
render :json => {:hello => render_to_string(:partial => 'partial')}
|
||||
end
|
||||
end
|
||||
|
||||
class RenderTest < ActionController::TestCase
|
||||
tests TestController
|
||||
|
||||
def setup
|
||||
@@ -40,8 +44,8 @@ class RenderTest < ActionController::TestCase
|
||||
@controller.logger = Logger.new(nil)
|
||||
|
||||
@request.host = "www.nextangle.com"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_render_json_nil
|
||||
get :render_json_nil
|
||||
assert_equal 'null', @response.body
|
||||
@@ -76,5 +80,5 @@ class RenderTest < ActionController::TestCase
|
||||
get :render_json_with_render_to_string
|
||||
assert_equal '{"hello":"partial html"}', @response.body
|
||||
assert_equal 'application/json', @response.content_type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,139 +2,144 @@ require 'abstract_unit'
|
||||
require 'controller/fake_models'
|
||||
require 'pathname'
|
||||
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
layout :determine_layout
|
||||
class RenderOtherTest < ActionController::TestCase
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
module RenderTestHelper
|
||||
def rjs_helper_method_from_module
|
||||
page.visual_effect :highlight
|
||||
def self.controller_path
|
||||
'test'
|
||||
end
|
||||
end
|
||||
|
||||
helper RenderTestHelper
|
||||
helper do
|
||||
def rjs_helper_method(value)
|
||||
page.visual_effect :highlight, value
|
||||
end
|
||||
end
|
||||
layout :determine_layout
|
||||
|
||||
def enum_rjs_test
|
||||
render :update do |page|
|
||||
page.select('.product').each do |value|
|
||||
page.rjs_helper_method_from_module
|
||||
page.rjs_helper_method(value)
|
||||
page.sortable(value, :url => { :action => "order" })
|
||||
page.draggable(value)
|
||||
module RenderTestHelper
|
||||
def rjs_helper_method_from_module
|
||||
page.visual_effect :highlight
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_explicit_html_template
|
||||
end
|
||||
|
||||
def render_custom_code_rjs
|
||||
render :update, :status => 404 do |page|
|
||||
page.replace :foo, :partial => 'partial'
|
||||
end
|
||||
end
|
||||
|
||||
def render_implicit_html_template
|
||||
end
|
||||
|
||||
def render_js_with_explicit_template
|
||||
@project_id = 4
|
||||
render :template => 'test/delete_with_js'
|
||||
end
|
||||
|
||||
def render_js_with_explicit_action_template
|
||||
@project_id = 4
|
||||
render :action => 'delete_with_js'
|
||||
end
|
||||
|
||||
def delete_with_js
|
||||
@project_id = 4
|
||||
end
|
||||
|
||||
def update_page
|
||||
render :update do |page|
|
||||
page.replace_html 'balance', '$37,000,000.00'
|
||||
page.visual_effect :highlight, 'balance'
|
||||
helper RenderTestHelper
|
||||
helper do
|
||||
def rjs_helper_method(value)
|
||||
page.visual_effect :highlight, value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update_page_with_instance_variables
|
||||
@money = '$37,000,000.00'
|
||||
@div_id = 'balance'
|
||||
render :update do |page|
|
||||
page.replace_html @div_id, @money
|
||||
page.visual_effect :highlight, @div_id
|
||||
def enum_rjs_test
|
||||
render :update do |page|
|
||||
page.select('.product').each do |value|
|
||||
page.rjs_helper_method_from_module
|
||||
page.rjs_helper_method(value)
|
||||
page.sortable(value, :url => { :action => "order" })
|
||||
page.draggable(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update_page_with_view_method
|
||||
render :update do |page|
|
||||
page.replace_html 'person', pluralize(2, 'person')
|
||||
def render_explicit_html_template
|
||||
end
|
||||
end
|
||||
|
||||
def partial_as_rjs
|
||||
render :update do |page|
|
||||
page.replace :foo, :partial => 'partial'
|
||||
end
|
||||
end
|
||||
|
||||
def respond_to_partial_as_rjs
|
||||
respond_to do |format|
|
||||
format.js do
|
||||
def render_custom_code_rjs
|
||||
render :update, :status => 404 do |page|
|
||||
page.replace :foo, :partial => 'partial'
|
||||
end
|
||||
end
|
||||
|
||||
def render_implicit_html_template
|
||||
end
|
||||
|
||||
def render_js_with_explicit_template
|
||||
@project_id = 4
|
||||
render :template => 'test/delete_with_js'
|
||||
end
|
||||
|
||||
def render_js_with_explicit_action_template
|
||||
@project_id = 4
|
||||
render :action => 'delete_with_js'
|
||||
end
|
||||
|
||||
def delete_with_js
|
||||
@project_id = 4
|
||||
end
|
||||
|
||||
def update_page
|
||||
render :update do |page|
|
||||
page.replace_html 'balance', '$37,000,000.00'
|
||||
page.visual_effect :highlight, 'balance'
|
||||
end
|
||||
end
|
||||
|
||||
def update_page_with_instance_variables
|
||||
@money = '$37,000,000.00'
|
||||
@div_id = 'balance'
|
||||
render :update do |page|
|
||||
page.replace_html @div_id, @money
|
||||
page.visual_effect :highlight, @div_id
|
||||
end
|
||||
end
|
||||
|
||||
def update_page_with_view_method
|
||||
render :update do |page|
|
||||
page.replace_html 'person', pluralize(2, 'person')
|
||||
end
|
||||
end
|
||||
|
||||
def partial_as_rjs
|
||||
render :update do |page|
|
||||
page.replace :foo, :partial => 'partial'
|
||||
end
|
||||
end
|
||||
|
||||
def respond_to_partial_as_rjs
|
||||
respond_to do |format|
|
||||
format.js do
|
||||
render :update do |page|
|
||||
page.replace :foo, :partial => 'partial'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_alternate_default
|
||||
# For this test, the method "default_render" is overridden:
|
||||
@alternate_default_render = lambda do
|
||||
render :update do |page|
|
||||
page.replace :foo, :partial => 'partial'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def render_alternate_default
|
||||
# For this test, the method "default_render" is overridden:
|
||||
@alternate_default_render = lambda do
|
||||
render :update do |page|
|
||||
page.replace :foo, :partial => 'partial'
|
||||
|
||||
private
|
||||
def default_render
|
||||
if @alternate_default_render
|
||||
@alternate_default_render.call
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def determine_layout
|
||||
case action_name
|
||||
when "hello_world", "layout_test", "rendering_without_layout",
|
||||
"rendering_nothing_on_layout", "render_text_hello_world",
|
||||
"render_text_hello_world_with_layout",
|
||||
"hello_world_with_layout_false",
|
||||
"partial_only", "partial_only_with_layout",
|
||||
"accessing_params_in_template",
|
||||
"accessing_params_in_template_with_layout",
|
||||
"render_with_explicit_template",
|
||||
"render_with_explicit_string_template",
|
||||
"update_page", "update_page_with_instance_variables"
|
||||
|
||||
"layouts/standard"
|
||||
when "action_talk_to_layout", "layout_overriding_layout"
|
||||
"layouts/talk_from_action"
|
||||
when "render_implicit_html_template_from_xhr_request"
|
||||
(request.xhr? ? 'layouts/xhr' : 'layouts/standard')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def default_render
|
||||
if @alternate_default_render
|
||||
@alternate_default_render.call
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def determine_layout
|
||||
case action_name
|
||||
when "hello_world", "layout_test", "rendering_without_layout",
|
||||
"rendering_nothing_on_layout", "render_text_hello_world",
|
||||
"render_text_hello_world_with_layout",
|
||||
"hello_world_with_layout_false",
|
||||
"partial_only", "partial_only_with_layout",
|
||||
"accessing_params_in_template",
|
||||
"accessing_params_in_template_with_layout",
|
||||
"render_with_explicit_template",
|
||||
"render_with_explicit_string_template",
|
||||
"update_page", "update_page_with_instance_variables"
|
||||
|
||||
"layouts/standard"
|
||||
when "action_talk_to_layout", "layout_overriding_layout"
|
||||
"layouts/talk_from_action"
|
||||
when "render_implicit_html_template_from_xhr_request"
|
||||
(request.xhr? ? 'layouts/xhr' : 'layouts/standard')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class RenderTest < ActionController::TestCase
|
||||
tests TestController
|
||||
|
||||
def setup
|
||||
@@ -144,8 +149,8 @@ class RenderTest < ActionController::TestCase
|
||||
@controller.logger = Logger.new(nil)
|
||||
|
||||
@request.host = "www.nextangle.com"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_enum_rjs_test
|
||||
ActiveSupport::SecureRandom.stubs(:base64).returns("asdf")
|
||||
get :enum_rjs_test
|
||||
@@ -153,13 +158,13 @@ class RenderTest < ActionController::TestCase
|
||||
$$(".product").each(function(value, index) {
|
||||
new Effect.Highlight(element,{});
|
||||
new Effect.Highlight(value,{});
|
||||
Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}});
|
||||
Sortable.create(value, {onUpdate:function(){new Ajax.Request('/render_other_test/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}});
|
||||
new Draggable(value, {});
|
||||
});
|
||||
}.gsub(/^ /, '').strip
|
||||
assert_equal body, @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_explicitly_rendering_an_html_template_with_implicit_html_template_renders_should_be_possible_from_an_rjs_template
|
||||
[:js, "js"].each do |format|
|
||||
assert_nothing_raised do
|
||||
@@ -167,14 +172,14 @@ class RenderTest < ActionController::TestCase
|
||||
assert_equal %(document.write("Hello world\\n");), @response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_render_custom_code_rjs
|
||||
get :render_custom_code_rjs
|
||||
assert_response 404
|
||||
assert_equal %(Element.replace("foo", "partial html");), @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_render_in_an_rjs_template_should_pick_html_templates_when_available
|
||||
[:js, "js"].each do |format|
|
||||
assert_nothing_raised do
|
||||
@@ -183,7 +188,7 @@ class RenderTest < ActionController::TestCase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_render_rjs_template_explicitly
|
||||
get :render_js_with_explicit_template
|
||||
assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
|
||||
@@ -193,12 +198,12 @@ class RenderTest < ActionController::TestCase
|
||||
get :render_js_with_explicit_action_template
|
||||
assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_render_rjs_with_default
|
||||
get :delete_with_js
|
||||
assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_update_page
|
||||
get :update_page
|
||||
assert_template nil
|
||||
@@ -219,8 +224,8 @@ class RenderTest < ActionController::TestCase
|
||||
assert_template nil
|
||||
assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
|
||||
assert_match /2 people/, @response.body
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_should_render_html_formatted_partial_with_rjs
|
||||
xhr :get, :partial_as_rjs
|
||||
assert_equal %(Element.replace("foo", "partial html");), @response.body
|
||||
@@ -230,9 +235,9 @@ class RenderTest < ActionController::TestCase
|
||||
xhr :get, :respond_to_partial_as_rjs
|
||||
assert_equal %(Element.replace("foo", "partial html");), @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_should_render_with_alternate_default_render
|
||||
xhr :get, :render_alternate_default
|
||||
assert_equal %(Element.replace("foo", "partial html");), @response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,37 +2,41 @@ require 'abstract_unit'
|
||||
require 'controller/fake_models'
|
||||
require 'pathname'
|
||||
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
class RenderXmlTest < ActionController::TestCase
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
def render_with_location
|
||||
render :xml => "<hello/>", :location => "http://example.com", :status => 201
|
||||
def self.controller_path
|
||||
'test'
|
||||
end
|
||||
|
||||
def render_with_location
|
||||
render :xml => "<hello/>", :location => "http://example.com", :status => 201
|
||||
end
|
||||
|
||||
def render_with_object_location
|
||||
customer = Customer.new("Some guy", 1)
|
||||
render :xml => "<customer/>", :location => customer, :status => :created
|
||||
end
|
||||
|
||||
def render_with_to_xml
|
||||
to_xmlable = Class.new do
|
||||
def to_xml
|
||||
"<i-am-xml/>"
|
||||
end
|
||||
end.new
|
||||
|
||||
render :xml => to_xmlable
|
||||
end
|
||||
|
||||
def formatted_xml_erb
|
||||
end
|
||||
|
||||
def render_xml_with_custom_content_type
|
||||
render :xml => "<blah/>", :content_type => "application/atomsvc+xml"
|
||||
end
|
||||
end
|
||||
|
||||
def render_with_object_location
|
||||
customer = Customer.new("Some guy", 1)
|
||||
render :xml => "<customer/>", :location => customer, :status => :created
|
||||
end
|
||||
|
||||
def render_with_to_xml
|
||||
to_xmlable = Class.new do
|
||||
def to_xml
|
||||
"<i-am-xml/>"
|
||||
end
|
||||
end.new
|
||||
|
||||
render :xml => to_xmlable
|
||||
end
|
||||
|
||||
def formatted_xml_erb
|
||||
end
|
||||
|
||||
def render_xml_with_custom_content_type
|
||||
render :xml => "<blah/>", :content_type => "application/atomsvc+xml"
|
||||
end
|
||||
end
|
||||
|
||||
class RenderTest < ActionController::TestCase
|
||||
tests TestController
|
||||
|
||||
def setup
|
||||
@@ -42,8 +46,8 @@ class RenderTest < ActionController::TestCase
|
||||
@controller.logger = Logger.new(nil)
|
||||
|
||||
@request.host = "www.nextangle.com"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_rendering_with_location_should_set_header
|
||||
get :render_with_location
|
||||
assert_equal "http://example.com", @response.headers["Location"]
|
||||
@@ -53,7 +57,7 @@ class RenderTest < ActionController::TestCase
|
||||
get :render_with_to_xml
|
||||
assert_equal "<i-am-xml/>", @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_rendering_with_object_location_should_set_header_with_url_for
|
||||
with_routing do |set|
|
||||
set.draw do |map|
|
||||
@@ -65,19 +69,19 @@ class RenderTest < ActionController::TestCase
|
||||
assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_should_render_formatted_xml_erb_template
|
||||
get :formatted_xml_erb, :format => :xml
|
||||
assert_equal '<test>passed formatted xml erb</test>', @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_should_render_xml_but_keep_custom_content_type
|
||||
get :render_xml_with_custom_content_type
|
||||
assert_equal "application/atomsvc+xml", @response.content_type
|
||||
end
|
||||
|
||||
|
||||
def test_should_use_implicit_content_type
|
||||
get :implicit_content_type, :format => 'atom'
|
||||
assert_equal Mime::ATOM, @response.content_type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -227,12 +227,6 @@ class ControllerInheritanceRescueControllerTest < ActionController::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
rescue_from ActionController::RoutingError do
|
||||
render :text => 'no way'
|
||||
end
|
||||
end
|
||||
|
||||
class RescueControllerTest < ActionController::TestCase
|
||||
def test_rescue_handler
|
||||
get :not_authorized
|
||||
@@ -332,23 +326,20 @@ class RescueTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
test 'rescue routing exceptions' do
|
||||
assert_equal 1, ApplicationController.rescue_handlers.length
|
||||
|
||||
begin
|
||||
with_test_routing do
|
||||
get '/no_way'
|
||||
assert_equal 'no way', response.body
|
||||
end
|
||||
ensure
|
||||
ActionController::Base.rescue_handlers.clear
|
||||
app = ActionDispatch::Rescue.new(ActionController::Routing::Routes) do
|
||||
rescue_from ActionController::RoutingError, lambda { |env| [200, {"Content-Type" => "text/html"}, "Gotcha!"] }
|
||||
end
|
||||
@integration_session = open_session(app)
|
||||
|
||||
get '/b00m'
|
||||
assert_equal "Gotcha!", response.body
|
||||
end
|
||||
|
||||
test 'unrescued exception' do
|
||||
with_test_routing do
|
||||
get '/b00m'
|
||||
assert_match(/Action Controller: Exception caught/, response.body)
|
||||
end
|
||||
app = ActionDispatch::Rescue.new(ActionController::Routing::Routes)
|
||||
@integration_session = open_session(app)
|
||||
|
||||
assert_raise(ActionController::RoutingError) { get '/b00m' }
|
||||
end
|
||||
|
||||
private
|
||||
@@ -359,6 +350,7 @@ class RescueTest < ActionController::IntegrationTest
|
||||
map.connect 'invalid', :controller => "rescue_test/test", :action => 'invalid'
|
||||
map.connect 'b00m', :controller => "rescue_test/test", :action => 'b00m'
|
||||
end
|
||||
reset!
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
@@ -135,7 +135,7 @@ class ResourcesTest < ActionController::TestCase
|
||||
|
||||
def test_with_custom_conditions
|
||||
with_restful_routing :messages, :conditions => { :subdomain => 'app' } do
|
||||
assert_equal 'app', ActionController::Routing::Routes.named_routes.routes[:messages].conditions[:subdomain]
|
||||
assert ActionController::Routing::Routes.recognize_path("/messages", :method => :get, :subdomain => 'app')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1130,7 +1130,8 @@ class ResourcesTest < ActionController::TestCase
|
||||
map.resource :product
|
||||
end
|
||||
|
||||
assert_equal :get, set.named_routes.routes[:product].conditions[:method]
|
||||
assert_routing '/product', :controller => 'products', :action => 'show'
|
||||
assert set.recognize_path("/product", :method => :get)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -232,14 +232,18 @@ class LegacyRouteSetTests < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_basic_named_route
|
||||
rs.add_named_route :home, '', :controller => 'content', :action => 'list'
|
||||
rs.draw do |map|
|
||||
map.home '', :controller => 'content', :action => 'list'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
assert_equal("http://test.host/",
|
||||
x.send(:home_url))
|
||||
end
|
||||
|
||||
def test_basic_named_route_with_relative_url_root
|
||||
rs.add_named_route :home, '', :controller => 'content', :action => 'list'
|
||||
rs.draw do |map|
|
||||
map.home '', :controller => 'content', :action => 'list'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
ActionController::Base.relative_url_root = "/foo"
|
||||
assert_equal("http://test.host/foo/",
|
||||
@@ -249,14 +253,18 @@ class LegacyRouteSetTests < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_named_route_with_option
|
||||
rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page'
|
||||
rs.draw do |map|
|
||||
map.page 'page/:title', :controller => 'content', :action => 'show_page'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
assert_equal("http://test.host/page/new%20stuff",
|
||||
x.send(:page_url, :title => 'new stuff'))
|
||||
end
|
||||
|
||||
def test_named_route_with_default
|
||||
rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage'
|
||||
rs.draw do |map|
|
||||
map.page 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
assert_equal("http://test.host/page/AboutRails",
|
||||
x.send(:page_url, :title => "AboutRails"))
|
||||
@@ -264,36 +272,46 @@ class LegacyRouteSetTests < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_named_route_with_name_prefix
|
||||
rs.add_named_route :page, 'page', :controller => 'content', :action => 'show_page', :name_prefix => 'my_'
|
||||
rs.draw do |map|
|
||||
map.page 'page', :controller => 'content', :action => 'show_page', :name_prefix => 'my_'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
assert_equal("http://test.host/page",
|
||||
x.send(:my_page_url))
|
||||
end
|
||||
|
||||
def test_named_route_with_path_prefix
|
||||
rs.add_named_route :page, 'page', :controller => 'content', :action => 'show_page', :path_prefix => 'my'
|
||||
rs.draw do |map|
|
||||
map.page 'page', :controller => 'content', :action => 'show_page', :path_prefix => 'my'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
assert_equal("http://test.host/my/page",
|
||||
x.send(:page_url))
|
||||
end
|
||||
|
||||
def test_named_route_with_blank_path_prefix
|
||||
rs.add_named_route :page, 'page', :controller => 'content', :action => 'show_page', :path_prefix => ''
|
||||
rs.draw do |map|
|
||||
map.page 'page', :controller => 'content', :action => 'show_page', :path_prefix => ''
|
||||
end
|
||||
x = setup_for_named_route
|
||||
assert_equal("http://test.host/page",
|
||||
x.send(:page_url))
|
||||
end
|
||||
|
||||
def test_named_route_with_nested_controller
|
||||
rs.add_named_route :users, 'admin/user', :controller => 'admin/user', :action => 'index'
|
||||
rs.draw do |map|
|
||||
map.users 'admin/user', :controller => 'admin/user', :action => 'index'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
assert_equal("http://test.host/admin/user",
|
||||
x.send(:users_url))
|
||||
end
|
||||
|
||||
def test_optimised_named_route_call_never_uses_url_for
|
||||
rs.add_named_route :users, 'admin/user', :controller => '/admin/user', :action => 'index'
|
||||
rs.add_named_route :user, 'admin/user/:id', :controller=>'/admin/user', :action=>'show'
|
||||
rs.draw do |map|
|
||||
map.users 'admin/user', :controller => '/admin/user', :action => 'index'
|
||||
map.user 'admin/user/:id', :controller=>'/admin/user', :action=>'show'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
x.expects(:url_for).never
|
||||
x.send(:users_url)
|
||||
@@ -303,7 +321,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_optimised_named_route_with_host
|
||||
rs.add_named_route :pages, 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com'
|
||||
rs.draw do |map|
|
||||
map.pages 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com'
|
||||
end
|
||||
x = setup_for_named_route
|
||||
x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once
|
||||
x.send(:pages_url)
|
||||
@@ -378,7 +398,9 @@ class LegacyRouteSetTests < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_paths_slashes_unescaped_with_ordered_parameters
|
||||
rs.add_named_route :path, '/file/*path', :controller => 'content'
|
||||
rs.draw do |map|
|
||||
map.path '/file/*path', :controller => 'content'
|
||||
end
|
||||
|
||||
# No / to %2F in URI, only for query params.
|
||||
x = setup_for_named_route
|
||||
@@ -1781,23 +1803,23 @@ class RouteSetTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
def test_default_route_recognition
|
||||
expected = {:controller => 'accounts', :action => 'show', :id => '10'}
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show/10')
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show/10/')
|
||||
expected = {:controller => 'pages', :action => 'show', :id => '10'}
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show/10')
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show/10/')
|
||||
|
||||
expected[:id] = 'jamis'
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show/jamis/')
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show/jamis/')
|
||||
|
||||
expected.delete :id
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show')
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show/')
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show')
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show/')
|
||||
|
||||
expected[:action] = 'index'
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/')
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts')
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/')
|
||||
assert_equal expected, default_route_set.recognize_path('/pages')
|
||||
|
||||
assert_raise(ActionController::RoutingError) { default_route_set.recognize_path('/') }
|
||||
assert_raise(ActionController::RoutingError) { default_route_set.recognize_path('/accounts/how/goood/it/is/to/be/free') }
|
||||
assert_raise(ActionController::RoutingError) { default_route_set.recognize_path('/pages/how/goood/it/is/to/be/free') }
|
||||
end
|
||||
|
||||
def test_default_route_should_omit_default_action
|
||||
@@ -1813,15 +1835,15 @@ class RouteSetTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
def test_default_route_should_uri_escape_pluses
|
||||
expected = { :controller => 'accounts', :action => 'show', :id => 'hello world' }
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show/hello world')
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show/hello%20world')
|
||||
assert_equal '/accounts/show/hello%20world', default_route_set.generate(expected, expected)
|
||||
expected = { :controller => 'pages', :action => 'show', :id => 'hello world' }
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show/hello world')
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show/hello%20world')
|
||||
assert_equal '/pages/show/hello%20world', default_route_set.generate(expected, expected)
|
||||
|
||||
expected[:id] = 'hello+world'
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show/hello+world')
|
||||
assert_equal expected, default_route_set.recognize_path('/accounts/show/hello%2Bworld')
|
||||
assert_equal '/accounts/show/hello+world', default_route_set.generate(expected, expected)
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show/hello+world')
|
||||
assert_equal expected, default_route_set.recognize_path('/pages/show/hello%2Bworld')
|
||||
assert_equal '/pages/show/hello+world', default_route_set.generate(expected, expected)
|
||||
end
|
||||
|
||||
def test_parameter_shell
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'abstract_unit'
|
||||
require 'controller/fake_controllers'
|
||||
|
||||
ActionController::UrlRewriter
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class ViewLoadPathsTest < ActionController::TestCase
|
||||
end
|
||||
|
||||
def expand(array)
|
||||
array.map {|x| File.expand_path(x)}
|
||||
array.map {|x| File.expand_path(x.to_s)}
|
||||
end
|
||||
|
||||
def assert_paths(*paths)
|
||||
|
||||
@@ -30,7 +30,7 @@ class CookieStoreTest < ActionController::IntegrationTest
|
||||
end
|
||||
|
||||
def get_session_id
|
||||
render :text => "foo: #{session[:foo].inspect}; id: #{request.session_options[:id]}"
|
||||
render :text => "id: #{request.session_options[:id]}"
|
||||
end
|
||||
|
||||
def call_reset_session
|
||||
@@ -119,7 +119,7 @@ class CookieStoreTest < ActionController::IntegrationTest
|
||||
|
||||
get '/get_session_id'
|
||||
assert_response :success
|
||||
assert_equal "foo: \"bar\"; id: #{session_id}", response.body
|
||||
assert_equal "id: #{session_id}", response.body
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -70,8 +70,7 @@ class ShowExceptionsTest < ActionController::IntegrationTest
|
||||
|
||||
test "localize public rescue message" do
|
||||
# Change locale
|
||||
old_locale = I18n.locale
|
||||
I18n.locale = :da
|
||||
old_locale, I18n.locale = I18n.locale, :da
|
||||
|
||||
begin
|
||||
@integration_session = open_session(ProductionApp)
|
||||
|
||||
@@ -5,7 +5,7 @@ class TestRequestTest < ActiveSupport::TestCase
|
||||
env = ActionDispatch::TestRequest.new.env
|
||||
|
||||
assert_equal "GET", env.delete("REQUEST_METHOD")
|
||||
assert_equal "off", env.delete("HTTPS")
|
||||
assert_equal nil, env.delete("HTTPS")
|
||||
assert_equal "http", env.delete("rack.url_scheme")
|
||||
assert_equal "example.org", env.delete("SERVER_NAME")
|
||||
assert_equal "80", env.delete("SERVER_PORT")
|
||||
@@ -18,7 +18,7 @@ class TestRequestTest < ActiveSupport::TestCase
|
||||
assert_equal "0.0.0.0", env.delete("REMOTE_ADDR")
|
||||
assert_equal "Rails Testing", env.delete("HTTP_USER_AGENT")
|
||||
|
||||
assert_equal [1, 0], env.delete("rack.version")
|
||||
assert_equal [0, 1], env.delete("rack.version")
|
||||
assert_equal "", env.delete("rack.input").string
|
||||
assert_kind_of StringIO, env.delete("rack.errors")
|
||||
assert_equal true, env.delete("rack.multithread")
|
||||
|
||||
@@ -9,7 +9,15 @@ module Admin
|
||||
class UserController < ActionController::Base; end
|
||||
class NewsFeedController < ActionController::Base; end
|
||||
end
|
||||
|
||||
class ElsewhereController < ActionController::Base; end
|
||||
class AddressesController < ActionController::Base; end
|
||||
class SessionsController < ActionController::Base; end
|
||||
class FooController < ActionController::Base; end
|
||||
class CController < ActionController::Base; end
|
||||
class HiController < ActionController::Base; end
|
||||
class BraveController < ActionController::Base; end
|
||||
class ImageController < ActionController::Base; end
|
||||
class WeblogController < ActionController::Base; end
|
||||
|
||||
# For speed test
|
||||
class SpeedController < ActionController::Base; end
|
||||
@@ -24,7 +32,6 @@ class UsersController < SpeedController; end
|
||||
class SettingsController < SpeedController; end
|
||||
class ChannelsController < SpeedController; end
|
||||
class ChannelVideosController < SpeedController; end
|
||||
class SessionsController < SpeedController; end
|
||||
class LostPasswordsController < SpeedController; end
|
||||
class PagesController < SpeedController; end
|
||||
|
||||
|
||||
@@ -1,67 +1,24 @@
|
||||
module ActionView #:nodoc:
|
||||
class FixtureResolver < Resolver
|
||||
class FixtureResolver < PathResolver
|
||||
def initialize(hash = {}, options = {})
|
||||
super(options)
|
||||
@hash = hash
|
||||
end
|
||||
|
||||
def find_templates(name, details, prefix, partial)
|
||||
if regexp = details_to_regexp(name, details, prefix, partial)
|
||||
cached(regexp) do
|
||||
templates = []
|
||||
@hash.select { |k,v| k =~ regexp }.each do |path, source|
|
||||
templates << Template.new(source, path, *path_to_details(path))
|
||||
end
|
||||
templates.sort_by {|t| -t.details.values.compact.size }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def formats_regexp
|
||||
@formats_regexp ||= begin
|
||||
formats = Mime::SET.symbols
|
||||
'(?:' + formats.map { |l| "\\.#{Regexp.escape(l.to_s)}" }.join('|') + ')?'
|
||||
end
|
||||
end
|
||||
|
||||
def handler_regexp
|
||||
e = TemplateHandlers.extensions.map{|h| "\\.#{Regexp.escape(h.to_s)}"}.join("|")
|
||||
"(?:#{e})"
|
||||
end
|
||||
|
||||
def details_to_regexp(name, details, prefix, partial)
|
||||
path = ""
|
||||
path << "#{prefix}/" unless prefix.empty?
|
||||
path << (partial ? "_#{name}" : name)
|
||||
|
||||
extensions = ""
|
||||
[:locales, :formats].each do |k|
|
||||
extensions << if exts = details[k]
|
||||
'(?:' + exts.map {|e| "\\.#{Regexp.escape(e.to_s)}"}.join('|') + ')?'
|
||||
else
|
||||
k == :formats ? formats_regexp : ''
|
||||
end
|
||||
def query(path, exts)
|
||||
query = Regexp.escape(path)
|
||||
exts.each do |ext|
|
||||
query << '(?:' << ext.map {|e| e && Regexp.escape(".#{e}") }.join('|') << ')'
|
||||
end
|
||||
|
||||
%r'^#{Regexp.escape(path)}#{extensions}#{handler_regexp}$'
|
||||
end
|
||||
|
||||
# TODO: fix me
|
||||
# :api: plugin
|
||||
def path_to_details(path)
|
||||
# [:erb, :format => :html, :locale => :en, :partial => true/false]
|
||||
if m = path.match(%r'(_)?[\w-]+((?:\.[\w-]+)*)\.(\w+)$')
|
||||
partial = m[1] == '_'
|
||||
details = (m[2]||"").split('.').reject { |e| e.empty? }
|
||||
handler = Template.handler_class_for_extension(m[3])
|
||||
|
||||
format = Mime[details.last] && details.pop.to_sym
|
||||
locale = details.last && details.pop.to_sym
|
||||
|
||||
return handler, :format => format, :locale => locale, :partial => partial
|
||||
templates = []
|
||||
@hash.select { |k,v| k =~ /^#{query}$/ }.each do |path, source|
|
||||
templates << Template.new(source, path, *path_to_details(path))
|
||||
end
|
||||
templates.sort_by {|t| -t.details.values.compact.size }
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
# Tests the controller dispatching happy path
|
||||
module Dispatching
|
||||
@@ -65,4 +65,4 @@ module Dispatching
|
||||
assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
18
actionpack/test/new_base/content_negotiation_test.rb
Normal file
18
actionpack/test/new_base/content_negotiation_test.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
require 'abstract_unit'
|
||||
|
||||
module ContentNegotiation
|
||||
|
||||
# This has no layout and it works
|
||||
class BasicController < ActionController::Base
|
||||
self.view_paths = [ActionView::FixtureResolver.new(
|
||||
"content_negotiation/basic/hello.html.erb" => "Hello world <%= request.formats %>!"
|
||||
)]
|
||||
end
|
||||
|
||||
class TestContentNegotiation < SimpleRouteCase
|
||||
test "A */* Accept header will return HTML" do
|
||||
get "/content_negotiation/basic/hello", {}, "HTTP_ACCEPT" => "*/*"
|
||||
assert_body "Hello world */*!"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module ContentType
|
||||
class BaseController < ActionController::Base
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module Etags
|
||||
class BasicController < ActionController::Base
|
||||
@@ -43,4 +43,4 @@ module Etags
|
||||
%("#{Digest::MD5.hexdigest(text)}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module MetalTest
|
||||
class MetalMiddleware < ActionController::Middleware
|
||||
@@ -41,4 +41,3 @@ module MetalTest
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
77
actionpack/test/new_base/middleware_test.rb
Normal file
77
actionpack/test/new_base/middleware_test.rb
Normal file
@@ -0,0 +1,77 @@
|
||||
require 'abstract_unit'
|
||||
|
||||
module MiddlewareTest
|
||||
class MyMiddleware
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
result = @app.call(env)
|
||||
result[1]["Middleware-Test"] = "Success"
|
||||
result[1]["Middleware-Order"] = "First"
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
class ExclaimerMiddleware
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
result = @app.call(env)
|
||||
result[1]["Middleware-Order"] << "!"
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
class MyController < ActionController::Metal
|
||||
use MyMiddleware
|
||||
|
||||
middleware.insert_before MyMiddleware, ExclaimerMiddleware
|
||||
|
||||
def index
|
||||
self.response_body = "Hello World"
|
||||
end
|
||||
end
|
||||
|
||||
class InheritedController < MyController
|
||||
end
|
||||
|
||||
module MiddlewareTests
|
||||
extend ActiveSupport::Testing::Declarative
|
||||
|
||||
test "middleware that is 'use'd is called as part of the Rack application" do
|
||||
result = @app.call(env_for("/"))
|
||||
assert_equal "Hello World", result[2]
|
||||
assert_equal "Success", result[1]["Middleware-Test"]
|
||||
end
|
||||
|
||||
test "the middleware stack is exposed as 'middleware' in the controller" do
|
||||
result = @app.call(env_for("/"))
|
||||
assert_equal "First!", result[1]["Middleware-Order"]
|
||||
end
|
||||
end
|
||||
|
||||
class TestMiddleware < ActiveSupport::TestCase
|
||||
include MiddlewareTests
|
||||
|
||||
def setup
|
||||
@app = MyController.action(:index)
|
||||
end
|
||||
|
||||
def env_for(url)
|
||||
Rack::MockRequest.env_for(url)
|
||||
end
|
||||
end
|
||||
|
||||
class TestInheritedMiddleware < TestMiddleware
|
||||
def setup
|
||||
@app = InheritedController.action(:index)
|
||||
end
|
||||
|
||||
test "middleware inherits" do
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1 +0,0 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module RenderAction
|
||||
# This has no layout and it works
|
||||
@@ -317,4 +317,4 @@ module RenderActionWithBothLayouts
|
||||
assert_status 200
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module RenderFile
|
||||
|
||||
class BasicController < ActionController::Base
|
||||
self.view_paths = "."
|
||||
self.view_paths = File.dirname(__FILE__)
|
||||
|
||||
def index
|
||||
render :file => File.join(File.dirname(__FILE__), *%w[.. fixtures test hello_world])
|
||||
@@ -107,4 +107,4 @@ module RenderFile
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module RenderImplicitAction
|
||||
class SimpleController < ::ApplicationController
|
||||
@@ -25,4 +25,4 @@ module RenderImplicitAction
|
||||
assert_status 200
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module ControllerLayouts
|
||||
class ImplicitController < ::ApplicationController
|
||||
@@ -98,4 +98,4 @@ module ControllerLayouts
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
|
||||
require 'abstract_unit'
|
||||
|
||||
module RenderPartial
|
||||
|
||||
@@ -24,4 +24,4 @@ module RenderPartial
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user