From e58ad8ed9cb0e67fde93c7edc8a0e13b8bc342ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 30 Dec 2009 11:09:27 +0100 Subject: Setup and teardown now use new callbacks. --- activesupport/lib/active_support/callbacks.rb | 2 +- .../active_support/testing/setup_and_teardown.rb | 73 ++++++++++++++-------- activesupport/test/test_test.rb | 9 +-- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 97e2a478b5..05bc453dbf 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -90,7 +90,7 @@ module ActiveSupport class Callback @@_callback_sequence = 0 - attr_accessor :chain, :filter, :kind, :options, :per_key, :klass + attr_accessor :chain, :filter, :kind, :options, :per_key, :klass, :raw_filter def initialize(chain, filter, kind, options, klass) @chain, @kind, @klass = chain, kind, klass diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb index 0e998d2dbe..6ce9495cee 100644 --- a/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -1,16 +1,26 @@ module ActiveSupport module Testing module SetupAndTeardown - def self.included(base) - base.class_eval do - include ActiveSupport::DeprecatedCallbacks - define_callbacks :setup, :teardown + extend ActiveSupport::Concern - if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions - include ForMiniTest - else - include ForClassicTestUnit - end + included do + include ActiveSupport::Callbacks + define_callbacks :setup, :teardown + + if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions + include ForMiniTest + else + include ForClassicTestUnit + end + end + + module ClassMethods + def setup(*args, &block) + set_callback(:setup, :before, *args, &block) + end + + def teardown(*args, &block) + set_callback(:teardown, :after, *args, &block) end end @@ -18,13 +28,14 @@ module ActiveSupport def run(runner) result = '.' begin - run_callbacks :setup - result = super + _run_setup_callbacks do + result = super + end rescue Exception => e result = runner.puke(self.class, method_name, e) ensure begin - run_callbacks :teardown, :enumerator => :reverse_each + _run_teardown_callbacks rescue Exception => e result = runner.puke(self.class, method_name, e) end @@ -42,23 +53,17 @@ module ActiveSupport def run(result) return if @method_name.to_s == "default_test" - if using_mocha = respond_to?(:mocha_verify) - assertion_counter_klass = if defined?(Mocha::TestCaseAdapter::AssertionCounter) - Mocha::TestCaseAdapter::AssertionCounter - else - Mocha::Integration::TestUnit::AssertionCounter - end - assertion_counter = assertion_counter_klass.new(result) - end - + mocha_counter = retrieve_mocha_counter(result) yield(Test::Unit::TestCase::STARTED, name) @_result = result + begin begin - run_callbacks :setup - setup - __send__(@method_name) - mocha_verify(assertion_counter) if using_mocha + _run_setup_callbacks do + setup + __send__(@method_name) + mocha_verify(mocha_counter) if mocha_counter + end rescue Mocha::ExpectationError => e add_failure(e.message, e.backtrace) rescue Test::Unit::AssertionFailedError => e @@ -69,7 +74,7 @@ module ActiveSupport ensure begin teardown - run_callbacks :teardown, :enumerator => :reverse_each + _run_teardown_callbacks rescue Test::Unit::AssertionFailedError => e add_failure(e.message, e.backtrace) rescue Exception => e @@ -78,12 +83,26 @@ module ActiveSupport end end ensure - mocha_teardown if using_mocha + mocha_teardown if mocha_counter end + result.add_run yield(Test::Unit::TestCase::FINISHED, name) end + + protected + + def retrieve_mocha_counter(result) #:nodoc: + if using_mocha = respond_to?(:mocha_verify) + if defined?(Mocha::TestCaseAdapter::AssertionCounter) + Mocha::TestCaseAdapter::AssertionCounter.new(result) + else + Mocha::Integration::TestUnit::AssertionCounter.new(result) + end + end + end end + end end end diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb index 5cbffb81fc..1928da51ca 100644 --- a/activesupport/test/test_test.rb +++ b/activesupport/test/test_test.rb @@ -102,9 +102,9 @@ class SetupAndTeardownTest < ActiveSupport::TestCase teardown :foo, :sentinel, :foo def test_inherited_setup_callbacks - assert_equal [:reset_callback_record, :foo], self.class.setup_callback_chain.map(&:method) + assert_equal [:reset_callback_record, :foo], self.class._setup_callbacks.map(&:raw_filter) assert_equal [:foo], @called_back - assert_equal [:foo, :sentinel, :foo], self.class.teardown_callback_chain.map(&:method) + assert_equal [:foo, :sentinel, :foo], self.class._teardown_callbacks.map(&:raw_filter) end def setup @@ -114,6 +114,7 @@ class SetupAndTeardownTest < ActiveSupport::TestCase end protected + def reset_callback_record @called_back = [] end @@ -133,9 +134,9 @@ class SubclassSetupAndTeardownTest < SetupAndTeardownTest teardown :bar def test_inherited_setup_callbacks - assert_equal [:reset_callback_record, :foo, :bar], self.class.setup_callback_chain.map(&:method) + assert_equal [:reset_callback_record, :foo, :bar], self.class._setup_callbacks.map(&:raw_filter) assert_equal [:foo, :bar], @called_back - assert_equal [:foo, :sentinel, :foo, :bar], self.class.teardown_callback_chain.map(&:method) + assert_equal [:foo, :sentinel, :foo, :bar], self.class._teardown_callbacks.map(&:raw_filter) end protected -- cgit v1.2.3 From 97a64b6b22d87cb6f89a224f7832433b86b545c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 30 Dec 2009 11:43:34 +0100 Subject: Get rid of DeprecatedCallbacks in ActiveRecord::Associations and finally remove it. --- .../associations/association_collection.rb | 9 +- activerecord/lib/active_record/callbacks.rb | 2 +- activerecord/lib/active_record/validations.rb | 2 - activesupport/lib/active_support.rb | 1 - .../lib/active_support/deprecated_callbacks.rb | 284 --------------------- 5 files changed, 9 insertions(+), 289 deletions(-) delete mode 100644 activesupport/lib/active_support/deprecated_callbacks.rb diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index b2b3a9789c..1ceb0dbf96 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -485,7 +485,14 @@ module ActiveRecord def callback(method, record) callbacks_for(method).each do |callback| - ActiveSupport::DeprecatedCallbacks::Callback.new(method, callback, record).call(@owner, record) + case callback + when Symbol + @owner.send(callback, record) + when Proc + callback.call(@owner, record) + else + callback.send(method, @owner, record) + end end end diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index e1d772bd95..e2a8f03c8f 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -274,7 +274,7 @@ module ActiveRecord def deprecated_callback_method(symbol) #:nodoc: if respond_to?(symbol) - ActiveSupport::Deprecation.warn("Base##{symbol} has been deprecated, please use Base.#{symbol} :method instead") + ActiveSupport::Deprecation.warn("Overwriting #{symbol} in your models has been deprecated, please use Base##{symbol} :method_name instead") send(symbol) end end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index e8a2a72735..12c1f23763 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -17,8 +17,6 @@ module ActiveRecord module Validations extend ActiveSupport::Concern - - include ActiveSupport::DeprecatedCallbacks include ActiveModel::Validations included do diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 8215cfaf0d..3463000529 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -50,7 +50,6 @@ module ActiveSupport autoload :Callbacks autoload :Concern autoload :Configurable - autoload :DeprecatedCallbacks autoload :Deprecation autoload :Gzip autoload :Inflector diff --git a/activesupport/lib/active_support/deprecated_callbacks.rb b/activesupport/lib/active_support/deprecated_callbacks.rb deleted file mode 100644 index f56fef0b6d..0000000000 --- a/activesupport/lib/active_support/deprecated_callbacks.rb +++ /dev/null @@ -1,284 +0,0 @@ -require 'active_support/core_ext/array/extract_options' -require 'active_support/core_ext/array/wrap' - -module ActiveSupport - # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic - # before or after an alteration of the object state. - # - # Mixing in this module allows you to define callbacks in your class. - # - # Example: - # class Storage - # include ActiveSupport::DeprecatedCallbacks - # - # define_callbacks :before_save, :after_save - # end - # - # class ConfigStorage < Storage - # before_save :saving_message - # def saving_message - # puts "saving..." - # end - # - # after_save do |object| - # puts "saved" - # end - # - # def save - # run_callbacks(:before_save) - # puts "- save" - # run_callbacks(:after_save) - # end - # end - # - # config = ConfigStorage.new - # config.save - # - # Output: - # saving... - # - save - # saved - # - # Callbacks from parent classes are inherited. - # - # Example: - # class Storage - # include ActiveSupport::DeprecatedCallbacks - # - # define_callbacks :before_save, :after_save - # - # before_save :prepare - # def prepare - # puts "preparing save" - # end - # end - # - # class ConfigStorage < Storage - # before_save :saving_message - # def saving_message - # puts "saving..." - # end - # - # after_save do |object| - # puts "saved" - # end - # - # def save - # run_callbacks(:before_save) - # puts "- save" - # run_callbacks(:after_save) - # end - # end - # - # config = ConfigStorage.new - # config.save - # - # Output: - # preparing save - # saving... - # - save - # saved - module DeprecatedCallbacks - class CallbackChain < Array - def self.build(kind, *methods, &block) - methods, options = extract_options(*methods, &block) - methods.map! { |method| Callback.new(kind, method, options) } - new(methods) - end - - def run(object, options = {}, &terminator) - enumerator = options[:enumerator] || :each - - unless block_given? - send(enumerator) { |callback| callback.call(object) } - else - send(enumerator) do |callback| - result = callback.call(object) - break result if terminator.call(result, object) - end - end - end - - # TODO: Decompose into more Array like behavior - def replace_or_append!(chain) - if index = index(chain) - self[index] = chain - else - self << chain - end - self - end - - def find(callback, &block) - select { |c| c == callback && (!block_given? || yield(c)) }.first - end - - def delete(callback) - super(callback.is_a?(Callback) ? callback : find(callback)) - end - - private - def self.extract_options(*methods, &block) - methods.flatten! - options = methods.extract_options! - methods << block if block_given? - return methods, options - end - - def extract_options(*methods, &block) - self.class.extract_options(*methods, &block) - end - end - - class Callback - attr_reader :kind, :method, :identifier, :options - - def initialize(kind, method, options = {}) - @kind = kind - @method = method - @identifier = options[:identifier] - @options = options - end - - def ==(other) - case other - when Callback - (self.identifier && self.identifier == other.identifier) || self.method == other.method - else - (self.identifier && self.identifier == other) || self.method == other - end - end - - def eql?(other) - self == other - end - - def dup - self.class.new(@kind, @method, @options.dup) - end - - def hash - if @identifier - @identifier.hash - else - @method.hash - end - end - - def call(*args, &block) - evaluate_method(method, *args, &block) if should_run_callback?(*args) - rescue LocalJumpError - raise ArgumentError, - "Cannot yield from a Proc type filter. The Proc must take two " + - "arguments and execute #call on the second argument." - end - - private - def evaluate_method(method, *args, &block) - case method - when Symbol - object = args.shift - object.send(method, *args, &block) - when String - eval(method, args.first.instance_eval { binding }) - when Proc, Method - method.call(*args, &block) - else - if method.respond_to?(kind) - method.send(kind, *args, &block) - else - raise ArgumentError, - "Callbacks must be a symbol denoting the method to call, a string to be evaluated, " + - "a block to be invoked, or an object responding to the callback method." - end - end - end - - def should_run_callback?(*args) - Array.wrap(options[:if]).flatten.compact.all? { |a| evaluate_method(a, *args) } && - !Array.wrap(options[:unless]).flatten.compact.any? { |a| evaluate_method(a, *args) } - end - end - - def self.included(base) - base.extend ClassMethods - end - - module ClassMethods - def define_callbacks(*callbacks) - ActiveSupport::Deprecation.warn('ActiveSupport::DeprecatedCallbacks has been deprecated in favor of ActiveSupport::Callbacks', caller) - - callbacks.each do |callback| - class_eval <<-"end_eval", __FILE__, __LINE__ + 1 - def self.#{callback}(*methods, &block) # def self.before_save(*methods, &block) - callbacks = CallbackChain.build(:#{callback}, *methods, &block) # callbacks = CallbackChain.build(:before_save, *methods, &block) - @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new - @#{callback}_callbacks.concat callbacks # @before_save_callbacks.concat callbacks - end # end - # - def self.#{callback}_callback_chain # def self.before_save_callback_chain - @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new - # - if superclass.respond_to?(:#{callback}_callback_chain) # if superclass.respond_to?(:before_save_callback_chain) - CallbackChain.new( # CallbackChain.new( - superclass.#{callback}_callback_chain + # superclass.before_save_callback_chain + - @#{callback}_callbacks # @before_save_callbacks - ) # ) - else # else - @#{callback}_callbacks # @before_save_callbacks - end # end - end # end - end_eval - end - end - end - - # Runs all the callbacks defined for the given options. - # - # If a block is given it will be called after each callback receiving as arguments: - # - # * the result from the callback - # * the object which has the callback - # - # If the result from the block evaluates to +true+, the callback chain is stopped. - # - # Example: - # class Storage - # include ActiveSupport::DeprecatedCallbacks - # - # define_callbacks :before_save, :after_save - # end - # - # class ConfigStorage < Storage - # before_save :pass - # before_save :pass - # before_save :stop - # before_save :pass - # - # def pass - # puts "pass" - # end - # - # def stop - # puts "stop" - # return false - # end - # - # def save - # result = run_callbacks(:before_save) { |result, object| result == false } - # puts "- save" if result - # end - # end - # - # config = ConfigStorage.new - # config.save - # - # Output: - # pass - # pass - # stop - def run_callbacks(kind, options = {}, &block) - self.class.send("#{kind}_callback_chain").run(self, options, &block) - end - end -end -- cgit v1.2.3 From 4ecdf24bdedfdd1cca1f079259ff2490e2074067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 30 Dec 2009 13:07:48 +0100 Subject: Kick AR logging back to life and move ControllerRuntime inside ActiveRecord::Rails. --- .../test/activerecord/controller_runtime_test.rb | 39 ++++++++++++++++++++++ activerecord/lib/active_record/base.rb | 1 - .../connection_adapters/abstract_adapter.rb | 10 ++++-- .../lib/active_record/controller_runtime.rb | 27 --------------- activerecord/lib/active_record/rails.rb | 3 +- .../lib/active_record/rails/controller_runtime.rb | 29 ++++++++++++++++ 6 files changed, 77 insertions(+), 32 deletions(-) create mode 100644 actionpack/test/activerecord/controller_runtime_test.rb delete mode 100644 activerecord/lib/active_record/controller_runtime.rb create mode 100644 activerecord/lib/active_record/rails/controller_runtime.rb diff --git a/actionpack/test/activerecord/controller_runtime_test.rb b/actionpack/test/activerecord/controller_runtime_test.rb new file mode 100644 index 0000000000..dd31add4b4 --- /dev/null +++ b/actionpack/test/activerecord/controller_runtime_test.rb @@ -0,0 +1,39 @@ +require 'active_record_unit' +require 'active_record/rails/controller_runtime' +require 'fixtures/project' + +ActionController::Base.send :include, ActiveRecord::Rails::ControllerRuntime + +class ARLoggingController < ActionController::Base + def show + render :inline => "<%= Project.all %>" + end +end + +class ARLoggingTest < ActionController::TestCase + tests ARLoggingController + + def setup + super + set_logger + end + + def wait + ActiveSupport::Notifications.notifier.wait + end + + def test_log_with_active_record + get :show + wait + assert_match /ActiveRecord runtime/, logs[3] + end + + private + def set_logger + @controller.logger = MockLogger.new + end + + def logs + @logs ||= @controller.logger.logged.compact.map {|l| l.to_s.strip} + end +end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 07c5545171..c4bdbdad08 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1,4 +1,3 @@ -require 'benchmark' require 'yaml' require 'set' require 'active_support/benchmarkable' diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 8fae26b790..d09aa3c4d2 100755 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -1,6 +1,7 @@ require 'date' require 'bigdecimal' require 'bigdecimal/util' +require 'active_support/core_ext/benchmark' # TODO: Autoload these files require 'active_record/connection_adapters/abstract/schema_definitions' @@ -191,7 +192,6 @@ module ActiveRecord end def log_info(sql, name, ms) - @runtime += ms if @logger && @logger.debug? name = '%s (%.1fms)' % [name || 'SQL', ms] @logger.debug(format_log_entry(name, sql.squeeze(' '))) @@ -199,8 +199,12 @@ module ActiveRecord end protected - def log(sql, name, &block) - ActiveSupport::Notifications.instrument(:sql, :sql => sql, :name => name, &block) + def log(sql, name) + result = nil + ActiveSupport::Notifications.instrument(:sql, :sql => sql, :name => name) do + @runtime += Benchmark.ms { result = yield } + end + result rescue Exception => e # Log message and raise exception. # Set last_verification to 0, so that connection gets verified diff --git a/activerecord/lib/active_record/controller_runtime.rb b/activerecord/lib/active_record/controller_runtime.rb deleted file mode 100644 index 1281901ae8..0000000000 --- a/activerecord/lib/active_record/controller_runtime.rb +++ /dev/null @@ -1,27 +0,0 @@ -module ActiveRecord - module ControllerRuntime - extend ActiveSupport::Concern - - attr_internal :db_runtime - - def cleanup_view_runtime - if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? - db_rt_before_render = ActiveRecord::Base.connection.reset_runtime - runtime = super - db_rt_after_render = ActiveRecord::Base.connection.reset_runtime - self.db_runtime = db_rt_before_render + db_rt_after_render - runtime - db_rt_after_render - else - super - end - end - - module ClassMethods - def process_log_action(controller) - super - db_runtime = controller.send :db_runtime - logger.info(" ActiveRecord runtime: %.1fms" % db_runtime.to_f) if db_runtime - end - end - end -end \ No newline at end of file diff --git a/activerecord/lib/active_record/rails.rb b/activerecord/lib/active_record/rails.rb index e7de699974..69f38e75c8 100644 --- a/activerecord/lib/active_record/rails.rb +++ b/activerecord/lib/active_record/rails.rb @@ -3,13 +3,14 @@ # here. This is needed for correctly setting up the middleware. # In the future, this might become an optional require. require "action_controller/rails" +require "active_record/rails/controller_runtime" module ActiveRecord class Plugin < Rails::Plugin plugin_name :active_record include_modules_in "ActiveRecord::Base" - config.action_controller.include "ActiveRecord::ControllerRuntime" + config.action_controller.include "ActiveRecord::Rails::ControllerRuntime" rake_tasks do load "active_record/rails/databases.rake" diff --git a/activerecord/lib/active_record/rails/controller_runtime.rb b/activerecord/lib/active_record/rails/controller_runtime.rb new file mode 100644 index 0000000000..9ae40c5c8f --- /dev/null +++ b/activerecord/lib/active_record/rails/controller_runtime.rb @@ -0,0 +1,29 @@ +module ActiveRecord + module Rails + module ControllerRuntime + extend ActiveSupport::Concern + + attr_internal :db_runtime + + def cleanup_view_runtime + if ActiveRecord::Base.connected? + db_rt_before_render = ActiveRecord::Base.connection.reset_runtime + runtime = super + db_rt_after_render = ActiveRecord::Base.connection.reset_runtime + self.db_runtime = db_rt_before_render + db_rt_after_render + runtime - db_rt_after_render + else + super + end + end + + module ClassMethods + def log_process_action(controller) + super + db_runtime = controller.send :db_runtime + logger.info(" ActiveRecord runtime: %.1fms" % db_runtime.to_f) if db_runtime + end + end + end + end +end \ No newline at end of file -- cgit v1.2.3 From bb153f42e45160c5ef3593c393db5d3c6857fb70 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Wed, 30 Dec 2009 12:58:40 -0800 Subject: ActionDispatch should require as little of ActiveSupport as possible --- actionpack/lib/action_dispatch.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 7f61ff5657..49e1634af5 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -21,9 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ -activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) -$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) -require 'active_support/ruby/shim' +require 'active_support' require 'active_support/dependencies/autoload' require 'rack' -- cgit v1.2.3 From a6e2d16b1ef1fbde28325f0e0e2b8855d6a7606c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 30 Dec 2009 11:09:27 +0100 Subject: Setup and teardown now use new callbacks. --- activesupport/lib/active_support/callbacks.rb | 2 +- .../active_support/testing/setup_and_teardown.rb | 73 ++++++++++++++-------- activesupport/test/test_test.rb | 9 +-- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 97e2a478b5..05bc453dbf 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -90,7 +90,7 @@ module ActiveSupport class Callback @@_callback_sequence = 0 - attr_accessor :chain, :filter, :kind, :options, :per_key, :klass + attr_accessor :chain, :filter, :kind, :options, :per_key, :klass, :raw_filter def initialize(chain, filter, kind, options, klass) @chain, @kind, @klass = chain, kind, klass diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb index 0e998d2dbe..6ce9495cee 100644 --- a/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -1,16 +1,26 @@ module ActiveSupport module Testing module SetupAndTeardown - def self.included(base) - base.class_eval do - include ActiveSupport::DeprecatedCallbacks - define_callbacks :setup, :teardown + extend ActiveSupport::Concern - if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions - include ForMiniTest - else - include ForClassicTestUnit - end + included do + include ActiveSupport::Callbacks + define_callbacks :setup, :teardown + + if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions + include ForMiniTest + else + include ForClassicTestUnit + end + end + + module ClassMethods + def setup(*args, &block) + set_callback(:setup, :before, *args, &block) + end + + def teardown(*args, &block) + set_callback(:teardown, :after, *args, &block) end end @@ -18,13 +28,14 @@ module ActiveSupport def run(runner) result = '.' begin - run_callbacks :setup - result = super + _run_setup_callbacks do + result = super + end rescue Exception => e result = runner.puke(self.class, method_name, e) ensure begin - run_callbacks :teardown, :enumerator => :reverse_each + _run_teardown_callbacks rescue Exception => e result = runner.puke(self.class, method_name, e) end @@ -42,23 +53,17 @@ module ActiveSupport def run(result) return if @method_name.to_s == "default_test" - if using_mocha = respond_to?(:mocha_verify) - assertion_counter_klass = if defined?(Mocha::TestCaseAdapter::AssertionCounter) - Mocha::TestCaseAdapter::AssertionCounter - else - Mocha::Integration::TestUnit::AssertionCounter - end - assertion_counter = assertion_counter_klass.new(result) - end - + mocha_counter = retrieve_mocha_counter(result) yield(Test::Unit::TestCase::STARTED, name) @_result = result + begin begin - run_callbacks :setup - setup - __send__(@method_name) - mocha_verify(assertion_counter) if using_mocha + _run_setup_callbacks do + setup + __send__(@method_name) + mocha_verify(mocha_counter) if mocha_counter + end rescue Mocha::ExpectationError => e add_failure(e.message, e.backtrace) rescue Test::Unit::AssertionFailedError => e @@ -69,7 +74,7 @@ module ActiveSupport ensure begin teardown - run_callbacks :teardown, :enumerator => :reverse_each + _run_teardown_callbacks rescue Test::Unit::AssertionFailedError => e add_failure(e.message, e.backtrace) rescue Exception => e @@ -78,12 +83,26 @@ module ActiveSupport end end ensure - mocha_teardown if using_mocha + mocha_teardown if mocha_counter end + result.add_run yield(Test::Unit::TestCase::FINISHED, name) end + + protected + + def retrieve_mocha_counter(result) #:nodoc: + if using_mocha = respond_to?(:mocha_verify) + if defined?(Mocha::TestCaseAdapter::AssertionCounter) + Mocha::TestCaseAdapter::AssertionCounter.new(result) + else + Mocha::Integration::TestUnit::AssertionCounter.new(result) + end + end + end end + end end end diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb index 5cbffb81fc..1928da51ca 100644 --- a/activesupport/test/test_test.rb +++ b/activesupport/test/test_test.rb @@ -102,9 +102,9 @@ class SetupAndTeardownTest < ActiveSupport::TestCase teardown :foo, :sentinel, :foo def test_inherited_setup_callbacks - assert_equal [:reset_callback_record, :foo], self.class.setup_callback_chain.map(&:method) + assert_equal [:reset_callback_record, :foo], self.class._setup_callbacks.map(&:raw_filter) assert_equal [:foo], @called_back - assert_equal [:foo, :sentinel, :foo], self.class.teardown_callback_chain.map(&:method) + assert_equal [:foo, :sentinel, :foo], self.class._teardown_callbacks.map(&:raw_filter) end def setup @@ -114,6 +114,7 @@ class SetupAndTeardownTest < ActiveSupport::TestCase end protected + def reset_callback_record @called_back = [] end @@ -133,9 +134,9 @@ class SubclassSetupAndTeardownTest < SetupAndTeardownTest teardown :bar def test_inherited_setup_callbacks - assert_equal [:reset_callback_record, :foo, :bar], self.class.setup_callback_chain.map(&:method) + assert_equal [:reset_callback_record, :foo, :bar], self.class._setup_callbacks.map(&:raw_filter) assert_equal [:foo, :bar], @called_back - assert_equal [:foo, :sentinel, :foo, :bar], self.class.teardown_callback_chain.map(&:method) + assert_equal [:foo, :sentinel, :foo, :bar], self.class._teardown_callbacks.map(&:raw_filter) end protected -- cgit v1.2.3 From cb3c0d490b7e8ac867068ccec6bbeb09a6a04b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 30 Dec 2009 11:43:34 +0100 Subject: Get rid of DeprecatedCallbacks in ActiveRecord::Associations and finally remove it. --- .../associations/association_collection.rb | 9 +- activerecord/lib/active_record/callbacks.rb | 2 +- activerecord/lib/active_record/validations.rb | 2 - activesupport/lib/active_support.rb | 1 - .../lib/active_support/deprecated_callbacks.rb | 284 --------------------- 5 files changed, 9 insertions(+), 289 deletions(-) delete mode 100644 activesupport/lib/active_support/deprecated_callbacks.rb diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index b2b3a9789c..1ceb0dbf96 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -485,7 +485,14 @@ module ActiveRecord def callback(method, record) callbacks_for(method).each do |callback| - ActiveSupport::DeprecatedCallbacks::Callback.new(method, callback, record).call(@owner, record) + case callback + when Symbol + @owner.send(callback, record) + when Proc + callback.call(@owner, record) + else + callback.send(method, @owner, record) + end end end diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index e1d772bd95..e2a8f03c8f 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -274,7 +274,7 @@ module ActiveRecord def deprecated_callback_method(symbol) #:nodoc: if respond_to?(symbol) - ActiveSupport::Deprecation.warn("Base##{symbol} has been deprecated, please use Base.#{symbol} :method instead") + ActiveSupport::Deprecation.warn("Overwriting #{symbol} in your models has been deprecated, please use Base##{symbol} :method_name instead") send(symbol) end end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index e8a2a72735..12c1f23763 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -17,8 +17,6 @@ module ActiveRecord module Validations extend ActiveSupport::Concern - - include ActiveSupport::DeprecatedCallbacks include ActiveModel::Validations included do diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 8215cfaf0d..3463000529 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -50,7 +50,6 @@ module ActiveSupport autoload :Callbacks autoload :Concern autoload :Configurable - autoload :DeprecatedCallbacks autoload :Deprecation autoload :Gzip autoload :Inflector diff --git a/activesupport/lib/active_support/deprecated_callbacks.rb b/activesupport/lib/active_support/deprecated_callbacks.rb deleted file mode 100644 index f56fef0b6d..0000000000 --- a/activesupport/lib/active_support/deprecated_callbacks.rb +++ /dev/null @@ -1,284 +0,0 @@ -require 'active_support/core_ext/array/extract_options' -require 'active_support/core_ext/array/wrap' - -module ActiveSupport - # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic - # before or after an alteration of the object state. - # - # Mixing in this module allows you to define callbacks in your class. - # - # Example: - # class Storage - # include ActiveSupport::DeprecatedCallbacks - # - # define_callbacks :before_save, :after_save - # end - # - # class ConfigStorage < Storage - # before_save :saving_message - # def saving_message - # puts "saving..." - # end - # - # after_save do |object| - # puts "saved" - # end - # - # def save - # run_callbacks(:before_save) - # puts "- save" - # run_callbacks(:after_save) - # end - # end - # - # config = ConfigStorage.new - # config.save - # - # Output: - # saving... - # - save - # saved - # - # Callbacks from parent classes are inherited. - # - # Example: - # class Storage - # include ActiveSupport::DeprecatedCallbacks - # - # define_callbacks :before_save, :after_save - # - # before_save :prepare - # def prepare - # puts "preparing save" - # end - # end - # - # class ConfigStorage < Storage - # before_save :saving_message - # def saving_message - # puts "saving..." - # end - # - # after_save do |object| - # puts "saved" - # end - # - # def save - # run_callbacks(:before_save) - # puts "- save" - # run_callbacks(:after_save) - # end - # end - # - # config = ConfigStorage.new - # config.save - # - # Output: - # preparing save - # saving... - # - save - # saved - module DeprecatedCallbacks - class CallbackChain < Array - def self.build(kind, *methods, &block) - methods, options = extract_options(*methods, &block) - methods.map! { |method| Callback.new(kind, method, options) } - new(methods) - end - - def run(object, options = {}, &terminator) - enumerator = options[:enumerator] || :each - - unless block_given? - send(enumerator) { |callback| callback.call(object) } - else - send(enumerator) do |callback| - result = callback.call(object) - break result if terminator.call(result, object) - end - end - end - - # TODO: Decompose into more Array like behavior - def replace_or_append!(chain) - if index = index(chain) - self[index] = chain - else - self << chain - end - self - end - - def find(callback, &block) - select { |c| c == callback && (!block_given? || yield(c)) }.first - end - - def delete(callback) - super(callback.is_a?(Callback) ? callback : find(callback)) - end - - private - def self.extract_options(*methods, &block) - methods.flatten! - options = methods.extract_options! - methods << block if block_given? - return methods, options - end - - def extract_options(*methods, &block) - self.class.extract_options(*methods, &block) - end - end - - class Callback - attr_reader :kind, :method, :identifier, :options - - def initialize(kind, method, options = {}) - @kind = kind - @method = method - @identifier = options[:identifier] - @options = options - end - - def ==(other) - case other - when Callback - (self.identifier && self.identifier == other.identifier) || self.method == other.method - else - (self.identifier && self.identifier == other) || self.method == other - end - end - - def eql?(other) - self == other - end - - def dup - self.class.new(@kind, @method, @options.dup) - end - - def hash - if @identifier - @identifier.hash - else - @method.hash - end - end - - def call(*args, &block) - evaluate_method(method, *args, &block) if should_run_callback?(*args) - rescue LocalJumpError - raise ArgumentError, - "Cannot yield from a Proc type filter. The Proc must take two " + - "arguments and execute #call on the second argument." - end - - private - def evaluate_method(method, *args, &block) - case method - when Symbol - object = args.shift - object.send(method, *args, &block) - when String - eval(method, args.first.instance_eval { binding }) - when Proc, Method - method.call(*args, &block) - else - if method.respond_to?(kind) - method.send(kind, *args, &block) - else - raise ArgumentError, - "Callbacks must be a symbol denoting the method to call, a string to be evaluated, " + - "a block to be invoked, or an object responding to the callback method." - end - end - end - - def should_run_callback?(*args) - Array.wrap(options[:if]).flatten.compact.all? { |a| evaluate_method(a, *args) } && - !Array.wrap(options[:unless]).flatten.compact.any? { |a| evaluate_method(a, *args) } - end - end - - def self.included(base) - base.extend ClassMethods - end - - module ClassMethods - def define_callbacks(*callbacks) - ActiveSupport::Deprecation.warn('ActiveSupport::DeprecatedCallbacks has been deprecated in favor of ActiveSupport::Callbacks', caller) - - callbacks.each do |callback| - class_eval <<-"end_eval", __FILE__, __LINE__ + 1 - def self.#{callback}(*methods, &block) # def self.before_save(*methods, &block) - callbacks = CallbackChain.build(:#{callback}, *methods, &block) # callbacks = CallbackChain.build(:before_save, *methods, &block) - @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new - @#{callback}_callbacks.concat callbacks # @before_save_callbacks.concat callbacks - end # end - # - def self.#{callback}_callback_chain # def self.before_save_callback_chain - @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new - # - if superclass.respond_to?(:#{callback}_callback_chain) # if superclass.respond_to?(:before_save_callback_chain) - CallbackChain.new( # CallbackChain.new( - superclass.#{callback}_callback_chain + # superclass.before_save_callback_chain + - @#{callback}_callbacks # @before_save_callbacks - ) # ) - else # else - @#{callback}_callbacks # @before_save_callbacks - end # end - end # end - end_eval - end - end - end - - # Runs all the callbacks defined for the given options. - # - # If a block is given it will be called after each callback receiving as arguments: - # - # * the result from the callback - # * the object which has the callback - # - # If the result from the block evaluates to +true+, the callback chain is stopped. - # - # Example: - # class Storage - # include ActiveSupport::DeprecatedCallbacks - # - # define_callbacks :before_save, :after_save - # end - # - # class ConfigStorage < Storage - # before_save :pass - # before_save :pass - # before_save :stop - # before_save :pass - # - # def pass - # puts "pass" - # end - # - # def stop - # puts "stop" - # return false - # end - # - # def save - # result = run_callbacks(:before_save) { |result, object| result == false } - # puts "- save" if result - # end - # end - # - # config = ConfigStorage.new - # config.save - # - # Output: - # pass - # pass - # stop - def run_callbacks(kind, options = {}, &block) - self.class.send("#{kind}_callback_chain").run(self, options, &block) - end - end -end -- cgit v1.2.3 From 1a0c372b19b6d6521df7c39a01a02ef5350ab300 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 14:31:02 -0800 Subject: depends on Module#attr_internal --- activerecord/lib/active_record/rails/controller_runtime.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/rails/controller_runtime.rb b/activerecord/lib/active_record/rails/controller_runtime.rb index 9ae40c5c8f..b8d5a77a0d 100644 --- a/activerecord/lib/active_record/rails/controller_runtime.rb +++ b/activerecord/lib/active_record/rails/controller_runtime.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/module/attr_internal' + module ActiveRecord module Rails module ControllerRuntime @@ -26,4 +28,4 @@ module ActiveRecord end end end -end \ No newline at end of file +end -- cgit v1.2.3 From 8ad9d14494dbe2a02d95ff6d23373b5662eede52 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 17:34:53 -0800 Subject: Partially revert "ActionDispatch should require as little of ActiveSupport as possible" Removes load path change from commit bb153f42e45160c5ef3593c393db5d3c6857fb70. --- actionpack/lib/action_dispatch.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index 49e1634af5..1e87a016f9 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -21,6 +21,8 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ +activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__) +$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path) require 'active_support' require 'active_support/dependencies/autoload' -- cgit v1.2.3 From d349b22097e6b50a9593ba5ba4c028070688342a Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 19:00:12 -0800 Subject: Remove self-require --- railties/lib/rails/core.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/railties/lib/rails/core.rb b/railties/lib/rails/core.rb index c819e90dd7..ab95edc676 100644 --- a/railties/lib/rails/core.rb +++ b/railties/lib/rails/core.rb @@ -12,7 +12,6 @@ require 'rails/railties_path' require 'rails/version' require 'rails/rack' require 'rails/paths' -require 'rails/core' require 'rails/configuration' require 'rails/deprecation' require 'rails/ruby_version_check' @@ -103,4 +102,4 @@ module Rails @@public_path = path end end -end \ No newline at end of file +end -- cgit v1.2.3 From 10a2638db099baddfa46da98f780df3a72a718d4 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 19:24:00 -0800 Subject: Fix up AR extension by using Railties module instead of Rails and requiring ControllerRuntime at initialization time instead of boot --- activerecord/lib/active_record.rb | 1 - activerecord/lib/active_record/rails.rb | 15 +- .../lib/active_record/rails/controller_runtime.rb | 31 -- .../lib/active_record/rails/databases.rake | 469 --------------------- .../active_record/railties/controller_runtime.rb | 31 ++ .../lib/active_record/railties/databases.rake | 469 +++++++++++++++++++++ 6 files changed, 509 insertions(+), 507 deletions(-) delete mode 100644 activerecord/lib/active_record/rails/controller_runtime.rb delete mode 100644 activerecord/lib/active_record/rails/databases.rake create mode 100644 activerecord/lib/active_record/railties/controller_runtime.rb create mode 100644 activerecord/lib/active_record/railties/databases.rake diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 87de480263..a524dc50a1 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -60,7 +60,6 @@ module ActiveRecord autoload :Batches autoload :Calculations autoload :Callbacks - autoload :ControllerRuntime autoload :DynamicFinderMatch autoload :DynamicScopeMatch autoload :Migration diff --git a/activerecord/lib/active_record/rails.rb b/activerecord/lib/active_record/rails.rb index 69f38e75c8..8bc49c3d96 100644 --- a/activerecord/lib/active_record/rails.rb +++ b/activerecord/lib/active_record/rails.rb @@ -3,17 +3,14 @@ # here. This is needed for correctly setting up the middleware. # In the future, this might become an optional require. require "action_controller/rails" -require "active_record/rails/controller_runtime" module ActiveRecord class Plugin < Rails::Plugin plugin_name :active_record include_modules_in "ActiveRecord::Base" - config.action_controller.include "ActiveRecord::Rails::ControllerRuntime" - rake_tasks do - load "active_record/rails/databases.rake" + load "active_record/railties/databases.rake" end initializer "active_record.set_configs" do |app| @@ -34,6 +31,12 @@ module ActiveRecord ActiveRecord::Base.default_timezone = :utc end + # Expose database runtime to controller for logging. + initializer "active_record.log_runtime" do |app| + require "active_record/railties/controller_runtime" + ActionController::Base.send :include, ActiveRecord::Railties::ControllerRuntime + end + # Setup database middleware after initializers have run initializer "active_record.initialize_database_middleware" do |app| middleware = app.config.middleware @@ -52,7 +55,7 @@ module ActiveRecord # TODO: ActiveRecord::Base.logger should delegate to its own config.logger initializer "active_record.logger" do - ActiveRecord::Base.logger ||= Rails.logger + ActiveRecord::Base.logger ||= ::Rails.logger end initializer "active_record.notifications" do @@ -64,4 +67,4 @@ module ActiveRecord end end -end \ No newline at end of file +end diff --git a/activerecord/lib/active_record/rails/controller_runtime.rb b/activerecord/lib/active_record/rails/controller_runtime.rb deleted file mode 100644 index b8d5a77a0d..0000000000 --- a/activerecord/lib/active_record/rails/controller_runtime.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'active_support/core_ext/module/attr_internal' - -module ActiveRecord - module Rails - module ControllerRuntime - extend ActiveSupport::Concern - - attr_internal :db_runtime - - def cleanup_view_runtime - if ActiveRecord::Base.connected? - db_rt_before_render = ActiveRecord::Base.connection.reset_runtime - runtime = super - db_rt_after_render = ActiveRecord::Base.connection.reset_runtime - self.db_runtime = db_rt_before_render + db_rt_after_render - runtime - db_rt_after_render - else - super - end - end - - module ClassMethods - def log_process_action(controller) - super - db_runtime = controller.send :db_runtime - logger.info(" ActiveRecord runtime: %.1fms" % db_runtime.to_f) if db_runtime - end - end - end - end -end diff --git a/activerecord/lib/active_record/rails/databases.rake b/activerecord/lib/active_record/rails/databases.rake deleted file mode 100644 index a35a6c156b..0000000000 --- a/activerecord/lib/active_record/rails/databases.rake +++ /dev/null @@ -1,469 +0,0 @@ -namespace :db do - task :load_config => :rails_env do - require 'active_record' - ActiveRecord::Base.configurations = Rails::Configuration.new.database_configuration - end - - namespace :create do - desc 'Create all the local databases defined in config/database.yml' - task :all => :load_config do - ActiveRecord::Base.configurations.each_value do |config| - # Skip entries that don't have a database key, such as the first entry here: - # - # defaults: &defaults - # adapter: mysql - # username: root - # password: - # host: localhost - # - # development: - # database: blog_development - # <<: *defaults - next unless config['database'] - # Only connect to local databases - local_database?(config) { create_database(config) } - end - end - end - - desc 'Create the database defined in config/database.yml for the current RAILS_ENV' - task :create => :load_config do - create_database(ActiveRecord::Base.configurations[RAILS_ENV]) - end - - def create_database(config) - begin - if config['adapter'] =~ /sqlite/ - if File.exist?(config['database']) - $stderr.puts "#{config['database']} already exists" - else - begin - # Create the SQLite database - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection - rescue - $stderr.puts $!, *($!.backtrace) - $stderr.puts "Couldn't create database for #{config.inspect}" - end - end - return # Skip the else clause of begin/rescue - else - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection - end - rescue - case config['adapter'] - when 'mysql' - @charset = ENV['CHARSET'] || 'utf8' - @collation = ENV['COLLATION'] || 'utf8_unicode_ci' - creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)} - begin - ActiveRecord::Base.establish_connection(config.merge('database' => nil)) - ActiveRecord::Base.connection.create_database(config['database'], creation_options) - ActiveRecord::Base.establish_connection(config) - rescue Mysql::Error => sqlerr - if sqlerr.errno == Mysql::Error::ER_ACCESS_DENIED_ERROR - print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>" - root_password = $stdin.gets.strip - grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \ - "TO '#{config['username']}'@'localhost' " \ - "IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;" - ActiveRecord::Base.establish_connection(config.merge( - 'database' => nil, 'username' => 'root', 'password' => root_password)) - ActiveRecord::Base.connection.create_database(config['database'], creation_options) - ActiveRecord::Base.connection.execute grant_statement - ActiveRecord::Base.establish_connection(config) - else - $stderr.puts sqlerr.error - $stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}" - $stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset'] - end - end - when 'postgresql' - @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8' - begin - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding)) - ActiveRecord::Base.establish_connection(config) - rescue - $stderr.puts $!, *($!.backtrace) - $stderr.puts "Couldn't create database for #{config.inspect}" - end - end - else - $stderr.puts "#{config['database']} already exists" - end - end - - namespace :drop do - desc 'Drops all the local databases defined in config/database.yml' - task :all => :load_config do - ActiveRecord::Base.configurations.each_value do |config| - # Skip entries that don't have a database key - next unless config['database'] - begin - # Only connect to local databases - local_database?(config) { drop_database(config) } - rescue Exception => e - puts "Couldn't drop #{config['database']} : #{e.inspect}" - end - end - end - end - - desc 'Drops the database for the current RAILS_ENV' - task :drop => :load_config do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - begin - drop_database(config) - rescue Exception => e - puts "Couldn't drop #{config['database']} : #{e.inspect}" - end - end - - def local_database?(config, &block) - if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank? - yield - else - puts "This task only modifies local databases. #{config['database']} is on a remote host." - end - end - - - desc "Migrate the database through scripts in db/migrate and update db/schema.rb by invoking db:schema:dump. Target specific version with VERSION=x. Turn off output with VERBOSE=false." - task :migrate => :environment do - ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true - ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - namespace :migrate do - desc 'Rollbacks the database one migration and re migrate up. If you want to rollback more than one step, define STEP=x. Target specific version with VERSION=x.' - task :redo => :environment do - if ENV["VERSION"] - Rake::Task["db:migrate:down"].invoke - Rake::Task["db:migrate:up"].invoke - else - Rake::Task["db:rollback"].invoke - Rake::Task["db:migrate"].invoke - end - end - - desc 'Resets your database using your migrations for the current environment' - task :reset => ["db:drop", "db:create", "db:migrate"] - - desc 'Runs the "up" for a given migration VERSION.' - task :up => :environment do - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:up, "db/migrate/", version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - desc 'Runs the "down" for a given migration VERSION.' - task :down => :environment do - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - raise "VERSION is required" unless version - ActiveRecord::Migrator.run(:down, "db/migrate/", version) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - end - - desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n' - task :rollback => :environment do - step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.rollback('db/migrate/', step) - Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby - end - - desc 'Pushes the schema to the next version. Specify the number of steps with STEP=n' - task :forward => :environment do - step = ENV['STEP'] ? ENV['STEP'].to_i : 1 - ActiveRecord::Migrator.forward('db/migrate/', step) - 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 and loads the seeds.' - task :reset => [ 'db:drop', 'db:setup' ] - - desc "Retrieves the charset for the current environment's database" - task :charset => :environment do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.charset - when 'postgresql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.encoding - else - puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' - end - end - - desc "Retrieves the collation for the current environment's database" - task :collation => :environment do - config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.collation - else - puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' - end - end - - desc "Retrieves the current schema version number" - task :version => :environment do - puts "Current version: #{ActiveRecord::Migrator.current_version}" - end - - desc "Raises an error if there are pending migrations" - task :abort_if_pending_migrations => :environment do - if defined? ActiveRecord - pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations - - if pending_migrations.any? - puts "You have #{pending_migrations.size} pending migrations:" - pending_migrations.each do |pending_migration| - puts ' %4d %s' % [pending_migration.version, pending_migration.name] - end - abort %{Run "rake db:migrate" to update your database then try again.} - end - 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 - require 'active_record/fixtures' - ActiveRecord::Base.establish_connection(Rails.env) - base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') - fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir - - (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file| - Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*')) - end - end - - desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures." - task :identify => :environment do - require "active_record/fixtures" - - label, id = ENV["LABEL"], ENV["ID"] - raise "LABEL or ID required" if label.blank? && id.blank? - - puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label - - base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') - Dir["#{base_dir}/**/*.yml"].each do |file| - if data = YAML::load(ERB.new(IO.read(file)).result) - data.keys.each do |key| - key_id = Fixtures.identify(key) - - if key == label || key_id == id.to_i - puts "#{file}: #{key} (#{key_id})" - end - end - end - end - end - end - - namespace :schema do - desc "Create a db/schema.rb file that can be portably used against any DB supported by AR" - task :dump => :environment do - require 'active_record/schema_dumper' - File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", "w") do |file| - ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) - end - Rake::Task["db:schema:dump"].reenable - end - - desc "Load a schema.rb file into the database" - task :load => :environment do - file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb" - if File.exists?(file) - load(file) - else - abort %{#{file} doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to prevent active_record from loading: config.frameworks -= [ :active_record ]} - end - end - end - - namespace :structure do - desc "Dump the database structure to a SQL file" - task :dump => :environment do - abcs = ActiveRecord::Base.configurations - case abcs[RAILS_ENV]["adapter"] - when "mysql", "oci", "oracle" - ActiveRecord::Base.establish_connection(abcs[RAILS_ENV]) - File.open("#{Rails.root}/db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump } - when "postgresql" - ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"] - ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"] - ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"] - search_path = abcs[RAILS_ENV]["schema_search_path"] - unless search_path.blank? - search_path = search_path.split(",").map{|search_path| "--schema=#{search_path.strip}" }.join(" ") - end - `pg_dump -i -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{search_path} #{abcs[RAILS_ENV]["database"]}` - raise "Error dumping database" if $?.exitstatus == 1 - when "sqlite", "sqlite3" - dbfile = abcs[RAILS_ENV]["database"] || abcs[RAILS_ENV]["dbfile"] - `#{abcs[RAILS_ENV]["adapter"]} #{dbfile} .schema > db/#{RAILS_ENV}_structure.sql` - when "sqlserver" - `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r` - `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r` - when "firebird" - set_firebird_env(abcs[RAILS_ENV]) - db_string = firebird_db_string(abcs[RAILS_ENV]) - sh "isql -a #{db_string} > #{Rails.root}/db/#{RAILS_ENV}_structure.sql" - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - - if ActiveRecord::Base.connection.supports_migrations? - File.open("#{Rails.root}/db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information } - end - end - end - - namespace :test do - desc "Recreate the test database from the current schema.rb" - task :load => 'db:test:purge' do - ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) - ActiveRecord::Schema.verbose = false - Rake::Task["db:schema:load"].invoke - end - - desc "Recreate the test database from the current environment's database schema" - task :clone => %w(db:schema:dump db:test:load) - - desc "Recreate the test databases from the development structure" - task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do - abcs = ActiveRecord::Base.configurations - case abcs["test"]["adapter"] - when "mysql" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') - IO.readlines("#{Rails.root}/db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table| - ActiveRecord::Base.connection.execute(table) - end - when "postgresql" - ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"] - ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"] - ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"] - `psql -U "#{abcs["test"]["username"]}" -f #{Rails.root}/db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}` - when "sqlite", "sqlite3" - dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] - `#{abcs["test"]["adapter"]} #{dbfile} < #{Rails.root}/db/#{RAILS_ENV}_structure.sql` - when "sqlserver" - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` - when "oci", "oracle" - ActiveRecord::Base.establish_connection(:test) - IO.readlines("#{Rails.root}/db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl| - ActiveRecord::Base.connection.execute(ddl) - end - when "firebird" - set_firebird_env(abcs["test"]) - db_string = firebird_db_string(abcs["test"]) - sh "isql -i #{Rails.root}/db/#{RAILS_ENV}_structure.sql #{db_string}" - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - end - - desc "Empty the test database" - task :purge => :environment do - abcs = ActiveRecord::Base.configurations - case abcs["test"]["adapter"] - when "mysql" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"], abcs["test"]) - when "postgresql" - ActiveRecord::Base.clear_active_connections! - drop_database(abcs['test']) - create_database(abcs['test']) - when "sqlite","sqlite3" - dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] - File.delete(dbfile) if File.exist?(dbfile) - when "sqlserver" - dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-') - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}` - `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` - when "oci", "oracle" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl| - ActiveRecord::Base.connection.execute(ddl) - end - when "firebird" - ActiveRecord::Base.establish_connection(:test) - ActiveRecord::Base.connection.recreate_database! - else - raise "Task not supported by '#{abcs["test"]["adapter"]}'" - end - end - - desc 'Check for pending migrations and load the test schema' - task :prepare => 'db:abort_if_pending_migrations' do - if defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank? - Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:load" }[ActiveRecord::Base.schema_format]].invoke - end - end - end - - namespace :sessions do - desc "Creates a sessions migration for use with ActiveRecord::SessionStore" - task :create => :environment do - raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations? - require 'rails/generators' - require 'rails/generators/rails/session_migration/session_migration_generator' - Rails::Generators::SessionMigrationGenerator.start [ ENV["MIGRATION"] || "add_sessions_table" ] - end - - desc "Clear the sessions table" - task :clear => :environment do - ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}" - end - end -end - -def drop_database(config) - case config['adapter'] - when 'mysql' - ActiveRecord::Base.establish_connection(config) - ActiveRecord::Base.connection.drop_database config['database'] - when /^sqlite/ - require 'pathname' - path = Pathname.new(config['database']) - file = path.absolute? ? path.to_s : File.join(Rails.root, path) - - FileUtils.rm(file) - when 'postgresql' - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.drop_database config['database'] - end -end - -def session_table_name - ActiveRecord::SessionStore::Session.table_name -end - -def set_firebird_env(config) - ENV["ISC_USER"] = config["username"].to_s if config["username"] - ENV["ISC_PASSWORD"] = config["password"].to_s if config["password"] -end - -def firebird_db_string(config) - FireRuby::Database.db_string_for(config.symbolize_keys) -end diff --git a/activerecord/lib/active_record/railties/controller_runtime.rb b/activerecord/lib/active_record/railties/controller_runtime.rb new file mode 100644 index 0000000000..535e967ec3 --- /dev/null +++ b/activerecord/lib/active_record/railties/controller_runtime.rb @@ -0,0 +1,31 @@ +require 'active_support/core_ext/module/attr_internal' + +module ActiveRecord + module Railties + module ControllerRuntime + extend ActiveSupport::Concern + + attr_internal :db_runtime + + def cleanup_view_runtime + if ActiveRecord::Base.connected? + db_rt_before_render = ActiveRecord::Base.connection.reset_runtime + runtime = super + db_rt_after_render = ActiveRecord::Base.connection.reset_runtime + self.db_runtime = db_rt_before_render + db_rt_after_render + runtime - db_rt_after_render + else + super + end + end + + module ClassMethods + def log_process_action(controller) + super + db_runtime = controller.send :db_runtime + logger.info(" ActiveRecord runtime: %.1fms" % db_runtime.to_f) if db_runtime + end + end + end + end +end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake new file mode 100644 index 0000000000..a35a6c156b --- /dev/null +++ b/activerecord/lib/active_record/railties/databases.rake @@ -0,0 +1,469 @@ +namespace :db do + task :load_config => :rails_env do + require 'active_record' + ActiveRecord::Base.configurations = Rails::Configuration.new.database_configuration + end + + namespace :create do + desc 'Create all the local databases defined in config/database.yml' + task :all => :load_config do + ActiveRecord::Base.configurations.each_value do |config| + # Skip entries that don't have a database key, such as the first entry here: + # + # defaults: &defaults + # adapter: mysql + # username: root + # password: + # host: localhost + # + # development: + # database: blog_development + # <<: *defaults + next unless config['database'] + # Only connect to local databases + local_database?(config) { create_database(config) } + end + end + end + + desc 'Create the database defined in config/database.yml for the current RAILS_ENV' + task :create => :load_config do + create_database(ActiveRecord::Base.configurations[RAILS_ENV]) + end + + def create_database(config) + begin + if config['adapter'] =~ /sqlite/ + if File.exist?(config['database']) + $stderr.puts "#{config['database']} already exists" + else + begin + # Create the SQLite database + ActiveRecord::Base.establish_connection(config) + ActiveRecord::Base.connection + rescue + $stderr.puts $!, *($!.backtrace) + $stderr.puts "Couldn't create database for #{config.inspect}" + end + end + return # Skip the else clause of begin/rescue + else + ActiveRecord::Base.establish_connection(config) + ActiveRecord::Base.connection + end + rescue + case config['adapter'] + when 'mysql' + @charset = ENV['CHARSET'] || 'utf8' + @collation = ENV['COLLATION'] || 'utf8_unicode_ci' + creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)} + begin + ActiveRecord::Base.establish_connection(config.merge('database' => nil)) + ActiveRecord::Base.connection.create_database(config['database'], creation_options) + ActiveRecord::Base.establish_connection(config) + rescue Mysql::Error => sqlerr + if sqlerr.errno == Mysql::Error::ER_ACCESS_DENIED_ERROR + print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>" + root_password = $stdin.gets.strip + grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \ + "TO '#{config['username']}'@'localhost' " \ + "IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;" + ActiveRecord::Base.establish_connection(config.merge( + 'database' => nil, 'username' => 'root', 'password' => root_password)) + ActiveRecord::Base.connection.create_database(config['database'], creation_options) + ActiveRecord::Base.connection.execute grant_statement + ActiveRecord::Base.establish_connection(config) + else + $stderr.puts sqlerr.error + $stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}" + $stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset'] + end + end + when 'postgresql' + @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8' + begin + ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) + ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding)) + ActiveRecord::Base.establish_connection(config) + rescue + $stderr.puts $!, *($!.backtrace) + $stderr.puts "Couldn't create database for #{config.inspect}" + end + end + else + $stderr.puts "#{config['database']} already exists" + end + end + + namespace :drop do + desc 'Drops all the local databases defined in config/database.yml' + task :all => :load_config do + ActiveRecord::Base.configurations.each_value do |config| + # Skip entries that don't have a database key + next unless config['database'] + begin + # Only connect to local databases + local_database?(config) { drop_database(config) } + rescue Exception => e + puts "Couldn't drop #{config['database']} : #{e.inspect}" + end + end + end + end + + desc 'Drops the database for the current RAILS_ENV' + task :drop => :load_config do + config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] + begin + drop_database(config) + rescue Exception => e + puts "Couldn't drop #{config['database']} : #{e.inspect}" + end + end + + def local_database?(config, &block) + if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank? + yield + else + puts "This task only modifies local databases. #{config['database']} is on a remote host." + end + end + + + desc "Migrate the database through scripts in db/migrate and update db/schema.rb by invoking db:schema:dump. Target specific version with VERSION=x. Turn off output with VERBOSE=false." + task :migrate => :environment do + ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true + ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil) + Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + end + + namespace :migrate do + desc 'Rollbacks the database one migration and re migrate up. If you want to rollback more than one step, define STEP=x. Target specific version with VERSION=x.' + task :redo => :environment do + if ENV["VERSION"] + Rake::Task["db:migrate:down"].invoke + Rake::Task["db:migrate:up"].invoke + else + Rake::Task["db:rollback"].invoke + Rake::Task["db:migrate"].invoke + end + end + + desc 'Resets your database using your migrations for the current environment' + task :reset => ["db:drop", "db:create", "db:migrate"] + + desc 'Runs the "up" for a given migration VERSION.' + task :up => :environment do + version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil + raise "VERSION is required" unless version + ActiveRecord::Migrator.run(:up, "db/migrate/", version) + Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + end + + desc 'Runs the "down" for a given migration VERSION.' + task :down => :environment do + version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil + raise "VERSION is required" unless version + ActiveRecord::Migrator.run(:down, "db/migrate/", version) + Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + end + end + + desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n' + task :rollback => :environment do + step = ENV['STEP'] ? ENV['STEP'].to_i : 1 + ActiveRecord::Migrator.rollback('db/migrate/', step) + Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby + end + + desc 'Pushes the schema to the next version. Specify the number of steps with STEP=n' + task :forward => :environment do + step = ENV['STEP'] ? ENV['STEP'].to_i : 1 + ActiveRecord::Migrator.forward('db/migrate/', step) + 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 and loads the seeds.' + task :reset => [ 'db:drop', 'db:setup' ] + + desc "Retrieves the charset for the current environment's database" + task :charset => :environment do + config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] + case config['adapter'] + when 'mysql' + ActiveRecord::Base.establish_connection(config) + puts ActiveRecord::Base.connection.charset + when 'postgresql' + ActiveRecord::Base.establish_connection(config) + puts ActiveRecord::Base.connection.encoding + else + puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' + end + end + + desc "Retrieves the collation for the current environment's database" + task :collation => :environment do + config = ActiveRecord::Base.configurations[RAILS_ENV || 'development'] + case config['adapter'] + when 'mysql' + ActiveRecord::Base.establish_connection(config) + puts ActiveRecord::Base.connection.collation + else + puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' + end + end + + desc "Retrieves the current schema version number" + task :version => :environment do + puts "Current version: #{ActiveRecord::Migrator.current_version}" + end + + desc "Raises an error if there are pending migrations" + task :abort_if_pending_migrations => :environment do + if defined? ActiveRecord + pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations + + if pending_migrations.any? + puts "You have #{pending_migrations.size} pending migrations:" + pending_migrations.each do |pending_migration| + puts ' %4d %s' % [pending_migration.version, pending_migration.name] + end + abort %{Run "rake db:migrate" to update your database then try again.} + end + 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 + require 'active_record/fixtures' + ActiveRecord::Base.establish_connection(Rails.env) + base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') + fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir + + (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file| + Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*')) + end + end + + desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures." + task :identify => :environment do + require "active_record/fixtures" + + label, id = ENV["LABEL"], ENV["ID"] + raise "LABEL or ID required" if label.blank? && id.blank? + + puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label + + base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures') + Dir["#{base_dir}/**/*.yml"].each do |file| + if data = YAML::load(ERB.new(IO.read(file)).result) + data.keys.each do |key| + key_id = Fixtures.identify(key) + + if key == label || key_id == id.to_i + puts "#{file}: #{key} (#{key_id})" + end + end + end + end + end + end + + namespace :schema do + desc "Create a db/schema.rb file that can be portably used against any DB supported by AR" + task :dump => :environment do + require 'active_record/schema_dumper' + File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", "w") do |file| + ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) + end + Rake::Task["db:schema:dump"].reenable + end + + desc "Load a schema.rb file into the database" + task :load => :environment do + file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb" + if File.exists?(file) + load(file) + else + abort %{#{file} doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to prevent active_record from loading: config.frameworks -= [ :active_record ]} + end + end + end + + namespace :structure do + desc "Dump the database structure to a SQL file" + task :dump => :environment do + abcs = ActiveRecord::Base.configurations + case abcs[RAILS_ENV]["adapter"] + when "mysql", "oci", "oracle" + ActiveRecord::Base.establish_connection(abcs[RAILS_ENV]) + File.open("#{Rails.root}/db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump } + when "postgresql" + ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"] + ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"] + ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"] + search_path = abcs[RAILS_ENV]["schema_search_path"] + unless search_path.blank? + search_path = search_path.split(",").map{|search_path| "--schema=#{search_path.strip}" }.join(" ") + end + `pg_dump -i -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{search_path} #{abcs[RAILS_ENV]["database"]}` + raise "Error dumping database" if $?.exitstatus == 1 + when "sqlite", "sqlite3" + dbfile = abcs[RAILS_ENV]["database"] || abcs[RAILS_ENV]["dbfile"] + `#{abcs[RAILS_ENV]["adapter"]} #{dbfile} .schema > db/#{RAILS_ENV}_structure.sql` + when "sqlserver" + `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r` + `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r` + when "firebird" + set_firebird_env(abcs[RAILS_ENV]) + db_string = firebird_db_string(abcs[RAILS_ENV]) + sh "isql -a #{db_string} > #{Rails.root}/db/#{RAILS_ENV}_structure.sql" + else + raise "Task not supported by '#{abcs["test"]["adapter"]}'" + end + + if ActiveRecord::Base.connection.supports_migrations? + File.open("#{Rails.root}/db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information } + end + end + end + + namespace :test do + desc "Recreate the test database from the current schema.rb" + task :load => 'db:test:purge' do + ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) + ActiveRecord::Schema.verbose = false + Rake::Task["db:schema:load"].invoke + end + + desc "Recreate the test database from the current environment's database schema" + task :clone => %w(db:schema:dump db:test:load) + + desc "Recreate the test databases from the development structure" + task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do + abcs = ActiveRecord::Base.configurations + case abcs["test"]["adapter"] + when "mysql" + ActiveRecord::Base.establish_connection(:test) + ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') + IO.readlines("#{Rails.root}/db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table| + ActiveRecord::Base.connection.execute(table) + end + when "postgresql" + ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"] + ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"] + ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"] + `psql -U "#{abcs["test"]["username"]}" -f #{Rails.root}/db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}` + when "sqlite", "sqlite3" + dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] + `#{abcs["test"]["adapter"]} #{dbfile} < #{Rails.root}/db/#{RAILS_ENV}_structure.sql` + when "sqlserver" + `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` + when "oci", "oracle" + ActiveRecord::Base.establish_connection(:test) + IO.readlines("#{Rails.root}/db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl| + ActiveRecord::Base.connection.execute(ddl) + end + when "firebird" + set_firebird_env(abcs["test"]) + db_string = firebird_db_string(abcs["test"]) + sh "isql -i #{Rails.root}/db/#{RAILS_ENV}_structure.sql #{db_string}" + else + raise "Task not supported by '#{abcs["test"]["adapter"]}'" + end + end + + desc "Empty the test database" + task :purge => :environment do + abcs = ActiveRecord::Base.configurations + case abcs["test"]["adapter"] + when "mysql" + ActiveRecord::Base.establish_connection(:test) + ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"], abcs["test"]) + when "postgresql" + ActiveRecord::Base.clear_active_connections! + drop_database(abcs['test']) + create_database(abcs['test']) + when "sqlite","sqlite3" + dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"] + File.delete(dbfile) if File.exist?(dbfile) + when "sqlserver" + dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-') + `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}` + `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql` + when "oci", "oracle" + ActiveRecord::Base.establish_connection(:test) + ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl| + ActiveRecord::Base.connection.execute(ddl) + end + when "firebird" + ActiveRecord::Base.establish_connection(:test) + ActiveRecord::Base.connection.recreate_database! + else + raise "Task not supported by '#{abcs["test"]["adapter"]}'" + end + end + + desc 'Check for pending migrations and load the test schema' + task :prepare => 'db:abort_if_pending_migrations' do + if defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank? + Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:load" }[ActiveRecord::Base.schema_format]].invoke + end + end + end + + namespace :sessions do + desc "Creates a sessions migration for use with ActiveRecord::SessionStore" + task :create => :environment do + raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations? + require 'rails/generators' + require 'rails/generators/rails/session_migration/session_migration_generator' + Rails::Generators::SessionMigrationGenerator.start [ ENV["MIGRATION"] || "add_sessions_table" ] + end + + desc "Clear the sessions table" + task :clear => :environment do + ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}" + end + end +end + +def drop_database(config) + case config['adapter'] + when 'mysql' + ActiveRecord::Base.establish_connection(config) + ActiveRecord::Base.connection.drop_database config['database'] + when /^sqlite/ + require 'pathname' + path = Pathname.new(config['database']) + file = path.absolute? ? path.to_s : File.join(Rails.root, path) + + FileUtils.rm(file) + when 'postgresql' + ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) + ActiveRecord::Base.connection.drop_database config['database'] + end +end + +def session_table_name + ActiveRecord::SessionStore::Session.table_name +end + +def set_firebird_env(config) + ENV["ISC_USER"] = config["username"].to_s if config["username"] + ENV["ISC_PASSWORD"] = config["password"].to_s if config["password"] +end + +def firebird_db_string(config) + FireRuby::Database.db_string_for(config.symbolize_keys) +end -- cgit v1.2.3 From 1fbd02e44618f1f56e1d9d0af85c6a4108a66532 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 19:33:32 -0800 Subject: Revert "Add config.action_controller.include behavior to plugins." This reverts commit 7e8b7f46bfc086a36db996420fbee93348c5268e. Conflicts: railties/lib/rails/plugin.rb --- actionpack/lib/action_controller/rails.rb | 3 +-- activerecord/lib/active_record/rails.rb | 1 - railties/lib/rails/configuration.rb | 20 +------------------- railties/lib/rails/plugin.rb | 20 +------------------- railties/test/plugins/configuration_test.rb | 16 ---------------- 5 files changed, 3 insertions(+), 57 deletions(-) diff --git a/actionpack/lib/action_controller/rails.rb b/actionpack/lib/action_controller/rails.rb index 6ebb50887b..df708c315b 100644 --- a/actionpack/lib/action_controller/rails.rb +++ b/actionpack/lib/action_controller/rails.rb @@ -1,7 +1,6 @@ module ActionController class Plugin < Rails::Plugin plugin_name :action_controller - include_modules_in "ActionController::Base" initializer "action_controller.set_configs" do |app| app.config.action_controller.each do |k,v| @@ -91,4 +90,4 @@ module ActionController end end -end \ No newline at end of file +end diff --git a/activerecord/lib/active_record/rails.rb b/activerecord/lib/active_record/rails.rb index 8bc49c3d96..a13bd2a5da 100644 --- a/activerecord/lib/active_record/rails.rb +++ b/activerecord/lib/active_record/rails.rb @@ -7,7 +7,6 @@ require "action_controller/rails" module ActiveRecord class Plugin < Rails::Plugin plugin_name :active_record - include_modules_in "ActiveRecord::Base" rake_tasks do load "active_record/railties/databases.rake" diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index cb321536d2..086f67a419 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,24 +1,6 @@ require 'active_support/ordered_options' module Rails - # Create a Plugin::Options from ActiveSuppot::OrderedOptions, - # which support the following syntax: - # - # controller.action_controller.include FooBar - # - class Plugin::Options < ActiveSupport::OrderedOptions #:nodoc: - attr_reader :includes - - def initialize(*args) - @includes = [] - super - end - - def include(*args) - @includes.concat(args) - end - end - # Temporarily separate the plugin configuration class from the main # configuration class while this bit is being cleaned up. class Plugin::Configuration @@ -34,7 +16,7 @@ module Rails @options = base.options.dup @middleware = base.middleware.dup else - @options = Hash.new { |h,k| h[k] = Rails::Plugin::Options.new } + @options = Hash.new { |h,k| h[k] = ActiveSupport::OrderedOptions.new } @middleware = ActionDispatch::MiddlewareStack.new end end diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index c64042cf7d..e154e9b706 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -40,24 +40,6 @@ module Rails rake_tasks.each { |blk| blk.call } end - # Creates an initializer which includes all given modules to the given class. - # - # module Rails - # class ActionController < Rails::Plugin - # plugin_name :action_controller - # include_modules_in "ActionController::Base" - # end - # end - # - def self.include_modules_in(klass, from=plugin_name) - self.initializer :"#{from}.include_modules" do |app| - klass = klass.constantize if klass.is_a?(String) - app.config.send(from).includes.each do |mod| - klass.send(:include, mod.is_a?(String) ? mod.constantize : mod) - end - end - end - class Vendored < Plugin def self.all(list, paths) plugins = [] @@ -121,4 +103,4 @@ module Rails end end end -end \ No newline at end of file +end diff --git a/railties/test/plugins/configuration_test.rb b/railties/test/plugins/configuration_test.rb index 0843d05577..5786316d1d 100644 --- a/railties/test/plugins/configuration_test.rb +++ b/railties/test/plugins/configuration_test.rb @@ -8,10 +8,6 @@ module PluginsTest require "rails" end - module Bar; end - module Baz; end - module All; end - test "config is available to plugins" do class Foo < Rails::Plugin ; end assert_nil Foo.config.action_controller.foo @@ -28,18 +24,6 @@ module PluginsTest assert_equal "hello", AppTemplate::Application.config.foo.greetings end - test "plugin configurations allow modules to be given" do - class Foo < Rails::Plugin ; config.foo.include(Bar, Baz) ; end - assert_equal [Bar, Baz], Foo.config.foo.includes - end - - test "plugin includes given modules in given class" do - class Foo < Rails::Plugin ; config.foo.include(Bar, "PluginsTest::ConfigurationTest::Baz") ; include_modules_in All ; end - Foo.new.run_initializers(Foo) - assert All.ancestors.include?(Bar) - assert All.ancestors.include?(Baz) - end - test "plugin config merges are deep" do class Foo < Rails::Plugin ; config.foo.greetings = 'hello' ; end class MyApp < Rails::Application -- cgit v1.2.3 From d39d7f5f444db724ddfb2dc5c15177e519b349f0 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Wed, 30 Dec 2009 20:48:15 -0800 Subject: Allow ActiveSupport's isolation tests to run with MiniTest on 1.9 --- .../lib/active_support/testing/isolation.rb | 64 +++-- activesupport/test/isolation_test.rb | 266 +++++++++++---------- 2 files changed, 189 insertions(+), 141 deletions(-) diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb index 81f7e3c9df..453f4fcc0f 100644 --- a/activesupport/lib/active_support/testing/isolation.rb +++ b/activesupport/lib/active_support/testing/isolation.rb @@ -36,28 +36,56 @@ module ActiveSupport !ENV["NO_FORK"] && RUBY_PLATFORM !~ /mswin|mingw|java/ end - def run(result) - unless defined?(@@ran_class_setup) - self.class.setup if self.class.respond_to?(:setup) - @@ran_class_setup = true + def self.included(base) + if defined?(::MiniTest) && base < ::MiniTest::Unit::TestCase + base.send :include, MiniTest + elsif defined?(Test::Unit) + base.send :include, TestUnit end + end + + module TestUnit + def run(result) + unless defined?(@@ran_class_setup) + self.class.setup if self.class.respond_to?(:setup) + @@ran_class_setup = true + end - yield(Test::Unit::TestCase::STARTED, name) + yield(Test::Unit::TestCase::STARTED, name) - @_result = result + @_result = result - serialized = run_in_isolation do |proxy| - begin - super(proxy) { } - rescue Exception => e - proxy.add_error(Test::Unit::Error.new(name, e)) + serialized = run_in_isolation do |proxy| + begin + super(proxy) { } + rescue Exception => e + proxy.add_error(Test::Unit::Error.new(name, e)) + end end + + retval, proxy = Marshal.load(serialized) + proxy.__replay__(@_result) + + yield(Test::Unit::TestCase::FINISHED, name) + retval end + end - proxy = Marshal.load(serialized) - proxy.__replay__(@_result) + module MiniTest + def run(runner) + unless defined?(@@ran_class_setup) + self.class.setup if self.class.respond_to?(:setup) + @@ran_class_setup = true + end - yield(Test::Unit::TestCase::FINISHED, name) + serialized = run_in_isolation do |runner| + super(runner) + end + + retval, proxy = Marshal.load(serialized) + proxy.__replay__(runner) + retval + end end module Forking @@ -67,8 +95,8 @@ module ActiveSupport pid = fork do read.close proxy = ProxyTestResult.new - yield proxy - write.puts [Marshal.dump(proxy)].pack("m") + retval = yield proxy + write.puts [Marshal.dump([retval, proxy])].pack("m") exit! end @@ -87,9 +115,9 @@ module ActiveSupport if ENV["ISOLATION_TEST"] proxy = ProxyTestResult.new - yield proxy + retval = yield proxy File.open(ENV["ISOLATION_OUTPUT"], "w") do |file| - file.puts [Marshal.dump(proxy)].pack("m") + file.puts [Marshal.dump([retval, proxy])].pack("m") end exit! else diff --git a/activesupport/test/isolation_test.rb b/activesupport/test/isolation_test.rb index 20e11df1dd..39c2166016 100644 --- a/activesupport/test/isolation_test.rb +++ b/activesupport/test/isolation_test.rb @@ -1,162 +1,182 @@ require 'abstract_unit' require 'rbconfig' -if defined?(MiniTest) || defined?(Test::Unit::TestResultFailureSupport) - $stderr.puts "Isolation tests can test test-unit 1 only" +# if defined?(MiniTest) || defined?(Test::Unit::TestResultFailureSupport) +# $stderr.puts "Isolation tests can test test-unit 1 only" -else - # Does awesome - if ENV['CHILD'] - class ChildIsolationTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation - - def self.setup - File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "a") do |f| - f.puts "hello" - end - end +if ENV['CHILD'] + class ChildIsolationTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation - def setup - @instance = "HELLO" + def self.setup + File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "a") do |f| + f.puts "hello" end + end - def teardown - raise if @boom - end + def setup + @instance = "HELLO" + end - test "runs the test" do - assert true - end + def teardown + raise if @boom + end - test "captures errors" do - raise - end + test "runs the test" do + assert true + end - test "captures failures" do - assert false - end + test "captures errors" do + raise + end - test "first runs in isolation" do - assert_nil $x - $x = 1 - end + test "captures failures" do + assert false + end - test "second runs in isolation" do - assert_nil $x - $x = 2 - end + test "first runs in isolation" do + assert_nil $x + $x = 1 + end - test "runs with slow tests" do - sleep 0.3 - assert true - sleep 0.2 - end + test "second runs in isolation" do + assert_nil $x + $x = 2 + end - test "runs setup" do - assert "HELLO", @instance - end + test "runs with slow tests" do + sleep 0.3 + assert true + sleep 0.2 + end - test "runs teardown" do - @boom = true - end + test "runs setup" do + assert "HELLO", @instance + end - test "resets requires one" do - assert !defined?(OmgOmg) - assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size - require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg")) - end + test "runs teardown" do + @boom = true + end - test "resets requires two" do - assert !defined?(OmgOmg) - assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size - require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg")) - end + test "resets requires one" do + assert !defined?(OmgOmg) + assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size + require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg")) end - else - class ParentIsolationTest < ActiveSupport::TestCase - - File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "w") {} - - ENV["CHILD"] = "1" - OUTPUT = `#{RbConfig::CONFIG["bindir"]}/#{RbConfig::CONFIG["ruby_install_name"]} -I#{File.dirname(__FILE__)} "#{File.expand_path(__FILE__)}" -v` - ENV.delete("CHILD") - - def setup - # Extract the results - @results = {} - OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result| - result =~ %r'^(\w+)\(\w+\):\s*(\.|E|F)$' - @results[$1] = { 'E' => :error, '.' => :success, 'F' => :failure }[$2] - end - - # Extract the backtraces - @backtraces = {} - OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace| - # \n 1) Error:\ntest_captures_errors(ChildIsolationTest): - backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i - @backtraces[$2] = { :type => $1, :output => backtrace } - end - end - def assert_failing(name) - assert_equal :failure, @results[name.to_s], "Test #{name} did not fail" - end + test "resets requires two" do + assert !defined?(OmgOmg) + assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/omgomg/).size + require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "omgomg")) + end + end +else + class ParentIsolationTest < ActiveSupport::TestCase - def assert_passing(name) - assert_equal :success, @results[name.to_s], "Test #{name} did not pass" - end + File.open(File.join(File.dirname(__FILE__), "fixtures", "isolation_test"), "w") {} - def assert_erroring(name) - assert_equal :error, @results[name.to_s], "Test #{name} did not error" - end + ENV["CHILD"] = "1" + OUTPUT = `#{RbConfig::CONFIG["bindir"]}/#{RbConfig::CONFIG["ruby_install_name"]} -I#{File.dirname(__FILE__)} "#{File.expand_path(__FILE__)}" -v` + ENV.delete("CHILD") - test "has all tests" do - assert_equal 10, @results.length - end + def setup + defined?(::MiniTest) ? parse_minitest : parse_testunit + end - test "passing tests are still reported" do - assert_passing :test_runs_the_test - assert_passing :test_runs_with_slow_tests + def parse_testunit + @results = {} + OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result| + result =~ %r'^(\w+)\(\w+\):\s*(\.|E|F)$' + @results[$1] = { 'E' => :error, '.' => :success, 'F' => :failure }[$2] end - test "resets global variables" do - assert_passing :test_first_runs_in_isolation - assert_passing :test_second_runs_in_isolation + # Extract the backtraces + @backtraces = {} + OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace| + # \n 1) Error:\ntest_captures_errors(ChildIsolationTest): + backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i + @backtraces[$2] = { :type => $1, :output => backtrace } end + end - test "resets requires" do - assert_passing :test_resets_requires_one - assert_passing :test_resets_requires_two - end + def parse_minitest + @results = {} + OUTPUT[/Started\n\s*(.*)\s*\nFinished/mi, 1].to_s.split(/\s*\n\s*/).each do |result| + result =~ %r'^\w+#(\w+):.*:\s*(.*Assertion.*|.*RuntimeError.*|\.\s*)$' + val = :success + val = :error if $2.include?('RuntimeError') + val = :failure if $2.include?('Assertion') - test "erroring tests are still reported" do - assert_erroring :test_captures_errors + @results[$1] = val end - test "runs setup and teardown methods" do - assert_passing :test_runs_setup - assert_erroring :test_runs_teardown + # Extract the backtraces + @backtraces = {} + OUTPUT.scan(/^\s*\d+\).*?\n\n/m).each do |backtrace| + # \n 1) Error:\ntest_captures_errors(ChildIsolationTest): + backtrace =~ %r'\s*\d+\)\s*(Error|Failure):\n(\w+)'i + @backtraces[$2] = { :type => $1, :output => backtrace } end + end - test "correct tests fail" do - assert_failing :test_captures_failures - end + def assert_failing(name) + assert_equal :failure, @results[name.to_s], "Test #{name} failed" + end - test "backtrace is printed for errors" do - assert_equal 'Error', @backtraces["test_captures_errors"][:type] - assert_match %r{isolation_test.rb:\d+:in `test_captures_errors'}, @backtraces["test_captures_errors"][:output] - end + def assert_passing(name) + assert_equal :success, @results[name.to_s], "Test #{name} passed" + end - test "backtrace is printed for failures" do - assert_equal 'Failure', @backtraces["test_captures_failures"][:type] - assert_match %r{isolation_test.rb:\d+:in `test_captures_failures'}, @backtraces["test_captures_failures"][:output] - end + def assert_erroring(name) + assert_equal :error, @results[name.to_s], "Test #{name} errored" + end - test "self.setup is run only once" do - text = File.read(File.join(File.dirname(__FILE__), "fixtures", "isolation_test")) - assert_equal "hello\n", text - end + test "has all tests" do + assert_equal 10, @results.length + end + + test "passing tests are still reported" do + assert_passing :test_runs_the_test + assert_passing :test_runs_with_slow_tests + end + test "resets global variables" do + assert_passing :test_first_runs_in_isolation + assert_passing :test_second_runs_in_isolation end + + test "resets requires" do + assert_passing :test_resets_requires_one + assert_passing :test_resets_requires_two + end + + test "erroring tests are still reported" do + assert_erroring :test_captures_errors + end + + test "runs setup and teardown methods" do + assert_passing :test_runs_setup + assert_erroring :test_runs_teardown + end + + test "correct tests fail" do + assert_failing :test_captures_failures + end + + test "backtrace is printed for errors" do + assert_equal 'Error', @backtraces["test_captures_errors"][:type] + assert_match %r{isolation_test.rb:\d+}, @backtraces["test_captures_errors"][:output] + end + + test "backtrace is printed for failures" do + assert_equal 'Failure', @backtraces["test_captures_failures"][:type] + assert_match %r{isolation_test.rb:\d+}, @backtraces["test_captures_failures"][:output] + end + + test "self.setup is run only once" do + text = File.read(File.join(File.dirname(__FILE__), "fixtures", "isolation_test")) + assert_equal "hello\n", text + end + end end -- cgit v1.2.3 From c4c2502df8b0b7b5fa28d796bdb1d4bd02af4b3d Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 30 Dec 2009 22:14:57 -0800 Subject: Fix controller runtime test --- actionpack/test/activerecord/controller_runtime_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/test/activerecord/controller_runtime_test.rb b/actionpack/test/activerecord/controller_runtime_test.rb index dd31add4b4..0f534da14b 100644 --- a/actionpack/test/activerecord/controller_runtime_test.rb +++ b/actionpack/test/activerecord/controller_runtime_test.rb @@ -1,8 +1,8 @@ require 'active_record_unit' -require 'active_record/rails/controller_runtime' +require 'active_record/railties/controller_runtime' require 'fixtures/project' -ActionController::Base.send :include, ActiveRecord::Rails::ControllerRuntime +ActionController::Base.send :include, ActiveRecord::Railties::ControllerRuntime class ARLoggingController < ActionController::Base def show -- cgit v1.2.3