aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/Rakefile14
-rw-r--r--actionpack/lib/action_controller/abstract.rb2
-rw-r--r--actionpack/lib/action_controller/abstract/base.rb73
-rw-r--r--actionpack/lib/action_controller/abstract/callbacks.rb10
-rw-r--r--actionpack/lib/action_controller/abstract/exceptions.rb2
-rw-r--r--actionpack/lib/action_controller/abstract/helpers.rb20
-rw-r--r--actionpack/lib/action_controller/abstract/layouts.rb28
-rw-r--r--actionpack/lib/action_controller/abstract/logger.rb2
-rw-r--r--actionpack/lib/action_controller/abstract/renderer.rb37
-rw-r--r--actionpack/lib/action_controller/base/base.rb29
-rw-r--r--actionpack/lib/action_controller/dispatch/dispatcher.rb2
-rw-r--r--actionpack/lib/action_controller/dispatch/middlewares.rb2
-rw-r--r--actionpack/lib/action_controller/new_base.rb30
-rw-r--r--actionpack/lib/action_controller/new_base/base.rb103
-rw-r--r--actionpack/lib/action_controller/new_base/compatibility.rb58
-rw-r--r--actionpack/lib/action_controller/new_base/conditional_get.rb131
-rw-r--r--actionpack/lib/action_controller/new_base/hide_actions.rb13
-rw-r--r--actionpack/lib/action_controller/new_base/http.rb64
-rw-r--r--actionpack/lib/action_controller/new_base/layouts.rb16
-rw-r--r--actionpack/lib/action_controller/new_base/renderer.rb52
-rw-r--r--actionpack/lib/action_controller/new_base/testing.rb25
-rw-r--r--actionpack/lib/action_controller/new_base/url_for.rb6
-rw-r--r--actionpack/lib/action_controller/routing/route_set.rb2
-rw-r--r--actionpack/lib/action_controller/testing/integration.rb15
-rw-r--r--actionpack/lib/action_controller/testing/process.rb5
-rw-r--r--actionpack/lib/action_controller/testing/process2.rb69
-rw-r--r--actionpack/lib/action_dispatch/middleware/show_exceptions.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb2
-rw-r--r--actionpack/lib/action_view/paths.rb2
-rw-r--r--actionpack/lib/action_view/template/text.rb7
-rw-r--r--actionpack/test/abstract_controller/abstract_controller_test.rb48
-rw-r--r--actionpack/test/abstract_controller/callbacks_test.rb18
-rw-r--r--actionpack/test/abstract_controller/helper_test.rb6
-rw-r--r--actionpack/test/abstract_controller/layouts_test.rb24
-rw-r--r--actionpack/test/abstract_controller/test_helper.rb16
-rw-r--r--actionpack/test/abstract_unit2.rb133
-rw-r--r--actionpack/test/controller/content_type_test.rb10
-rw-r--r--actionpack/test/controller/filters_test.rb3
-rw-r--r--actionpack/test/controller/helper_test.rb44
-rw-r--r--actionpack/test/controller/render_test.rb74
-rw-r--r--actionpack/test/lib/fixture_template.rb115
-rw-r--r--actionpack/test/new_base/base_test.rb51
-rw-r--r--actionpack/test/new_base/content_type_test.rb111
-rw-r--r--actionpack/test/new_base/etag_test.rb47
-rw-r--r--actionpack/test/new_base/render_action_test.rb14
-rw-r--r--actionpack/test/new_base/render_implicit_action_test.rb30
-rw-r--r--actionpack/test/new_base/render_layout_test.rb22
-rw-r--r--actionpack/test/new_base/render_template_test.rb92
-rw-r--r--actionpack/test/new_base/render_test.rb88
-rw-r--r--actionpack/test/new_base/render_text_test.rb79
-rw-r--r--actionpack/test/new_base/test_helper.rb43
-rw-r--r--actionpack/test/template/output_buffer_test.rb44
-rw-r--r--activerecord/lib/active_record/aggregations.rb4
-rw-r--r--activerecord/lib/active_record/association_preload.rb8
-rwxr-xr-xactiverecord/lib/active_record/associations.rb36
-rw-r--r--activerecord/lib/active_record/associations/has_one_association.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb22
-rw-r--r--activerecord/lib/active_record/autosave_association.rb13
-rw-r--r--activerecord/lib/active_record/batches.rb4
-rw-r--r--activerecord/lib/active_record/calculations.rb5
-rw-r--r--activerecord/lib/active_record/callbacks.rb12
-rw-r--r--activerecord/lib/active_record/dirty.rb21
-rw-r--r--activerecord/lib/active_record/fixtures.rb38
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb16
-rw-r--r--activerecord/lib/active_record/named_scope.rb9
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb20
-rw-r--r--activerecord/lib/active_record/observer.rb4
-rw-r--r--activerecord/lib/active_record/reflection.rb4
-rw-r--r--activerecord/lib/active_record/serializers/json_serializer.rb7
-rw-r--r--activerecord/lib/active_record/timestamp.rb12
-rw-r--r--activerecord/lib/active_record/transactions.rb12
-rw-r--r--activerecord/lib/active_record/validations.rb15
-rw-r--r--activerecord/test/cases/associations/eager_load_nested_include_test.rb13
-rw-r--r--activerecord/test/cases/associations/eager_test.rb12
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb9
-rw-r--r--activerecord/test/cases/associations/inverse_associations_test.rb61
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb18
-rw-r--r--activerecord/test/cases/repair_helper.rb6
-rw-r--r--activerecord/test/fixtures/organizations.yml4
-rw-r--r--activerecord/test/fixtures/sponsors.yml4
-rw-r--r--activerecord/test/models/organization.rb4
-rw-r--r--activerecord/test/models/pirate.rb2
-rw-r--r--activerecord/test/schema/schema.rb4
-rw-r--r--activeresource/Rakefile3
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/conversions.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/time/conversions.rb2
-rw-r--r--activesupport/lib/active_support/dependency_module.rb7
-rw-r--r--activesupport/lib/active_support/new_callbacks.rb12
-rw-r--r--activesupport/lib/active_support/ordered_hash.rb14
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb4
-rw-r--r--activesupport/test/new_callbacks_test.rb40
-rw-r--r--activesupport/test/ordered_hash_test.rb10
-rw-r--r--railties/CHANGELOG5
-rw-r--r--railties/Rakefile3
-rw-r--r--railties/configs/seeds.rb7
-rw-r--r--railties/lib/rails_generator/generators/applications/app/app_generator.rb5
-rw-r--r--railties/lib/tasks/databases.rake13
99 files changed, 1819 insertions, 654 deletions
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 300c2ebf81..ef76eedfd7 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -4,7 +4,6 @@ require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
-require 'rake/contrib/sshpublisher'
require File.join(File.dirname(__FILE__), 'lib', 'action_pack', 'version')
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
@@ -23,14 +22,14 @@ task :default => [ :test ]
# Run the unit tests
desc "Run all unit tests"
-task :test => [:test_action_pack, :test_active_record_integration]
+task :test => [:test_action_pack, :test_active_record_integration, :test_new_base]
Rake::TestTask.new(:test_action_pack) do |t|
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/[cdft]*/**/*_test.rb" ).sort
+ t.test_files = Dir.glob( "test/{controller,dispatch,template}/**/*_test.rb" ).sort
t.verbose = true
#t.warning = true
@@ -43,6 +42,13 @@ Rake::TestTask.new(:test_active_record_integration) do |t|
t.verbose = true
end
+desc 'New Controller Tests'
+Rake::TestTask.new(:test_new_base) do |t|
+ t.libs << "test"
+ t.test_files = Dir.glob("test/{abstract_controller,new_base}/*_test.rb")
+ t.verbose = true
+end
+
# Genereate the RDoc documentation
@@ -136,12 +142,14 @@ task :update_js => [ :update_scriptaculous ]
desc "Publish the API documentation"
task :pgem => [:package] do
+ require 'rake/contrib/sshpublisher'
Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
`ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
+ require 'rake/contrib/sshpublisher'
Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/ap", "doc").upload
end
diff --git a/actionpack/lib/action_controller/abstract.rb b/actionpack/lib/action_controller/abstract.rb
index 9442d4559f..3f5c4a185f 100644
--- a/actionpack/lib/action_controller/abstract.rb
+++ b/actionpack/lib/action_controller/abstract.rb
@@ -7,4 +7,4 @@ module AbstractController
autoload :Renderer, "action_controller/abstract/renderer"
# === Exceptions
autoload :ActionNotFound, "action_controller/abstract/exceptions"
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb
index 39e9ad0440..ab9aed0b26 100644
--- a/actionpack/lib/action_controller/abstract/base.rb
+++ b/actionpack/lib/action_controller/abstract/base.rb
@@ -1,38 +1,85 @@
module AbstractController
class Base
+
attr_internal :response_body
attr_internal :response_obj
attr_internal :action_name
- def self.process(action)
- new.process(action)
- end
+ class << self
+ attr_reader :abstract
+
+ def abstract!
+ @abstract = true
+ end
+
+ alias_method :abstract?, :abstract
+
+ def internal_methods
+ controller = self
+ controller = controller.superclass until controller.abstract?
+ controller.public_instance_methods(true)
+ end
+
+ def process(action)
+ new.process(action.to_s)
+ end
- def self.inherited(klass)
+ def hidden_actions
+ []
+ end
+
+ def action_methods
+ @action_methods ||=
+ # All public instance methods of this class, including ancestors
+ public_instance_methods(true).map { |m| m.to_s }.to_set -
+ # Except for public instance methods of Base and its ancestors
+ internal_methods.map { |m| m.to_s } +
+ # Be sure to include shadowed public instance methods of this class
+ public_instance_methods(false).map { |m| m.to_s } -
+ # And always exclude explicitly hidden actions
+ hidden_actions
+ end
end
-
+
+ abstract!
+
def initialize
self.response_obj = {}
end
-
+
def process(action_name)
unless respond_to_action?(action_name)
raise ActionNotFound, "The action '#{action_name}' could not be found"
end
-
+
@_action_name = action_name
process_action
- self.response_obj[:body] = self.response_body
self
end
-
+
private
+
+ def action_methods
+ self.class.action_methods
+ end
+
+ # It is possible for respond_to?(action_name) to be false and
+ # respond_to?(:action_missing) to be false if respond_to_action?
+ # is overridden in a subclass. For instance, ActionController::Base
+ # overrides it to include the case where a template matching the
+ # action_name is found.
def process_action
- respond_to?(action_name) ? send(action_name) : send(:action_missing, action_name)
+ if respond_to?(action_name) then send(action_name)
+ elsif respond_to?(:action_missing, true) then action_missing(action_name)
+ end
end
-
+
+ # Override this to change the conditions that will raise an
+ # ActionNotFound error. If you accept a difference case,
+ # you must handle it by also overriding process_action and
+ # handling the case.
def respond_to_action?(action_name)
- respond_to?(action_name) || respond_to?(:action_missing, true)
+ action_methods.include?(action_name) || respond_to?(:action_missing, true)
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/callbacks.rb b/actionpack/lib/action_controller/abstract/callbacks.rb
index cb8aade0be..6e15b3e81b 100644
--- a/actionpack/lib/action_controller/abstract/callbacks.rb
+++ b/actionpack/lib/action_controller/abstract/callbacks.rb
@@ -13,19 +13,19 @@ module AbstractController
super
end
end
-
+
module ClassMethods
def _normalize_callback_options(options)
if only = options[:only]
- only = Array(only).map {|o| "action_name == :#{o}"}.join(" || ")
+ only = Array(only).map {|o| "action_name == '#{o}'"}.join(" || ")
options[:per_key] = {:if => only}
end
if except = options[:except]
- except = Array(except).map {|e| "action_name == :#{e}"}.join(" || ")
+ except = Array(except).map {|e| "action_name == '#{e}'"}.join(" || ")
options[:per_key] = {:unless => except}
end
end
-
+
[:before, :after, :around].each do |filter|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{filter}_filter(*names, &blk)
@@ -40,4 +40,4 @@ module AbstractController
end
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/exceptions.rb b/actionpack/lib/action_controller/abstract/exceptions.rb
index a7d07868bb..ec4680629b 100644
--- a/actionpack/lib/action_controller/abstract/exceptions.rb
+++ b/actionpack/lib/action_controller/abstract/exceptions.rb
@@ -1,3 +1,3 @@
module AbstractController
class ActionNotFound < StandardError ; end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/helpers.rb b/actionpack/lib/action_controller/abstract/helpers.rb
index 38e3ce8127..968d3080c1 100644
--- a/actionpack/lib/action_controller/abstract/helpers.rb
+++ b/actionpack/lib/action_controller/abstract/helpers.rb
@@ -9,13 +9,6 @@ module AbstractController
self.master_helper_module = Module.new
end
- # def self.included(klass)
- # klass.class_eval do
- # extlib_inheritable_accessor :master_helper_module
- # self.master_helper_module = Module.new
- # end
- # end
-
def _action_view
@_action_view ||= begin
av = super
@@ -23,19 +16,19 @@ module AbstractController
av
end
end
-
+
module ClassMethods
def inherited(klass)
klass.master_helper_module = Module.new
klass.master_helper_module.__send__ :include, master_helper_module
-
+
super
end
-
+
def add_template_helper(mod)
master_helper_module.module_eval { include mod }
end
-
+
def helper_method(*meths)
meths.flatten.each do |meth|
master_helper_module.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
@@ -45,7 +38,7 @@ module AbstractController
ruby_eval
end
end
-
+
def helper(*args, &blk)
args.flatten.each do |arg|
case arg
@@ -56,5 +49,6 @@ module AbstractController
master_helper_module.module_eval(&blk) if block_given?
end
end
+
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/layouts.rb b/actionpack/lib/action_controller/abstract/layouts.rb
index 69fe4efc19..e48b8b2b4b 100644
--- a/actionpack/lib/action_controller/abstract/layouts.rb
+++ b/actionpack/lib/action_controller/abstract/layouts.rb
@@ -9,18 +9,18 @@ module AbstractController
unless [String, Symbol, FalseClass, NilClass].include?(layout.class)
raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil"
end
-
+
@_layout = layout || false # Converts nil to false
_write_layout_method
end
-
+
def _implied_layout_name
name.underscore
end
-
+
# Takes the specified layout and creates a _layout method to be called
# by _default_layout
- #
+ #
# If the specified layout is a:
# String:: return the string
# Symbol:: call the method specified by the symbol
@@ -49,22 +49,26 @@ module AbstractController
end
end
end
-
+
def _render_template(template, options)
- _action_view._render_template_with_layout(template, options[:_layout])
+ _action_view._render_template_with_layout(template, options[:_layout], options)
end
-
+
private
+
def _layout() end # This will be overwritten
-
+
+ # :api: plugin
+ # ====
+ # Override this to mutate the inbound layout name
def _layout_for_name(name)
unless [String, FalseClass, NilClass].include?(name.class)
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
-
+
name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
end
-
+
def _default_layout(require_layout = false)
if require_layout && !_layout
raise ArgumentError,
@@ -74,9 +78,9 @@ module AbstractController
begin
layout = _layout_for_name(_layout)
rescue NameError => e
- raise NoMethodError,
+ raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
end
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/logger.rb b/actionpack/lib/action_controller/abstract/logger.rb
index c3bccd7778..5fb78f1755 100644
--- a/actionpack/lib/action_controller/abstract/logger.rb
+++ b/actionpack/lib/action_controller/abstract/logger.rb
@@ -6,4 +6,4 @@ module AbstractController
cattr_accessor :logger
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/abstract/renderer.rb b/actionpack/lib/action_controller/abstract/renderer.rb
index b5c31a27ee..b58688c9da 100644
--- a/actionpack/lib/action_controller/abstract/renderer.rb
+++ b/actionpack/lib/action_controller/abstract/renderer.rb
@@ -1,6 +1,15 @@
require "action_controller/abstract/logger"
module AbstractController
+ class AbstractControllerError < StandardError; end
+ class DoubleRenderError < AbstractControllerError
+ DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"."
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
module Renderer
extend ActiveSupport::DependencyModule
@@ -15,31 +24,36 @@ module AbstractController
end
def _action_view
- @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
+ @_action_view ||= ActionView::Base.new(self.class.view_paths, {}, self)
end
-
+
def render(options = {})
+ if response_body
+ raise AbstractController::DoubleRenderError, "OMG"
+ end
+
self.response_body = render_to_body(options)
end
-
+
# Raw rendering of a template to a Rack-compatible body.
# ====
# @option _prefix<String> The template's path prefix
# @option _layout<String> The relative path to the layout template to use
- #
+ #
# :api: plugin
def render_to_body(options = {})
name = options[:_template_name] || action_name
-
- template = options[:_template] || view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
- _render_template(template, options)
+
+ options[:_template] ||= view_paths.find_by_parts(name.to_s, {:formats => formats}, options[:_prefix])
+
+ _render_template(options[:_template], options)
end
# Raw rendering of a template to a string.
# ====
# @option _prefix<String> The template's path prefix
# @option _layout<String> The relative path to the layout template to use
- #
+ #
# :api: plugin
def render_to_string(options = {})
AbstractController::Renderer.body_to_s(render_to_body(options))
@@ -48,7 +62,7 @@ module AbstractController
def _render_template(template, options)
_action_view._render_template_with_layout(template)
end
-
+
def view_paths() _view_paths end
# Return a string representation of a Rack-compatible response body.
@@ -64,14 +78,15 @@ module AbstractController
end
module ClassMethods
+
def append_view_path(path)
self.view_paths << path
end
-
+
def view_paths
self._view_paths
end
-
+
def view_paths=(paths)
self._view_paths = paths.is_a?(ActionView::PathSet) ?
paths : ActionView::Base.process_view_paths(paths)
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index 7bbde519cc..d25801b17b 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -365,17 +365,23 @@ module ActionController #:nodoc:
attr_reader :template
- class << self
- def call(env)
- new.call(env)
- end
+ def action(name, env)
+ # HACK: For global rescue to have access to the original request and response
+ request = env["action_controller.rescue.request"] ||= ActionDispatch::Request.new(env)
+ response = env["action_controller.rescue.response"] ||= ActionDispatch::Response.new
+ self.action_name = name && name.to_s
+ process(request, response).to_a
+ end
- # Factory for the standard create, process loop where the controller is discarded after processing.
- def process(request, response) #:nodoc:
- ActiveSupport::Deprecation.warn("Controller.process has been deprecated. Use Controller.call instead", caller)
- new.process(request, response)
- end
+ class << self
+ def action(name = nil)
+ @actions ||= {}
+ @actions[name] ||= proc do |env|
+ new.action(name, env)
+ end
+ end
+
# Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".
def controller_class_name
@controller_class_name ||= name.demodulize
@@ -518,7 +524,6 @@ module ActionController #:nodoc:
assign_shortcuts(request, response)
initialize_template_class(response)
initialize_current_url
- assign_names
log_processing
send(method, *arguments)
@@ -882,10 +887,6 @@ module ActionController #:nodoc:
@performed_render || @performed_redirect
end
- def assign_names
- @action_name = (params['action'] || 'index')
- end
-
def reset_variables_added_to_assigns
@template.instance_variable_set("@assigns_added", nil)
end
diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb
index cce3b6175d..63866caed9 100644
--- a/actionpack/lib/action_controller/dispatch/dispatcher.rb
+++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb
@@ -48,7 +48,7 @@ module ActionController
cattr_accessor :middleware
self.middleware = ActionDispatch::MiddlewareStack.new do |middleware|
middlewares = File.join(File.dirname(__FILE__), "middlewares.rb")
- middleware.instance_eval(File.read(middlewares))
+ middleware.instance_eval(File.read(middlewares), middlewares, 1)
end
include ActiveSupport::Callbacks
diff --git a/actionpack/lib/action_controller/dispatch/middlewares.rb b/actionpack/lib/action_controller/dispatch/middlewares.rb
index 31a7b00d28..f99637b109 100644
--- a/actionpack/lib/action_controller/dispatch/middlewares.rb
+++ b/actionpack/lib/action_controller/dispatch/middlewares.rb
@@ -14,4 +14,4 @@ use lambda { ActionController::Base.session_store },
use "ActionDispatch::ParamsParser"
use "Rack::MethodOverride"
-use "Rack::Head"
+use "Rack::Head" \ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base.rb b/actionpack/lib/action_controller/new_base.rb
index 29dc3aaddc..8a7de1476c 100644
--- a/actionpack/lib/action_controller/new_base.rb
+++ b/actionpack/lib/action_controller/new_base.rb
@@ -1,7 +1,27 @@
module ActionController
- autoload :AbstractBase, "action_controller/new_base/base"
- autoload :HideActions, "action_controller/new_base/hide_actions"
- autoload :Layouts, "action_controller/new_base/layouts"
- autoload :Renderer, "action_controller/new_base/renderer"
- autoload :UrlFor, "action_controller/new_base/url_for"
+ autoload :Base, "action_controller/new_base/base"
+ autoload :ConditionalGet, "action_controller/new_base/conditional_get"
+ autoload :HideActions, "action_controller/new_base/hide_actions"
+ autoload :Http, "action_controller/new_base/http"
+ autoload :Layouts, "action_controller/new_base/layouts"
+ autoload :Rails2Compatibility, "action_controller/new_base/compatibility"
+ autoload :Renderer, "action_controller/new_base/renderer"
+ autoload :Testing, "action_controller/new_base/testing"
+ autoload :UrlFor, "action_controller/new_base/url_for"
+
+ # Ported modules
+ # require 'action_controller/routing'
+ autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
+ autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes'
+ autoload :RecordIdentifier, 'action_controller/record_identifier'
+ autoload :Resources, 'action_controller/routing/resources'
+ autoload :SessionManagement, 'action_controller/base/session_management'
+ autoload :TestCase, 'action_controller/testing/test_case'
+ autoload :UrlRewriter, 'action_controller/routing/generation/url_rewriter'
+ autoload :UrlWriter, 'action_controller/routing/generation/url_rewriter'
+
+ require 'action_controller/routing'
end
+
+require 'action_dispatch'
+require 'action_view' \ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb
index 2dd5390c99..4892886341 100644
--- a/actionpack/lib/action_controller/new_base/base.rb
+++ b/actionpack/lib/action_controller/new_base/base.rb
@@ -1,59 +1,62 @@
module ActionController
- class AbstractBase < AbstractController::Base
- # :api: public
- attr_internal :request, :response, :params
-
- # :api: public
- def self.controller_name
- @controller_name ||= controller_path.split("/").last
+ class Base < Http
+ abstract!
+
+ include AbstractController::Callbacks
+ include AbstractController::Helpers
+ include AbstractController::Logger
+
+ include ActionController::HideActions
+ include ActionController::UrlFor
+ include ActionController::Renderer
+ include ActionController::Layouts
+ include ActionController::ConditionalGet
+
+ # Legacy modules
+ include SessionManagement
+ include ActionDispatch::StatusCodes
+
+ # Rails 2.x compatibility
+ include ActionController::Rails2Compatibility
+
+ def self.inherited(klass)
+ ::ActionController::Base.subclasses << klass.to_s
+ super
end
-
- # :api: public
- def controller_name() self.class.controller_name end
-
- # :api: public
- def self.controller_path
- @controller_path ||= self.name.sub(/Controller$/, '').underscore
+
+ def self.subclasses
+ @subclasses ||= []
end
-
- # :api: public
- def controller_path() self.class.controller_path end
-
- # :api: private
- def self.action_methods
- @action_names ||= Set.new(self.public_instance_methods - self::CORE_METHODS)
+
+ def self.app_loaded!
+ @subclasses.each do |subclass|
+ subclass.constantize._write_layout_method
+ end
end
-
- # :api: private
- def self.action_names() action_methods end
-
- # :api: private
- def action_methods() self.class.action_names end
-
- # :api: private
- def action_names() action_methods end
-
- # :api: plugin
- def self.call(env)
- controller = new
- controller.call(env).to_rack
+
+ def render(action = action_name, options = {})
+ if action.is_a?(Hash)
+ options, action = action, nil
+ else
+ options.merge! :action => action
+ end
+
+ super(options)
end
-
- # :api: plugin
- def response_body=(body)
- @_response.body = body
+
+ def render_to_body(options = {})
+ options = {:template => options} if options.is_a?(String)
+ super
end
-
- # :api: private
- def call(env)
- @_request = ActionDispatch::Request.new(env)
- @_response = ActionDispatch::Response.new
- process(@_request.parameters[:action])
+
+ def process_action
+ ret = super
+ render if response_body.nil?
+ ret
end
-
- # :api: private
- def to_rack
- response.to_a
+
+ def respond_to_action?(action_name)
+ super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path)
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/compatibility.rb b/actionpack/lib/action_controller/new_base/compatibility.rb
new file mode 100644
index 0000000000..4655a94923
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/compatibility.rb
@@ -0,0 +1,58 @@
+module ActionController
+ module Rails2Compatibility
+ extend ActiveSupport::DependencyModule
+
+ # Temporary hax
+ included do
+ ::ActionController::UnknownAction = ::AbstractController::ActionNotFound
+ ::ActionController::DoubleRenderError = ::AbstractController::DoubleRenderError
+
+ cattr_accessor :session_options
+ self.send(:class_variable_set, "@@session_options", {})
+
+ cattr_accessor :allow_concurrency
+ self.send(:class_variable_set, "@@allow_concurrency", false)
+
+ cattr_accessor :param_parsers
+ self.send(:class_variable_set, "@@param_parsers", { Mime::MULTIPART_FORM => :multipart_form,
+ Mime::URL_ENCODED_FORM => :url_encoded_form,
+ Mime::XML => :xml_simple,
+ Mime::JSON => :json })
+
+ cattr_accessor :relative_url_root
+ self.send(:class_variable_set, "@@relative_url_root", ENV['RAILS_RELATIVE_URL_ROOT'])
+
+ cattr_accessor :default_charset
+ self.send(:class_variable_set, "@@default_charset", "utf-8")
+
+ cattr_reader :protected_instance_variables
+ self.send(:class_variable_set, "@@protected_instance_variables", %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller
+ @action_name @before_filter_chain_aborted @action_cache_path @_headers @_params
+ @_flash @_response))
+ end
+
+ module ClassMethods
+ def protect_from_forgery() end
+ def consider_all_requests_local() end
+ def rescue_action(env)
+ raise env["action_dispatch.rescue.exception"]
+ end
+ end
+
+ def render_to_body(options)
+ if options.is_a?(Hash) && options.key?(:template)
+ options[:template].sub!(/^\//, '')
+ end
+
+ options[:text] = nil if options[:nothing] == true
+
+ super
+ end
+
+ def _layout_for_name(name)
+ name &&= name.sub(%r{^/?layouts/}, '')
+ super
+ end
+
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/conditional_get.rb b/actionpack/lib/action_controller/new_base/conditional_get.rb
new file mode 100644
index 0000000000..e1407e671a
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/conditional_get.rb
@@ -0,0 +1,131 @@
+module ActionController
+ module ConditionalGet
+
+ # Sets the etag, last_modified, or both on the response and renders a
+ # "304 Not Modified" response if the request is already fresh.
+ #
+ # Parameters:
+ # * <tt>:etag</tt>
+ # * <tt>:last_modified</tt>
+ # * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
+ #
+ # Example:
+ #
+ # def show
+ # @article = Article.find(params[:id])
+ # fresh_when(:etag => @article, :last_modified => @article.created_at.utc, :public => true)
+ # end
+ #
+ # This will render the show template if the request isn't sending a matching etag or
+ # If-Modified-Since header and just a "304 Not Modified" response if there's a match.
+ #
+ def fresh_when(options)
+ options.assert_valid_keys(:etag, :last_modified, :public)
+
+ response.etag = options[:etag] if options[:etag]
+ response.last_modified = options[:last_modified] if options[:last_modified]
+
+ if options[:public]
+ cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip }
+ cache_control.delete("private")
+ cache_control.delete("no-cache")
+ cache_control << "public"
+ response.headers["Cache-Control"] = cache_control.join(', ')
+ end
+
+ if request.fresh?(response)
+ head :not_modified
+ end
+ end
+
+ # Return a response that has no content (merely headers). The options
+ # argument is interpreted to be a hash of header names and values.
+ # This allows you to easily return a response that consists only of
+ # significant headers:
+ #
+ # head :created, :location => person_path(@person)
+ #
+ # It can also be used to return exceptional conditions:
+ #
+ # return head(:method_not_allowed) unless request.post?
+ # return head(:bad_request) unless valid_request?
+ # render
+ def head(*args)
+ if args.length > 2
+ raise ArgumentError, "too many arguments to head"
+ elsif args.empty?
+ raise ArgumentError, "too few arguments to head"
+ end
+ options = args.extract_options!
+ status = interpret_status(args.shift || options.delete(:status) || :ok)
+
+ options.each do |key, value|
+ headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s
+ end
+
+ render :nothing => true, :status => status
+ end
+
+ # Sets the etag and/or last_modified on the response and checks it against
+ # the client request. If the request doesn't match the options provided, the
+ # request is considered stale and should be generated from scratch. Otherwise,
+ # it's fresh and we don't need to generate anything and a reply of "304 Not Modified" is sent.
+ #
+ # Parameters:
+ # * <tt>:etag</tt>
+ # * <tt>:last_modified</tt>
+ # * <tt>:public</tt> By default the Cache-Control header is private, set this to true if you want your application to be cachable by other devices (proxy caches).
+ #
+ # Example:
+ #
+ # def show
+ # @article = Article.find(params[:id])
+ #
+ # if stale?(:etag => @article, :last_modified => @article.created_at.utc)
+ # @statistics = @article.really_expensive_call
+ # respond_to do |format|
+ # # all the supported formats
+ # end
+ # end
+ # end
+ def stale?(options)
+ fresh_when(options)
+ !request.fresh?(response)
+ end
+
+ # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that
+ # intermediate caches shouldn't cache the response.
+ #
+ # Examples:
+ # expires_in 20.minutes
+ # expires_in 3.hours, :public => true
+ # expires in 3.hours, 'max-stale' => 5.hours, :public => true
+ #
+ # This method will overwrite an existing Cache-Control header.
+ # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
+ def expires_in(seconds, options = {}) #:doc:
+ cache_control = response.headers["Cache-Control"].split(",").map {|k| k.strip }
+
+ cache_control << "max-age=#{seconds}"
+ cache_control.delete("no-cache")
+ if options[:public]
+ cache_control.delete("private")
+ cache_control << "public"
+ else
+ cache_control << "private"
+ end
+
+ # This allows for additional headers to be passed through like 'max-stale' => 5.hours
+ cache_control += options.symbolize_keys.reject{|k,v| k == :public || k == :private }.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"}
+
+ response.headers["Cache-Control"] = cache_control.join(', ')
+ end
+
+ # Sets a HTTP 1.1 Cache-Control header of "no-cache" so no caching should occur by the browser or
+ # intermediate caches (like caching proxy servers).
+ def expires_now #:doc:
+ response.headers["Cache-Control"] = "no-cache"
+ end
+
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/hide_actions.rb b/actionpack/lib/action_controller/new_base/hide_actions.rb
index 422ea180c4..d1857a9169 100644
--- a/actionpack/lib/action_controller/new_base/hide_actions.rb
+++ b/actionpack/lib/action_controller/new_base/hide_actions.rb
@@ -1,25 +1,28 @@
module ActionController
module HideActions
+ extend ActiveSupport::DependencyModule
+
included do
extlib_inheritable_accessor :hidden_actions
self.hidden_actions ||= Set.new
end
def action_methods() self.class.action_names end
- def action_names() action_methods end
-
+ def action_names() action_methods end
+
private
+
def respond_to_action?(action_name)
!hidden_actions.include?(action_name) && (super || respond_to?(:method_missing))
end
-
+
module ClassMethods
def hide_action(*args)
args.each do |arg|
self.hidden_actions << arg.to_s
end
end
-
+
def action_methods
@action_names ||= Set.new(super.reject {|name| self.hidden_actions.include?(name.to_s)})
end
@@ -27,4 +30,4 @@ module ActionController
def self.action_names() action_methods end
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/http.rb b/actionpack/lib/action_controller/new_base/http.rb
new file mode 100644
index 0000000000..f269fe70db
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/http.rb
@@ -0,0 +1,64 @@
+module ActionController
+ class Http < AbstractController::Base
+ abstract!
+
+ # :api: public
+ attr_internal :request, :response, :params
+
+ # :api: public
+ def self.controller_name
+ @controller_name ||= controller_path.split("/").last
+ end
+
+ # :api: public
+ def controller_name() self.class.controller_name end
+
+ # :api: public
+ def self.controller_path
+ @controller_path ||= self.name.sub(/Controller$/, '').underscore
+ end
+
+ # :api: public
+ def controller_path() self.class.controller_path end
+
+ # :api: private
+ def self.internal_methods
+ ActionController::Http.public_instance_methods(true)
+ end
+
+ # :api: private
+ def self.action_names() action_methods end
+
+ # :api: private
+ def action_names() action_methods end
+
+ # :api: plugin
+ def self.call(env)
+ controller = new
+ controller.call(env).to_rack
+ end
+
+ # :api: private
+ def call(name, env)
+ @_request = ActionDispatch::Request.new(env)
+ @_response = ActionDispatch::Response.new
+ @_response.request = request
+ process(name)
+ @_response.body = response_body
+ @_response.prepare!
+ to_rack
+ end
+
+ def self.action(name)
+ @actions ||= {}
+ @actions[name] ||= proc do |env|
+ new.call(name, env)
+ end
+ end
+
+ # :api: private
+ def to_rack
+ @_response.to_a
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/new_base/layouts.rb b/actionpack/lib/action_controller/new_base/layouts.rb
index 228162421d..e851eb5f9a 100644
--- a/actionpack/lib/action_controller/new_base/layouts.rb
+++ b/actionpack/lib/action_controller/new_base/layouts.rb
@@ -4,34 +4,36 @@ module ActionController
depends_on ActionController::Renderer
depends_on AbstractController::Layouts
-
+
module ClassMethods
def _implied_layout_name
controller_path
end
end
-
+
def render_to_body(options)
# render :text => ..., :layout => ...
# or
# render :anything_else
- if !options.key?(:text) || options.key?(:layout)
+ if (!options.key?(:text) && !options.key?(:inline)) || options.key?(:layout)
options[:_layout] = options.key?(:layout) ? _layout_for_option(options[:layout]) : _default_layout
end
-
+
super
end
-
+
private
+
def _layout_for_option(name)
case name
when String then _layout_for_name(name)
when true then _default_layout(true)
when false, nil then nil
else
- raise ArgumentError,
- "String, true, or false, expected for `layout'; you passed #{name.inspect}"
+ raise ArgumentError,
+ "String, true, or false, expected for `layout'; you passed #{name.inspect}"
end
end
+
end
end
diff --git a/actionpack/lib/action_controller/new_base/renderer.rb b/actionpack/lib/action_controller/new_base/renderer.rb
index d7ea9ec4a5..41e3dfbe23 100644
--- a/actionpack/lib/action_controller/new_base/renderer.rb
+++ b/actionpack/lib/action_controller/new_base/renderer.rb
@@ -3,48 +3,44 @@ module ActionController
extend ActiveSupport::DependencyModule
depends_on AbstractController::Renderer
-
+
def initialize(*)
self.formats = [:html]
super
end
-
- def render(action, options = {})
- # TODO: Move this into #render_to_body
- if action.is_a?(Hash)
- options, action = action, nil
- else
- options.merge! :action => action
- end
-
+
+ def render(options = {})
_process_options(options)
-
- self.response_body = render_to_body(options)
+
+ super(options)
end
def render_to_body(options)
- unless options.is_a?(Hash)
- options = {:action => options}
- end
-
if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(_text(options))
template = nil
+ elsif options.key?(:inline)
+ handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")
+ template = ActionView::Template.new(options[:inline], "inline #{options[:inline].inspect}", handler, {})
+ options[:_template] = template
elsif options.key?(:template)
options[:_template_name] = options[:template]
- elsif options.key?(:action)
- options[:_template_name] = options[:action].to_s
- options[:_prefix] = _prefix
+ else
+ options[:_template_name] = (options[:action] || action_name).to_s
+ options[:_prefix] = _prefix
end
-
- super(options)
+
+ ret = super(options)
+ response.content_type ||= options[:_template].mime_type
+ ret
end
-
+
private
+
def _prefix
controller_path
- end
-
+ end
+
def _text(options)
text = options[:text]
@@ -53,11 +49,11 @@ module ActionController
else text.to_s
end
end
-
+
def _process_options(options)
- if status = options[:status]
- response.status = status.to_i
- end
+ status, content_type = options.values_at(:status, :content_type)
+ response.status = status.to_i if status
+ response.content_type = content_type if content_type
end
end
end
diff --git a/actionpack/lib/action_controller/new_base/testing.rb b/actionpack/lib/action_controller/new_base/testing.rb
new file mode 100644
index 0000000000..106990b9ba
--- /dev/null
+++ b/actionpack/lib/action_controller/new_base/testing.rb
@@ -0,0 +1,25 @@
+module ActionController
+ module Testing
+
+ # OMG MEGA HAX
+ def process_with_test(request, response)
+ @_request = request
+ @_response = response
+ @_response.request = request
+ ret = process(request.parameters[:action])
+ @_response.body = self.response_body
+ @_response.prepare!
+ set_test_assigns
+ ret
+ end
+
+ def set_test_assigns
+ @assigns = {}
+ (instance_variable_names - self.class.protected_instance_variables).each do |var|
+ name, value = var[1..-1], instance_variable_get(var)
+ @assigns[name] = value
+ end
+ end
+
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/new_base/url_for.rb b/actionpack/lib/action_controller/new_base/url_for.rb
index 3179c8cd5b..af5b21012b 100644
--- a/actionpack/lib/action_controller/new_base/url_for.rb
+++ b/actionpack/lib/action_controller/new_base/url_for.rb
@@ -16,7 +16,7 @@ module ActionController
# by this method.
def default_url_options(options = nil)
end
-
+
def rewrite_options(options) #:nodoc:
if defaults = default_url_options(options)
defaults.merge(options)
@@ -24,7 +24,7 @@ module ActionController
options
end
end
-
+
def url_for(options = {})
options ||= {}
case options
@@ -37,4 +37,4 @@ module ActionController
end
end
end
-end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_controller/routing/route_set.rb b/actionpack/lib/action_controller/routing/route_set.rb
index 172b867bf0..45ad8a3a3b 100644
--- a/actionpack/lib/action_controller/routing/route_set.rb
+++ b/actionpack/lib/action_controller/routing/route_set.rb
@@ -430,7 +430,7 @@ module ActionController
def call(env)
request = ActionDispatch::Request.new(env)
app = Routing::Routes.recognize(request)
- app.call(env)
+ app.action(request.parameters[:action] || 'index').call(env)
end
def recognize(request)
diff --git a/actionpack/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb
index 4f39ee6a01..d6991ab4f5 100644
--- a/actionpack/lib/action_controller/testing/integration.rb
+++ b/actionpack/lib/action_controller/testing/integration.rb
@@ -309,24 +309,21 @@ module ActionController
def self.included(base)
base.extend(ClassMethods)
base.class_eval do
- class << self
- alias_method_chain :new, :capture
- end
+ alias_method_chain :initialize, :capture
end
end
+ def initialize_with_capture(*args)
+ initialize_without_capture
+ self.class.last_instantiation ||= self
+ end
+
module ClassMethods #:nodoc:
mattr_accessor :last_instantiation
def clear_last_instantiation!
self.last_instantiation = nil
end
-
- def new_with_capture(*args)
- controller = new_without_capture(*args)
- self.last_instantiation ||= controller
- controller
- end
end
end
diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb
index 49e8322491..21023ac101 100644
--- a/actionpack/lib/action_controller/testing/process.rb
+++ b/actionpack/lib/action_controller/testing/process.rb
@@ -131,6 +131,9 @@ module ActionController #:nodoc:
@request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
build_request_uri(action, parameters)
+ @request.env["action_controller.rescue.request"] = @request
+ @request.env["action_controller.rescue.response"] = @response
+
Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
env = @request.env
@@ -139,7 +142,7 @@ module ActionController #:nodoc:
# TODO: Enable Lint
# app = Rack::Lint.new(app)
- status, headers, body = app.call(env)
+ status, headers, body = app.action(action, env)
response = Rack::MockResponse.new(status, headers, body)
@response.request, @response.template = @request, @controller.template
diff --git a/actionpack/lib/action_controller/testing/process2.rb b/actionpack/lib/action_controller/testing/process2.rb
new file mode 100644
index 0000000000..18b7335450
--- /dev/null
+++ b/actionpack/lib/action_controller/testing/process2.rb
@@ -0,0 +1,69 @@
+require "action_controller/testing/process"
+
+module ActionController
+ module TestProcess
+
+ # Executes a request simulating GET HTTP method and set/volley the response
+ def get(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "GET")
+ end
+
+ # Executes a request simulating POST HTTP method and set/volley the response
+ def post(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "POST")
+ end
+
+ # Executes a request simulating PUT HTTP method and set/volley the response
+ def put(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "PUT")
+ end
+
+ # Executes a request simulating DELETE HTTP method and set/volley the response
+ def delete(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "DELETE")
+ end
+
+ # Executes a request simulating HEAD HTTP method and set/volley the response
+ def head(action, parameters = nil, session = nil, flash = nil)
+ process(action, parameters, session, flash, "HEAD")
+ end
+
+ def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
+ # Sanity check for required instance variables so we can give an
+ # understandable error message.
+ %w(@controller @request @response).each do |iv_name|
+ if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil?
+ raise "#{iv_name} is nil: make sure you set it in your test's setup method."
+ end
+ end
+
+ @request.recycle!
+ @response.recycle!
+ @controller.response_body = nil
+
+ @html_document = nil
+ @request.env['REQUEST_METHOD'] = http_method
+
+ parameters ||= {}
+ @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters)
+
+ @request.session = ActionController::TestSession.new(session) unless session.nil?
+ @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
+ build_request_uri(action, parameters)
+ @controller.params.merge!(parameters)
+ # Base.class_eval { include ProcessWithTest } unless Base < ProcessWithTest
+ @controller.process_with_test(@request, @response)
+ end
+
+ def build_request_uri(action, parameters)
+ unless @request.env['REQUEST_URI']
+ options = @controller.__send__(:rewrite_options, parameters)
+ options.update(:only_path => true, :action => action)
+
+ url = ActionController::UrlRewriter.new(@request, parameters)
+ @request.request_uri = url.rewrite(options)
+ end
+ end
+
+ end
+end \ No newline at end of file
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 791254cdf2..71c1e1b9a9 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -43,6 +43,8 @@ module ActionDispatch
def call(env)
@app.call(env)
rescue Exception => exception
+ raise exception if env['rack.test']
+
log_error(exception) if logger
request = Request.new(env)
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index ec8a9ca76e..ade2d6f05e 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -34,8 +34,6 @@ module ActionDispatch
else
@klass.to_s.constantize
end
- rescue NameError
- @klass
end
def active?
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index f6d021c92a..95c56faf9c 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -2,7 +2,7 @@ module ActionView #:nodoc:
class PathSet < Array #:nodoc:
def self.type_cast(obj)
if obj.is_a?(String)
- cache = !Object.const_defined?(:Rails) || Rails.configuration.cache_classes
+ cache = !defined?(Rails) || !Rails.respond_to?(:configuration) || Rails.configuration.cache_classes
Template::FileSystemPathWithFallback.new(obj, :cache => cache)
else
obj
diff --git a/actionpack/lib/action_view/template/text.rb b/actionpack/lib/action_view/template/text.rb
index f81174d707..a777021a12 100644
--- a/actionpack/lib/action_view/template/text.rb
+++ b/actionpack/lib/action_view/template/text.rb
@@ -1,9 +1,12 @@
module ActionView #:nodoc:
class TextTemplate < String #:nodoc:
+
+ def identifier() self end
def render(*) self end
- def exempt_from_layout?() false end
-
+ def mime_type() Mime::HTML end
+
+ def partial?() false end
end
end
diff --git a/actionpack/test/abstract_controller/abstract_controller_test.rb b/actionpack/test/abstract_controller/abstract_controller_test.rb
index 331797afcf..689aa99fd8 100644
--- a/actionpack/test/abstract_controller/abstract_controller_test.rb
+++ b/actionpack/test/abstract_controller/abstract_controller_test.rb
@@ -20,14 +20,14 @@ module AbstractController
class TestBasic < ActiveSupport::TestCase
test "dispatching works" do
result = Me.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
end
# Test Render mixin
# ====
class RenderingController < AbstractController::Base
- use Renderer
+ include Renderer
def _prefix() end
@@ -58,38 +58,38 @@ module AbstractController
end
def rendering_to_body
- render_to_body "naked_render.erb"
+ self.response_body = render_to_body :_template_name => "naked_render.erb"
end
def rendering_to_string
- render_to_string "naked_render.erb"
+ self.response_body = render_to_string :_template_name => "naked_render.erb"
end
end
class TestRenderer < ActiveSupport::TestCase
test "rendering templates works" do
result = Me2.process(:index)
- assert_equal "Hello from index.erb", result.response_obj[:body]
+ assert_equal "Hello from index.erb", result.response_body
end
test "rendering passes ivars to the view" do
result = Me2.process(:action_with_ivars)
- assert_equal "Hello from index_with_ivars.erb", result.response_obj[:body]
+ assert_equal "Hello from index_with_ivars.erb", result.response_body
end
test "rendering with no template name" do
result = Me2.process(:naked_render)
- assert_equal "Hello from naked_render.erb", result.response_obj[:body]
+ assert_equal "Hello from naked_render.erb", result.response_body
end
test "rendering to a rack body" do
result = Me2.process(:rendering_to_body)
- assert_equal "Hello from naked_render.erb", result.response_obj[:body]
+ assert_equal "Hello from naked_render.erb", result.response_body
end
test "rendering to a string" do
result = Me2.process(:rendering_to_string)
- assert_equal "Hello from naked_render.erb", result.response_obj[:body]
+ assert_equal "Hello from naked_render.erb", result.response_body
end
end
@@ -121,12 +121,12 @@ module AbstractController
class TestPrefixedViews < ActiveSupport::TestCase
test "templates are located inside their 'prefix' folder" do
result = Me3.process(:index)
- assert_equal "Hello from me3/index.erb", result.response_obj[:body]
+ assert_equal "Hello from me3/index.erb", result.response_body
end
test "templates included their format" do
result = Me3.process(:formatted)
- assert_equal "Hello from me3/formatted.html.erb", result.response_obj[:body]
+ assert_equal "Hello from me3/formatted.html.erb", result.response_body
end
end
@@ -134,7 +134,12 @@ module AbstractController
# ====
# self._layout is used when defined
class WithLayouts < PrefixedViews
- use Layouts
+ include Layouts
+
+ def self.inherited(klass)
+ klass._write_layout_method
+ super
+ end
private
def self.layout(formats)
@@ -147,13 +152,9 @@ module AbstractController
end
end
end
-
- def _layout
- self.class.layout(formats)
- end
-
+
def render_to_body(options = {})
- options[:_layout] = options[:layout] || _layout
+ options[:_layout] = options[:layout] || _default_layout
super
end
end
@@ -173,12 +174,7 @@ module AbstractController
class TestLayouts < ActiveSupport::TestCase
test "layouts are included" do
result = Me4.process(:index)
- assert_equal "Me4 Enter : Hello from me4/index.erb : Exit", result.response_obj[:body]
- end
-
- test "it can fall back to the application layout" do
- result = Me5.process(:index)
- assert_equal "Application Enter : Hello from me5/index.erb : Exit", result.response_obj[:body]
+ assert_equal "Me4 Enter : Hello from me4/index.erb : Exit", result.response_body
end
end
@@ -207,7 +203,7 @@ module AbstractController
private
def respond_to_action?(action_name)
- action_name != :fail
+ action_name.to_s != "fail"
end
end
@@ -215,7 +211,7 @@ module AbstractController
class TestRespondToAction < ActiveSupport::TestCase
def assert_dispatch(klass, body = "success", action = :index)
- response = klass.process(action).response_obj[:body]
+ response = klass.process(action).response_body
assert_equal body, response
end
diff --git a/actionpack/test/abstract_controller/callbacks_test.rb b/actionpack/test/abstract_controller/callbacks_test.rb
index 89243b631e..410b1e57a6 100644
--- a/actionpack/test/abstract_controller/callbacks_test.rb
+++ b/actionpack/test/abstract_controller/callbacks_test.rb
@@ -22,7 +22,7 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "basic callbacks work" do
result = Callback1.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
end
@@ -53,7 +53,7 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "before_filter works" do
result = Callback2.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
test "after_filter works" do
@@ -84,7 +84,7 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "before_filter works with procs" do
result = Callback3.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
test "after_filter works with procs" do
@@ -119,12 +119,12 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "when :only is specified, a before filter is triggered on that action" do
result = CallbacksWithConditions.process(:index)
- assert_equal "Hello, World", result.response_obj[:body]
+ assert_equal "Hello, World", result.response_body
end
test "when :only is specified, a before filter is not triggered on other actions" do
result = CallbacksWithConditions.process(:sekrit_data)
- assert_equal "true", result.response_obj[:body]
+ assert_equal "true", result.response_body
end
test "when :except is specified, an after filter is not triggered on that action" do
@@ -159,12 +159,12 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "when :only is specified with an array, a before filter is triggered on that action" do
result = CallbacksWithArrayConditions.process(:index)
- assert_equal "Hello, World", result.response_obj[:body]
+ assert_equal "Hello, World", result.response_body
end
test "when :only is specified with an array, a before filter is not triggered on other actions" do
result = CallbacksWithArrayConditions.process(:sekrit_data)
- assert_equal "true", result.response_obj[:body]
+ assert_equal "true", result.response_body
end
test "when :except is specified with an array, an after filter is not triggered on that action" do
@@ -184,12 +184,12 @@ module AbstractController
class TestCallbacks < ActiveSupport::TestCase
test "when a callback is modified in a child with :only, it works for the :only action" do
result = ChangedConditions.process(:index)
- assert_equal "Hello world", result.response_obj[:body]
+ assert_equal "Hello world", result.response_body
end
test "when a callback is modified in a child with :only, it does not work for other actions" do
result = ChangedConditions.process(:not_index)
- assert_equal "", result.response_obj[:body]
+ assert_equal "", result.response_body
end
end
diff --git a/actionpack/test/abstract_controller/helper_test.rb b/actionpack/test/abstract_controller/helper_test.rb
index 6284fa4f70..f91aefe606 100644
--- a/actionpack/test/abstract_controller/helper_test.rb
+++ b/actionpack/test/abstract_controller/helper_test.rb
@@ -4,8 +4,8 @@ module AbstractController
module Testing
class ControllerWithHelpers < AbstractController::Base
- use Renderer
- use Helpers
+ include Renderer
+ include Helpers
def render(string)
super(:_template_name => string)
@@ -35,7 +35,7 @@ module AbstractController
class TestHelpers < ActiveSupport::TestCase
def test_helpers
result = MyHelpers1.process(:index)
- assert_equal "Hello World : Included", result.response_obj[:body]
+ assert_equal "Hello World : Included", result.response_body
end
end
diff --git a/actionpack/test/abstract_controller/layouts_test.rb b/actionpack/test/abstract_controller/layouts_test.rb
index a305a30a54..6e1c2bf9e8 100644
--- a/actionpack/test/abstract_controller/layouts_test.rb
+++ b/actionpack/test/abstract_controller/layouts_test.rb
@@ -8,7 +8,7 @@ module AbstractControllerTests
include AbstractController::Renderer
include AbstractController::Layouts
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/hello.erb" => "With String <%= yield %>",
"layouts/hello_override.erb" => "With Override <%= yield %>",
"layouts/abstract_controller_tests/layouts/with_string_implied_child.erb" =>
@@ -152,12 +152,12 @@ module AbstractControllerTests
class TestBase < ActiveSupport::TestCase
test "when no layout is specified, and no default is available, render without a layout" do
result = Blank.process(:index)
- assert_equal "Hello blank!", result.response_obj[:body]
+ assert_equal "Hello blank!", result.response_body
end
test "when layout is specified as a string, render with that layout" do
result = WithString.process(:index)
- assert_equal "With String Hello string!", result.response_obj[:body]
+ assert_equal "With String Hello string!", result.response_body
end
test "when layout is specified as a string, but the layout is missing, raise an exception" do
@@ -166,22 +166,22 @@ module AbstractControllerTests
test "when layout is specified as false, do not use a layout" do
result = WithFalseLayout.process(:index)
- assert_equal "Hello false!", result.response_obj[:body]
+ assert_equal "Hello false!", result.response_body
end
test "when layout is specified as nil, do not use a layout" do
result = WithNilLayout.process(:index)
- assert_equal "Hello nil!", result.response_obj[:body]
+ assert_equal "Hello nil!", result.response_body
end
test "when layout is specified as a symbol, call the requested method and use the layout returned" do
result = WithSymbol.process(:index)
- assert_equal "OMGHI2U Hello symbol!", result.response_obj[:body]
+ assert_equal "OMGHI2U Hello symbol!", result.response_body
end
test "when layout is specified as a symbol and the method returns nil, don't use a layout" do
result = WithSymbolReturningNil.process(:index)
- assert_equal "Hello nilz!", result.response_obj[:body]
+ assert_equal "Hello nilz!", result.response_body
end
test "when the layout is specified as a symbol and the method doesn't exist, raise an exception" do
@@ -194,28 +194,28 @@ module AbstractControllerTests
test "when a child controller does not have a layout, use the parent controller layout" do
result = WithStringChild.process(:index)
- assert_equal "With String Hello string!", result.response_obj[:body]
+ assert_equal "With String Hello string!", result.response_body
end
test "when a child controller has specified a layout, use that layout and not the parent controller layout" do
result = WithStringOverriddenChild.process(:index)
- assert_equal "With Override Hello string!", result.response_obj[:body]
+ assert_equal "With Override Hello string!", result.response_body
end
test "when a child controller has an implied layout, use that layout and not the parent controller layout" do
result = WithStringImpliedChild.process(:index)
- assert_equal "With Implied Hello string!", result.response_obj[:body]
+ assert_equal "With Implied Hello string!", result.response_body
end
test "when a child controller specifies layout nil, do not use the parent layout" do
result = WithNilChild.process(:index)
- assert_equal "Hello string!", result.response_obj[:body]
+ assert_equal "Hello string!", result.response_body
end
test "when a grandchild has no layout specified, the child has an implied layout, and the " \
"parent has specified a layout, use the child controller layout" do
result = WithChildOfImplied.process(:index)
- assert_equal "With Implied Hello string!", result.response_obj[:body]
+ assert_equal "With Implied Hello string!", result.response_body
end
test "raises an exception when specifying layout true" do
diff --git a/actionpack/test/abstract_controller/test_helper.rb b/actionpack/test/abstract_controller/test_helper.rb
index b9248c6bbd..a08ab5a6d7 100644
--- a/actionpack/test/abstract_controller/test_helper.rb
+++ b/actionpack/test/abstract_controller/test_helper.rb
@@ -2,11 +2,14 @@ $:.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/core/all'
require 'active_support/test_case'
-require 'action_controller'
+require 'action_controller/abstract'
+require 'action_view'
require 'action_view/base'
+require 'action_dispatch'
require 'fixture_template'
begin
@@ -15,11 +18,4 @@ begin
Debugger.start
rescue LoadError
# Debugging disabled. `gem install ruby-debug` to enable.
-end
-
-require 'action_controller/abstract'
-# require 'action_controller/abstract/base'
-# require 'action_controller/abstract/renderer'
-# require 'action_controller/abstract/layouts'
-# require 'action_controller/abstract/callbacks'
-# require 'action_controller/abstract/helpers' \ No newline at end of file
+end \ No newline at end of file
diff --git a/actionpack/test/abstract_unit2.rb b/actionpack/test/abstract_unit2.rb
new file mode 100644
index 0000000000..95e7b2e273
--- /dev/null
+++ b/actionpack/test/abstract_unit2.rb
@@ -0,0 +1,133 @@
+$:.unshift(File.dirname(__FILE__) + '/../lib')
+$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
+$:.unshift(File.dirname(__FILE__) + '/lib')
+
+
+require 'test/unit'
+require 'active_support'
+require 'active_support/core/all'
+require 'active_support/test_case'
+require 'action_controller/abstract'
+require 'action_controller/new_base'
+require 'fixture_template'
+require 'action_controller/testing/process2'
+require 'action_view/test_case'
+
+FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures')
+
+module ActionController
+
+ class ActionControllerError < StandardError #:nodoc:
+ end
+
+ class SessionRestoreError < ActionControllerError #:nodoc:
+ end
+
+ class RenderError < ActionControllerError #:nodoc:
+ end
+
+ class RoutingError < ActionControllerError #:nodoc:
+ attr_reader :failures
+ def initialize(message, failures=[])
+ super(message)
+ @failures = failures
+ end
+ end
+
+ class MethodNotAllowed < ActionControllerError #:nodoc:
+ attr_reader :allowed_methods
+
+ def initialize(*allowed_methods)
+ super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.")
+ @allowed_methods = allowed_methods
+ end
+
+ def allowed_methods_header
+ allowed_methods.map { |method_symbol| method_symbol.to_s.upcase } * ', '
+ end
+
+ def handle_response!(response)
+ response.headers['Allow'] ||= allowed_methods_header
+ end
+ end
+
+ class NotImplemented < MethodNotAllowed #:nodoc:
+ end
+
+ class UnknownController < ActionControllerError #:nodoc:
+ end
+
+ class MissingFile < ActionControllerError #:nodoc:
+ end
+
+ class RenderError < ActionControllerError #:nodoc:
+ end
+
+ class SessionOverflowError < ActionControllerError #:nodoc:
+ DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
+
+ def initialize(message = nil)
+ super(message || DEFAULT_MESSAGE)
+ end
+ end
+
+ class UnknownHttpMethod < ActionControllerError #:nodoc:
+ end
+
+ class Base
+ use ActionController::Testing
+ end
+
+ Base.view_paths = FIXTURE_LOAD_PATH
+
+ class TestCase
+ include TestProcess
+ setup do
+ ActionController::Routing::Routes.draw do |map|
+ map.connect ':controller/:action/:id'
+ end
+ end
+
+ def assert_template(options = {}, message = nil)
+ validate_response!
+
+ clean_backtrace do
+ case options
+ when NilClass, String
+ hax = @controller._action_view.instance_variable_get(:@_rendered)
+ rendered = (hax[:template] || []).map { |t| t.identifier }
+ msg = build_message(message,
+ "expecting <?> but rendering with <?>",
+ options, rendered.join(', '))
+ assert_block(msg) do
+ if options.nil?
+ hax[:template].blank?
+ else
+ rendered.any? { |t| t.match(options) }
+ end
+ end
+ when Hash
+ if expected_partial = options[:partial]
+ partials = hax[:partials]
+ if expected_count = options[:count]
+ found = partials.detect { |p, _| p.identifier.match(expected_partial) }
+ actual_count = found.nil? ? 0 : found.second
+ msg = build_message(message,
+ "expecting ? to be rendered ? time(s) but rendered ? time(s)",
+ expected_partial, expected_count, actual_count)
+ assert(actual_count == expected_count.to_i, msg)
+ else
+ msg = build_message(message,
+ "expecting partial <?> but action rendered <?>",
+ options[:partial], partials.keys)
+ assert(partials.keys.any? { |p| p.identifier.match(expected_partial) }, msg)
+ end
+ else
+ assert hax[:partials].empty?,
+ "Expected no partials to be rendered"
+ end
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb
index 7377546631..64b8b10d5b 100644
--- a/actionpack/test/controller/content_type_test.rb
+++ b/actionpack/test/controller/content_type_test.rb
@@ -1,24 +1,29 @@
require 'abstract_unit'
class ContentTypeController < ActionController::Base
+ # :ported:
def render_content_type_from_body
response.content_type = Mime::RSS
render :text => "hello world!"
end
+ # :ported:
def render_defaults
render :text => "hello world!"
end
+ # :ported:
def render_content_type_from_render
render :text => "hello world!", :content_type => Mime::RSS
end
+ # :ported:
def render_charset_from_body
response.charset = "utf-16"
render :text => "hello world!"
end
+ # :ported:
def render_nil_charset_from_body
response.charset = nil
render :text => "hello world!"
@@ -60,6 +65,7 @@ class ContentTypeTest < ActionController::TestCase
@controller.logger = Logger.new(nil)
end
+ # :ported:
def test_render_defaults
get :render_defaults
assert_equal "utf-8", @response.charset
@@ -74,24 +80,28 @@ class ContentTypeTest < ActionController::TestCase
ContentTypeController.default_charset = "utf-8"
end
+ # :ported:
def test_content_type_from_body
get :render_content_type_from_body
assert_equal "application/rss+xml", @response.content_type
assert_equal "utf-8", @response.charset
end
+ # :ported:
def test_content_type_from_render
get :render_content_type_from_render
assert_equal "application/rss+xml", @response.content_type
assert_equal "utf-8", @response.charset
end
+ # :ported:
def test_charset_from_body
get :render_charset_from_body
assert_equal Mime::HTML, @response.content_type
assert_equal "utf-16", @response.charset
end
+ # :ported:
def test_nil_charset_from_body
get :render_nil_charset_from_body
assert_equal Mime::HTML, @response.content_type
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 5fd3eb0446..9ad49e9282 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -607,8 +607,9 @@ class FilterTest < Test::Unit::TestCase
def test_dynamic_dispatch
%w(foo bar baz).each do |action|
request = ActionController::TestRequest.new
+ request.env["action_controller.rescue.request"] = request
request.query_parameters[:choose] = action
- response = Rack::MockResponse.new(*DynamicDispatchController.call(request.env))
+ response = DynamicDispatchController.action.call(request.env).last
assert_equal action, response.body
end
end
diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb
index e72bce1791..19cd5f4db2 100644
--- a/actionpack/test/controller/helper_test.rb
+++ b/actionpack/test/controller/helper_test.rb
@@ -101,20 +101,30 @@ class HelperTest < Test::Unit::TestCase
assert master_helper_methods.include?('delegate_attr=')
end
- def test_helper_for_nested_controller
- request = ActionController::TestRequest.new
- request.action = 'render_hello_world'
+ def call_controller(klass, action)
+ request = ActionController::TestRequest.new
+ request.env["action_controller.rescue.request"] = request
+ klass.action(action).call(request.env)
+ end
- response = Rack::MockResponse.new(*Fun::GamesController.call(request.env))
- assert_equal 'hello: Iz guuut!', response.body
+ def test_helper_for_nested_controller
+ assert_equal 'hello: Iz guuut!',
+ call_controller(Fun::GamesController, "render_hello_world").last.body
+ # request = ActionController::TestRequest.new
+ # request.env["action_controller.rescue.request"] = request
+ #
+ # resp = Fun::GamesController.action(:render_hello_world).call(request.env)
+ # assert_equal 'hello: Iz guuut!', resp.last.body
end
def test_helper_for_acronym_controller
- request = ActionController::TestRequest.new
- request.action = 'test'
-
- response = Rack::MockResponse.new(*Fun::PdfController.call(request.env))
- assert_equal 'test: baz', response.body
+ assert_equal "test: baz", call_controller(Fun::PdfController, "test").last.body
+ #
+ # request = ActionController::TestRequest.new
+ # response = ActionController::TestResponse.new
+ # request.action = 'test'
+ #
+ # assert_equal 'test: baz', Fun::PdfController.process(request, response).body
end
def test_all_helpers
@@ -204,6 +214,12 @@ class IsolatedHelpersTest < Test::Unit::TestCase
end
end
+ def call_controller(klass, action)
+ request = ActionController::TestRequest.new
+ request.env["action_controller.rescue.request"] = request
+ klass.action(action).call(request.env)
+ end
+
def setup
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@@ -211,16 +227,14 @@ class IsolatedHelpersTest < Test::Unit::TestCase
end
def test_helper_in_a
- assert_raise(ActionView::TemplateError) { A.call(@request.env) }
+ assert_raise(ActionView::TemplateError) { call_controller(A, "index") }
end
def test_helper_in_b
- response = Rack::MockResponse.new(*B.call(@request.env))
- assert_equal 'B', response.body
+ assert_equal 'B', call_controller(B, "index").last.body
end
def test_helper_in_c
- response = Rack::MockResponse.new(*C.call(@request.env))
- assert_equal 'C', response.body
+ assert_equal 'C', call_controller(C, "index").last.body
end
end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index dd2dd7a502..a58d9b08b5 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -1,9 +1,10 @@
-require 'abstract_unit'
+require ENV['new_base'] ? 'abstract_unit2' : 'abstract_unit'
require 'controller/fake_models'
require 'pathname'
module Fun
class GamesController < ActionController::Base
+ # :ported:
def hello_world
end
end
@@ -80,6 +81,7 @@ class TestController < ActionController::Base
fresh_when(:last_modified => Time.now.utc.beginning_of_day, :etag => [ :foo, 123 ])
end
+ # :ported:
def render_hello_world
render :template => "test/hello_world"
end
@@ -94,23 +96,28 @@ class TestController < ActionController::Base
render :template => "test/hello_world"
end
+ # :ported: compatibility
def render_hello_world_with_forward_slash
render :template => "/test/hello_world"
end
+ # :ported:
def render_template_in_top_directory
render :template => 'shared'
end
+ # :deprecated:
def render_template_in_top_directory_with_slash
render :template => '/shared'
end
+ # :ported:
def render_hello_world_from_variable
@person = "david"
render :text => "hello #{@person}"
end
+ # :ported:
def render_action_hello_world
render :action => "hello_world"
end
@@ -123,10 +130,12 @@ class TestController < ActionController::Base
render :action => :hello_world
end
+ # :ported:
def render_text_hello_world
render :text => "hello world"
end
+ # :ported:
def render_text_hello_world_with_layout
@variable_for_layout = ", I'm here!"
render :text => "hello world", :layout => true
@@ -218,6 +227,7 @@ class TestController < ActionController::Base
render :json => {:hello => render_to_string(:partial => 'partial')}
end
+ # :ported:
def render_custom_code
render :text => "hello world", :status => 404
end
@@ -228,14 +238,17 @@ class TestController < ActionController::Base
end
end
+ # :ported:
def render_text_with_nil
render :text => nil
end
+ # :ported:
def render_text_with_false
render :text => false
end
+ # :ported:
def render_nothing_with_appendix
render :text => "appended"
end
@@ -244,6 +257,10 @@ class TestController < ActionController::Base
render :js => "alert('hello')"
end
+ # This test is testing 3 things:
+ # render :file in AV :ported:
+ # render :template in AC :ported:
+ # setting content type
def render_xml_hello
@name = "David"
render :template => "test/hello"
@@ -270,10 +287,12 @@ class TestController < ActionController::Base
# let's just rely on the template
end
+ # :ported:
def blank_response
render :text => ' '
end
+ # :ported:
def layout_test
render :action => "hello_world"
end
@@ -281,7 +300,8 @@ class TestController < ActionController::Base
def builder_layout_test
render :action => "hello", :layout => "layouts/builder"
end
-
+
+ # :move: test this in ActionView
def builder_partial_test
render :action => "hello_world_container"
end
@@ -391,6 +411,7 @@ class TestController < ActionController::Base
render :layout => true, :inline => "Hello: <%= params[:name] %>"
end
+ # :ported:
def render_with_explicit_template
render :template => "test/hello_world"
end
@@ -399,10 +420,12 @@ class TestController < ActionController::Base
render "test/hello_world"
end
+ # :ported:
def render_with_explicit_template_with_locals
render :template => "test/render_file_with_locals", :locals => { :secret => 'area51' }
end
+ # :ported:
def double_render
render :text => "hello"
render :text => "world"
@@ -434,10 +457,15 @@ class TestController < ActionController::Base
render :action => "potential_conflicts"
end
+ # :deprecated:
+ # Tests being able to pick a .builder template over a .erb
+ # For instance, being able to have hello.xml.builder and hello.xml.erb
+ # and select one via "hello.builder" or "hello.erb"
def hello_world_from_rxml_using_action
render :action => "hello_world_from_rxml.builder"
end
+ # :deprecated:
def hello_world_from_rxml_using_template
render :template => "test/hello_world_from_rxml.builder"
end
@@ -506,6 +534,7 @@ class TestController < ActionController::Base
# Action template sets variable that's picked up by layout
end
+ # :addressed:
def render_text_with_assigns
@hello = "world"
render :text => "foo"
@@ -755,6 +784,7 @@ class RenderTest < ActionController::TestCase
@request.host = "www.nextangle.com"
end
+ # :ported:
def test_simple_show
get :hello_world
assert_response 200
@@ -763,11 +793,13 @@ class RenderTest < ActionController::TestCase
assert_equal "<html>Hello world!</html>", @response.body
end
+ # :ported:
def test_renders_default_template_for_missing_action
get :'hyphen-ated'
assert_template 'test/hyphen-ated'
end
+ # :ported:
def test_render
get :render_hello_world
assert_template "test/hello_world"
@@ -785,54 +817,64 @@ class RenderTest < ActionController::TestCase
end
end
+ # :ported: compatibility
def test_render_with_forward_slash
get :render_hello_world_with_forward_slash
assert_template "test/hello_world"
end
+ # :ported:
def test_render_in_top_directory
get :render_template_in_top_directory
assert_template "shared"
assert_equal "Elastica", @response.body
end
+ # :ported:
def test_render_in_top_directory_with_slash
get :render_template_in_top_directory_with_slash
assert_template "shared"
assert_equal "Elastica", @response.body
end
+ # :ported:
def test_render_from_variable
get :render_hello_world_from_variable
assert_equal "hello david", @response.body
end
+ # :ported:
def test_render_action
get :render_action_hello_world
assert_template "test/hello_world"
end
+ # :ported:
def test_render_action_hello_world_as_string
get :render_action_hello_world_as_string
assert_equal "Hello world!", @response.body
assert_template "test/hello_world"
end
+ # :ported:
def test_render_action_with_symbol
get :render_action_hello_world_with_symbol
assert_template "test/hello_world"
end
+ # :ported:
def test_render_text
get :render_text_hello_world
assert_equal "hello world", @response.body
end
+ # :ported:
def test_do_with_render_text_and_layout
get :render_text_hello_world_with_layout
assert_equal "<html>hello world, I'm here!</html>", @response.body
end
+ # :ported:
def test_do_with_render_action_and_layout_false
get :hello_world_with_layout_false
assert_equal 'Hello world!', @response.body
@@ -914,6 +956,7 @@ class RenderTest < ActionController::TestCase
assert_equal 'application/json', @response.content_type
end
+ # :ported:
def test_render_custom_code
get :render_custom_code
assert_response 404
@@ -927,31 +970,37 @@ class RenderTest < ActionController::TestCase
assert_equal %(Element.replace("foo", "partial html");), @response.body
end
+ # :ported:
def test_render_text_with_nil
get :render_text_with_nil
assert_response 200
assert_equal ' ', @response.body
end
+ # :ported:
def test_render_text_with_false
get :render_text_with_false
assert_equal 'false', @response.body
end
+ # :ported:
def test_render_nothing_with_appendix
get :render_nothing_with_appendix
assert_response 200
assert_equal 'appended', @response.body
end
+ # :ported:
def test_attempt_to_access_object_method
assert_raise(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
end
+ # :ported:
def test_private_methods
assert_raise(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
end
+ # :ported:
def test_access_to_request_in_view
get :accessing_request_in_template
assert_equal "Hello: www.nextangle.com", @response.body
@@ -962,11 +1011,13 @@ class RenderTest < ActionController::TestCase
assert_equal "Logger", @response.body
end
+ # :ported:
def test_access_to_action_name_in_view
get :accessing_action_name_in_template
assert_equal "accessing_action_name_in_template", @response.body
end
+ # :ported:
def test_access_to_controller_name_in_view
get :accessing_controller_name_in_template
assert_equal "test", @response.body # name is explicitly set to 'test' inside the controller.
@@ -978,6 +1029,7 @@ class RenderTest < ActionController::TestCase
assert_equal "text/javascript", @response.content_type
end
+ # :ported:
def test_render_xml
get :render_xml_hello
assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body
@@ -990,6 +1042,7 @@ class RenderTest < ActionController::TestCase
assert_equal "application/xml", @response.content_type
end
+ # :ported:
def test_render_xml_with_default
get :greeting
assert_equal "<p>This is grand!</p>\n", @response.body
@@ -1044,6 +1097,7 @@ class RenderTest < ActionController::TestCase
assert_template "test/hello_world"
end
+ # :ported:
def test_nested_rendering
@controller = Fun::GamesController.new
get :hello_world
@@ -1204,6 +1258,7 @@ class RenderTest < ActionController::TestCase
assert_equal "<html>Hello world!</html>", @response.body
end
+ # :ported:
def test_double_render
assert_raise(ActionController::DoubleRenderError) { get :double_render }
end
@@ -1232,11 +1287,13 @@ class RenderTest < ActionController::TestCase
assert_equal "<title>Talking to the layout</title>\nAction was here!", @response.body
end
+ # :addressed:
def test_render_text_with_assigns
get :render_text_with_assigns
assert_equal "world", assigns["hello"]
end
+ # :ported:
def test_template_with_locals
get :render_with_explicit_template_with_locals
assert_equal "The secret is area51\n", @response.body
@@ -1603,13 +1660,13 @@ class EtagRenderTest < ActionController::TestCase
def test_render_against_etag_request_should_200_when_no_match
@request.if_none_match = etag_for("hello somewhere else")
get :render_hello_world_from_variable
- assert_equal 200, @response.status
+ assert_equal 200, @response.status.to_i
assert !@response.body.empty?
end
def test_render_should_not_set_etag_when_last_modified_has_been_specified
get :render_hello_world_with_last_modified_set
- assert_equal 200, @response.status
+ assert_equal 200, @response.status.to_i
assert_not_nil @response.last_modified
assert_nil @response.etag
assert @response.body.present?
@@ -1623,11 +1680,12 @@ class EtagRenderTest < ActionController::TestCase
@request.if_none_match = expected_etag
get :render_hello_world_from_variable
- assert_equal 304, @response.status
+ assert_equal 304, @response.status.to_i
+ @response = ActionController::TestResponse.new
@request.if_none_match = "\"diftag\""
get :render_hello_world_from_variable
- assert_equal 200, @response.status
+ assert_equal 200, @response.status.to_i
end
def render_with_404_shouldnt_have_etag
@@ -1695,7 +1753,7 @@ class LastModifiedRenderTest < ActionController::TestCase
def test_request_not_modified
@request.if_modified_since = @last_modified
get :conditional_hello
- assert_equal 304, @response.status
+ assert_equal 304, @response.status.to_i
assert @response.body.blank?, @response.body
assert_equal @last_modified, @response.headers['Last-Modified']
end
@@ -1710,7 +1768,7 @@ class LastModifiedRenderTest < ActionController::TestCase
def test_request_modified
@request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT'
get :conditional_hello
- assert_equal 200, @response.status
+ assert_equal 200, @response.status.to_i
assert !@response.body.blank?
assert_equal @last_modified, @response.headers['Last-Modified']
end
diff --git a/actionpack/test/lib/fixture_template.rb b/actionpack/test/lib/fixture_template.rb
index 26f6ec2d0c..e43e329a9e 100644
--- a/actionpack/test/lib/fixture_template.rb
+++ b/actionpack/test/lib/fixture_template.rb
@@ -1,35 +1,104 @@
module ActionView #:nodoc:
- class FixtureTemplate < Template
- class FixturePath < Template::Path
- def initialize(hash = {})
- @hash = {}
-
- hash.each do |k, v|
- @hash[k.sub(/\.\w+$/, '')] = FixtureTemplate.new(v, k.split("/").last, self)
+class Template
+ class FixturePath < Path
+ 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
end
-
- super("fixtures://root")
- end
-
- def find_template(path)
- @hash[path]
end
end
- def initialize(body, *args)
- @body = body
- super(*args)
+ private
+
+ def formats_regexp
+ @formats_regexp ||= begin
+ formats = Mime::SET.map { |m| m.symbol }
+ '(?:' + formats.map { |l| "\\.#{Regexp.escape(l.to_s)}" }.join('|') + ')?'
+ end
end
- def source
- @body
+ def handler_regexp
+ e = TemplateHandlers.extensions.map{|h| "\\.#{Regexp.escape(h.to_s)}"}.join("|")
+ "(?:#{e})?"
end
- private
-
- def find_full_path(path, load_paths)
- return '/', path
+ 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
+ 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
+ end
end
-
end
+
+
+ # class FixtureTemplate < Template
+ # class FixturePath < Template::Path
+ # def initialize(hash = {})
+ # @hash = {}
+ #
+ # hash.each do |k, v|
+ # @hash[k.sub(/\.\w+$/, '')] = FixtureTemplate.new(v, k.split("/").last, self)
+ # end
+ #
+ # super("fixtures://root")
+ # end
+ #
+ # def find_template(path)
+ # @hash[path]
+ # end
+ # end
+ #
+ # def initialize(body, *args)
+ # @body = body
+ # super(*args)
+ # end
+ #
+ # def source
+ # @body
+ # end
+ #
+ # private
+ #
+ # def find_full_path(path, load_paths)
+ # return '/', path
+ # end
+ #
+ # end
+end
end \ No newline at end of file
diff --git a/actionpack/test/new_base/base_test.rb b/actionpack/test/new_base/base_test.rb
index 4f46cb6492..a32653f128 100644
--- a/actionpack/test/new_base/base_test.rb
+++ b/actionpack/test/new_base/base_test.rb
@@ -1,8 +1,8 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
# Tests the controller dispatching happy path
-module HappyPath
- class SimpleDispatchController < ActionController::Base2
+module Dispatching
+ class SimpleController < ActionController::Base
def index
render :text => "success"
end
@@ -23,7 +23,7 @@ module HappyPath
class TestSimpleDispatch < SimpleRouteCase
- get "/happy_path/simple_dispatch/index"
+ get "/dispatching/simple/index"
test "sets the body" do
assert_body "success"
@@ -34,57 +34,56 @@ module HappyPath
end
test "sets the content type" do
- assert_content_type Mime::HTML
+ assert_content_type "text/html; charset=utf-8"
end
test "sets the content length" do
- assert_header "Content-Length", 7
+ assert_header "Content-Length", "7"
end
end
# :api: plugin
class TestDirectResponseMod < SimpleRouteCase
- get "/happy_path/simple_dispatch/modify_response_body"
+ get "/dispatching/simple/modify_response_body"
test "sets the body" do
assert_body "success"
end
test "setting the body manually sets the content length" do
- assert_header "Content-Length", 7
+ assert_header "Content-Length", "7"
end
end
# :api: plugin
class TestDirectResponseModTwice < SimpleRouteCase
- get "/happy_path/simple_dispatch/modify_response_body_twice"
+ get "/dispatching/simple/modify_response_body_twice"
test "self.response_body= returns the body being set" do
assert_body "success!"
end
test "updating the response body updates the content length" do
- assert_header "Content-Length", 8
+ assert_header "Content-Length", "8"
end
end
-end
-
-
-class EmptyController < ActionController::Base2 ; end
-module Submodule
- class ContainedEmptyController < ActionController::Base2 ; end
-end
+
+ class EmptyController < ActionController::Base ; end
+ module Submodule
+ class ContainedEmptyController < ActionController::Base ; end
+ end
-class ControllerClassTests < Test::Unit::TestCase
- def test_controller_path
- assert_equal 'empty', EmptyController.controller_path
- assert_equal EmptyController.controller_path, EmptyController.new.controller_path
- assert_equal 'submodule/contained_empty', Submodule::ContainedEmptyController.controller_path
- assert_equal Submodule::ContainedEmptyController.controller_path, Submodule::ContainedEmptyController.new.controller_path
+ class ControllerClassTests < Test::Unit::TestCase
+ def test_controller_path
+ assert_equal 'dispatching/empty', EmptyController.controller_path
+ assert_equal EmptyController.controller_path, EmptyController.new.controller_path
+ assert_equal 'dispatching/submodule/contained_empty', Submodule::ContainedEmptyController.controller_path
+ assert_equal Submodule::ContainedEmptyController.controller_path, Submodule::ContainedEmptyController.new.controller_path
+ end
+ def test_controller_name
+ assert_equal 'empty', EmptyController.controller_name
+ assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name
+ end
end
- def test_controller_name
- assert_equal 'empty', EmptyController.controller_name
- assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name
- end
end \ No newline at end of file
diff --git a/actionpack/test/new_base/content_type_test.rb b/actionpack/test/new_base/content_type_test.rb
new file mode 100644
index 0000000000..a5c04e9cb6
--- /dev/null
+++ b/actionpack/test/new_base/content_type_test.rb
@@ -0,0 +1,111 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module ContentType
+ class BaseController < ActionController::Base
+ def index
+ render :text => "Hello world!"
+ end
+
+ def set_on_response_obj
+ response.content_type = Mime::RSS
+ render :text => "Hello world!"
+ end
+
+ def set_on_render
+ render :text => "Hello world!", :content_type => Mime::RSS
+ end
+ end
+
+ class TestDefault < SimpleRouteCase
+ describe "a default response is HTML and UTF8"
+
+ get "/content_type/base"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+
+ class TestSetOnResponseObj < SimpleRouteCase
+ describe "setting the content type of the response directly on the response object"
+
+ get "/content_type/base/set_on_response_obj"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "application/rss+xml; charset=utf-8"
+ end
+
+ class TestSetOnRender < SimpleRouteCase
+ describe "setting the content type of the response as an option to render"
+
+ get "/content_type/base/set_on_render"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "application/rss+xml; charset=utf-8"
+ end
+
+ class ImpliedController < ActionController::Base
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "content_type/implied/i_am_html_erb.html.erb" => "Hello world!",
+ "content_type/implied/i_am_xml_erb.xml.erb" => "<xml>Hello world!</xml>",
+ "content_type/implied/i_am_html_builder.html.builder" => "xml.p 'Hello'",
+ "content_type/implied/i_am_xml_builder.xml.builder" => "xml.awesome 'Hello'"
+ )]
+
+ def i_am_html_erb() end
+ def i_am_xml_erb() end
+ def i_am_html_builder() end
+ def i_am_xml_builder() end
+ end
+
+ class TestImpliedController < SimpleRouteCase
+ describe "the template's mime type is used if no content_type is specified"
+
+ test "sets Content-Type as text/html when rendering *.html.erb" do
+ get "/content_type/implied/i_am_html_erb"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+
+ test "sets Content-Type as application/xml when rendering *.xml.erb" do
+ get "/content_type/implied/i_am_xml_erb"
+ assert_header "Content-Type", "application/xml; charset=utf-8"
+ end
+
+ test "sets Content-Type as text/html when rendering *.html.builder" do
+ get "/content_type/implied/i_am_html_builder"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+
+ test "sets Content-Type as application/xml when rendering *.xml.builder" do
+ get "/content_type/implied/i_am_xml_builder"
+ assert_header "Content-Type", "application/xml; charset=utf-8"
+ end
+
+ end
+end
+
+module Charset
+ class BaseController < ActionController::Base
+ def set_on_response_obj
+ response.charset = "utf-16"
+ render :text => "Hello world!"
+ end
+
+ def set_as_nil_on_response_obj
+ response.charset = nil
+ render :text => "Hello world!"
+ end
+ end
+
+ class TestSetOnResponseObj < SimpleRouteCase
+ describe "setting the charset of the response directly on the response object"
+
+ get "/charset/base/set_on_response_obj"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-16"
+ end
+
+ class TestSetAsNilOnResponseObj < SimpleRouteCase
+ describe "setting the charset of the response as nil directly on the response object"
+
+ get "/charset/base/set_as_nil_on_response_obj"
+ assert_body "Hello world!"
+ assert_header "Content-Type", "text/html; charset=utf-8"
+ end
+end \ No newline at end of file
diff --git a/actionpack/test/new_base/etag_test.rb b/actionpack/test/new_base/etag_test.rb
new file mode 100644
index 0000000000..7af5febfb3
--- /dev/null
+++ b/actionpack/test/new_base/etag_test.rb
@@ -0,0 +1,47 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module Etags
+
+ class BasicController < ActionController::Base
+
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "etags/basic/base.html.erb" => "Hello from without_layout.html.erb",
+ "layouts/etags.html.erb" => "teh <%= yield %> tagz"
+ )]
+
+ def without_layout
+ render :action => "base"
+ end
+
+ def with_layout
+ render :action => "base", :layout => "etag"
+ end
+
+ end
+
+ class TestBasic < SimpleRouteCase
+ describe "Rendering without any special etag options returns an etag that is an MD5 hash of its text"
+
+ test "an action without a layout" do
+ get "/etags/basic/without_layout"
+ body = "Hello from without_layout.html.erb"
+ assert_body body
+ assert_header "Etag", etag_for(body)
+ assert_status 200
+ end
+
+ test "an action with a layout" do
+ get "/etags/basic/with_layout"
+ body = "teh Hello from without_layout.html.erb tagz"
+ assert_body body
+ assert_header "Etag", etag_for(body)
+ assert_status 200
+ end
+
+ def etag_for(text)
+ %("#{Digest::MD5.hexdigest(text)}")
+ end
+ end
+
+
+end \ No newline at end of file
diff --git a/actionpack/test/new_base/render_action_test.rb b/actionpack/test/new_base/render_action_test.rb
index 2bfb374a31..348d70381b 100644
--- a/actionpack/test/new_base/render_action_test.rb
+++ b/actionpack/test/new_base/render_action_test.rb
@@ -3,9 +3,9 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module RenderAction
# This has no layout and it works
- class BasicController < ActionController::Base2
+ class BasicController < ActionController::Base
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"render_action/basic/hello_world.html.erb" => "Hello world!"
)]
@@ -129,7 +129,7 @@ module RenderActionWithApplicationLayout
class BasicController < ::ApplicationController
# Set the view path to an application view structure with layouts
- self.view_paths = self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new(
"render_action_with_application_layout/basic/hello_world.html.erb" => "Hello World!",
"layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI",
"layouts/greetings.html.erb" => "Greetings <%= yield %> Bai"
@@ -203,8 +203,8 @@ end
module RenderActionWithControllerLayout
- class BasicController < ActionController::Base2
- self.view_paths = self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ class BasicController < ActionController::Base
+ self.view_paths = self.view_paths = [ActionView::Template::FixturePath.new(
"render_action_with_controller_layout/basic/hello_world.html.erb" => "Hello World!",
"layouts/render_action_with_controller_layout/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI"
)]
@@ -266,8 +266,8 @@ end
module RenderActionWithBothLayouts
- class BasicController < ActionController::Base2
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new({
+ class BasicController < ActionController::Base
+ self.view_paths = [ActionView::Template::FixturePath.new({
"render_action_with_both_layouts/basic/hello_world.html.erb" => "Hello World!",
"layouts/application.html.erb" => "OHAI <%= yield %> KTHXBAI",
"layouts/render_action_with_both_layouts/basic.html.erb" => "With Controller Layout! <%= yield %> KTHXBAI"
diff --git a/actionpack/test/new_base/render_implicit_action_test.rb b/actionpack/test/new_base/render_implicit_action_test.rb
index 798505b539..58f5cec181 100644
--- a/actionpack/test/new_base/render_implicit_action_test.rb
+++ b/actionpack/test/new_base/render_implicit_action_test.rb
@@ -1,16 +1,28 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
-module HappyPath
-
- class RenderImplicitActionController < ActionController::Base2
- # No actions yet, they are implicit
+module RenderImplicitAction
+ class SimpleController < ::ApplicationController
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "render_implicit_action/simple/hello_world.html.erb" => "Hello world!",
+ "render_implicit_action/simple/hyphen-ated.html.erb" => "Hello hyphen-ated!"
+ )]
+
+ def hello_world() end
end
- class TestRendersActionImplicitly < SimpleRouteCase
-
- test "renders action implicitly" do
- assert true
- end
+ class TestImplicitRender < SimpleRouteCase
+ describe "render a simple action with new explicit call to render"
+
+ get "/render_implicit_action/simple/hello_world"
+ assert_body "Hello world!"
+ assert_status 200
+ end
+ class TestImplicitWithSpecialCharactersRender < SimpleRouteCase
+ describe "render an action with a missing method and has special characters"
+
+ get "/render_implicit_action/simple/hyphen-ated"
+ assert_body "Hello hyphen-ated!"
+ assert_status 200
end
end \ No newline at end of file
diff --git a/actionpack/test/new_base/render_layout_test.rb b/actionpack/test/new_base/render_layout_test.rb
index facf67ea85..5d28926cc6 100644
--- a/actionpack/test/new_base/render_layout_test.rb
+++ b/actionpack/test/new_base/render_layout_test.rb
@@ -3,14 +3,23 @@ require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
module ControllerLayouts
class ImplicitController < ::ApplicationController
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "OMG <%= yield %> KTHXBAI",
- "basic.html.erb" => "Hello world!"
+ "layouts/override.html.erb" => "Override! <%= yield %>",
+ "basic.html.erb" => "Hello world!"
)]
def index
render :template => "basic"
end
+
+ def override
+ render :template => "basic", :layout => "override"
+ end
+
+ def builder_override
+
+ end
end
class TestImplicitLayout < SimpleRouteCase
@@ -23,7 +32,7 @@ module ControllerLayouts
class ImplicitNameController < ::ApplicationController
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/controller_layouts/implicit_name.html.erb" => "OMGIMPLICIT <%= yield %> KTHXBAI",
"basic.html.erb" => "Hello world!"
)]
@@ -41,5 +50,10 @@ module ControllerLayouts
assert_status 200
end
-
+ class TestOverridingImplicitLayout < SimpleRouteCase
+ describe "overriding an implicit layout with render :layout option"
+
+ get "/controller_layouts/implicit/override"
+ assert_body "Override! Hello world!"
+ end
end \ No newline at end of file
diff --git a/actionpack/test/new_base/render_template_test.rb b/actionpack/test/new_base/render_template_test.rb
index c6c0269b40..c09eeb1926 100644
--- a/actionpack/test/new_base/render_template_test.rb
+++ b/actionpack/test/new_base/render_template_test.rb
@@ -1,43 +1,35 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
-module HappyPath
-
- class RenderTemplateWithoutLayoutController < ActionController::Base2
+module RenderTemplate
+ class WithoutLayoutController < ActionController::Base
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
- "shared.html.erb" => "Elastica"
+ "shared.html.erb" => "Elastica",
+ "locals.html.erb" => "The secret is <%= secret %>"
)]
- def render_hello_world
+ def index
render :template => "test/basic"
end
- def render_hello_world_with_forward_slash
- render :template => "/test/basic"
- end
-
- def render_template_in_top_directory
+ def in_top_directory
render :template => 'shared'
end
- def render_template_in_top_directory_with_slash
+ def in_top_directory_with_slash
render :template => '/shared'
end
- end
-
- class TestTemplateRenderWithoutLayout < SimpleRouteCase
- describe "rendering a normal template with full path without layout"
- get "/happy_path/render_template_without_layout/render_hello_world"
- assert_body "Hello from basic.html.erb"
- assert_status 200
+ def with_locals
+ render :template => "locals", :locals => { :secret => 'area51' }
+ end
end
- class TestTemplateRenderWithForwardSlash < SimpleRouteCase
- describe "rendering a normal template with full path starting with a leading slash"
+ class TestWithoutLayout < SimpleRouteCase
+ describe "rendering a normal template with full path without layout"
- get "/happy_path/render_template_without_layout/render_hello_world_with_forward_slash"
+ get "/render_template/without_layout"
assert_body "Hello from basic.html.erb"
assert_status 200
end
@@ -45,7 +37,7 @@ module HappyPath
class TestTemplateRenderInTopDirectory < SimpleRouteCase
describe "rendering a template not in a subdirectory"
- get "/happy_path/render_template_without_layout/render_template_in_top_directory"
+ get "/render_template/without_layout/in_top_directory"
assert_body "Elastica"
assert_status 200
end
@@ -53,37 +45,45 @@ module HappyPath
class TestTemplateRenderInTopDirectoryWithSlash < SimpleRouteCase
describe "rendering a template not in a subdirectory with a leading slash"
- get "/happy_path/render_template_without_layout/render_template_in_top_directory_with_slash"
+ get "/render_template/without_layout/in_top_directory_with_slash"
assert_body "Elastica"
assert_status 200
end
+
+ class TestTemplateRenderWithLocals < SimpleRouteCase
+ describe "rendering a template with local variables"
- class RenderTemplateWithLayoutController < ::ApplicationController
+ get "/render_template/without_layout/with_locals"
+ assert_body "The secret is area51"
+ assert_status 200
+ end
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ class WithLayoutController < ::ApplicationController
+
+ self.view_paths = [ActionView::Template::FixturePath.new(
"test/basic.html.erb" => "Hello from basic.html.erb",
"shared.html.erb" => "Elastica",
"layouts/application.html.erb" => "<%= yield %>, I'm here!",
"layouts/greetings.html.erb" => "<%= yield %>, I wish thee well."
)]
- def render_hello_world
+ def index
render :template => "test/basic"
end
- def render_hello_world_with_layout
+ def with_layout
render :template => "test/basic", :layout => true
end
- def render_hello_world_with_layout_false
+ def with_layout_false
render :template => "test/basic", :layout => false
end
- def render_hello_world_with_layout_nil
+ def with_layout_nil
render :template => "test/basic", :layout => nil
end
- def render_hello_world_with_custom_layout
+ def with_custom_layout
render :template => "test/basic", :layout => "greetings"
end
end
@@ -91,7 +91,7 @@ module HappyPath
class TestTemplateRenderWithLayout < SimpleRouteCase
describe "rendering a normal template with full path with layout"
- get "/happy_path/render_template_with_layout/render_hello_world"
+ get "/render_template/with_layout"
assert_body "Hello from basic.html.erb, I'm here!"
assert_status 200
end
@@ -99,7 +99,7 @@ module HappyPath
class TestTemplateRenderWithLayoutTrue < SimpleRouteCase
describe "rendering a normal template with full path with layout => :true"
- get "/happy_path/render_template_with_layout/render_hello_world_with_layout"
+ get "/render_template/with_layout/with_layout"
assert_body "Hello from basic.html.erb, I'm here!"
assert_status 200
end
@@ -107,7 +107,7 @@ module HappyPath
class TestTemplateRenderWithLayoutFalse < SimpleRouteCase
describe "rendering a normal template with full path with layout => :false"
- get "/happy_path/render_template_with_layout/render_hello_world_with_layout_false"
+ get "/render_template/with_layout/with_layout_false"
assert_body "Hello from basic.html.erb"
assert_status 200
end
@@ -115,7 +115,7 @@ module HappyPath
class TestTemplateRenderWithLayoutNil < SimpleRouteCase
describe "rendering a normal template with full path with layout => :nil"
- get "/happy_path/render_template_with_layout/render_hello_world_with_layout_nil"
+ get "/render_template/with_layout/with_layout_nil"
assert_body "Hello from basic.html.erb"
assert_status 200
end
@@ -123,11 +123,29 @@ module HappyPath
class TestTemplateRenderWithCustomLayout < SimpleRouteCase
describe "rendering a normal template with full path with layout => 'greetings'"
- get "/happy_path/render_template_with_layout/render_hello_world_with_custom_layout"
+ get "/render_template/with_layout/with_custom_layout"
assert_body "Hello from basic.html.erb, I wish thee well."
assert_status 200
end
-
+ module Compatibility
+ class WithoutLayoutController < ActionController::Base
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "test/basic.html.erb" => "Hello from basic.html.erb",
+ "shared.html.erb" => "Elastica"
+ )]
+ def with_forward_slash
+ render :template => "/test/basic"
+ end
+ end
+
+ class TestTemplateRenderWithForwardSlash < SimpleRouteCase
+ describe "rendering a normal template with full path starting with a leading slash"
+
+ get "/render_template/compatibility/without_layout/with_forward_slash"
+ assert_body "Hello from basic.html.erb"
+ assert_status 200
+ end
+ end
end \ No newline at end of file
diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb
new file mode 100644
index 0000000000..b1867fdcc2
--- /dev/null
+++ b/actionpack/test/new_base/render_test.rb
@@ -0,0 +1,88 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
+
+module Render
+ class BlankRenderController < ActionController::Base
+ self.view_paths = [ActionView::Template::FixturePath.new(
+ "render/blank_render/index.html.erb" => "Hello world!",
+ "render/blank_render/access_request.html.erb" => "The request: <%= request.method.to_s.upcase %>",
+ "render/blank_render/access_action_name.html.erb" => "Action Name: <%= action_name %>",
+ "render/blank_render/access_controller_name.html.erb" => "Controller Name: <%= controller_name %>"
+ )]
+
+ def index
+ render
+ end
+
+ def access_request
+ render :action => "access_request"
+ end
+
+ def render_action_name
+ render :action => "access_action_name"
+ end
+
+ private
+
+ def secretz
+ render :text => "FAIL WHALE!"
+ end
+ end
+
+ class TestBlankRender < SimpleRouteCase
+ describe "Render with blank"
+
+ get "/render/blank_render"
+ assert_body "Hello world!"
+ assert_status 200
+ end
+
+ class DoubleRenderController < ActionController::Base
+ def index
+ render :text => "hello"
+ render :text => "world"
+ end
+ end
+
+ class TestBasic < SimpleRouteCase
+ describe "Rendering more than once"
+
+ test "raises an exception" do
+ assert_raises(AbstractController::DoubleRenderError) do
+ get "/render/double_render"
+ end
+ end
+ end
+
+ class TestOnlyRenderPublicActions < SimpleRouteCase
+ describe "Only public methods on actual controllers are callable actions"
+
+ test "raises an exception when a method of Object is called" do
+ assert_raises(AbstractController::ActionNotFound) do
+ get "/render/blank_render/clone"
+ end
+ end
+
+ test "raises an exception when a private method is called" do
+ assert_raises(AbstractController::ActionNotFound) do
+ get "/render/blank_render/secretz"
+ end
+ end
+ end
+
+ class TestVariousObjectsAvailableInView < SimpleRouteCase
+ test "The request object is accessible in the view" do
+ get "/render/blank_render/access_request"
+ assert_body "The request: GET"
+ end
+
+ test "The action_name is accessible in the view" do
+ get "/render/blank_render/render_action_name"
+ assert_body "Action Name: render_action_name"
+ end
+
+ test "The controller_name is accessible in the view" do
+ get "/render/blank_render/access_controller_name"
+ assert_body "Controller Name: blank_render"
+ end
+ end
+end \ No newline at end of file
diff --git a/actionpack/test/new_base/render_text_test.rb b/actionpack/test/new_base/render_text_test.rb
index a20ca5fb8c..39f2f7abbf 100644
--- a/actionpack/test/new_base/render_text_test.rb
+++ b/actionpack/test/new_base/render_text_test.rb
@@ -1,77 +1,82 @@
require File.join(File.expand_path(File.dirname(__FILE__)), "test_helper")
-class ApplicationController < ActionController::Base2
+class ApplicationController < ActionController::Base
end
-module HappyPath
-
- class RenderTextWithoutLayoutsController < ActionController::Base2
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new]
+module RenderText
+ class SimpleController < ActionController::Base
+ self.view_paths = [ActionView::Template::FixturePath.new]
- def render_hello_world
+ def index
render :text => "hello david"
end
end
- class RenderTextWithLayoutsController < ::ApplicationController
- self.view_paths = [ActionView::FixtureTemplate::FixturePath.new(
+ class TestSimpleTextRenderWithNoLayout < SimpleRouteCase
+ describe "Rendering text from a action with default options renders the text with the layout"
+
+ get "/render_text/simple"
+ assert_body "hello david"
+ assert_status 200
+ end
+
+ class WithLayoutController < ::ApplicationController
+ self.view_paths = [ActionView::Template::FixturePath.new(
"layouts/application.html.erb" => "<%= yield %>, I'm here!",
- "layouts/greetings.html.erb" => "<%= yield %>, I wish thee well."
+ "layouts/greetings.html.erb" => "<%= yield %>, I wish thee well.",
+ "layouts/ivar.html.erb" => "<%= yield %>, <%= @ivar %>"
)]
- def render_hello_world
+ def index
render :text => "hello david"
end
- def render_custom_code
+ def custom_code
render :text => "hello world", :status => 404
end
- def render_with_custom_code_as_string
+ def with_custom_code_as_string
render :text => "hello world", :status => "404 Not Found"
end
- def render_text_with_nil
+ def with_nil
render :text => nil
end
- def render_text_with_nil_and_status
+ def with_nil_and_status
render :text => nil, :status => 403
end
- def render_text_with_false
+ def with_false
render :text => false
end
- def render_text_with_layout
+ def with_layout_true
render :text => "hello world", :layout => true
end
- def render_text_with_layout_false
+ def with_layout_false
render :text => "hello world", :layout => false
end
- def render_text_with_layout_nil
+ def with_layout_nil
render :text => "hello world", :layout => nil
end
- def render_text_with_custom_layout
+ def with_custom_layout
render :text => "hello world", :layout => "greetings"
end
- end
-
- class TestSimpleTextRenderWithNoLayout < SimpleRouteCase
- describe "Rendering text from a action with default options renders the text with the layout"
- get "/happy_path/render_text_without_layouts/render_hello_world"
- assert_body "hello david"
- assert_status 200
+ def with_ivar_in_layout
+ @ivar = "hello world"
+ render :text => "hello world", :layout => "ivar"
+ end
end
-
+
class TestSimpleTextRenderWithLayout < SimpleRouteCase
describe "Rendering text from a action with default options renders the text without the layout"
- get "/happy_path/render_text_with_layouts/render_hello_world"
+ get "/render_text/with_layout"
assert_body "hello david"
assert_status 200
end
@@ -79,7 +84,7 @@ module HappyPath
class TestTextRenderWithStatus < SimpleRouteCase
describe "Rendering text, while also providing a custom status code"
- get "/happy_path/render_text_with_layouts/render_custom_code"
+ get "/render_text/with_layout/custom_code"
assert_body "hello world"
assert_status 404
end
@@ -87,7 +92,7 @@ module HappyPath
class TestTextRenderWithNil < SimpleRouteCase
describe "Rendering text with nil returns a single space character"
- get "/happy_path/render_text_with_layouts/render_text_with_nil"
+ get "/render_text/with_layout/with_nil"
assert_body " "
assert_status 200
end
@@ -95,7 +100,7 @@ module HappyPath
class TestTextRenderWithNilAndStatus < SimpleRouteCase
describe "Rendering text with nil and custom status code returns a single space character with the status"
- get "/happy_path/render_text_with_layouts/render_text_with_nil_and_status"
+ get "/render_text/with_layout/with_nil_and_status"
assert_body " "
assert_status 403
end
@@ -103,7 +108,7 @@ module HappyPath
class TestTextRenderWithFalse < SimpleRouteCase
describe "Rendering text with false returns the string 'false'"
- get "/happy_path/render_text_with_layouts/render_text_with_false"
+ get "/render_text/with_layout/with_false"
assert_body "false"
assert_status 200
end
@@ -111,7 +116,7 @@ module HappyPath
class TestTextRenderWithLayoutTrue < SimpleRouteCase
describe "Rendering text with :layout => true"
- get "/happy_path/render_text_with_layouts/render_text_with_layout"
+ get "/render_text/with_layout/with_layout_true"
assert_body "hello world, I'm here!"
assert_status 200
end
@@ -119,7 +124,7 @@ module HappyPath
class TestTextRenderWithCustomLayout < SimpleRouteCase
describe "Rendering text with :layout => 'greetings'"
- get "/happy_path/render_text_with_layouts/render_text_with_custom_layout"
+ get "/render_text/with_layout/with_custom_layout"
assert_body "hello world, I wish thee well."
assert_status 200
end
@@ -127,7 +132,7 @@ module HappyPath
class TestTextRenderWithLayoutFalse < SimpleRouteCase
describe "Rendering text with :layout => false"
- get "/happy_path/render_text_with_layouts/render_text_with_layout_false"
+ get "/render_text/with_layout/with_layout_false"
assert_body "hello world"
assert_status 200
end
@@ -135,10 +140,10 @@ module HappyPath
class TestTextRenderWithLayoutNil < SimpleRouteCase
describe "Rendering text with :layout => nil"
- get "/happy_path/render_text_with_layouts/render_text_with_layout_nil"
+ get "/render_text/with_layout/with_layout_nil"
assert_body "hello world"
assert_status 200
end
end
-ActionController::Base2.app_loaded! \ No newline at end of file
+ActionController::Base.app_loaded! \ No newline at end of file
diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb
index 89c29d9af3..78662dc989 100644
--- a/actionpack/test/new_base/test_helper.rb
+++ b/actionpack/test/new_base/test_helper.rb
@@ -5,8 +5,7 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
require 'test/unit'
require 'active_support'
require 'active_support/test_case'
-require 'action_controller'
-require 'action_view/base'
+require 'action_view'
require 'fixture_template'
begin
@@ -24,35 +23,11 @@ require 'pp' # require 'pp' early to prevent hidden_methods from not picking up
require 'rubygems'
require 'rack/test'
-module ActionController
- class Base2 < AbstractBase
- include AbstractController::Callbacks
- include AbstractController::Helpers
- include AbstractController::Logger
-
- include ActionController::HideActions
- include ActionController::UrlFor
- include ActionController::Renderer
- include ActionController::Layouts
-
- def self.inherited(klass)
- ::ActionController::Base2.subclasses << klass.to_s
- super
- end
-
- def self.subclasses
- @subclasses ||= []
- end
-
- def self.app_loaded!
- @subclasses.each do |subclass|
- subclass.constantize._write_layout_method
- end
- end
-
- # append_view_path File.join(File.dirname(__FILE__), '..', 'fixtures')
-
- CORE_METHODS = self.public_instance_methods
+module Rails
+ def self.env
+ x = Object.new
+ def x.test?() true end
+ x
end
end
@@ -64,7 +39,7 @@ class Rack::TestCase < ActiveSupport::TestCase
ActionController::Base.session_options[:key] = "abc"
ActionController::Base.session_options[:secret] = ("*" * 30)
- controllers = ActionController::Base2.subclasses.map do |k|
+ controllers = ActionController::Base.subclasses.map do |k|
k.underscore.sub(/_controller$/, '')
end
@@ -91,7 +66,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
def assert_body(body)
- assert_equal [body], last_response.body
+ assert_equal body, Array.wrap(last_response.body).join
end
def self.assert_body(body)
@@ -132,7 +107,7 @@ class Rack::TestCase < ActiveSupport::TestCase
end
-class ::ApplicationController < ActionController::Base2
+class ::ApplicationController < ActionController::Base
end
class SimpleRouteCase < Rack::TestCase
diff --git a/actionpack/test/template/output_buffer_test.rb b/actionpack/test/template/output_buffer_test.rb
index 3faea64db3..171cfb63e1 100644
--- a/actionpack/test/template/output_buffer_test.rb
+++ b/actionpack/test/template/output_buffer_test.rb
@@ -10,32 +10,32 @@ class OutputBufferTest < ActionController::TestCase
tests TestController
def test_flush_output_buffer
- pending do
+ pending
# TODO: This tests needs to be rewritten due
# The @response is not the same response object assigned
# to the @controller.template
# Start with the default body parts
- get :index
- assert_equal ['foo'], @response.body_parts
- assert_nil @controller.template.output_buffer
-
- # Nil output buffer is skipped
- @controller.template.flush_output_buffer
- assert_nil @controller.template.output_buffer
- assert_equal ['foo'], @response.body_parts
-
- # Empty output buffer is skipped
- @controller.template.output_buffer = ''
- @controller.template.flush_output_buffer
- assert_equal '', @controller.template.output_buffer
- assert_equal ['foo'], @response.body_parts
-
- # Flushing appends the output buffer to the body parts
- @controller.template.output_buffer = 'bar'
- @controller.template.flush_output_buffer
- assert_equal '', @controller.template.output_buffer
- assert_equal ['foo', 'bar'], @response.body_parts
- end
+ # ---
+ # get :index
+ # assert_equal ['foo'], @response.body_parts
+ # assert_nil @controller.template.output_buffer
+ #
+ # # Nil output buffer is skipped
+ # @controller.template.flush_output_buffer
+ # assert_nil @controller.template.output_buffer
+ # assert_equal ['foo'], @response.body_parts
+ #
+ # # Empty output buffer is skipped
+ # @controller.template.output_buffer = ''
+ # @controller.template.flush_output_buffer
+ # assert_equal '', @controller.template.output_buffer
+ # assert_equal ['foo'], @response.body_parts
+ #
+ # # Flushing appends the output buffer to the body parts
+ # @controller.template.output_buffer = 'bar'
+ # @controller.template.flush_output_buffer
+ # assert_equal '', @controller.template.output_buffer
+ # assert_equal ['foo', 'bar'], @response.body_parts
end
end
diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb
index 1eefebb3b3..359e70f5ed 100644
--- a/activerecord/lib/active_record/aggregations.rb
+++ b/activerecord/lib/active_record/aggregations.rb
@@ -1,8 +1,6 @@
module ActiveRecord
module Aggregations # :nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::DependencyModule
def clear_aggregation_cache #:nodoc:
self.class.reflect_on_all_aggregations.to_a.each do |assoc|
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index e4ab69aa1b..5df76bb183 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -1,9 +1,7 @@
module ActiveRecord
# See ActiveRecord::AssociationPreload::ClassMethods for documentation.
module AssociationPreload #:nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::DependencyModule
# Implements the details of eager loading of ActiveRecord associations.
# Application developers should not use this module directly.
@@ -126,6 +124,7 @@ module ActiveRecord
association_proxy = parent_record.send(reflection_name)
association_proxy.loaded
association_proxy.target.push(*[associated_record].flatten)
+ association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
end
end
@@ -152,7 +151,8 @@ module ActiveRecord
seen_keys[associated_record[key].to_s] = true
mapped_records = id_to_record_map[associated_record[key].to_s]
mapped_records.each do |mapped_record|
- mapped_record.send("set_#{reflection_name}_target", associated_record)
+ association_proxy = mapped_record.send("set_#{reflection_name}_target", associated_record)
+ association_proxy.__send__(:set_inverse_instance, associated_record, mapped_record)
end
end
end
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index b23cb14c1b..2fe08b2456 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -77,6 +77,8 @@ module ActiveRecord
# See ActiveRecord::Associations::ClassMethods for documentation.
module Associations # :nodoc:
+ extend ActiveSupport::DependencyModule
+
# These classes will be loaded when associations are created.
# So there is no need to eager load them.
autoload :AssociationCollection, 'active_record/associations/association_collection'
@@ -89,10 +91,6 @@ module ActiveRecord
autoload :HasOneAssociation, 'active_record/associations/has_one_association'
autoload :HasOneThroughAssociation, 'active_record/associations/has_one_through_association'
- def self.included(base)
- base.extend(ClassMethods)
- end
-
# Clears out the association cache
def clear_association_cache #:nodoc:
self.class.reflect_on_all_associations.to_a.each do |assoc|
@@ -1679,17 +1677,29 @@ module ActiveRecord
string.scan(/([\.a-zA-Z_]+).?\./).flatten
end
+ def tables_in_hash(hash)
+ return [] if hash.blank?
+ tables = hash.map do |key, value|
+ if value.is_a?(Hash)
+ key.to_s
+ else
+ tables_in_string(key) if key.is_a?(String)
+ end
+ end
+ tables.flatten.compact
+ end
+
def conditions_tables(options)
# look in both sets of conditions
conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond|
case cond
when nil then all
- when Array then all << cond.first
- when Hash then all << cond.keys
- else all << cond
+ when Array then all << tables_in_string(cond.first)
+ when Hash then all << tables_in_hash(cond)
+ else all << tables_in_string(cond)
end
end
- tables_in_string(conditions.join(' '))
+ conditions.flatten
end
def order_tables(options)
@@ -1924,21 +1934,27 @@ module ActiveRecord
return nil if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil?
association = join.instantiate(row)
collection.target.push(association)
+ collection.__send__(:set_inverse_instance, association, record)
when :has_one
return if record.id.to_s != join.parent.record_id(row).to_s
return if record.instance_variable_defined?("@#{join.reflection.name}")
association = join.instantiate(row) unless row[join.aliased_primary_key].nil?
- record.send("set_#{join.reflection.name}_target", association)
+ set_target_and_inverse(join, association, record)
when :belongs_to
return if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil?
association = join.instantiate(row)
- record.send("set_#{join.reflection.name}_target", association)
+ set_target_and_inverse(join, association, record)
else
raise ConfigurationError, "unknown macro: #{join.reflection.macro}"
end
return association
end
+ def set_target_and_inverse(join, association, record)
+ association_proxy = record.send("set_#{join.reflection.name}_target", association)
+ association_proxy.__send__(:set_inverse_instance, association, record)
+ end
+
class JoinBase # :nodoc:
attr_reader :active_record, :table_joins
delegate :table_name, :column_names, :primary_key, :reflections, :sanitize_sql, :to => :active_record
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index 4908005d2e..b72b84343b 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -90,7 +90,7 @@ module ActiveRecord
when @reflection.options[:as]
@finder_sql =
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " +
- "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.name.to_s)}"
+ "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
else
@finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
end
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 3ffc48941c..8d68d77eac 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -1,17 +1,21 @@
module ActiveRecord
module AttributeMethods #:nodoc:
+ extend ActiveSupport::DependencyModule
+
DEFAULT_SUFFIXES = %w(= ? _before_type_cast)
ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date]
- def self.included(base)
- base.extend ClassMethods
- base.attribute_method_suffix(*DEFAULT_SUFFIXES)
- base.cattr_accessor :attribute_types_cached_by_default, :instance_writer => false
- base.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
- base.cattr_accessor :time_zone_aware_attributes, :instance_writer => false
- base.time_zone_aware_attributes = false
- base.class_inheritable_accessor :skip_time_zone_conversion_for_attributes, :instance_writer => false
- base.skip_time_zone_conversion_for_attributes = []
+ included do
+ attribute_method_suffix(*DEFAULT_SUFFIXES)
+
+ cattr_accessor :attribute_types_cached_by_default, :instance_writer => false
+ self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
+
+ cattr_accessor :time_zone_aware_attributes, :instance_writer => false
+ self.time_zone_aware_attributes = false
+
+ class_inheritable_accessor :skip_time_zone_conversion_for_attributes, :instance_writer => false
+ self.skip_time_zone_conversion_for_attributes = []
end
# Declare and check for suffixed attribute methods.
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index 9717ca3d8b..4ab2818282 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -125,16 +125,15 @@ module ActiveRecord
# post.author.name = ''
# post.save(false) # => true
module AutosaveAssociation
+ extend ActiveSupport::DependencyModule
+
ASSOCIATION_TYPES = %w{ has_one belongs_to has_many has_and_belongs_to_many }
- def self.included(base)
- base.class_eval do
- base.extend(ClassMethods)
- alias_method_chain :reload, :autosave_associations
+ included do
+ alias_method_chain :reload, :autosave_associations
- ASSOCIATION_TYPES.each do |type|
- base.send("valid_keys_for_#{type}_association") << :autosave
- end
+ ASSOCIATION_TYPES.each do |type|
+ send("valid_keys_for_#{type}_association") << :autosave
end
end
diff --git a/activerecord/lib/active_record/batches.rb b/activerecord/lib/active_record/batches.rb
index 5a6cecd4ad..4836601297 100644
--- a/activerecord/lib/active_record/batches.rb
+++ b/activerecord/lib/active_record/batches.rb
@@ -1,8 +1,6 @@
module ActiveRecord
module Batches # :nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::DependencyModule
# When processing large numbers of records, it's often a good idea to do
# so in batches to prevent memory ballooning.
diff --git a/activerecord/lib/active_record/calculations.rb b/activerecord/lib/active_record/calculations.rb
index 9d04686a5f..98f9450662 100644
--- a/activerecord/lib/active_record/calculations.rb
+++ b/activerecord/lib/active_record/calculations.rb
@@ -1,9 +1,8 @@
module ActiveRecord
module Calculations #:nodoc:
+ extend ActiveSupport::DependencyModule
+
CALCULATIONS_OPTIONS = [:conditions, :joins, :order, :select, :group, :having, :distinct, :limit, :offset, :include, :from]
- def self.included(base)
- base.extend(ClassMethods)
- end
module ClassMethods
# Count operates using three different approaches.
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index e375037b5b..a77fdb1c13 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -211,21 +211,23 @@ module ActiveRecord
# needs to be aware of it because an ordinary +save+ will raise such exception
# instead of quietly returning +false+.
module Callbacks
+ extend ActiveSupport::DependencyModule
+
CALLBACKS = %w(
after_find after_initialize before_save after_save before_create after_create before_update after_update before_validation
after_validation before_validation_on_create after_validation_on_create before_validation_on_update
after_validation_on_update before_destroy after_destroy
)
- def self.included(base) #:nodoc:
- base.extend Observable
+ included do
+ extend Observable
[:create_or_update, :valid?, :create, :update, :destroy].each do |method|
- base.send :alias_method_chain, method, :callbacks
+ alias_method_chain method, :callbacks
end
- base.send :include, ActiveSupport::Callbacks
- base.define_callbacks *CALLBACKS
+ include ActiveSupport::Callbacks
+ define_callbacks *CALLBACKS
end
# Is called when the object was instantiated by one of the finders, like <tt>Base.find</tt>.
diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb
index 4a2510aa63..fac6ca40d3 100644
--- a/activerecord/lib/active_record/dirty.rb
+++ b/activerecord/lib/active_record/dirty.rb
@@ -34,20 +34,21 @@ module ActiveRecord
# person.name << 'by'
# person.name_change # => ['uncle bob', 'uncle bobby']
module Dirty
+ extend ActiveSupport::DependencyModule
+
DIRTY_SUFFIXES = ['_changed?', '_change', '_will_change!', '_was']
- def self.included(base)
- base.attribute_method_suffix *DIRTY_SUFFIXES
- base.alias_method_chain :write_attribute, :dirty
- base.alias_method_chain :save, :dirty
- base.alias_method_chain :save!, :dirty
- base.alias_method_chain :update, :dirty
- base.alias_method_chain :reload, :dirty
+ included do
+ attribute_method_suffix *DIRTY_SUFFIXES
- base.superclass_delegating_accessor :partial_updates
- base.partial_updates = true
+ alias_method_chain :write_attribute, :dirty
+ alias_method_chain :save, :dirty
+ alias_method_chain :save!, :dirty
+ alias_method_chain :update, :dirty
+ alias_method_chain :reload, :dirty
- base.send(:extend, ClassMethods)
+ superclass_delegating_accessor :partial_updates
+ self.partial_updates = true
end
# Do any attributes have unsaved changes?
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index c6501113bf..91b4b4e182 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -805,27 +805,25 @@ end
module ActiveRecord
module TestFixtures
- def self.included(base)
- base.class_eval do
- setup :setup_fixtures
- teardown :teardown_fixtures
-
- superclass_delegating_accessor :fixture_path
- superclass_delegating_accessor :fixture_table_names
- superclass_delegating_accessor :fixture_class_names
- superclass_delegating_accessor :use_transactional_fixtures
- superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
- superclass_delegating_accessor :pre_loaded_fixtures
-
- self.fixture_table_names = []
- self.use_transactional_fixtures = false
- self.use_instantiated_fixtures = true
- self.pre_loaded_fixtures = false
-
- self.fixture_class_names = {}
- end
+ extend ActiveSupport::DependencyModule
+
+ included do
+ setup :setup_fixtures
+ teardown :teardown_fixtures
+
+ superclass_delegating_accessor :fixture_path
+ superclass_delegating_accessor :fixture_table_names
+ superclass_delegating_accessor :fixture_class_names
+ superclass_delegating_accessor :use_transactional_fixtures
+ superclass_delegating_accessor :use_instantiated_fixtures # true, false, or :no_instances
+ superclass_delegating_accessor :pre_loaded_fixtures
+
+ self.fixture_table_names = []
+ self.use_transactional_fixtures = false
+ self.use_instantiated_fixtures = true
+ self.pre_loaded_fixtures = false
- base.extend ClassMethods
+ self.fixture_class_names = {}
end
module ClassMethods
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index a4f5dd8516..e51748b7d2 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -42,17 +42,17 @@ module ActiveRecord
# To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method.
# This method uses the same syntax as <tt>set_table_name</tt>
module Optimistic
- def self.included(base) #:nodoc:
- base.extend ClassMethods
+ extend ActiveSupport::DependencyModule
- base.cattr_accessor :lock_optimistically, :instance_writer => false
- base.lock_optimistically = true
+ included do
+ cattr_accessor :lock_optimistically, :instance_writer => false
+ self.lock_optimistically = true
- base.alias_method_chain :update, :lock
- base.alias_method_chain :destroy, :lock
- base.alias_method_chain :attributes_from_column_definition, :lock
+ alias_method_chain :update, :lock
+ alias_method_chain :destroy, :lock
+ alias_method_chain :attributes_from_column_definition, :lock
- class << base
+ class << self
alias_method :locking_column=, :set_locking_column
end
end
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 3df7089096..32bb36c07c 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -1,5 +1,7 @@
module ActiveRecord
module NamedScope
+ extend ActiveSupport::DependencyModule
+
# All subclasses of ActiveRecord::Base have one named scope:
# * <tt>scoped</tt> - which allows for the creation of anonymous \scopes, on the fly: <tt>Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions)</tt>
#
@@ -7,11 +9,8 @@ module ActiveRecord
# intermediate values (scopes) around as first-class objects is convenient.
#
# You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
- def self.included(base)
- base.class_eval do
- extend ClassMethods
- named_scope :scoped, lambda { |scope| scope }
- end
+ included do
+ named_scope :scoped, lambda { |scope| scope }
end
module ClassMethods
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index e3122d195a..1ea2f53fd8 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -1,9 +1,10 @@
module ActiveRecord
module NestedAttributes #:nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- base.class_inheritable_accessor :reject_new_nested_attributes_procs, :instance_writer => false
- base.reject_new_nested_attributes_procs = {}
+ extend ActiveSupport::DependencyModule
+
+ included do
+ class_inheritable_accessor :reject_new_nested_attributes_procs, :instance_writer => false
+ self.reject_new_nested_attributes_procs = {}
end
# == Nested Attributes
@@ -180,10 +181,14 @@ module ActiveRecord
# and the Proc should return either +true+ or +false+. When no Proc
# is specified a record will be built for all attribute hashes that
# do not have a <tt>_delete</tt> that evaluates to true.
+ # Passing <tt>:all_blank</tt> instead of a Proc will create a proc
+ # that will reject a record where all the attributes are blank.
#
# Examples:
# # creates avatar_attributes=
# accepts_nested_attributes_for :avatar, :reject_if => proc { |attributes| attributes['name'].blank? }
+ # # creates avatar_attributes=
+ # accepts_nested_attributes_for :avatar, :reject_if => :all_blank
# # creates avatar_attributes= and posts_attributes=
# accepts_nested_attributes_for :avatar, :posts, :allow_destroy => true
def accepts_nested_attributes_for(*attr_names)
@@ -201,7 +206,12 @@ module ActiveRecord
end
reflection.options[:autosave] = true
- self.reject_new_nested_attributes_procs[association_name.to_sym] = options[:reject_if]
+
+ self.reject_new_nested_attributes_procs[association_name.to_sym] = if options[:reject_if] == :all_blank
+ proc { |attributes| attributes.all? {|k,v| v.blank?} }
+ else
+ options[:reject_if]
+ end
# def pirate_attributes=(attributes)
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes, false)
diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb
index b35e407cc1..1ca76c7b2f 100644
--- a/activerecord/lib/active_record/observer.rb
+++ b/activerecord/lib/active_record/observer.rb
@@ -3,9 +3,7 @@ require 'set'
module ActiveRecord
module Observing # :nodoc:
- def self.included(base)
- base.extend ClassMethods
- end
+ extend ActiveSupport::DependencyModule
module ClassMethods
# Activates the observers assigned. Examples:
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index ec0175497d..3747ba449d 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -1,8 +1,6 @@
module ActiveRecord
module Reflection # :nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::DependencyModule
# Reflection allows you to interrogate Active Record classes and objects about their associations and aggregations.
# This information can, for example, be used in a form builder that took an Active Record object and created input
diff --git a/activerecord/lib/active_record/serializers/json_serializer.rb b/activerecord/lib/active_record/serializers/json_serializer.rb
index 48df15d2c0..d376fd5e1b 100644
--- a/activerecord/lib/active_record/serializers/json_serializer.rb
+++ b/activerecord/lib/active_record/serializers/json_serializer.rb
@@ -2,9 +2,10 @@ require 'active_support/json'
module ActiveRecord #:nodoc:
module Serialization
- def self.included(base)
- base.cattr_accessor :include_root_in_json, :instance_writer => false
- base.extend ClassMethods
+ extend ActiveSupport::DependencyModule
+
+ included do
+ cattr_accessor :include_root_in_json, :instance_writer => false
end
# Returns a JSON string representing the model. Some configuration is
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index d9e1ef351f..3734e170af 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -8,12 +8,14 @@ module ActiveRecord
# Timestamps are in the local timezone by default but you can use UTC by setting
# <tt>ActiveRecord::Base.default_timezone = :utc</tt>
module Timestamp
- def self.included(base) #:nodoc:
- base.alias_method_chain :create, :timestamps
- base.alias_method_chain :update, :timestamps
+ extend ActiveSupport::DependencyModule
- base.class_inheritable_accessor :record_timestamps, :instance_writer => false
- base.record_timestamps = true
+ included do
+ alias_method_chain :create, :timestamps
+ alias_method_chain :update, :timestamps
+
+ class_inheritable_accessor :record_timestamps, :instance_writer => false
+ self.record_timestamps = true
end
# Saves the record with the updated_at/on attributes set to the current time.
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index b059eb7f6f..471a81dfb5 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -3,16 +3,14 @@ require 'thread'
module ActiveRecord
# See ActiveRecord::Transactions::ClassMethods for documentation.
module Transactions
+ extend ActiveSupport::DependencyModule
+
class TransactionError < ActiveRecordError # :nodoc:
end
- def self.included(base)
- base.extend(ClassMethods)
-
- base.class_eval do
- [:destroy, :save, :save!].each do |method|
- alias_method_chain method, :transactions
- end
+ included do
+ [:destroy, :save, :save!].each do |method|
+ alias_method_chain method, :transactions
end
end
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index e6b61e0b35..9907a3c9b7 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -301,17 +301,16 @@ module ActiveRecord
#
# An Errors object is automatically created for every Active Record.
module Validations
+ extend ActiveSupport::DependencyModule
+
VALIDATIONS = %w( validate validate_on_create validate_on_update )
- def self.included(base) # :nodoc:
- base.extend ClassMethods
- base.class_eval do
- alias_method_chain :save, :validation
- alias_method_chain :save!, :validation
- end
+ included do
+ alias_method_chain :save, :validation
+ alias_method_chain :save!, :validation
- base.send :include, ActiveSupport::Callbacks
- base.define_callbacks *VALIDATIONS
+ include ActiveSupport::Callbacks
+ define_callbacks *VALIDATIONS
end
# Active Record classes can implement validations in several ways. The highest level, easiest to read,
diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
index 677226ec89..5f824f9c74 100644
--- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb
+++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
@@ -6,13 +6,12 @@ require 'models/category'
require 'models/categorization'
module Remembered
- def self.included(base)
- base.extend ClassMethods
- base.class_eval do
- after_create :remember
- protected
- def remember; self.class.remembered << self; end
- end
+ extend ActiveSupport::DependencyModule
+
+ included do
+ after_create :remember
+ protected
+ def remember; self.class.remembered << self; end
end
module ClassMethods
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 40723814c5..d23f86b700 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -223,6 +223,18 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
end
+ def test_eager_association_loading_with_belongs_to_and_conditions_hash
+ comments = []
+ assert_nothing_raised do
+ comments = Comment.find(:all, :include => :post, :conditions => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id')
+ end
+ assert_equal 3, comments.length
+ assert_equal [5,6,7], comments.collect { |c| c.id }
+ assert_no_queries do
+ comments.first.post
+ end
+ end
+
def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
assert_nothing_raised do
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 3984945f9f..1ddb3f49bf 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -2,11 +2,9 @@ require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
-require 'models/sponsor'
-require 'models/organization'
class HasOneAssociationsTest < ActiveRecord::TestCase
- fixtures :accounts, :companies, :developers, :projects, :developers_projects, :organizations, :sponsors
+ fixtures :accounts, :companies, :developers, :projects, :developers_projects
def setup
Account.destroyed_account_ids.clear
@@ -308,9 +306,4 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
Firm.find(@firm.id, :include => :account).save!
end
end
-
- def test_polymorphic_sti
- assert_equal organizations(:sponsorable), sponsors(:org_sponsor).sponsorable
- assert_equal sponsors(:org_sponsor), organizations(:sponsorable).sponsor
- end
end
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
index 616f8dfbbe..47f83db112 100644
--- a/activerecord/test/cases/associations/inverse_associations_test.rb
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -94,6 +94,25 @@ class InverseHasOneTests < ActiveRecord::TestCase
assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
end
+
+ def test_parent_instance_should_be_shared_with_eager_loaded_child_on_find
+ m = Man.find(:first, :include => :face)
+ f = m.face
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
+
+ m = Man.find(:first, :include => :face, :order => 'faces.id')
+ f = m.face
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
def test_parent_instance_should_be_shared_with_newly_built_child
m = Man.find(:first)
f = m.build_face(:description => 'haunted')
@@ -136,6 +155,29 @@ class InverseHasManyTests < ActiveRecord::TestCase
end
end
+ def test_parent_instance_should_be_shared_with_eager_loaded_children
+ m = Man.find(:first, :include => :interests)
+ is = m.interests
+ is.each do |i|
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
+ m = Man.find(:first, :include => :interests, :order => 'interests.id')
+ is = m.interests
+ is.each do |i|
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
+ end
+
def test_parent_instance_should_be_shared_with_newly_built_child
m = Man.find(:first)
i = m.interests.build(:topic => 'Industrial Revolution Re-enactment')
@@ -188,6 +230,25 @@ class InverseBelongsToTests < ActiveRecord::TestCase
assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
end
+ def test_eager_loaded_child_instance_should_be_shared_with_parent_on_find
+ f = Face.find(:first, :include => :man)
+ m = f.man
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
+
+
+ f = Face.find(:first, :include => :man, :order => 'men.id')
+ m = f.man
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
+ end
+
def test_child_instance_should_be_shared_with_newly_built_parent
f = Face.find(:first)
m = f.build_man(:name => 'Charles')
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index cd6277c24b..f1741ed54d 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -31,11 +31,27 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
end
def test_should_add_a_proc_to_reject_new_nested_attributes_procs
- [:parrots, :birds].each do |name|
+ [:parrots, :birds, :birds_with_reject_all_blank].each do |name|
assert_instance_of Proc, Pirate.reject_new_nested_attributes_procs[name]
end
end
+ def test_should_not_build_a_new_record_if_reject_all_blank_returns_false
+ pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
+ pirate.birds_with_reject_all_blank_attributes = [{:name => '', :color => ''}]
+ pirate.save!
+
+ assert pirate.birds_with_reject_all_blank.empty?
+ end
+
+ def test_should_build_a_new_record_if_reject_all_blank_does_not_return_false
+ pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
+ pirate.birds_with_reject_all_blank_attributes = [{:name => 'Tweetie', :color => ''}]
+ pirate.save!
+
+ assert_equal 1, pirate.birds_with_reject_all_blank.count
+ end
+
def test_should_raise_an_ArgumentError_for_non_existing_associations
assert_raise_with_message ArgumentError, "No association found for name `honesty'. Has it been defined yet?" do
Pirate.accepts_nested_attributes_for :honesty
diff --git a/activerecord/test/cases/repair_helper.rb b/activerecord/test/cases/repair_helper.rb
index 0155668811..686bfee46d 100644
--- a/activerecord/test/cases/repair_helper.rb
+++ b/activerecord/test/cases/repair_helper.rb
@@ -1,11 +1,7 @@
module ActiveRecord
module Testing
module RepairHelper
- def self.included(base)
- base.class_eval do
- extend ClassMethods
- end
- end
+ extend ActiveSupport::DependencyModule
module Toolbox
def self.record_validations(*model_classes)
diff --git a/activerecord/test/fixtures/organizations.yml b/activerecord/test/fixtures/organizations.yml
index 05d620fbc6..25295bff87 100644
--- a/activerecord/test/fixtures/organizations.yml
+++ b/activerecord/test/fixtures/organizations.yml
@@ -2,6 +2,4 @@ nsa:
name: No Such Agency
discordians:
name: Discordians
-sponsorable:
- name: We Need Money
- type: SponsorableOrganization
+
diff --git a/activerecord/test/fixtures/sponsors.yml b/activerecord/test/fixtures/sponsors.yml
index 97a7784047..42df8957d1 100644
--- a/activerecord/test/fixtures/sponsors.yml
+++ b/activerecord/test/fixtures/sponsors.yml
@@ -6,6 +6,4 @@ boring_club_sponsor_for_groucho:
sponsorable: some_other_guy (Member)
crazy_club_sponsor_for_groucho:
sponsor_club: crazy_club
- sponsorable: some_other_guy (Member)
-org_sponsor:
- sponsorable: sponsorable (SponsorableOrganization) \ No newline at end of file
+ sponsorable: some_other_guy (Member) \ No newline at end of file
diff --git a/activerecord/test/models/organization.rb b/activerecord/test/models/organization.rb
index 5d1308354d..d79d5037c8 100644
--- a/activerecord/test/models/organization.rb
+++ b/activerecord/test/models/organization.rb
@@ -1,8 +1,4 @@
class Organization < ActiveRecord::Base
has_many :member_details
has_many :members, :through => :member_details
-end
-
-class SponsorableOrganization < Organization
- has_one :sponsor, :as => :sponsorable
end \ No newline at end of file
diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb
index 238917bf30..acf53fce8b 100644
--- a/activerecord/test/models/pirate.rb
+++ b/activerecord/test/models/pirate.rb
@@ -28,11 +28,13 @@ class Pirate < ActiveRecord::Base
:after_add => proc {|p,b| p.ship_log << "after_adding_proc_bird_#{b.id || '<new>'}"},
:before_remove => proc {|p,b| p.ship_log << "before_removing_proc_bird_#{b.id}"},
:after_remove => proc {|p,b| p.ship_log << "after_removing_proc_bird_#{b.id}"}
+ has_many :birds_with_reject_all_blank, :class_name => "Bird"
accepts_nested_attributes_for :parrots, :birds, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
accepts_nested_attributes_for :parrots_with_method_callbacks, :parrots_with_proc_callbacks,
:birds_with_method_callbacks, :birds_with_proc_callbacks, :allow_destroy => true
+ accepts_nested_attributes_for :birds_with_reject_all_blank, :reject_if => :all_blank
validates_presence_of :catchphrase
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 3b0e17c867..a776cd974b 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -57,6 +57,7 @@ ActiveRecord::Schema.define do
create_table :birds, :force => true do |t|
t.string :name
+ t.string :color
t.integer :pirate_id
end
@@ -283,7 +284,6 @@ ActiveRecord::Schema.define do
create_table :organizations, :force => true do |t|
t.string :name
- t.string :type
end
create_table :owners, :primary_key => :owner_id ,:force => true do |t|
@@ -389,7 +389,7 @@ ActiveRecord::Schema.define do
create_table :sponsors, :force => true do |t|
t.integer :club_id
t.integer :sponsorable_id
- t.string :sponsorable_type
+ t.string :sponsorable_type
end
create_table :subscribers, :force => true, :id => false do |t|
diff --git a/activeresource/Rakefile b/activeresource/Rakefile
index bf7bbb0201..c3cde26b6c 100644
--- a/activeresource/Rakefile
+++ b/activeresource/Rakefile
@@ -4,7 +4,6 @@ require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
-require 'rake/contrib/sshpublisher'
require File.join(File.dirname(__FILE__), 'lib', 'active_resource', 'version')
@@ -117,12 +116,14 @@ end
desc "Publish the beta gem"
task :pgem => [:package] do
+ require 'rake/contrib/sshpublisher'
Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
`ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
+ require 'rake/contrib/sshpublisher'
Rake::SshDirPublisher.new("wrath.rubyonrails.org", "public_html/ar", "doc").upload
end
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index ca5ab13a46..032f0fb9c1 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Change spelling of Kyev timezone to Kyiv #2613 [Alexander Dymo]
+
* Add ActiveSupport.parse_json_times to disable time parsing in JSON backends that don't support it or don't need it. [rick]
* Add pluggable JSON backends with support for the JSON gem. [rick]
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index 04a32edefd..1fe4ffb8e1 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -132,7 +132,7 @@ class Date
# Short-hand for years_since(1)
def next_year
years_since(1)
- end
+ end unless method_defined?(:next_year)
# Short-hand for months_ago(1)
def last_month
@@ -142,7 +142,7 @@ class Date
# Short-hand for months_since(1)
def next_month
months_since(1)
- end
+ end unless method_defined?(:next_month)
# Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
def beginning_of_week
diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
index ddfa8d610d..5f01bc4fd6 100644
--- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
@@ -58,7 +58,7 @@ class DateTime
# Converts self to a Ruby Date object; time portion is discarded
def to_date
::Date.new(year, month, day)
- end
+ end unless method_defined?(:to_date)
# Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class
# If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time
@@ -69,12 +69,12 @@ class DateTime
# To be able to keep Times, Dates and DateTimes interchangeable on conversions
def to_datetime
self
- end
+ end unless method_defined?(:to_datetime)
# Converts datetime to an appropriate format for use in XML
def xmlschema
strftime("%Y-%m-%dT%H:%M:%S%Z")
- end if RUBY_VERSION < '1.9'
+ end unless method_defined?(:xmlschema)
# Converts self to a floating-point number of seconds since the Unix epoch
def to_f
diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb
index 94e01597a9..6d9c080442 100644
--- a/activesupport/lib/active_support/core_ext/time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/time/conversions.rb
@@ -69,7 +69,7 @@ class Time
# In this case, it simply returns +self+.
def to_time
self
- end
+ end unless method_defined?(:to_time)
# Converts a Time instance to a Ruby DateTime instance, preserving UTC offset.
#
diff --git a/activesupport/lib/active_support/dependency_module.rb b/activesupport/lib/active_support/dependency_module.rb
index c690b49a2b..8c202acc8f 100644
--- a/activesupport/lib/active_support/dependency_module.rb
+++ b/activesupport/lib/active_support/dependency_module.rb
@@ -4,14 +4,15 @@ module ActiveSupport
return if base < self
(@_dependencies ||= []).each { |dep| base.send(:include, dep) }
super
+ base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
+ base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
end
def included(base = nil, &block)
- if base.nil? && block_given?
+ if base.nil?
@_included_block = block
else
- base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
- base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
+ super
end
end
diff --git a/activesupport/lib/active_support/new_callbacks.rb b/activesupport/lib/active_support/new_callbacks.rb
index 7a48dbac04..9316d6d2b6 100644
--- a/activesupport/lib/active_support/new_callbacks.rb
+++ b/activesupport/lib/active_support/new_callbacks.rb
@@ -304,15 +304,6 @@ module ActiveSupport
end
end
- # This method_missing is supplied to catch callbacks with keys and create
- # the appropriate callback for future use.
- def method_missing(meth, *args, &blk)
- if meth.to_s =~ /_run__([\w:]+)__(\w+)__(\w+)__callbacks/
- return self.class._create_and_run_keyed_callback($1, $2.to_sym, $3.to_sym, self, &blk)
- end
- super
- end
-
# An Array with a compile method
class CallbackChain < Array
def initialize(symbol)
@@ -325,7 +316,7 @@ module ActiveSupport
each do |callback|
method << callback.start(key, options)
end
- method << "yield self if block_given?"
+ method << "yield self if block_given? && !halted"
reverse_each do |callback|
method << callback.end(key, options)
end
@@ -356,6 +347,7 @@ module ActiveSupport
str = <<-RUBY_EVAL
def _run_#{symbol}_callbacks(key = nil)
if key
+ key = key.hash.to_s.gsub(/-/, '_')
name = "_run__\#{self.class.name.split("::").last}__#{symbol}__\#{key}__callbacks"
if respond_to?(name)
diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb
index fed8094a24..8d1c0f5160 100644
--- a/activesupport/lib/active_support/ordered_hash.rb
+++ b/activesupport/lib/active_support/ordered_hash.rb
@@ -10,6 +10,16 @@ module ActiveSupport
@keys = []
end
+ def self.[](*args)
+ ordered_hash = new
+ args.each_with_index { |val,ind|
+ # Only every second value is a key.
+ next if ind % 2 != 0
+ ordered_hash[val] = args[ind + 1]
+ }
+ ordered_hash
+ end
+
def initialize_copy(other)
super
# make a deep copy of keys
@@ -57,6 +67,10 @@ module ActiveSupport
self
end
+ def to_a
+ @keys.map { |key| [ key, self[key] ] }
+ end
+
def each_key
@keys.each { |key| yield key }
end
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index e2d759aa50..b37dae1c2a 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -92,7 +92,7 @@ module ActiveSupport
"Bucharest" => "Europe/Bucharest",
"Cairo" => "Africa/Cairo",
"Helsinki" => "Europe/Helsinki",
- "Kyev" => "Europe/Kiev",
+ "Kyiv" => "Europe/Kiev",
"Riga" => "Europe/Riga",
"Sofia" => "Europe/Sofia",
"Tallinn" => "Europe/Tallinn",
@@ -336,7 +336,7 @@ module ActiveSupport
"Copenhagen", "Madrid", "Paris", "Amsterdam", "Berlin",
"Bern", "Rome", "Stockholm", "Vienna",
"West Central Africa" ],
- [ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyev", "Riga", "Sofia",
+ [ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyiv", "Riga", "Sofia",
"Tallinn", "Vilnius", "Athens", "Istanbul", "Minsk",
"Jerusalem", "Harare", "Pretoria" ],
[ 10_800, "Moscow", "St. Petersburg", "Volgograd", "Kuwait", "Riyadh",
diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb
index abe7790ebf..dec6106ac1 100644
--- a/activesupport/test/new_callbacks_test.rb
+++ b/activesupport/test/new_callbacks_test.rb
@@ -255,6 +255,26 @@ module NewCallbacksTest
end
end
+ class HyphenatedCallbacks
+ include ActiveSupport::NewCallbacks
+ define_callbacks :save
+ attr_reader :stuff
+
+ save_callback :before, :omg, :per_key => {:if => :yes}
+
+ def yes() true end
+
+ def omg
+ @stuff = "OMG"
+ end
+
+ def save
+ _run_save_callbacks("hyphen-ated") do
+ @stuff
+ end
+ end
+ end
+
class AroundCallbacksTest < Test::Unit::TestCase
def test_save_around
around = AroundPerson.new
@@ -345,7 +365,7 @@ module NewCallbacksTest
save_callback :after, :third
- attr_reader :history
+ attr_reader :history, :saved
def initialize
@history = []
end
@@ -370,7 +390,9 @@ module NewCallbacksTest
end
def save
- _run_save_callbacks
+ _run_save_callbacks do
+ @saved = true
+ end
end
end
@@ -380,5 +402,19 @@ module NewCallbacksTest
terminator.save
assert_equal ["first", "second", "third", "second", "first"], terminator.history
end
+
+ def test_block_never_called_if_terminated
+ obj = CallbackTerminator.new
+ obj.save
+ assert !obj.saved
+ end
end
+
+ class HyphenatedKeyTest < Test::Unit::TestCase
+ def test_save
+ obj = HyphenatedCallbacks.new
+ obj.save
+ assert_equal obj.stuff, "OMG"
+ end
+ end
end
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index 7cd8c8a8f4..647938dd87 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -51,6 +51,10 @@ class OrderedHashTest < Test::Unit::TestCase
assert_same @ordered_hash, @ordered_hash.to_hash
end
+ def test_to_a
+ assert_equal @keys.zip(@values), @ordered_hash.to_a
+ end
+
def test_has_key
assert_equal true, @ordered_hash.has_key?('blue')
assert_equal true, @ordered_hash.key?('blue')
@@ -158,4 +162,10 @@ class OrderedHashTest < Test::Unit::TestCase
def test_inspect
assert @ordered_hash.inspect.include?(@hash.inspect)
end
+
+ def test_alternate_initialization
+ alternate = ActiveSupport::OrderedHash[1,2,3,4]
+ assert_kind_of ActiveSupport::OrderedHash, alternate
+ assert_equal [1, 3], alternate.keys
+ end
end
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index 98e3a861e8..8e7dfb38cc 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,3 +1,8 @@
+*Edge*
+
+* Added db/seeds.rb as a default file for storing seed data for the database. Can be loaded with rake db:seed (or created alongside the db with db:setup). (This is also known as the "Stop Putting Gawd Damn Seed Data In Your Migrations" feature) [DHH]
+
+
*2.3.2 [Final] (March 15, 2009)*
* Remove outdated script/plugin options [Pratik Naik]
diff --git a/railties/Rakefile b/railties/Rakefile
index 9cd102df0f..4247742664 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -200,11 +200,14 @@ task :copy_configs do
cp "configs/locales/en.yml", "#{PKG_DESTINATION}/config/locales/en.yml"
+ cp "configs/seeds.rb", "#{PKG_DESTINATION}/db/seeds.rb"
+
cp "environments/boot.rb", "#{PKG_DESTINATION}/config/boot.rb"
cp "environments/environment.rb", "#{PKG_DESTINATION}/config/environment.rb"
cp "environments/production.rb", "#{PKG_DESTINATION}/config/environments/production.rb"
cp "environments/development.rb", "#{PKG_DESTINATION}/config/environments/development.rb"
cp "environments/test.rb", "#{PKG_DESTINATION}/config/environments/test.rb"
+
end
task :copy_binfiles do
diff --git a/railties/configs/seeds.rb b/railties/configs/seeds.rb
new file mode 100644
index 0000000000..3174d0cb8a
--- /dev/null
+++ b/railties/configs/seeds.rb
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+#
+# Examples:
+#
+# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
+# Major.create(:name => 'Daley', :city => cities.first)
diff --git a/railties/lib/rails_generator/generators/applications/app/app_generator.rb b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
index 2c31d89538..c8c2239f34 100644
--- a/railties/lib/rails_generator/generators/applications/app/app_generator.rb
+++ b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
@@ -125,6 +125,7 @@ class AppGenerator < Rails::Generator::Base
create_database_configuration_file(m)
create_routes_file(m)
create_locale_file(m)
+ create_seeds_file(m)
create_initializer_files(m)
create_environment_files(m)
end
@@ -176,6 +177,10 @@ class AppGenerator < Rails::Generator::Base
m.file "configs/routes.rb", "config/routes.rb"
end
+ def create_seeds_file(m)
+ m.file "configs/seeds.rb", "db/seeds.rb"
+ end
+
def create_initializer_files(m)
%w(
backtrace_silencers
diff --git a/railties/lib/tasks/databases.rake b/railties/lib/tasks/databases.rake
index 9588fabb2d..cdab5d8bb0 100644
--- a/railties/lib/tasks/databases.rake
+++ b/railties/lib/tasks/databases.rake
@@ -156,8 +156,8 @@ namespace :db do
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
end
- desc 'Drops and recreates the database from db/schema.rb for the current environment.'
- task :reset => ['db:drop', 'db:create', 'db:schema:load']
+ desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
+ task :reset => [ 'db:drop', 'db:setup' ]
desc "Retrieves the charset for the current environment's database"
task :charset => :environment do
@@ -206,6 +206,15 @@ namespace :db do
end
end
+ desc 'Create the database, load the schema, and initialize with the seed data'
+ task :setup => [ 'db:create', 'db:schema:load', 'db:seed' ]
+
+ desc 'Load the seed data from db/seeds.rb'
+ task :seed => :environment do
+ seed_file = File.join(Rails.root, 'db', 'seeds.rb')
+ load(seed_file) if File.exist?(seed_file)
+ end
+
namespace :fixtures do
desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
task :load => :environment do