diff options
303 files changed, 3123 insertions, 3456 deletions
diff --git a/RELEASING_RAILS.rdoc b/RELEASING_RAILS.rdoc index 7bad1d01b8..7a77f9bba2 100644 --- a/RELEASING_RAILS.rdoc +++ b/RELEASING_RAILS.rdoc @@ -25,12 +25,6 @@ for Rails. You can check the status of his tests here: Do not release with Red AWDwR tests. -=== Are the postgres tests green? If not, make them green - -Currently Travis CI doesn't run the Active Record postgres tests. They are -working to resolve this, but in the mean time, it is crucial to ensure that -the tests are still green before release. - === Do we have any git dependencies? If so, contact those authors. Having git dependencies indicates that we depend on unreleased code. @@ -66,8 +60,6 @@ for today: === Is Sam Ruby happy? If not, make him happy. -=== Are the postgres tests green? If not, make them green - === Contact the security team. CVE emails must be sent on this day. === Create a release branch. diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 2f9fff0f97..7d8852f961 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -1,6 +1,5 @@ require 'mail' require 'action_mailer/collector' -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/proc' require 'active_support/core_ext/string/inflections' @@ -122,8 +121,8 @@ module ActionMailer #:nodoc: # # <%= users_url(:host => "example.com") %> # - # You should use the <tt>named_route_url</tt> style (which generates absolute URLs) and avoid using the - # <tt>named_route_path</tt> style (which generates relative URLs), since clients reading the mail will + # You should use the <tt>named_route_url</tt> style (which generates absolute URLs) and avoid using the + # <tt>named_route_path</tt> style (which generates relative URLs), since clients reading the mail will # have no concept of a current URL from which to determine a relative path. # # It is also possible to set a default host that will be used in all mailers by setting the <tt>:host</tt> @@ -132,7 +131,7 @@ module ActionMailer #:nodoc: # config.action_mailer.default_url_options = { :host => "example.com" } # # When you decide to set a default <tt>:host</tt> for your mailers, then you need to make sure to use the - # <tt>:only_path => false</tt> option when using <tt>url_for</tt>. Since the <tt>url_for</tt> view helper + # <tt>:only_path => false</tt> option when using <tt>url_for</tt>. Since the <tt>url_for</tt> view helper # will generate relative URLs by default when a <tt>:host</tt> option isn't explicitly provided, passing # <tt>:only_path => false</tt> will ensure that absolute URLs are generated. # @@ -149,8 +148,8 @@ module ActionMailer #:nodoc: # # = Multipart Emails # - # Multipart messages can also be used implicitly because Action Mailer will automatically detect and use - # multipart templates, where each template is named after the name of the action, followed by the content + # Multipart messages can also be used implicitly because Action Mailer will automatically detect and use + # multipart templates, where each template is named after the name of the action, followed by the content # type. Each such detected template will be added as a separate part to the message. # # For example, if the following templates exist: @@ -333,7 +332,7 @@ module ActionMailer #:nodoc: include AbstractController::Translation include AbstractController::AssetPaths - self.protected_instance_variables = %w(@_action_has_layout) + self.protected_instance_variables = [:@_action_has_layout] helper ActionMailer::MailHelper @@ -707,7 +706,7 @@ module ActionMailer #:nodoc: end def each_template(paths, name, &block) #:nodoc: - templates = lookup_context.find_all(name, Array.wrap(paths)) + templates = lookup_context.find_all(name, Array(paths)) templates.uniq { |t| t.formats }.each(&block) end diff --git a/actionmailer/lib/action_mailer/log_subscriber.rb b/actionmailer/lib/action_mailer/log_subscriber.rb index 7ba57b19e0..a6c163832e 100644 --- a/actionmailer/lib/action_mailer/log_subscriber.rb +++ b/actionmailer/lib/action_mailer/log_subscriber.rb @@ -1,9 +1,7 @@ -require 'active_support/core_ext/array/wrap' - module ActionMailer class LogSubscriber < ActiveSupport::LogSubscriber def deliver(event) - recipients = Array.wrap(event.payload[:to]).join(', ') + recipients = Array(event.payload[:to]).join(', ') info("\nSent mail to #{recipients} (%1.fms)" % event.duration) debug(event.payload[:mail]) end @@ -19,4 +17,4 @@ module ActionMailer end end -ActionMailer::LogSubscriber.attach_to :action_mailer
\ No newline at end of file +ActionMailer::LogSubscriber.attach_to :action_mailer diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb index 4e48c0260f..529140dfad 100644 --- a/actionmailer/lib/action_mailer/test_case.rb +++ b/actionmailer/lib/action_mailer/test_case.rb @@ -1,3 +1,4 @@ +require 'active_support/test_case' require 'active_support/core_ext/class/attribute' module ActionMailer diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index d86e0dc4c0..3a519253f9 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -23,7 +23,7 @@ end lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") $:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) -require 'test/unit' +require 'minitest/autorun' require 'action_mailer' require 'action_mailer/test_case' diff --git a/actionmailer/test/asset_host_test.rb b/actionmailer/test/asset_host_test.rb index b24eca5fbb..696a9f1174 100644 --- a/actionmailer/test/asset_host_test.rb +++ b/actionmailer/test/asset_host_test.rb @@ -9,7 +9,7 @@ class AssetHostMailer < ActionMailer::Base end end -class AssetHostTest < Test::Unit::TestCase +class AssetHostTest < ActiveSupport::TestCase def setup set_delivery_method :test ActionMailer::Base.perform_deliveries = true diff --git a/actionmailer/test/mail_layout_test.rb b/actionmailer/test/mail_layout_test.rb index def8da81b8..71e93c29f1 100644 --- a/actionmailer/test/mail_layout_test.rb +++ b/actionmailer/test/mail_layout_test.rb @@ -43,7 +43,7 @@ class ExplicitLayoutMailer < ActionMailer::Base end end -class LayoutMailerTest < Test::Unit::TestCase +class LayoutMailerTest < ActiveSupport::TestCase def setup set_delivery_method :test ActionMailer::Base.perform_deliveries = true diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index f408c50390..6e609e6c7e 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,11 @@ +* check_box helper with :disabled => true will generate a disabled hidden field to conform with the HTML convention where disabled fields are not submitted with the form. + This is a behavior change, previously the hidden tag had a value of the disabled checkbox. + *Tadas Tamosauskas* + ## Rails 3.2.0 (unreleased) ## +* Rails initialization with initialize_on_precompile = false should set assets_dir *Santiago Pastorino* + * Add font_path helper method *Santiago Pastorino* * Depends on rack ~> 1.4.0 *Santiago Pastorino* diff --git a/actionpack/README.rdoc b/actionpack/README.rdoc index fc36423f83..076a93bbcd 100644 --- a/actionpack/README.rdoc +++ b/actionpack/README.rdoc @@ -206,7 +206,7 @@ A short rundown of some of the major features: You specify a logger through a class method, such as: - ActionController::Base.logger = Logger.new("Application Log") + ActionController::Base.logger = ActiveSupport::Logger.new("Application Log") ActionController::Base.logger = Log4r::Logger.new("Application Log") diff --git a/actionpack/Rakefile b/actionpack/Rakefile index d9e3e56fcc..effb6badfc 100755 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -16,7 +16,7 @@ Rake::TestTask.new(:test_action_pack) do |t| # make sure we include the tests in alphabetical order as on some systems # this will not happen automatically and the tests (as a whole) will error - t.test_files = Dir.glob('test/{abstract,controller,dispatch,template}/**/*_test.rb').sort + t.test_files = Dir.glob('test/{abstract,controller,dispatch,template,assertions}/**/*_test.rb').sort t.warning = true t.verbose = true diff --git a/actionpack/lib/abstract_controller/callbacks.rb b/actionpack/lib/abstract_controller/callbacks.rb index 7004e607a1..fffe3edac2 100644 --- a/actionpack/lib/abstract_controller/callbacks.rb +++ b/actionpack/lib/abstract_controller/callbacks.rb @@ -167,7 +167,7 @@ module AbstractController # for details on the allowed parameters. def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk) _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| - options[:if] = (Array.wrap(options[:if]) << "!halted") if #{filter == :after} # options[:if] = (Array.wrap(options[:if]) << "!halted") if false + options[:if] = (Array(options[:if]) << "!halted") if #{filter == :after} # options[:if] = (Array(options[:if]) << "!halted") if false set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before, name, options) end # end end # end @@ -176,7 +176,7 @@ module AbstractController # for details on the allowed parameters. def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk) _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options| - options[:if] = (Array.wrap(options[:if]) << "!halted") if #{filter == :after} # options[:if] = (Array.wrap(options[:if]) << "!halted") if false + options[:if] = (Array(options[:if]) << "!halted") if #{filter == :after} # options[:if] = (Array(options[:if]) << "!halted") if false set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true)) end # end end # end diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 9019c07bca..ddc93464cd 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -1,6 +1,5 @@ require "abstract_controller/base" require "action_view" -require "active_support/core_ext/object/instance_variables" module AbstractController class DoubleRenderError < Error @@ -109,20 +108,20 @@ module AbstractController view_renderer.render(view_context, options) end - DEFAULT_PROTECTED_INSTANCE_VARIABLES = %w( - @_action_name @_response_body @_formats @_prefixes @_config - @_view_context_class @_view_renderer @_lookup_context - ) + DEFAULT_PROTECTED_INSTANCE_VARIABLES = [ + :@_action_name, :@_response_body, :@_formats, :@_prefixes, :@_config, + :@_view_context_class, :@_view_renderer, :@_lookup_context + ] # This method should return a hash with assigns. # You can overwrite this configuration per controller. # :api: public def view_assigns hash = {} - variables = instance_variable_names + variables = instance_variables variables -= protected_instance_variables variables -= DEFAULT_PROTECTED_INSTANCE_VARIABLES - variables.each { |name| hash[name.to_s[1, name.length]] = instance_variable_get(name) } + variables.each { |name| hash[name[1..-1]] = instance_variable_get(name) } hash end diff --git a/actionpack/lib/abstract_controller/view_paths.rb b/actionpack/lib/abstract_controller/view_paths.rb index 96118b940f..c08b3a0e2a 100644 --- a/actionpack/lib/abstract_controller/view_paths.rb +++ b/actionpack/lib/abstract_controller/view_paths.rb @@ -89,7 +89,7 @@ module AbstractController # * <tt>paths</tt> - If a PathSet is provided, use that; # otherwise, process the parameter into a PathSet. def view_paths=(paths) - self._view_paths = ActionView::PathSet.new(Array.wrap(paths)) + self._view_paths = ActionView::PathSet.new(Array(paths)) end end end diff --git a/actionpack/lib/action_controller/metal/compatibility.rb b/actionpack/lib/action_controller/metal/compatibility.rb index 05dca445a4..43719d5808 100644 --- a/actionpack/lib/action_controller/metal/compatibility.rb +++ b/actionpack/lib/action_controller/metal/compatibility.rb @@ -18,10 +18,10 @@ module ActionController delegate :default_charset=, :to => "ActionDispatch::Response" end - self.protected_instance_variables = %w( - @_status @_headers @_params @_env @_response @_request - @_view_runtime @_stream @_url_options @_action_has_layout - ) + self.protected_instance_variables = [ + :@_status, :@_headers, :@_params, :@_env, :@_response, :@_request, + :@_view_runtime, :@_stream, :@_url_options, :@_action_has_layout + ] def rescue_action(env) raise env["action_dispatch.rescue.exception"] diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index 50d7aac300..d070eaae5d 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/attribute' module ActionController @@ -94,7 +93,7 @@ module ActionController def all_helpers_from_path(path) helpers = [] - Array.wrap(path).each do |_path| + Array(path).each do |_path| extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/ helpers += Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') } end diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index 5c28a8074f..fa760f2658 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -1,7 +1,6 @@ require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/hash/except' -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/module/anonymous' require 'action_dispatch/http/mime_types' @@ -43,9 +42,9 @@ module ActionController # wrap_parameters :person, :include => [:username, :password] # end # - # On ActiveRecord models with no +:include+ or +:exclude+ option set, + # On ActiveRecord models with no +:include+ or +:exclude+ option set, # if attr_accessible is set on that model, it will only wrap the accessible - # parameters, else it will only wrap the parameters returned by the class + # parameters, else it will only wrap the parameters returned by the class # method attribute_names. # # If you're going to pass the parameters to an +ActiveModel+ object (such as @@ -180,9 +179,9 @@ module ActionController controller_name.singularize end - options[:include] = Array.wrap(options[:include]).collect(&:to_s) if options[:include] - options[:exclude] = Array.wrap(options[:exclude]).collect(&:to_s) if options[:exclude] - options[:format] = Array.wrap(options[:format]) + options[:include] = Array(options[:include]).collect(&:to_s) if options[:include] + options[:exclude] = Array(options[:exclude]).collect(&:to_s) if options[:exclude] + options[:format] = Array(options[:format]) self._wrapper_options = options end diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index bc22e39efb..afa9243f02 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -74,7 +74,7 @@ module ActionController #:nodoc: # The actual before_filter that is used. Modify this to change how you handle unverified requests. def verify_authenticity_token unless verified_request? - logger.warn "WARNING: Can't verify CSRF token authenticity" if logger + logger.warn "Can't verify CSRF token authenticity" if logger handle_unverified_request end end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 7af256fd99..fb810c41b1 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -17,11 +17,14 @@ module ActionController ActiveSupport.on_load(:action_controller) { self.cache_store ||= RAILS_CACHE } end + initializer "action_controller.assets_config", :group => :all do |app| + app.config.action_controller.assets_dir ||= app.config.paths["public"].first + end + initializer "action_controller.set_configs" do |app| paths = app.config.paths options = app.config.action_controller - options.assets_dir ||= paths["public"].first options.javascripts_dir ||= paths["public/javascripts"].first options.stylesheets_dir ||= paths["public/stylesheets"].first options.page_cache_directory ||= paths["public"].first diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 5354099f87..fce6e29d5f 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -69,15 +69,12 @@ module ActionController # assert_template :partial => '_customer', :locals => { :customer => @customer } # def assert_template(options = {}, message = nil) - validate_request! - case options when NilClass, String, Symbol options = options.to_s if Symbol === options rendered = @templates - msg = build_message(message, - "expecting <?> but rendering with <?>", - options, rendered.keys.join(', ')) + msg = message || sprintf("expecting <%s> but rendering with <%s>", + options, rendered.keys) assert_block(msg) do if options rendered.any? { |t,num| t.match(options) } @@ -87,13 +84,12 @@ module ActionController end when Hash if expected_layout = options[:layout] - msg = build_message(message, - "expecting layout <?> but action rendered <?>", + msg = message || sprintf("expecting layout <%s> but action rendered <%s>", expected_layout, @layouts.keys) case expected_layout when String - assert(@layouts.keys.include?(expected_layout), msg) + assert_includes @layouts.keys, expected_layout, msg when Regexp assert(@layouts.keys.any? {|l| l =~ expected_layout }, msg) when nil @@ -109,15 +105,13 @@ module ActionController end elsif expected_count = options[:count] actual_count = @partials[expected_partial] - msg = build_message(message, - "expecting ? to be rendered ? time(s) but rendered ? time(s)", + msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)", expected_partial, expected_count, actual_count) assert(actual_count == expected_count.to_i, msg) else - msg = build_message(message, - "expecting partial <?> but action rendered <?>", + msg = message || sprintf("expecting partial <%s> but action rendered <%s>", options[:partial], @partials.keys) - assert(@partials.include?(expected_partial), msg) + assert_includes @partials, expected_partial, msg end else assert @partials.empty?, @@ -333,6 +327,12 @@ module ActionController # # assert_redirected_to page_url(:title => 'foo') class TestCase < ActiveSupport::TestCase + + # Use AS::TestCase for the base class when describing a model + register_spec_type(self) do |desc| + desc < ActionController::Base + end + module Behavior extend ActiveSupport::Concern include ActionDispatch::TestProcess @@ -404,7 +404,7 @@ module ActionController # Executes a request simulating HEAD HTTP method and set/volley the response def head(action, parameters = nil, session = nil, flash = nil) - process(action, parameters, session, flash, "HEAD") + process(action, "HEAD", parameters, session, flash) end def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) @@ -432,14 +432,14 @@ module ActionController def process(action, http_method = 'GET', *args) check_required_ivars - http_method, args = handle_old_process_api(http_method, args) - - if args.first.is_a?(String) + http_method, args = handle_old_process_api(http_method, args) + + if args.first.is_a?(String) && http_method != 'HEAD' @request.env['RAW_POST_DATA'] = args.shift end - + parameters, session, flash = args - + # Ensure that numbers and symbols passed as params are converted to # proper params, as is the case when engaging rack. parameters = paramify_values(parameters) @@ -507,13 +507,13 @@ module ActionController def check_required_ivars # Sanity check for required instance variables so we can give an # understandable error message. - %w(@routes @controller @request @response).each do |iv_name| - if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil? + [:@routes, :@controller, :@request, :@response].each do |iv_name| + if !instance_variable_defined?(iv_name) || instance_variable_get(iv_name).nil? raise "#{iv_name} is nil: make sure you set it in your test's setup method." end end end - + def handle_old_process_api(http_method, args) # 4.0: Remove this method. if http_method.is_a?(Hash) @@ -521,7 +521,7 @@ module ActionController args.unshift(http_method) http_method = args.last.is_a?(String) ? args.last : "GET" end - + [http_method, args] end diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 8dd1af7f3d..02a15ad599 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -50,7 +50,7 @@ module ActionDispatch end def env_filter - parameter_filter_for(Array.wrap(@env["action_dispatch.parameter_filter"]) << /RAW_POST_DATA/) + parameter_filter_for(Array(@env["action_dispatch.parameter_filter"]) << /RAW_POST_DATA/) end def parameter_filter_for(filters) diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb index 66ece60860..030ccb2017 100644 --- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb +++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb @@ -33,8 +33,8 @@ module ActionDispatch class GetIp def initialize(env, middleware) - @env = env - @middleware = middleware + @env = env + @middleware = middleware @calculated_ip = false end diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 3d06214bf1..836136eb95 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -1,6 +1,5 @@ require 'action_dispatch/http/request' require 'action_dispatch/middleware/exception_wrapper' -require 'active_support/deprecation' module ActionDispatch # This middleware rescues any exception returned by the application @@ -39,11 +38,6 @@ module ActionDispatch private - # Define this method because some plugins were monkey patching it. - # Remove this after 3.2 is out with the other deprecations in this class. - def status_code(*) - end - def render_exception(env, exception) wrapper = ExceptionWrapper.new(env, exception) status = wrapper.status_code diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 9d0a3e9993..2c21887220 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -533,7 +533,6 @@ module ActionDispatch end def url_for(options) - finalize! options = (options || {}).reverse_merge!(default_url_options) handle_positional_args(options) @@ -559,7 +558,6 @@ module ActionDispatch end def call(env) - finalize! @router.call(env) end diff --git a/actionpack/lib/action_dispatch/testing/assertions/dom.rb b/actionpack/lib/action_dispatch/testing/assertions/dom.rb index 47c84742aa..edea6dab39 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/dom.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/dom.rb @@ -13,9 +13,7 @@ module ActionDispatch def assert_dom_equal(expected, actual, message = "") expected_dom = HTML::Document.new(expected).root actual_dom = HTML::Document.new(actual).root - full_message = build_message(message, "<?> expected to be == to\n<?>.", expected_dom.to_s, actual_dom.to_s) - - assert_block(full_message) { expected_dom == actual_dom } + assert_equal expected_dom, actual_dom end # The negated form of +assert_dom_equivalent+. @@ -28,9 +26,7 @@ module ActionDispatch def assert_dom_not_equal(expected, actual, message = "") expected_dom = HTML::Document.new(expected).root actual_dom = HTML::Document.new(actual).root - full_message = build_message(message, "<?> expected to be != to\n<?>.", expected_dom.to_s, actual_dom.to_s) - - assert_block(full_message) { expected_dom != actual_dom } + refute_equal expected_dom, actual_dom end end end diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index 7381617dd7..094cfbfc76 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -26,16 +26,17 @@ module ActionDispatch # assert_response 401 # def assert_response(type, message = nil) - validate_request! + message ||= "Expected response to be a <#{type}>, but was <#{@response.response_code}>" - if type.in?([:success, :missing, :redirect, :error]) && @response.send("#{type}?") - assert_block("") { true } # to count the assertion - elsif type.is_a?(Fixnum) && @response.response_code == type - assert_block("") { true } # to count the assertion - elsif type.is_a?(Symbol) && @response.response_code == Rack::Utils::SYMBOL_TO_STATUS_CODE[type] - assert_block("") { true } # to count the assertion + if Symbol === type + if [:success, :missing, :redirect, :error].include?(type) + assert @response.send("#{type}?"), message + else + code = Rack::Utils::SYMBOL_TO_STATUS_CODE[type] + assert_equal @response.response_code, code, message + end else - flunk(build_message(message, "Expected response to be a <?>, but was <?>", type, @response.response_code)) + assert_equal type, @response.response_code, message end end @@ -61,9 +62,8 @@ module ActionDispatch redirect_is = normalize_argument_to_redirection(@response.location) redirect_expected = normalize_argument_to_redirection(options) - if redirect_is != redirect_expected - flunk "Expected response to be a redirect to <#{redirect_expected}> but was a redirect to <#{redirect_is}>" - end + message ||= "Expected response to be a redirect to <#{redirect_expected}> but was a redirect to <#{redirect_is}>" + assert_equal redirect_expected, redirect_is, message end private @@ -85,12 +85,6 @@ module ActionDispatch @controller.url_for(fragment) end.gsub(/[\r\n]/, '') end - - def validate_request! - unless @request.is_a?(ActionDispatch::Request) - raise ArgumentError, "@request must be an ActionDispatch::Request" - end - end end end end diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index b10aab9029..1552676fbb 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -45,9 +45,11 @@ module ActionDispatch extras.each_key { |key| expected_options.delete key } unless extras.nil? expected_options.stringify_keys! - msg = build_message(message, "The recognized options <?> did not match <?>, difference: <?>", + + # FIXME: minitest does object diffs, do we need to have our own? + message ||= sprintf("The recognized options <%s> did not match <%s>, difference: <%s>", request.path_parameters, expected_options, expected_options.diff(request.path_parameters)) - assert_equal(expected_options, request.path_parameters, msg) + assert_equal(expected_options, request.path_parameters, message) end # Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+. @@ -84,10 +86,10 @@ module ActionDispatch generated_path, extra_keys = @routes.generate_extras(options, defaults) found_extras = options.reject {|k, v| ! extra_keys.include? k} - msg = build_message(message, "found extras <?>, not <?>", found_extras, extras) + msg = message || sprintf("found extras <%s>, not <%s>", found_extras, extras) assert_equal(extras, found_extras, msg) - msg = build_message(message, "The generated path <?> did not match <?>", generated_path, + msg = message || sprintf("The generated path <%s> did not match <%s>", generated_path, expected_path) assert_equal(expected_path, generated_path, msg) end diff --git a/actionpack/lib/action_dispatch/testing/assertions/selector.rb b/actionpack/lib/action_dispatch/testing/assertions/selector.rb index b4555f4f59..4d963803e6 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/selector.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/selector.rb @@ -270,7 +270,7 @@ module ActionDispatch end text.strip! unless NO_STRIP.include?(match.name) unless match_with.is_a?(Regexp) ? (text =~ match_with) : (text == match_with.to_s) - content_mismatch ||= build_message(message, "<?> expected but was\n<?>.", match_with, text) + content_mismatch ||= sprintf("<%s> expected but was\n<%s>.", match_with, text) true end end @@ -279,7 +279,7 @@ module ActionDispatch html = match.children.map(&:to_s).join html.strip! unless NO_STRIP.include?(match.name) unless match_with.is_a?(Regexp) ? (html =~ match_with) : (html == match_with.to_s) - content_mismatch ||= build_message(message, "<?> expected but was\n<?>.", match_with, html) + content_mismatch ||= sprintf("<%s> expected but was\n<%s>.", match_with, html) true end end @@ -289,12 +289,15 @@ module ActionDispatch message ||= content_mismatch if matches.empty? # Test minimum/maximum occurrence. min, max, count = equals[:minimum], equals[:maximum], equals[:count] + + # FIXME: minitest provides messaging when we use assert_operator, + # so is this custom message really needed? message = message || %(Expected #{count_description(min, max, count)} matching "#{selector.to_s}", found #{matches.size}.) if count - assert matches.size == count, message + assert_equal matches.size, count, message else - assert matches.size >= min, message if min - assert matches.size <= max, message if max + assert_operator matches.size, :>=, min, message if min + assert_operator matches.size, :<=, max, message if max end # If a block is given call that block. Set @selected to allow diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 26db8662a8..08b7ff49c2 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -4,7 +4,6 @@ require 'active_support/core_ext/kernel/singleton_class' require 'active_support/core_ext/object/inclusion' require 'active_support/core_ext/object/try' require 'rack/test' -require 'test/unit/assertions' module ActionDispatch module Integration #:nodoc: @@ -127,7 +126,7 @@ module ActionDispatch class Session DEFAULT_HOST = "www.example.com" - include Test::Unit::Assertions + include MiniTest::Assertions include TestProcess, RequestHelpers, Assertions %w( status status_message headers body redirect? ).each do |method| diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 66a5d59857..08149df423 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -1,10 +1,8 @@ require 'active_support/core_ext/module/attr_internal' require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/class/attribute' -require 'active_support/core_ext/array/wrap' require 'active_support/ordered_options' require 'action_view/log_subscriber' -require 'active_support/core_ext/module/deprecation' module ActionView #:nodoc: # = Action View Base @@ -160,7 +158,7 @@ module ActionView #:nodoc: def process_view_paths(value) value.is_a?(PathSet) ? - value.dup : ActionView::PathSet.new(Array.wrap(value)) + value.dup : ActionView::PathSet.new(Array(value)) end deprecate :process_view_paths diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb index 262e0f1010..f2a3a494bc 100644 --- a/actionpack/lib/action_view/helpers.rb +++ b/actionpack/lib/action_view/helpers.rb @@ -1,5 +1,3 @@ -require 'active_support/benchmarkable' - module ActionView #:nodoc: module Helpers #:nodoc: extend ActiveSupport::Autoload @@ -7,6 +5,7 @@ module ActionView #:nodoc: autoload :ActiveModelHelper autoload :AssetTagHelper autoload :AtomFeedHelper + autoload :BenchmarkHelper autoload :CacheHelper autoload :CaptureHelper autoload :ControllerHelper @@ -33,10 +32,10 @@ module ActionView #:nodoc: extend SanitizeHelper::ClassMethods end - include ActiveSupport::Benchmarkable include ActiveModelHelper include AssetTagHelper include AtomFeedHelper + include BenchmarkHelper include CacheHelper include CaptureHelper include ControllerHelper diff --git a/actionpack/lib/action_view/helpers/benchmark_helper.rb b/actionpack/lib/action_view/helpers/benchmark_helper.rb new file mode 100644 index 0000000000..dfdd5a786d --- /dev/null +++ b/actionpack/lib/action_view/helpers/benchmark_helper.rb @@ -0,0 +1,13 @@ +require 'active_support/benchmarkable' + +module ActionView + module Helpers + module BenchmarkHelper + include ActiveSupport::Benchmarkable + + def benchmark(*) + capture { super } + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index d46ee4faef..fdddb33c31 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -1091,9 +1091,9 @@ module ActionView else add_default_name_and_id(options) end - hidden = tag("input", "name" => options["name"], "type" => "hidden", "value" => options['disabled'] && checked ? checked_value : unchecked_value) + hidden = unchecked_value ? tag("input", "name" => options["name"], "type" => "hidden", "value" => unchecked_value, "disabled" => options["disabled"]) : "" checkbox = tag("input", options) - (hidden + checkbox).html_safe + hidden + checkbox end def to_boolean_select_tag(options = {}) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 3ee0d8ebc5..ba9ff1d5aa 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -134,7 +134,7 @@ module ActionView # # ==== Gotcha # - # The HTML specification says when +multiple+ parameter passed to select and all options got deselected + # The HTML specification says when +multiple+ parameter passed to select and all options got deselected # web browsers do not send any value to server. Unfortunately this introduces a gotcha: # if an +User+ model has many +roles+ and have +role_ids+ accessor, and in the form that edits roles of the user # the user deselects all roles from +role_ids+ multiple select box, no +role_ids+ parameter is sent. So, @@ -322,8 +322,8 @@ module ActionView def options_for_select(container, selected = nil) return container if String === container - selected, disabled = extract_selected_and_disabled(selected).map do | r | - Array.wrap(r).map { |item| item.to_s } + selected, disabled = extract_selected_and_disabled(selected).map do |r| + Array(r).map { |item| item.to_s } end container.map do |element| @@ -333,7 +333,6 @@ module ActionView disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled) %(<option value="#{ERB::Util.html_escape(value)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{ERB::Util.html_escape(text)}</option>) end.join("\n").html_safe - end # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the @@ -508,9 +507,9 @@ module ActionView convert_zones = lambda { |list| list.map { |z| [ z.to_s, z.name ] } } if priority_zones - if priority_zones.is_a?(Regexp) + if priority_zones.is_a?(Regexp) priority_zones = model.all.find_all {|z| z =~ priority_zones} - end + end zone_options += options_for_select(convert_zones[priority_zones], selected) zone_options += "<option value=\"\" disabled=\"disabled\">-------------</option>\n" @@ -558,7 +557,8 @@ module ActionView else selected = Array.wrap(selected) options = selected.extract_options!.symbolize_keys - [ options.include?(:selected) ? options[:selected] : selected, options[:disabled] ] + selected_items = options.include?(:selected) ? options[:selected] : selected + [ selected_items, options[:disabled] ] end end @@ -629,7 +629,7 @@ module ActionView add_default_name_and_id(html_options) select = content_tag("select", add_options(option_tags, options, value(object)), html_options) if html_options["multiple"] - tag("input", :disabled => html_options["disabled"], :name => html_options["name"], :type => "hidden", :value => "") + select + tag("input", :disabled => html_options["disabled"], :name => html_options["name"], :type => "hidden", :value => "") + select else select end diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 3db1394df7..43122ef2ba 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -127,6 +127,7 @@ module ActionView defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {}) currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :default => {}) + currency[:negative_format] ||= "-" + currency[:format] if currency[:format] defaults = DEFAULT_CURRENCY_VALUES.merge(defaults).merge!(currency) defaults[:negative_format] = "-" + options[:format] if options[:format] diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 8c33ef09fa..93a3c40683 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -118,7 +118,7 @@ module ActionView # escape_once("<< Accept & Checkout") # # => "<< Accept & Checkout" def escape_once(html) - ActiveSupport::Multibyte.clean(html.to_s).gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] } + html.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] } end private diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 209360ee82..ce79a3da48 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -162,15 +162,15 @@ module ActionView options.reverse_merge!(:radius => 100, :omission => "...") phrase = Regexp.escape(phrase) - return unless found_pos = text.mb_chars =~ /(#{phrase})/i + return unless found_pos = text =~ /(#{phrase})/i start_pos = [ found_pos - options[:radius], 0 ].max - end_pos = [ [ found_pos + phrase.mb_chars.length + options[:radius] - 1, 0].max, text.mb_chars.length ].min + end_pos = [ [ found_pos + phrase.length + options[:radius] - 1, 0].max, text.length ].min prefix = start_pos > 0 ? options[:omission] : "" - postfix = end_pos < text.mb_chars.length - 1 ? options[:omission] : "" + postfix = end_pos < text.length - 1 ? options[:omission] : "" - prefix + text.mb_chars[start_pos..end_pos].strip + postfix + prefix + text[start_pos..end_pos].strip + postfix end # Attempts to pluralize the +singular+ word unless +count+ is 1. If diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb index 3f07314dda..90d88ca967 100644 --- a/actionpack/lib/action_view/lookup_context.rb +++ b/actionpack/lib/action_view/lookup_context.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/module/remove_method' @@ -29,7 +28,7 @@ module ActionView end def #{name}=(value) - value = value.present? ? Array.wrap(value) : default_#{name} + value = value.present? ? Array(value) : default_#{name} _set_detail(:#{name}, value) if value != @details[:#{name}] end @@ -102,7 +101,7 @@ module ActionView # Whenever setting view paths, makes a copy so we can manipulate then in # instance objects as we wish. def view_paths=(paths) - @view_paths = ActionView::PathSet.new(Array.wrap(paths)) + @view_paths = ActionView::PathSet.new(Array(paths)) end def find(name, prefixes = [], partial = false, keys = [], options = {}) diff --git a/actionpack/lib/action_view/renderer/abstract_renderer.rb b/actionpack/lib/action_view/renderer/abstract_renderer.rb index 5a611e9f63..a588abcee3 100644 --- a/actionpack/lib/action_view/renderer/abstract_renderer.rb +++ b/actionpack/lib/action_view/renderer/abstract_renderer.rb @@ -12,16 +12,16 @@ module ActionView end protected - + def extract_details(options) details = {} @lookup_context.registered_details.each do |key| next unless value = options[key] - details[key] = Array.wrap(value) + details[key] = Array(value) end details end - + def instrument(name, options={}) ActiveSupport::Notifications.instrument("render_#{name}.action_view", options){ yield } end diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb index 06148ccc98..f3abc6d533 100644 --- a/actionpack/lib/action_view/renderer/template_renderer.rb +++ b/actionpack/lib/action_view/renderer/template_renderer.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/object/try' -require 'active_support/core_ext/array/wrap' module ActionView class TemplateRenderer < AbstractRenderer #:nodoc: diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 2d9fc3df7a..593eaa2abf 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/try' require 'active_support/core_ext/kernel/singleton_class' @@ -122,7 +121,7 @@ module ActionView @locals = details[:locals] || [] @virtual_path = details[:virtual_path] @updated_at = details[:updated_at] || Time.now - @formats = Array.wrap(format).map { |f| f.is_a?(Mime::Type) ? f.ref : f } + @formats = Array(format).map { |f| f.is_a?(Mime::Type) ? f.ref : f } end # Returns if the underlying handler supports streaming. If so, diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb index 587e37a84f..83df2604bb 100644 --- a/actionpack/lib/action_view/template/error.rb +++ b/actionpack/lib/action_view/template/error.rb @@ -1,4 +1,3 @@ -require "active_support/core_ext/array/wrap" require "active_support/core_ext/enumerable" module ActionView @@ -30,7 +29,7 @@ module ActionView def initialize(paths, path, prefixes, partial, details, *) @path = path - prefixes = Array.wrap(prefixes) + prefixes = Array(prefixes) template_type = if partial "partial" elsif path =~ /layouts/i diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 9ebe498192..c734c914db 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -183,32 +183,32 @@ module ActionView alias_method :_view, :view - INTERNAL_IVARS = %w{ - @__name__ - @__io__ - @_assertion_wrapped - @_assertions - @_result - @_routes - @controller - @layouts - @locals - @method_name - @output_buffer - @partials - @passed - @rendered - @request - @routes - @templates - @options - @test_passed - @view - @view_context_class - } + INTERNAL_IVARS = [ + :@__name__, + :@__io__, + :@_assertion_wrapped, + :@_assertions, + :@_result, + :@_routes, + :@controller, + :@layouts, + :@locals, + :@method_name, + :@output_buffer, + :@partials, + :@passed, + :@rendered, + :@request, + :@routes, + :@templates, + :@options, + :@test_passed, + :@view, + :@view_context_class + ] def _user_defined_ivars - instance_variables.map(&:to_s) - INTERNAL_IVARS + instance_variables - INTERNAL_IVARS end # Returns a Hash of instance variables and their values, as defined by @@ -216,8 +216,8 @@ module ActionView # rendered. This is generally intended for internal use and extension # frameworks. def view_assigns - Hash[_user_defined_ivars.map do |var| - [var[1, var.length].to_sym, instance_variable_get(var)] + Hash[_user_defined_ivars.map do |ivar| + [ivar[1..-1].to_sym, instance_variable_get(ivar)] end] end diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake index a61a121d55..43405f3db9 100644 --- a/actionpack/lib/sprockets/assets.rake +++ b/actionpack/lib/sprockets/assets.rake @@ -1,12 +1,12 @@ require "fileutils" namespace :assets do - def ruby_rake_task(task) + def ruby_rake_task(task, fork = true) env = ENV['RAILS_ENV'] || 'production' groups = ENV['RAILS_GROUPS'] || 'assets' args = [$0, task,"RAILS_ENV=#{env}","RAILS_GROUPS=#{groups}"] args << "--trace" if Rake.application.options.trace - ruby(*args) + fork ? ruby(*args) : Kernel.exec(FileUtils::RUBY, *args) end # We are currently running with no explicit bundler group @@ -59,7 +59,7 @@ namespace :assets do # required in order to compile digestless assets as the # environment has already cached the assets on the primary # run. - ruby_rake_task "assets:precompile:nondigest" if Rails.application.config.assets.digest + ruby_rake_task("assets:precompile:nondigest", false) if Rails.application.config.assets.digest end task :primary => ["assets:environment", "tmp:cache:clear"] do diff --git a/actionpack/lib/sprockets/static_compiler.rb b/actionpack/lib/sprockets/static_compiler.rb index 32a9d66e6e..719df0bd51 100644 --- a/actionpack/lib/sprockets/static_compiler.rb +++ b/actionpack/lib/sprockets/static_compiler.rb @@ -11,6 +11,7 @@ module Sprockets @digest = options.key?(:digest) ? options.delete(:digest) : true @manifest = options.key?(:manifest) ? options.delete(:manifest) : true @manifest_path = options.delete(:manifest_path) || target + @zip_files = options.delete(:zip_files) || /\.(?:css|html|js|svg|txt|xml)$/ end def compile @@ -36,7 +37,7 @@ module Sprockets filename = File.join(target, path) FileUtils.mkdir_p File.dirname(filename) asset.write_to(filename) - asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/ + asset.write_to("#{filename}.gz") if filename.to_s =~ @zip_files end end diff --git a/actionpack/test/abstract/translation_test.rb b/actionpack/test/abstract/translation_test.rb index 8ec50fd57a..0194ee943f 100644 --- a/actionpack/test/abstract/translation_test.rb +++ b/actionpack/test/abstract/translation_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' # class TranslatingController < ActionController::Base # end -class TranslationControllerTest < Test::Unit::TestCase +class TranslationControllerTest < ActiveSupport::TestCase def setup @controller = ActionController::Base.new end @@ -23,4 +23,4 @@ class TranslationControllerTest < Test::Unit::TestCase def test_action_controller_base_responds_to_l assert_respond_to @controller, :l end -end
\ No newline at end of file +end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 63109d592a..0a25d7ba47 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -21,7 +21,7 @@ silence_warnings do Encoding.default_external = "UTF-8" end -require 'test/unit' +require 'minitest/autorun' require 'abstract_controller' require 'action_controller' require 'action_view' @@ -254,7 +254,7 @@ class Rack::TestCase < ActionDispatch::IntegrationTest end def assert_body(body) - assert_equal body, Array.wrap(response.body).join + assert_equal body, Array(response.body).join end def assert_status(code) @@ -262,7 +262,7 @@ class Rack::TestCase < ActionDispatch::IntegrationTest end def assert_response(body, status = 200, headers = {}) - assert_body body + assert_body body assert_status status headers.each do |header, value| assert_header header, value diff --git a/actionpack/test/assertions/response_assertions_test.rb b/actionpack/test/assertions/response_assertions_test.rb new file mode 100644 index 0000000000..ca1d58765d --- /dev/null +++ b/actionpack/test/assertions/response_assertions_test.rb @@ -0,0 +1,55 @@ +require 'abstract_unit' +require 'action_dispatch/testing/assertions/response' + +module ActionDispatch + module Assertions + class ResponseAssertionsTest < ActiveSupport::TestCase + include ResponseAssertions + + FakeResponse = Struct.new(:response_code) do + [:success, :missing, :redirect, :error].each do |sym| + define_method("#{sym}?") do + sym == response_code + end + end + end + + def test_assert_response_predicate_methods + [:success, :missing, :redirect, :error].each do |sym| + @response = FakeResponse.new sym + assert_response sym + + assert_raises(MiniTest::Assertion) { + assert_response :unauthorized + } + end + end + + def test_assert_response_fixnum + @response = FakeResponse.new 400 + assert_response 400 + + assert_raises(MiniTest::Assertion) { + assert_response :unauthorized + } + + assert_raises(MiniTest::Assertion) { + assert_response 500 + } + end + + def test_assert_response_sym_status + @response = FakeResponse.new 401 + assert_response :unauthorized + + assert_raises(MiniTest::Assertion) { + assert_response :ok + } + + assert_raises(MiniTest::Assertion) { + assert_response :success + } + end + end + end +end diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index bdbf158b36..01cafe1aca 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -338,7 +338,7 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase end def test_render_based_on_parameters - process :render_based_on_parameters, "name" => "David" + process :render_based_on_parameters, "GET", "name" => "David" assert_equal "Mr. David", @response.body end diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index a4f858d06d..c5c48bc559 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -106,7 +106,7 @@ class ControllerClassTests < ActiveSupport::TestCase end end -class ControllerInstanceTests < Test::Unit::TestCase +class ControllerInstanceTests < ActiveSupport::TestCase def setup @empty = EmptyController.new @contained = Submodule::ContainedEmptyController.new diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb index d51882066d..a312b7c32a 100644 --- a/actionpack/test/controller/content_type_test.rb +++ b/actionpack/test/controller/content_type_test.rb @@ -59,7 +59,7 @@ class ContentTypeTest < ActionController::TestCase super # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get # a more accurate simulation of what happens in "real life". - @controller.logger = Logger.new(nil) + @controller.logger = ActiveSupport::Logger.new(nil) end # :ported: diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index d5e3da4d88..9ad0dc75f5 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -16,7 +16,7 @@ class ActionController::Base def assigns(key = nil) assigns = {} - instance_variable_names.each do |ivar| + instance_variables.each do |ivar| next if ActionController::Base.protected_instance_variables.include?(ivar) assigns[ivar[1..-1]] = instance_variable_get(ivar) end diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 2ad95f5c29..a328372cff 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'controller/fake_controllers' require 'action_controller/vendor/html-scanner' -class SessionTest < Test::Unit::TestCase +class SessionTest < ActiveSupport::TestCase StubApp = lambda { |env| [200, {"Content-Type" => "text/html", "Content-Length" => "13"}, ["Hello, World!"]] } @@ -165,7 +165,7 @@ class SessionTest < Test::Unit::TestCase end end -class IntegrationTestTest < Test::Unit::TestCase +class IntegrationTestTest < ActiveSupport::TestCase def setup @test = ::ActionDispatch::IntegrationTest.new(:app) @test.class.stubs(:fixture_table_names).returns([]) diff --git a/actionpack/test/controller/new_base/render_streaming_test.rb b/actionpack/test/controller/new_base/render_streaming_test.rb index 1532bd5c98..61ea68e3f7 100644 --- a/actionpack/test/controller/new_base/render_streaming_test.rb +++ b/actionpack/test/controller/new_base/render_streaming_test.rb @@ -85,7 +85,7 @@ module RenderStreaming test "rendering with template exception logs the exception" do io = StringIO.new - _old, ActionController::Base.logger = ActionController::Base.logger, Logger.new(io) + _old, ActionController::Base.logger = ActionController::Base.logger, ActiveSupport::Logger.new(io) begin get "/render_streaming/basic/template_exception" diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb index f3e5ff8a47..eb38b81e85 100644 --- a/actionpack/test/controller/record_identifier_test.rb +++ b/actionpack/test/controller/record_identifier_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'controller/fake_models' -class RecordIdentifierTest < Test::Unit::TestCase +class RecordIdentifierTest < ActiveSupport::TestCase include ActionController::RecordIdentifier def setup diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 768cfb34ac..ec26315dc7 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -696,7 +696,7 @@ class RenderTest < ActionController::TestCase # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get # a more accurate simulation of what happens in "real life". super - @controller.logger = Logger.new(nil) + @controller.logger = ActiveSupport::Logger.new(nil) @request.host = "www.nextangle.com" end @@ -907,7 +907,7 @@ class RenderTest < ActionController::TestCase def test_access_to_logger_in_view get :accessing_logger_in_template - assert_equal "Logger", @response.body + assert_equal "ActiveSupport::Logger", @response.body end # :ported: diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb index ec4dc848ff..8b4f2f5349 100644 --- a/actionpack/test/controller/render_xml_test.rb +++ b/actionpack/test/controller/render_xml_test.rb @@ -48,7 +48,7 @@ class RenderXmlTest < ActionController::TestCase # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get # a more accurate simulation of what happens in "real life". super - @controller.logger = Logger.new(nil) + @controller.logger = ActiveSupport::Logger.new(nil) @request.host = "www.nextangle.com" end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index c9785d9b8a..bf33b8cdd7 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -12,7 +12,7 @@ end ROUTING = ActionDispatch::Routing # See RFC 3986, section 3.3 for allowed path characters. -class UriReservedCharactersRoutingTest < Test::Unit::TestCase +class UriReservedCharactersRoutingTest < ActiveSupport::TestCase include RoutingTestHelpers def setup @@ -72,7 +72,7 @@ class MockController end end -class LegacyRouteSetTests < Test::Unit::TestCase +class LegacyRouteSetTests < ActiveSupport::TestCase include RoutingTestHelpers attr_reader :rs diff --git a/actionpack/test/controller/runner_test.rb b/actionpack/test/controller/runner_test.rb index 24c220dcd5..3e9383abb2 100644 --- a/actionpack/test/controller/runner_test.rb +++ b/actionpack/test/controller/runner_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'action_dispatch/testing/integration' module ActionDispatch - class RunnerTest < Test::Unit::TestCase + class RunnerTest < ActiveSupport::TestCase class MyRunner include Integration::Runner diff --git a/actionpack/test/controller/selector_test.rb b/actionpack/test/controller/selector_test.rb index 8ce9e43402..5e302da212 100644 --- a/actionpack/test/controller/selector_test.rb +++ b/actionpack/test/controller/selector_test.rb @@ -7,7 +7,7 @@ require 'abstract_unit' require 'controller/fake_controllers' require 'action_controller/vendor/html-scanner' -class SelectorTest < Test::Unit::TestCase +class SelectorTest < ActiveSupport::TestCase # # Basic selector: element, id, class, attributes. # diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb index 73b860ac18..34b06df8d8 100644 --- a/actionpack/test/controller/test_case_test.rb +++ b/actionpack/test/controller/test_case_test.rb @@ -171,22 +171,31 @@ XML assert_equal params.to_query, @response.body end - + def test_document_body_and_params_with_post post :test_params, :id => 1 assert_equal("{\"id\"=>\"1\", \"controller\"=>\"test_test/test\", \"action\"=>\"test_params\"}", @response.body) end - + def test_document_body_with_post post :render_body, "document body" assert_equal "document body", @response.body end - + def test_document_body_with_put put :render_body, "document body" assert_equal "document body", @response.body end + def test_head + head :test_params + assert_equal 200, @response.status + end + + def test_head_params_as_sting + assert_raise(NoMethodError) { head :test_params, "document body", :id => 10 } + end + def test_process_without_flash process :set_flash assert_equal '><', flash['test'] @@ -245,7 +254,7 @@ XML process :test_uri, "GET", :id => 7 assert_equal "/test_test/test/test_uri/7", @response.body end - + def test_process_with_old_api assert_deprecated do process :test_uri, :id => 7 diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb index f5ac886c20..872f171c42 100644 --- a/actionpack/test/controller/view_paths_test.rb +++ b/actionpack/test/controller/view_paths_test.rb @@ -16,9 +16,11 @@ class ViewLoadPathsTest < ActionController::TestCase end end - class Test::SubController < ActionController::Base - layout 'test/sub' - def hello_world; render(:template => 'test/hello_world'); end + module Test + class SubController < ActionController::Base + layout 'test/sub' + def hello_world; render(:template => 'test/hello_world'); end + end end def setup diff --git a/actionpack/test/dispatch/reloader_test.rb b/actionpack/test/dispatch/reloader_test.rb index 3411bd14ea..e371c3b0c1 100644 --- a/actionpack/test/dispatch/reloader_test.rb +++ b/actionpack/test/dispatch/reloader_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class ReloaderTest < Test::Unit::TestCase +class ReloaderTest < ActiveSupport::TestCase Reloader = ActionDispatch::Reloader def test_prepare_callbacks diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb index ad44b4b16a..ae425dd406 100644 --- a/actionpack/test/dispatch/request/json_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb @@ -34,7 +34,7 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest with_test_routing do output = StringIO.new json = "[\"person]\": {\"name\": \"David\"}}" - post "/parse", json, {'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => Logger.new(output)} + post "/parse", json, {'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => ActiveSupport::Logger.new(output)} assert_response :error output.rewind && err = output.read assert err =~ /Error occurred while parsing request parameters/ diff --git a/actionpack/test/dispatch/request/xml_params_parsing_test.rb b/actionpack/test/dispatch/request/xml_params_parsing_test.rb index 0984f00066..afd400c2a9 100644 --- a/actionpack/test/dispatch/request/xml_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/xml_params_parsing_test.rb @@ -56,7 +56,7 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest with_test_routing do output = StringIO.new xml = "<person><name>David</name><avatar type='file' name='me.jpg' content_type='image/jpg'>#{::Base64.encode64('ABC')}</avatar></pineapple>" - post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => Logger.new(output)) + post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => ActiveSupport::Logger.new(output)) assert_response :error output.rewind && err = output.read assert err =~ /Error occurred while parsing request parameters/ diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index d5c1586600..e5ed11d1ea 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -1443,10 +1443,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_nested_optional_path_shorthand with_test_routes do get '/registrations/new' - assert @request.params[:locale].nil? + assert_nil @request.params[:locale] get '/en/registrations/new' - assert 'en', @request.params[:locale] + assert_equal 'en', @request.params[:locale] end end diff --git a/actionpack/test/template/benchmark_helper_test.rb b/actionpack/test/template/benchmark_helper_test.rb new file mode 100644 index 0000000000..1bdda22959 --- /dev/null +++ b/actionpack/test/template/benchmark_helper_test.rb @@ -0,0 +1,24 @@ +require 'abstract_unit' +require 'stringio' + +class BenchmarkHelperTest < ActionView::TestCase + include RenderERBUtils + tests ActionView::Helpers::BenchmarkHelper + + def test_output_in_erb + output = render_erb("Hello <%= benchmark do %>world<% end %>") + expected = 'Hello world' + assert_equal expected, output + end + + def test_returns_value_from_block + assert_equal 'test', benchmark { 'test' } + end + + def test_default_message + log = StringIO.new + self.stubs(:logger).returns(Logger.new(log)) + benchmark {} + assert_match(log.rewind && log.read, /Benchmarking \(\d+.\d+ms\)/) + end +end diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb index 30d798d693..f5dc2fbb33 100644 --- a/actionpack/test/template/compiled_templates_test.rb +++ b/actionpack/test/template/compiled_templates_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'controller/fake_models' -class CompiledTemplatesTest < Test::Unit::TestCase +class CompiledTemplatesTest < ActiveSupport::TestCase def setup # Clean up any details key cached to expose failures # that otherwise would appear just on isolated tests diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb index d45215acfd..e3d3d5ff77 100644 --- a/actionpack/test/template/date_helper_i18n_test.rb +++ b/actionpack/test/template/date_helper_i18n_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase +class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase include ActionView::Helpers::DateHelper attr_reader :request @@ -71,7 +71,7 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase end end -class DateHelperSelectTagsI18nTests < Test::Unit::TestCase +class DateHelperSelectTagsI18nTests < ActiveSupport::TestCase include ActionView::Helpers::DateHelper attr_reader :request diff --git a/actionpack/test/template/erb_util_test.rb b/actionpack/test/template/erb_util_test.rb index 790ab1c74c..eba2ef64e0 100644 --- a/actionpack/test/template/erb_util_test.rb +++ b/actionpack/test/template/erb_util_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/object/inclusion' -class ErbUtilTest < Test::Unit::TestCase +class ErbUtilTest < ActiveSupport::TestCase include ERB::Util ERB::Util::HTML_ESCAPE.each do |given, expected| diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 73b936b16e..82e001732d 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -65,7 +65,7 @@ class FormHelperTest < ActionView::TestCase def full_messages() [ "Author name can't be empty" ] end }.new end - def @post.id; 123; end + def @post.to_key; [123]; end def @post.id_before_type_cast; 123; end def @post.to_param; '123'; end @@ -330,6 +330,7 @@ class FormHelperTest < ActionView::TestCase end def test_check_box + assert check_box("post", "secret").html_safe? assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") @@ -373,6 +374,14 @@ class FormHelperTest < ActionView::TestCase ) end + def test_check_box_with_nil_unchecked_value + @post.secret = "on" + assert_dom_equal( + '<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="on" />', + check_box("post", "secret", {}, "on", nil) + ) + end + def test_check_box_with_multiple_behavior @post.comment_ids = [2,3] assert_dom_equal( @@ -385,11 +394,10 @@ class FormHelperTest < ActionView::TestCase ) end - - def test_checkbox_disabled_still_submits_checked_value + def test_checkbox_disabled_disables_hidden_field assert_dom_equal( - '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" disabled="disabled" id="post_secret" name="post[secret]" type="checkbox" value="1" />', - check_box("post", "secret", { :disabled => :true }) + '<input name="post[secret]" type="hidden" value="0" disabled="disabled"/><input checked="checked" disabled="disabled" id="post_secret" name="post[secret]" type="checkbox" value="1" />', + check_box("post", "secret", { :disabled => true }) ) end @@ -628,7 +636,7 @@ class FormHelperTest < ActionView::TestCase end def test_auto_index - pid = @post.id + pid = 123 assert_dom_equal( "<label for=\"post_#{pid}_title\">Title</label>", label("post[]", "title") @@ -654,7 +662,7 @@ class FormHelperTest < ActionView::TestCase end def test_auto_index_with_nil_id - pid = @post.id + pid = 123 assert_dom_equal( "<input name=\"post[#{pid}][title]\" size=\"30\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title", :id => nil) @@ -867,6 +875,7 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_remote_without_html @post.persisted = false + @post.stubs(:to_key).returns(nil) form_for(@post, :remote => true) do |f| concat f.text_field(:title) concat f.text_area(:body) @@ -1016,6 +1025,7 @@ class FormHelperTest < ActionView::TestCase old_locale, I18n.locale = I18n.locale, :submit @post.persisted = false + @post.stubs(:to_key).returns(nil) form_for(@post) do |f| concat f.submit end @@ -2087,7 +2097,7 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_new_object post = Post.new post.persisted = false - def post.id() nil end + def post.to_key; nil; end form_for(post) do |f| end diff --git a/actionpack/test/template/html-scanner/cdata_node_test.rb b/actionpack/test/template/html-scanner/cdata_node_test.rb index 1822cc565a..9b58174641 100644 --- a/actionpack/test/template/html-scanner/cdata_node_test.rb +++ b/actionpack/test/template/html-scanner/cdata_node_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class CDATANodeTest < Test::Unit::TestCase +class CDATANodeTest < ActiveSupport::TestCase def setup @node = HTML::CDATA.new(nil, 0, 0, "<p>howdy</p>") end diff --git a/actionpack/test/template/html-scanner/document_test.rb b/actionpack/test/template/html-scanner/document_test.rb index 3db2fba783..17f045d549 100644 --- a/actionpack/test/template/html-scanner/document_test.rb +++ b/actionpack/test/template/html-scanner/document_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class DocumentTest < Test::Unit::TestCase +class DocumentTest < ActiveSupport::TestCase def test_handle_doctype doc = nil assert_nothing_raised do diff --git a/actionpack/test/template/html-scanner/node_test.rb b/actionpack/test/template/html-scanner/node_test.rb index f4b9b198e8..5b5d092036 100644 --- a/actionpack/test/template/html-scanner/node_test.rb +++ b/actionpack/test/template/html-scanner/node_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class NodeTest < Test::Unit::TestCase +class NodeTest < ActiveSupport::TestCase class MockNode def initialize(matched, value) diff --git a/actionpack/test/template/html-scanner/tag_node_test.rb b/actionpack/test/template/html-scanner/tag_node_test.rb index 3b72243e7d..a29d2d43d7 100644 --- a/actionpack/test/template/html-scanner/tag_node_test.rb +++ b/actionpack/test/template/html-scanner/tag_node_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class TagNodeTest < Test::Unit::TestCase +class TagNodeTest < ActiveSupport::TestCase def test_open_without_attributes node = tag("<tag>") assert_equal "tag", node.name diff --git a/actionpack/test/template/html-scanner/text_node_test.rb b/actionpack/test/template/html-scanner/text_node_test.rb index 6f61253ffa..cbcb9e78f0 100644 --- a/actionpack/test/template/html-scanner/text_node_test.rb +++ b/actionpack/test/template/html-scanner/text_node_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class TextNodeTest < Test::Unit::TestCase +class TextNodeTest < ActiveSupport::TestCase def setup @node = HTML::Text.new(nil, 0, 0, "hello, howdy, aloha, annyeong") end diff --git a/actionpack/test/template/html-scanner/tokenizer_test.rb b/actionpack/test/template/html-scanner/tokenizer_test.rb index bf45a7c2e3..1d59de23b6 100644 --- a/actionpack/test/template/html-scanner/tokenizer_test.rb +++ b/actionpack/test/template/html-scanner/tokenizer_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class TokenizerTest < Test::Unit::TestCase +class TokenizerTest < ActiveSupport::TestCase def test_blank tokenize "" diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb index 5df09b4d3b..d6e9de9555 100644 --- a/actionpack/test/template/number_helper_i18n_test.rb +++ b/actionpack/test/template/number_helper_i18n_test.rb @@ -53,6 +53,13 @@ class NumberHelperTest < ActionView::TestCase assert_equal("-$10.00", number_to_currency(-10)) end end + + def test_number_to_currency_without_currency_negative_format + clean_i18n do + I18n.backend.store_translations 'ts', :number => { :currency => { :format => { :unit => '@', :format => '%n %u' } } } + assert_equal("-10.00 @", number_to_currency(-10, :locale => 'ts')) + end + end def test_number_with_i18n_precision #Delimiter was set to "" diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index f9c228f0c3..3084527f70 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -37,7 +37,7 @@ class TestERBTemplate < ActiveSupport::TestCase end def logger - Logger.new(STDERR) + ActiveSupport::Logger.new(STDERR) end def my_buffer diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index a75f1bc981..37858c1ba2 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -155,7 +155,7 @@ module ActionView test "view_assigns excludes internal ivars" do INTERNAL_IVARS.each do |ivar| assert defined?(ivar), "expected #{ivar} to be defined" - assert !view_assigns.keys.include?(ivar.sub('@','').to_sym), "expected #{ivar} to be excluded from view_assigns" + assert !view_assigns.keys.include?(ivar.to_s.sub('@', '').to_sym), "expected #{ivar} to be excluded from view_assigns" end end end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 839bf900dc..aa185d9cb0 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -81,10 +81,6 @@ class TextHelperTest < ActionView::TestCase end def test_truncate_multibyte - # .mb_chars always returns a UTF-8 String. - # assert_equal "\354\225\210\353\205\225\355...", - # truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10) - assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'), truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), :length => 10) end @@ -231,8 +227,6 @@ class TextHelperTest < ActionView::TestCase def test_excerpt_with_utf8 assert_equal("...\357\254\203ciency could not be...".force_encoding('UTF-8'), excerpt("That's why e\357\254\203ciency could not be helped".force_encoding('UTF-8'), 'could', 8)) - # .mb_chars always returns UTF-8, even in 1.9. This is not great, but it's how it works. Let's work this out. - # assert_equal("...\203ciency could not be...", excerpt("That's why e\357\254\203ciency could not be helped".force_encoding("BINARY"), 'could', 8)) end def test_word_wrap diff --git a/actionpack/test/ts_isolated.rb b/actionpack/test/ts_isolated.rb index 5670d93613..7430de2299 100644 --- a/actionpack/test/ts_isolated.rb +++ b/actionpack/test/ts_isolated.rb @@ -1,10 +1,12 @@ +$:.unshift(File.dirname(__FILE__)) $:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') -require 'test/unit' +require 'minitest/autorun' require 'rbconfig' require 'active_support/core_ext/kernel/reporting' +require 'abstract_unit' -class TestIsolated < Test::Unit::TestCase +class TestIsolated < ActiveSupport::TestCase ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) Dir["#{File.dirname(__FILE__)}/{abstract,controller,dispatch,template}/**/*_test.rb"].each do |file| diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb index 15103f1185..25d26ede52 100644 --- a/activemodel/lib/active_model/callbacks.rb +++ b/activemodel/lib/active_model/callbacks.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/callbacks' module ActiveModel @@ -93,7 +92,7 @@ module ActiveModel :only => [:before, :around, :after] }.merge(options) - types = Array.wrap(options.delete(:only)) + types = Array(options.delete(:only)) callbacks.each do |callback| define_callbacks(callback, options) @@ -125,7 +124,7 @@ module ActiveModel def self.after_#{callback}(*args, &block) options = args.extract_options! options[:prepend] = true - options[:if] = Array.wrap(options[:if]) << "!halted && value != false" + options[:if] = Array(options[:if]) << "!halted && value != false" set_callback(:#{callback}, :after, *(args << options), &block) end CALLBACK diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb index 80a3ba51c3..c7c805f1a2 100644 --- a/activemodel/lib/active_model/conversion.rb +++ b/activemodel/lib/active_model/conversion.rb @@ -39,11 +39,9 @@ module ActiveModel # Returns an Enumerable of all key attributes if any is set, regardless # if the object is persisted or not. - # - # Note the default implementation uses persisted? just because all objects - # in Ruby 1.8.x responds to <tt>:id</tt>. def to_key - persisted? ? [id] : nil + key = respond_to?(:id) && id + key ? [key] : nil end # Returns a string representing the object's key suitable for use in URLs, diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index aafd1c8a74..025915fe6f 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/object/blank' diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb index 9b12d9d281..13495d6786 100644 --- a/activemodel/lib/active_model/mass_assignment_security.rb +++ b/activemodel/lib/active_model/mass_assignment_security.rb @@ -1,6 +1,5 @@ require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/string/inflections' -require 'active_support/core_ext/array/wrap' require 'active_model/mass_assignment_security/permission_set' require 'active_model/mass_assignment_security/sanitizer' @@ -116,7 +115,7 @@ module ActiveModel self._protected_attributes = protected_attributes_configs.dup - Array.wrap(role).each do |name| + Array(role).each do |name| self._protected_attributes[name] = self.protected_attributes(name) + args end @@ -178,7 +177,7 @@ module ActiveModel self._accessible_attributes = accessible_attributes_configs.dup - Array.wrap(role).each do |name| + Array(role).each do |name| self._accessible_attributes[name] = self.accessible_attributes(name) + args end diff --git a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb index bbdddfb50d..cfeb4aa7cd 100644 --- a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb +++ b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb @@ -1,11 +1,6 @@ -require 'active_support/core_ext/module/delegation' - module ActiveModel module MassAssignmentSecurity class Sanitizer - def initialize(target=nil) - end - # Returns all attributes not denied by the authorizer. def sanitize(attributes, authorizer) sanitized_attributes = attributes.reject { |key, value| authorizer.deny?(key) } @@ -26,11 +21,13 @@ module ActiveModel end class LoggerSanitizer < Sanitizer - delegate :logger, :to => :@target - def initialize(target) @target = target - super + super() + end + + def logger + @target.logger end def logger? @@ -38,14 +35,18 @@ module ActiveModel end def process_removed_attributes(attrs) - logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger? + logger.warn "Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger? end end class StrictSanitizer < Sanitizer + def initialize(target = nil) + super() + end + def process_removed_attributes(attrs) return if (attrs - insensitive_attributes).empty? - raise ActiveModel::MassAssignmentSecurity::Error, "Can't mass-assign protected attributes: #{attrs.join(', ')}" + raise ActiveModel::MassAssignmentSecurity::Error.new(attrs) end def insensitive_attributes @@ -54,6 +55,9 @@ module ActiveModel end class Error < StandardError + def initialize(attrs) + super("Can't mass-assign protected attributes: #{attrs.join(', ')}") + end end end end diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb index cd8eb357de..a8309bf682 100644 --- a/activemodel/lib/active_model/observing.rb +++ b/activemodel/lib/active_model/observing.rb @@ -1,6 +1,5 @@ require 'singleton' require 'active_model/observer_array' -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/module/aliasing' require 'active_support/core_ext/module/remove_method' require 'active_support/core_ext/string/inflections' @@ -200,7 +199,7 @@ module ActiveModel # end # end def observed_classes - Array.wrap(observed_class) + Array(observed_class) end # The class observed by default is inferred from the observer's class name: diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index a4b58ab456..ba9721cc70 100644 --- a/activemodel/lib/active_model/serialization.rb +++ b/activemodel/lib/active_model/serialization.rb @@ -73,15 +73,15 @@ module ActiveModel attribute_names = attributes.keys.sort if only = options[:only] - attribute_names &= Array.wrap(only).map(&:to_s) + attribute_names &= Array(only).map(&:to_s) elsif except = options[:except] - attribute_names -= Array.wrap(except).map(&:to_s) + attribute_names -= Array(except).map(&:to_s) end hash = {} attribute_names.each { |n| hash[n] = read_attribute_for_serialization(n) } - method_names = Array.wrap(options[:methods]).select { |n| respond_to?(n) } + method_names = Array(options[:methods]).select { |n| respond_to?(n) } method_names.each { |n| hash[n] = send(n) } serializable_add_includes(options) do |association, records, opts| diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index d61d9d7119..5084298210 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/hash/conversions' @@ -56,7 +55,7 @@ module ActiveModel end def serializable_collection - methods = Array.wrap(options[:methods]).map(&:to_s) + methods = Array(options[:methods]).map(&:to_s) serializable_hash.map do |name, value| name = name.to_s if methods.include?(name) @@ -146,7 +145,7 @@ module ActiveModel def add_procs if procs = options.delete(:procs) - Array.wrap(procs).each do |proc| + Array(procs).each do |proc| if proc.arity == 1 proc.call(options) else diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 1779efd526..15b8e824ac 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/array/extract_options' -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/hash/except' @@ -133,7 +132,7 @@ module ActiveModel options = args.extract_options! if options.key?(:on) options = options.dup - options[:if] = Array.wrap(options[:if]) + options[:if] = Array(options[:if]) options[:if].unshift("validation_context == :#{options[:on]}") end args << options diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb index 22a77320dc..c80ace7b82 100644 --- a/activemodel/lib/active_model/validations/callbacks.rb +++ b/activemodel/lib/active_model/validations/callbacks.rb @@ -30,7 +30,7 @@ module ActiveModel def before_validation(*args, &block) options = args.last if options.is_a?(Hash) && options[:on] - options[:if] = Array.wrap(options[:if]) + options[:if] = Array(options[:if]) options[:if].unshift("self.validation_context == :#{options[:on]}") end set_callback(:validation, :before, *args, &block) @@ -39,7 +39,7 @@ module ActiveModel def after_validation(*args, &block) options = args.extract_options! options[:prepend] = true - options[:if] = Array.wrap(options[:if]) + options[:if] = Array(options[:if]) options[:if] << "!halted" options[:if].unshift("self.validation_context == :#{options[:on]}") if options[:on] set_callback(:validation, :after, *(args << options), &block) diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index 35ec98c822..2953126c3c 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require "active_support/core_ext/module/anonymous" require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/inclusion' @@ -137,7 +136,7 @@ module ActiveModel #:nodoc: # +options+ reader, however the <tt>:attributes</tt> option will be removed # and instead be made available through the +attributes+ reader. def initialize(options) - @attributes = Array.wrap(options.delete(:attributes)) + @attributes = Array(options.delete(:attributes)) raise ":attributes cannot be blank" if @attributes.empty? super check_validity! diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb index 2e860272a4..4347b17cbc 100644 --- a/activemodel/test/cases/helper.rb +++ b/activemodel/test/cases/helper.rb @@ -10,4 +10,4 @@ require 'active_support/core_ext/string/access' # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true -require 'test/unit' +require 'minitest/autorun' diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb index acda989eec..1e14d83bcb 100644 --- a/activemodel/test/cases/naming_test.rb +++ b/activemodel/test/cases/naming_test.rb @@ -210,7 +210,7 @@ class NamingUsingRelativeModelNameTest < ActiveModel::TestCase end end -class NamingHelpersTest < Test::Unit::TestCase +class NamingHelpersTest < ActiveModel::TestCase def setup @klass = Contact @record = @klass.new @@ -276,7 +276,7 @@ class NamingHelpersTest < Test::Unit::TestCase end end -class NameWithAnonymousClassTest < Test::Unit::TestCase +class NameWithAnonymousClassTest < ActiveModel::TestCase def test_anonymous_class_without_name_argument assert_raises(ArgumentError) do ActiveModel::Name.new(Class.new) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index c4feabfb5f..9c9314ec20 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,8 @@ ## Rails 4.0.0 (unreleased) ## +* Support for the `schema_info` table has been dropped. Please + switch to `schema_migrations`. + * Connections *must* be closed at the end of a thread. If not, your connection pool can fill and an exception will be raised. diff --git a/activerecord/README.rdoc b/activerecord/README.rdoc index 6f9f63ceee..30a66ff5f0 100644 --- a/activerecord/README.rdoc +++ b/activerecord/README.rdoc @@ -143,7 +143,7 @@ A short rundown of some of the major features: * Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]. - ActiveRecord::Base.logger = Logger.new(STDOUT) + ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) ActiveRecord::Base.logger = Log4r::Logger.new("Application Log") diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 0efa111d12..58725246c8 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/enumerable' require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/object/blank' diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb index 090f690f0d..8a17f0ced4 100644 --- a/activerecord/lib/active_record/associations/association_scope.rb +++ b/activerecord/lib/active_record/associations/association_scope.rb @@ -15,7 +15,7 @@ module ActiveRecord def scope scope = klass.unscoped - scope = scope.extending(*Array.wrap(options[:extend])) + scope = scope.extending(*Array(options[:extend])) # It's okay to just apply all these like this. The options will only be present if the # association supports that option; this is enforced by the association builder. diff --git a/activerecord/lib/active_record/associations/builder/collection_association.rb b/activerecord/lib/active_record/associations/builder/collection_association.rb index 35f9a3ae8e..768f70b6c9 100644 --- a/activerecord/lib/active_record/associations/builder/collection_association.rb +++ b/activerecord/lib/active_record/associations/builder/collection_association.rb @@ -32,7 +32,7 @@ module ActiveRecord::Associations::Builder private def wrap_block_extension - options[:extend] = Array.wrap(options[:extend]) + options[:extend] = Array(options[:extend]) if block_extension silence_warnings do @@ -51,7 +51,7 @@ module ActiveRecord::Associations::Builder # TODO : why do i need method_defined? I think its because of the inheritance chain model.class_attribute full_callback_name.to_sym unless model.method_defined?(full_callback_name) - model.send("#{full_callback_name}=", Array.wrap(options[callback_name.to_sym])) + model.send("#{full_callback_name}=", Array(options[callback_name.to_sym])) end def define_readers diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index fe9f30bd2a..7aed64d48c 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/array/wrap' - module ActiveRecord module Associations # = Active Record Association Collection @@ -67,7 +65,7 @@ module ActiveRecord # Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items def ids_writer(ids) pk_column = reflection.primary_key_column - ids = Array.wrap(ids).reject { |id| id.blank? } + ids = Array(ids).reject { |id| id.blank? } ids.map! { |i| pk_column.type_cast(i) } replace(klass.find(ids).index_by { |r| r.id }.values_at(*ids)) end @@ -400,12 +398,7 @@ module ActiveRecord return memory if persisted.empty? persisted.map! do |record| - # Unfortunately we cannot simply do memory.delete(record) since on 1.8 this returns - # record rather than memory.at(memory.index(record)). The behavior is fixed in 1.9. - mem_index = memory.index(record) - - if mem_index - mem_record = memory.delete_at(mem_index) + if mem_record = memory.delete(record) (record.attribute_names - mem_record.changes.keys).each do |name| mem_record[name] = record[name] diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index eb320bc774..ba01df00e3 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -52,7 +52,7 @@ module ActiveRecord def initialize(association) @association = association - Array.wrap(association.options[:extend]).each { |ext| proxy_extend(ext) } + Array(association.options[:extend]).each { |ext| proxy_extend(ext) } end alias_method :new, :build diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index c5834e2fef..02543db2ce 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -20,13 +20,15 @@ module ActiveRecord # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). # (Alias for the protected read_attribute method). - alias [] read_attribute + def [](attr_name) + read_attribute(attr_name) + end # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. # (Alias for the protected write_attribute method). - alias []= write_attribute - - public :[], :[]= + def []=(attr_name, value) + write_attribute(attr_name, value) + end end module ClassMethods diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index c86eaba498..8031912669 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/array/wrap' - module ActiveRecord # = Active Record Autosave Association # diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index d29cf82dad..d4d0220fb7 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'set' require 'active_support/benchmarkable' @@ -12,7 +7,6 @@ require 'active_support/time' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/class/attribute_accessors' require 'active_support/core_ext/class/delegating_attributes' -require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/array/extract_options' require 'active_support/core_ext/hash/deep_merge' require 'active_support/core_ext/hash/indifferent_access' diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 8b2fc69b00..a050fabf35 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/array/wrap' - module ActiveRecord # = Active Record Callbacks # diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 20d3b4a1ef..bfd5121a70 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/deprecation/reporting' module ActiveRecord @@ -42,7 +41,7 @@ module ActiveRecord # # Check an index with a custom name exists # index_exists?(:suppliers, :company_id, :name => "idx_company_id" def index_exists?(table_name, column_name, options = {}) - column_names = Array.wrap(column_name) + column_names = Array(column_name) index_name = options.key?(:name) ? options[:name].to_s : index_name(table_name, :column => column_names) if options[:unique] indexes(table_name).any?{ |i| i.unique && i.name == index_name } @@ -377,7 +376,7 @@ module ActiveRecord def index_name(table_name, options) #:nodoc: if Hash === options # legacy support if options[:column] - "index_#{table_name}_on_#{Array.wrap(options[:column]) * '_and_'}" + "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}" elsif options[:name] options[:name] else @@ -420,23 +419,11 @@ module ActiveRecord end add_index sm_table, :version, :unique => true, :name => "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}" - - # Backwards-compatibility: if we find schema_info, assume we've - # migrated up to that point: - si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix - - if table_exists?(si_table) - ActiveRecord::Deprecation.warn "Usage of the schema table `#{si_table}` is deprecated. Please switch to using `schema_migrations` table" - - old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i - assume_migrated_upto_version(old_version) - drop_table(si_table) - end end end def assume_migrated_upto_version(version, migrations_paths = ActiveRecord::Migrator.migrations_paths) - migrations_paths = Array.wrap(migrations_paths) + migrations_paths = Array(migrations_paths) version = version.to_i sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name) @@ -551,7 +538,7 @@ module ActiveRecord end def add_index_options(table_name, column_name, options = {}) - column_names = Array.wrap(column_name) + column_names = Array(column_name) index_name = index_name(table_name, :column => column_names) if Hash === options # legacy support, since this param was a string diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index d2361b5378..e6ddf8bf8f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -10,21 +10,23 @@ module ActiveRecord module ConnectionHandling # Establishes a connection to the database that's used by all Active Record objects def postgresql_connection(config) # :nodoc: - config = config.symbolize_keys - host = config[:host] - port = config[:port] || 5432 - username = config[:username].to_s if config[:username] - password = config[:password].to_s if config[:password] + conn_params = config.symbolize_keys - if config.key?(:database) - database = config[:database] - else - raise ArgumentError, "No database specified. Missing argument: database." + # Forward any unused config params to PGconn.connect. + [:statement_limit, :encoding, :min_messages, :schema_search_path, + :schema_order, :adapter, :pool, :wait_timeout, + :reaping_frequency].each do |key| + conn_params.delete key end + conn_params.delete_if { |k,v| v.nil? } + + # Map ActiveRecords param names to PGs. + conn_params[:user] = conn_params.delete(:username) if conn_params[:username] + conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database] # The postgres drivers don't allow the creation of an unconnected PGconn object, # so just pass a nil connection object for the time being. - ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, [host, port, nil, nil, database, username, password], config) + ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, conn_params, config) end end @@ -226,22 +228,29 @@ module ActiveRecord end end - # The PostgreSQL adapter works both with the native C (http://ruby.scripting.ca/postgres/) and the pure - # Ruby (available both as gem and from http://rubyforge.org/frs/?group_id=234&release_id=1944) drivers. + # The PostgreSQL adapter works with the native C (https://bitbucket.org/ged/ruby-pg) driver. # # Options: # - # * <tt>:host</tt> - Defaults to "localhost". + # * <tt>:host</tt> - Defaults to a Unix-domain socket in /tmp. On machines without Unix-domain sockets, + # the default is to connect to localhost. # * <tt>:port</tt> - Defaults to 5432. - # * <tt>:username</tt> - Defaults to nothing. - # * <tt>:password</tt> - Defaults to nothing. - # * <tt>:database</tt> - The name of the database. No default, must be provided. + # * <tt>:username</tt> - Defaults to be the same as the operating system name of the user running the application. + # * <tt>:password</tt> - Password to be used if the server demands password authentication. + # * <tt>:database</tt> - Defaults to be the same as the user name. # * <tt>:schema_search_path</tt> - An optional schema search path for the connection given # as a string of comma-separated schema names. This is backward-compatible with the <tt>:schema_order</tt> option. # * <tt>:encoding</tt> - An optional client encoding that is used in a <tt>SET client_encoding TO # <encoding></tt> call on the connection. # * <tt>:min_messages</tt> - An optional client min messages that is used in a # <tt>SET client_min_messages TO <min_messages></tt> call on the connection. + # + # Any further options are used as connection parameters to libpq. See + # http://www.postgresql.org/docs/9.1/static/libpq-connect.html for the + # list of parameters. + # + # In addition, default connection parameters of libpq can be set per environment variables. + # See http://www.postgresql.org/docs/9.1/static/libpq-envars.html . class PostgreSQLAdapter < AbstractAdapter class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition def xml(*args) @@ -1200,7 +1209,7 @@ module ActiveRecord # Connects to a PostgreSQL server and sets up the adapter depending on the # connected server's characteristics. def connect - @connection = PGconn.connect(*@connection_parameters) + @connection = PGconn.connect(@connection_parameters) # Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of # PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 980f8fe50f..89f6eccbd2 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -210,7 +210,7 @@ module ActiveRecord @attributes = cloned_attributes - _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks) + _run_initialize_callbacks if _initialize_callbacks.any? @changed_attributes = {} self.class.column_defaults.each do |attr, orig_value| @@ -317,26 +317,6 @@ module ActiveRecord "#<#{self.class} #{inspection}>" end - # Hackery to accomodate Syck. Remove for 4.0. - def to_yaml(opts = {}) #:nodoc: - if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? - super - else - coder = {} - encode_with(coder) - YAML.quick_emit(self, opts) do |out| - out.map(taguri, to_yaml_style) do |map| - coder.each { |k, v| map.add(k, v) } - end - end - end - end - - # Hackery to accomodate Syck. Remove for 4.0. - def yaml_initialize(tag, coder) #:nodoc: - init_with(coder) - end - private # Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 9ea8cf864c..cf315b687c 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -1,14 +1,7 @@ require 'erb' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'zlib' require 'active_support/dependencies' -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/object/blank' require 'active_support/ordered_hash' require 'active_record/fixtures/file' @@ -789,7 +782,7 @@ module ActiveRecord end def setup_fixture_accessors(fixture_names = nil) - fixture_names = Array.wrap(fixture_names || fixture_table_names) + fixture_names = Array(fixture_names || fixture_table_names) methods = Module.new do fixture_names.each do |fixture_name| fixture_name = fixture_name.to_s diff --git a/activerecord/lib/active_record/fixtures/file.rb b/activerecord/lib/active_record/fixtures/file.rb index 6bad36abb9..6547791144 100644 --- a/activerecord/lib/active_record/fixtures/file.rb +++ b/activerecord/lib/active_record/fixtures/file.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'erb' require 'yaml' diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 46464783fd..10073e2b37 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -1,6 +1,6 @@ require "active_support/core_ext/module/delegation" require "active_support/core_ext/class/attribute_accessors" -require "active_support/core_ext/array/wrap" +require 'active_support/deprecation' module ActiveRecord # Exception that can be raised to stop migrations from going backwards. @@ -345,12 +345,24 @@ module ActiveRecord @name = self.class.name @version = nil @connection = nil + @reverting = false end # instantiate the delegate object after initialize is defined self.verbose = true self.delegate = new + def revert + @reverting = true + yield + ensure + @reverting = false + end + + def reverting? + @reverting + end + def up self.class.delegate = self return unless self.class.respond_to?(:up) @@ -384,9 +396,11 @@ module ActiveRecord end @connection = conn time = Benchmark.measure { - recorder.inverse.each do |cmd, args| - send(cmd, *args) - end + self.revert { + recorder.inverse.each do |cmd, args| + send(cmd, *args) + end + } } else time = Benchmark.measure { change } @@ -441,9 +455,11 @@ module ActiveRecord arg_list = arguments.map{ |a| a.inspect } * ', ' say_with_time "#{method}(#{arg_list})" do - unless arguments.empty? || method == :execute - arguments[0] = Migrator.proper_table_name(arguments.first) - arguments[1] = Migrator.proper_table_name(arguments.second) if method == :rename_table + unless reverting? + unless arguments.empty? || method == :execute + arguments[0] = Migrator.proper_table_name(arguments.first) + arguments[1] = Migrator.proper_table_name(arguments.second) if method == :rename_table + end end return super unless connection.respond_to?(method) connection.send(method, *arguments, &block) @@ -508,7 +524,7 @@ module ActiveRecord File.basename(filename) end - delegate :migrate, :announce, :write, :to=>:migration + delegate :migrate, :announce, :write, :to => :migration private @@ -587,18 +603,17 @@ module ActiveRecord def migrations_paths @migrations_paths ||= ['db/migrate'] # just to not break things if someone uses: migration_path = some_string - Array.wrap(@migrations_paths) + Array(@migrations_paths) end def migrations_path migrations_paths.first end - def migrations(paths, subdirectories = true) - paths = Array.wrap(paths) + def migrations(paths) + paths = Array(paths) - glob = subdirectories ? "**/" : "" - files = Dir[*paths.map { |p| "#{p}/#{glob}[0-9]*_*.rb" }] + files = Dir[*paths.map { |p| "#{p}/**/[0-9]*_*.rb" }] seen = Hash.new false diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index a8ee43b598..9e21039c4f 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -382,7 +382,7 @@ module ActiveRecord if attributes_collection.is_a? Hash keys = attributes_collection.keys attributes_collection = if keys.include?('id') || keys.include?(:id) - Array.wrap(attributes_collection) + [attributes_collection] else attributes_collection.values end diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 165d0750dd..b1c8ae5b77 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -38,7 +38,7 @@ module ActiveRecord # first time. Also, make it output to STDERR. console do |app| require "active_record/railties/console_sandbox" if app.sandbox? - ActiveRecord::Base.logger = Logger.new(STDERR) + ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDERR) end initializer "active_record.initialize_timezone" do diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 60b73e9fe5..f02f0544c5 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -175,7 +175,7 @@ module ActiveRecord def initialize(macro, name, options, active_record) super - @collection = macro.in?([:has_many, :has_and_belongs_to_many]) + @collection = [:has_many, :has_and_belongs_to_many].include?(macro) end # Returns a new, unsaved instance of the associated class. +options+ will diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 6f2248fa21..bf1de4ba9d 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -8,7 +8,7 @@ module ActiveRecord JoinOperation = Struct.new(:relation, :join_class, :on) ASSOCIATION_METHODS = [:includes, :eager_load, :preload] MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] - SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq] + SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reordering, :reverse_order, :uniq] include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index e58c726e09..f1ac421a50 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -134,7 +134,7 @@ module ActiveRecord def last(*args) if args.any? if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash)) - if order_values.empty? && reorder_value.nil? + if order_values.empty? order("#{primary_key} DESC").limit(*args).reverse else to_a.last(*args) @@ -249,7 +249,7 @@ module ActiveRecord end def construct_limited_ids_condition(relation) - orders = (relation.reorder_value || relation.order_values).map { |val| val.presence }.compact + orders = relation.order_values.map { |val| val.presence }.compact values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders) relation = relation.dup diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index bfb5c27578..44ff8f7b22 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -9,7 +9,7 @@ module ActiveRecord :select_values, :group_values, :order_values, :joins_values, :where_values, :having_values, :bind_values, :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, - :from_value, :reorder_value, :reverse_order_value, + :from_value, :reordering_value, :reverse_order_value, :uniq_value def includes(*args) @@ -107,7 +107,8 @@ module ActiveRecord return self if args.blank? relation = clone - relation.reorder_value = args.flatten + relation.reordering_value = true + relation.order_values = args.flatten relation end @@ -273,7 +274,7 @@ module ActiveRecord arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty? - order = @reorder_value ? @reorder_value : @order_values + order = @order_values order = reverse_sql_order(order) if @reverse_order_value arel.order(*order.uniq.reject{|o| o.blank?}) unless order.empty? diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index a5194beae5..de639a48f2 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -22,7 +22,7 @@ module ActiveRecord end end - (Relation::MULTI_VALUE_METHODS - [:joins, :where]).each do |method| + (Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method| value = r.send(:"#{method}_values") merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present? end @@ -48,7 +48,7 @@ module ActiveRecord merged_relation.where_values = merged_wheres - (Relation::SINGLE_VALUE_METHODS - [:lock, :create_with]).each do |method| + (Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method| value = r.send(:"#{method}_value") merged_relation.send(:"#{method}_value=", value) unless value.nil? end @@ -57,6 +57,15 @@ module ActiveRecord merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty? + if (r.reordering_value) + # override any order specified in the original relation + merged_relation.reordering_value = true + merged_relation.order_values = r.order_values + else + # merge in order_values from r + merged_relation.order_values += r.order_values + end + # Apply scope extension modules merged_relation.send :apply_modules, r.extensions diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index cdde5cf3b9..2a565b51c6 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -112,7 +112,7 @@ HEADER # AR has an optimization which handles zero-scale decimals as integers. This # code ensures that the dumper still dumps the column as a decimal. - spec[:type] = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) } + spec[:type] = if column.type == :integer && /^(numeric|decimal)/ =~ column.sql_type 'decimal' else column.type.to_s @@ -127,10 +127,14 @@ HEADER end.compact # find all migration keys used in this table - keys = [:name, :limit, :precision, :scale, :default, :null] & column_specs.map{ |k| k.keys }.flatten + keys = [:name, :limit, :precision, :scale, :default, :null] # figure out the lengths for each column based on above keys - lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max } + lengths = keys.map { |key| + column_specs.map { |spec| + spec[key] ? spec[key].length + 2 : 0 + }.max + } # the string we're going to sprintf our values against, with standardized column widths format_string = lengths.map{ |len| "%-#{len}s" } diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb index 5ad40d8cd9..41e3b92499 100644 --- a/activerecord/lib/active_record/serialization.rb +++ b/activerecord/lib/active_record/serialization.rb @@ -7,8 +7,8 @@ module ActiveRecord #:nodoc: def serializable_hash(options = nil) options = options.try(:clone) || {} - options[:except] = Array.wrap(options[:except]).map { |n| n.to_s } - options[:except] |= Array.wrap(self.class.inheritance_column) + options[:except] = Array(options[:except]).map { |n| n.to_s } + options[:except] |= Array(self.class.inheritance_column) super(options) end diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb index 0e7f57aa43..7f1dba5095 100644 --- a/activerecord/lib/active_record/serializers/xml_serializer.rb +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/hash/conversions' module ActiveRecord #:nodoc: @@ -179,7 +178,7 @@ module ActiveRecord #:nodoc: class XmlSerializer < ActiveModel::Serializers::Xml::Serializer #:nodoc: def initialize(*args) super - options[:except] = Array.wrap(options[:except]) | Array.wrap(@serializable.class.inheritance_column) + options[:except] = Array(options[:except]) | Array(@serializable.class.inheritance_column) end class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc: diff --git a/activerecord/lib/active_record/session_store.rb b/activerecord/lib/active_record/session_store.rb index 1029bed064..ce43ae8066 100644 --- a/activerecord/lib/active_record/session_store.rb +++ b/activerecord/lib/active_record/session_store.rb @@ -116,7 +116,7 @@ module ActiveRecord define_method(:session_id) { sessid } define_method(:session_id=) { |session_id| self.sessid = session_id } else - class << self; remove_method :find_by_session_id; end + class << self; remove_possible_method :find_by_session_id; end def self.find_by_session_id(session_id) find :first, :conditions => {:session_id=>session_id} diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb index 5398a14fc6..64ecef2077 100644 --- a/activerecord/lib/active_record/test_case.rb +++ b/activerecord/lib/active_record/test_case.rb @@ -9,6 +9,10 @@ module ActiveRecord cleanup_identity_map end + def teardown + ActiveRecord::SQLCounter.log.clear + end + def cleanup_identity_map ActiveRecord::IdentityMap.clear end @@ -49,5 +53,9 @@ module ActiveRecord ensure ActiveRecord::SQLCounter.ignored_sql = prev_ignored_sql end + + def sqlite3? connection + connection.class.name.split('::').last == "SQLite3Adapter" + end end end diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 2c70d31b94..b492377d18 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -211,7 +211,7 @@ module ActiveRecord def after_commit(*args, &block) options = args.last if options.is_a?(Hash) && options[:on] - options[:if] = Array.wrap(options[:if]) + options[:if] = Array(options[:if]) options[:if] << "transaction_include_action?(:#{options[:on]})" end set_callback(:commit, :after, *args, &block) @@ -220,7 +220,7 @@ module ActiveRecord def after_rollback(*args, &block) options = args.last if options.is_a?(Hash) && options[:on] - options[:if] = Array.wrap(options[:if]) + options[:if] = Array(options[:if]) options[:if] << "transaction_include_action?(:#{options[:on]})" end set_callback(:rollback, :after, *args, &block) diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 2e2ea8c42b..3a741ba600 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/array/wrap' - module ActiveRecord module Validations class UniquenessValidator < ActiveModel::EachValidator @@ -25,8 +23,13 @@ module ActiveRecord relation = build_relation(finder_class, table, attribute, value) relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.send(:id))) if record.persisted? - Array.wrap(options[:scope]).each do |scope_item| + Array(options[:scope]).each do |scope_item| scope_value = record.send(scope_item) + reflection = record.class.reflect_on_association(scope_item) + if reflection + scope_value = record.send(reflection.foreign_key) + scope_item = reflection.foreign_key + end relation = relation.and(table[scope_item].eq(scope_value)) end @@ -53,14 +56,22 @@ module ActiveRecord end def build_relation(klass, table, attribute, value) #:nodoc: - column = klass.columns_hash[attribute.to_s] - value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text? + reflection = klass.reflect_on_association(attribute) + column = nil + if(reflection) + column = klass.columns_hash[reflection.foreign_key] + attribute = reflection.foreign_key + value = value.attributes[reflection.primary_key_column.name] + else + column = klass.columns_hash[attribute.to_s] + end + value = column.limit ? value.to_s[0, column.limit] : value.to_s if !value.nil? && column.text? if !options[:case_sensitive] && value && column.text? # will use SQL LOWER function before comparison, unless it detects a case insensitive collation relation = klass.connection.case_insensitive_comparison(table, attribute, column, value) else - value = klass.connection.case_sensitive_modifier(value) + value = klass.connection.case_sensitive_modifier(value) unless value.nil? relation = table[attribute].eq(value) end @@ -81,7 +92,7 @@ module ActiveRecord # # class Person < ActiveRecord::Base # validates_uniqueness_of :user_name, :scope => :account_id - # end + # end # # Or even multiple scope parameters. For example, making sure that a teacher can only be on the schedule once # per semester for a particular class. diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index 21b97b3b39..4baec749ff 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -2,6 +2,9 @@ require "cases/helper" module ActiveRecord class PostgresqlConnectionTest < ActiveRecord::TestCase + class NonExistentTable < ActiveRecord::Base + end + def setup super @connection = ActiveRecord::Base.connection @@ -10,5 +13,17 @@ module ActiveRecord def test_encoding assert_not_nil @connection.encoding end + + # Ensure, we can set connection params using the example of Generic + # Query Optimizer (geqo). It is 'on' per default. + def test_connection_options + params = ActiveRecord::Base.connection_config.dup + params[:options] = "-c geqo=off" + NonExistentTable.establish_connection(params) + + # Verify the connection param has been applied. + expect = NonExistentTable.connection.query('show geqo').first.first + assert_equal 'off', expect + end end end diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index cb777b9f78..4202d28061 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -67,7 +67,7 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase def test_find_with_implicit_inner_joins_does_not_set_associations authors = Author.joins(:posts).select('authors.*') assert !authors.empty?, "expected authors to be non-empty" - assert authors.all? {|a| !a.send(:instance_variable_names).include?("@posts")}, "expected no authors to have the @posts association loaded" + assert authors.all? { |a| !a.instance_variable_defined?(:@posts) }, "expected no authors to have the @posts association loaded" end def test_count_honors_implicit_inner_joins diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index b6cf26f978..d6de668a17 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -258,8 +258,14 @@ class AttributeMethodsTest < ActiveRecord::TestCase topic.send(:write_attribute, :title, "Still another topic") assert_equal "Still another topic", topic.title - topic.send(:write_attribute, "title", "Still another topic: part 2") + topic[:title] = "Still another topic: part 2" assert_equal "Still another topic: part 2", topic.title + + topic.send(:write_attribute, "title", "Still another topic: part 3") + assert_equal "Still another topic: part 3", topic.title + + topic["title"] = "Still another topic: part 4" + assert_equal "Still another topic: part 4", topic.title end def test_read_attribute @@ -312,6 +318,39 @@ class AttributeMethodsTest < ActiveRecord::TestCase # puts "" end + def test_overridden_write_attribute + topic = Topic.new + def topic.write_attribute(attr_name, value) + super(attr_name, value.downcase) + end + + topic.send(:write_attribute, :title, "Yet another topic") + assert_equal "yet another topic", topic.title + + topic[:title] = "Yet another topic: part 2" + assert_equal "yet another topic: part 2", topic.title + + topic.send(:write_attribute, "title", "Yet another topic: part 3") + assert_equal "yet another topic: part 3", topic.title + + topic["title"] = "Yet another topic: part 4" + assert_equal "yet another topic: part 4", topic.title + end + + def test_overridden_read_attribute + topic = Topic.new + topic.title = "Stop changing the topic" + def topic.read_attribute(attr_name) + super(attr_name).upcase + end + + assert_equal "STOP CHANGING THE TOPIC", topic.send(:read_attribute, "title") + assert_equal "STOP CHANGING THE TOPIC", topic["title"] + + assert_equal "STOP CHANGING THE TOPIC", topic.send(:read_attribute, :title) + assert_equal "STOP CHANGING THE TOPIC", topic[:title] + end + def test_read_overridden_attribute topic = Topic.new(:title => 'a') def topic.title() 'b' end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 4c3f2bda57..1376810adf 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -586,6 +586,7 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning') end @@ -908,6 +909,7 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning') end @@ -1031,6 +1033,7 @@ class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @ship = Ship.create(:name => 'Nights Dirty Lightning') @pirate = @ship.create_pirate(:catchphrase => "Don' botharrr talkin' like one, savvy?") end @@ -1279,6 +1282,7 @@ class TestAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @association_name = :birds @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @@ -1293,6 +1297,7 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @association_name = :parrots @habtm = true @@ -1308,6 +1313,7 @@ class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::Te self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @pirate.birds.create(:name => 'cookoo') end @@ -1324,6 +1330,7 @@ class TestAutosaveAssociationValidationsOnAHasOneAssociation < ActiveRecord::Tes self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @pirate.create_ship(:name => 'titanic') super @@ -1346,6 +1353,7 @@ class TestAutosaveAssociationValidationsOnABelongsToAssociation < ActiveRecord:: self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") end @@ -1366,6 +1374,7 @@ class TestAutosaveAssociationValidationsOnAHABTMAssociation < ActiveRecord::Test self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") end @@ -1388,6 +1397,7 @@ class TestAutosaveAssociationValidationMethodsGeneration < ActiveRecord::TestCas self.use_transactional_fixtures = false unless supports_savepoints? def setup + super @pirate = Pirate.new end diff --git a/activerecord/test/cases/dup_test.rb b/activerecord/test/cases/dup_test.rb index 0236f9b0a1..9705a11387 100644 --- a/activerecord/test/cases/dup_test.rb +++ b/activerecord/test/cases/dup_test.rb @@ -99,5 +99,13 @@ module ActiveRecord assert_not_nil new_topic.created_at end + def test_dup_after_initialize_callbacks + topic = Topic.new + assert Topic.after_initialize_called + Topic.after_initialize_called = false + topic.dup + assert Topic.after_initialize_called + end + end end diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 859c3d1947..d16cccdaea 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -2,11 +2,12 @@ require File.expand_path('../../../../load_paths', __FILE__) require 'config' -require 'test/unit' +require 'minitest/autorun' require 'stringio' require 'mocha' require 'active_record' +require 'active_record/test_case' require 'active_support/dependencies' require 'active_support/logger' @@ -71,8 +72,8 @@ module ActiveRecord attr_reader :ignore - def initialize(ignore = self.class.ignored_sql) - @ignore = ignore + def initialize(ignore = Regexp.union(self.class.ignored_sql)) + @ignore = ignore end def call(name, start, finish, message_id, values) @@ -80,7 +81,7 @@ module ActiveRecord # FIXME: this seems bad. we should probably have a better way to indicate # the query was cached - return if 'CACHE' == values[:name] || ignore.any? { |x| x =~ sql } + return if 'CACHE' == values[:name] || ignore =~ sql self.class.log << sql end end diff --git a/activerecord/test/cases/invertible_migration_test.rb b/activerecord/test/cases/invertible_migration_test.rb index 3ae7b63dff..8f1cdd47ea 100644 --- a/activerecord/test/cases/invertible_migration_test.rb +++ b/activerecord/test/cases/invertible_migration_test.rb @@ -88,5 +88,17 @@ module ActiveRecord LegacyMigration.down assert !ActiveRecord::Base.connection.table_exists?("horses"), "horses should not exist" end + + def test_migrate_down_with_table_name_prefix + ActiveRecord::Base.table_name_prefix = 'p_' + ActiveRecord::Base.table_name_suffix = '_s' + migration = InvertibleMigration.new + migration.migrate(:up) + assert_nothing_raised { migration.migrate(:down) } + assert !ActiveRecord::Base.connection.table_exists?("p_horses_s"), "p_horses_s should not exist" + ensure + ActiveRecord::Base.table_name_prefix = ActiveRecord::Base.table_name_suffix = '' + end + end end diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 65cd9f9755..0c458d5318 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -230,10 +230,13 @@ class OptimisticLockingTest < ActiveRecord::TestCase def test_polymorphic_destroy_with_dependencies_and_lock_version car = Car.create! - car.wheels << Wheel.create! - assert_equal 1, car.wheels.count - assert car.destroy - assert_equal 0, car.wheels.count + + assert_difference 'car.wheels.count' do + car.wheels << Wheel.create! + end + assert_difference 'car.wheels.count', -1 do + car.destroy + end assert car.destroyed? end end diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb new file mode 100644 index 0000000000..f8eedc712f --- /dev/null +++ b/activerecord/test/cases/migration/change_schema_test.rb @@ -0,0 +1,368 @@ +require 'cases/helper' + +module ActiveRecord + class Migration + class ChangeSchemaTest < ActiveRecord::TestCase + attr_reader :connection, :table_name + + def setup + super + @connection = ActiveRecord::Base.connection + @table_name = :testings + end + + def teardown + super + connection.drop_table :testings rescue nil + ActiveRecord::Base.primary_key_prefix_type = nil + end + + def test_index_exists + connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + t.column :bar, :string, :limit => 100 + end + connection.add_index :testings, :foo + + assert connection.index_exists?(:testings, :foo) + assert !connection.index_exists?(:testings, :bar) + end + + def test_index_exists_on_multiple_columns + connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + t.column :bar, :string, :limit => 100 + end + connection.add_index :testings, [:foo, :bar] + + assert connection.index_exists?(:testings, [:foo, :bar]) + end + + def test_unique_index_exists + connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + end + connection.add_index :testings, :foo, :unique => true + + assert connection.index_exists?(:testings, :foo, :unique => true) + end + + def test_named_index_exists + connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + end + connection.add_index :testings, :foo, :name => "custom_index_name" + + assert connection.index_exists?(:testings, :foo, :name => "custom_index_name") + end + + def test_create_table_without_id + testing_table_with_only_foo_attribute do + assert_equal connection.columns(:testings).size, 1 + end + end + + def test_add_column_with_primary_key_attribute + testing_table_with_only_foo_attribute do + connection.add_column :testings, :id, :primary_key + assert_equal connection.columns(:testings).size, 2 + end + end + + def test_create_table_adds_id + connection.create_table :testings do |t| + t.column :foo, :string + end + + assert_equal %w(foo id), connection.columns(:testings).map(&:name).sort + end + + def test_create_table_with_not_null_column + connection.create_table :testings do |t| + t.column :foo, :string, :null => false + end + + assert_raises(ActiveRecord::StatementInvalid) do + connection.execute "insert into testings (foo) values (NULL)" + end + end + + def test_create_table_with_defaults + # MySQL doesn't allow defaults on TEXT or BLOB columns. + mysql = current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter) + + connection.create_table :testings do |t| + t.column :one, :string, :default => "hello" + t.column :two, :boolean, :default => true + t.column :three, :boolean, :default => false + t.column :four, :integer, :default => 1 + t.column :five, :text, :default => "hello" unless mysql + end + + columns = connection.columns(:testings) + one = columns.detect { |c| c.name == "one" } + two = columns.detect { |c| c.name == "two" } + three = columns.detect { |c| c.name == "three" } + four = columns.detect { |c| c.name == "four" } + five = columns.detect { |c| c.name == "five" } unless mysql + + assert_equal "hello", one.default + assert_equal true, two.default + assert_equal false, three.default + assert_equal 1, four.default + assert_equal "hello", five.default unless mysql + end + + def test_create_table_with_limits + connection.create_table :testings do |t| + t.column :foo, :string, :limit => 255 + + t.column :default_int, :integer + + t.column :one_int, :integer, :limit => 1 + t.column :four_int, :integer, :limit => 4 + t.column :eight_int, :integer, :limit => 8 + t.column :eleven_int, :integer, :limit => 11 + end + + columns = connection.columns(:testings) + foo = columns.detect { |c| c.name == "foo" } + assert_equal 255, foo.limit + + default = columns.detect { |c| c.name == "default_int" } + one = columns.detect { |c| c.name == "one_int" } + four = columns.detect { |c| c.name == "four_int" } + eight = columns.detect { |c| c.name == "eight_int" } + eleven = columns.detect { |c| c.name == "eleven_int" } + + if current_adapter?(:PostgreSQLAdapter) + assert_equal 'integer', default.sql_type + assert_equal 'smallint', one.sql_type + assert_equal 'integer', four.sql_type + assert_equal 'bigint', eight.sql_type + assert_equal 'integer', eleven.sql_type + elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + assert_match 'int(11)', default.sql_type + assert_match 'tinyint', one.sql_type + assert_match 'int', four.sql_type + assert_match 'bigint', eight.sql_type + assert_match 'int(11)', eleven.sql_type + elsif current_adapter?(:OracleAdapter) + assert_equal 'NUMBER(38)', default.sql_type + assert_equal 'NUMBER(1)', one.sql_type + assert_equal 'NUMBER(4)', four.sql_type + assert_equal 'NUMBER(8)', eight.sql_type + end + end + + def test_create_table_with_primary_key_prefix_as_table_name_with_underscore + ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore + + connection.create_table :testings do |t| + t.column :foo, :string + end + + assert_equal %w(foo testing_id), connection.columns(:testings).map(&:name).sort + end + + def test_create_table_with_primary_key_prefix_as_table_name + ActiveRecord::Base.primary_key_prefix_type = :table_name + + connection.create_table :testings do |t| + t.column :foo, :string + end + + assert_equal %w(foo testingid), connection.columns(:testings).map(&:name).sort + end + + def test_create_table_with_timestamps_should_create_datetime_columns + connection.create_table table_name do |t| + t.timestamps + end + created_columns = connection.columns(table_name) + + created_at_column = created_columns.detect {|c| c.name == 'created_at' } + updated_at_column = created_columns.detect {|c| c.name == 'updated_at' } + + assert !created_at_column.null + assert !updated_at_column.null + end + + def test_create_table_with_timestamps_should_create_datetime_columns_with_options + connection.create_table table_name do |t| + t.timestamps :null => false + end + created_columns = connection.columns(table_name) + + created_at_column = created_columns.detect {|c| c.name == 'created_at' } + updated_at_column = created_columns.detect {|c| c.name == 'updated_at' } + + assert !created_at_column.null + assert !updated_at_column.null + end + + def test_create_table_without_a_block + connection.create_table table_name + end + + def test_add_column_not_null_without_default + # Sybase, and SQLite3 will not allow you to add a NOT NULL + # column to a table without a default value. + if current_adapter?(:SybaseAdapter, :SQLite3Adapter) + skip "not supported on #{connection.class}" + end + + + connection.create_table :testings do |t| + t.column :foo, :string + end + connection.add_column :testings, :bar, :string, :null => false + + assert_raise(ActiveRecord::StatementInvalid) do + connection.execute "insert into testings (foo, bar) values ('hello', NULL)" + end + end + + def test_add_column_not_null_with_default + connection.create_table :testings do |t| + t.column :foo, :string + end + + con = connection + connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter) + connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')" + connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter) + assert_nothing_raised {connection.add_column :testings, :bar, :string, :null => false, :default => "default" } + + assert_raises(ActiveRecord::StatementInvalid) do + unless current_adapter?(:OpenBaseAdapter) + connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)" + else + connection.insert("INSERT INTO testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) VALUES (2, 'hello', NULL)", + "Testing Insert","id",2) + end + end + end + + def test_change_column_quotes_column_names + connection.create_table :testings do |t| + t.column :select, :string + end + + connection.change_column :testings, :select, :string, :limit => 10 + + # Oracle needs primary key value from sequence + if current_adapter?(:OracleAdapter) + connection.execute "insert into testings (id, #{connection.quote_column_name('select')}) values (testings_seq.nextval, '7 chars')" + else + connection.execute "insert into testings (#{connection.quote_column_name('select')}) values ('7 chars')" + end + end + + def test_keeping_default_and_notnull_constaint_on_change + connection.create_table :testings do |t| + t.column :title, :string + end + person_klass = Class.new(ActiveRecord::Base) + person_klass.table_name = 'testings' + + person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99 + person_klass.reset_column_information + assert_equal 99, person_klass.columns_hash["wealth"].default + assert_equal false, person_klass.columns_hash["wealth"].null + # Oracle needs primary key value from sequence + if current_adapter?(:OracleAdapter) + assert_nothing_raised {person_klass.connection.execute("insert into testings (id, title) values (testings_seq.nextval, 'tester')")} + else + assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")} + end + + # change column default to see that column doesn't lose its not null definition + person_klass.connection.change_column_default "testings", "wealth", 100 + person_klass.reset_column_information + assert_equal 100, person_klass.columns_hash["wealth"].default + assert_equal false, person_klass.columns_hash["wealth"].null + + # rename column to see that column doesn't lose its not null and/or default definition + person_klass.connection.rename_column "testings", "wealth", "money" + person_klass.reset_column_information + assert_nil person_klass.columns_hash["wealth"] + assert_equal 100, person_klass.columns_hash["money"].default + assert_equal false, person_klass.columns_hash["money"].null + + # change column + person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000 + person_klass.reset_column_information + assert_equal 1000, person_klass.columns_hash["money"].default + assert_equal false, person_klass.columns_hash["money"].null + + # change column, make it nullable and clear default + person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil + person_klass.reset_column_information + assert_nil person_klass.columns_hash["money"].default + assert_equal true, person_klass.columns_hash["money"].null + + # change_column_null, make it not nullable and set null values to a default value + person_klass.connection.execute('UPDATE testings SET money = NULL') + person_klass.connection.change_column_null "testings", "money", false, 2000 + person_klass.reset_column_information + assert_nil person_klass.columns_hash["money"].default + assert_equal false, person_klass.columns_hash["money"].null + assert_equal 2000, connection.select_values("SELECT money FROM testings").first.to_i + end + + def test_column_exists + connection.create_table :testings do |t| + t.column :foo, :string + end + + assert connection.column_exists?(:testings, :foo) + refute connection.column_exists?(:testings, :bar) + end + + def test_column_exists_with_type + connection.create_table :testings do |t| + t.column :foo, :string + t.column :bar, :decimal, :precision => 8, :scale => 2 + end + + assert connection.column_exists?(:testings, :foo, :string) + refute connection.column_exists?(:testings, :foo, :integer) + + assert connection.column_exists?(:testings, :bar, :decimal) + refute connection.column_exists?(:testings, :bar, :integer) + end + + def test_column_exists_with_definition + connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + t.column :bar, :decimal, :precision => 8, :scale => 2 + end + + assert connection.column_exists?(:testings, :foo, :string, :limit => 100) + refute connection.column_exists?(:testings, :foo, :string, :limit => 50) + assert connection.column_exists?(:testings, :bar, :decimal, :precision => 8, :scale => 2) + refute connection.column_exists?(:testings, :bar, :decimal, :precision => 10, :scale => 2) + end + + def test_column_exists_on_table_with_no_options_parameter_supplied + connection.create_table :testings do |t| + t.string :foo + end + connection.change_table :testings do |t| + assert t.column_exists?(:foo) + assert !(t.column_exists?(:bar)) + end + end + + private + def testing_table_with_only_foo_attribute + connection.create_table :testings, :id => false do |t| + t.column :foo, :string + end + + yield + end + end + end +end diff --git a/activerecord/test/cases/migration/column_positioning_test.rb b/activerecord/test/cases/migration/column_positioning_test.rb new file mode 100644 index 0000000000..913d935f7c --- /dev/null +++ b/activerecord/test/cases/migration/column_positioning_test.rb @@ -0,0 +1,60 @@ +require 'cases/helper' + +module ActiveRecord + class Migration + class ColumnPositioningTest < ActiveRecord::TestCase + attr_reader :connection, :table_name + alias :conn :connection + + def setup + super + + unless current_adapter?(:MysqlAdapter, :Mysql2Adapter) + skip "not supported on #{connection.class}" + end + + @connection = ActiveRecord::Base.connection + + connection.create_table :testings, :id => false do |t| + t.column :first, :integer + t.column :second, :integer + t.column :third, :integer + end + end + + def teardown + super + connection.drop_table :testings rescue nil + ActiveRecord::Base.primary_key_prefix_type = nil + end + + def test_column_positioning + assert_equal %w(first second third), conn.columns(:testings).map {|c| c.name } + end + + def test_add_column_with_positioning + conn.add_column :testings, :new_col, :integer + assert_equal %w(first second third new_col), conn.columns(:testings).map {|c| c.name } + end + + def test_add_column_with_positioning_first + conn.add_column :testings, :new_col, :integer, :first => true + assert_equal %w(new_col first second third), conn.columns(:testings).map {|c| c.name } + end + + def test_add_column_with_positioning_after + conn.add_column :testings, :new_col, :integer, :after => :first + assert_equal %w(first new_col second third), conn.columns(:testings).map {|c| c.name } + end + + def test_change_column_with_positioning + conn.change_column :testings, :second, :integer, :first => true + assert_equal %w(second first third), conn.columns(:testings).map {|c| c.name } + + conn.change_column :testings, :second, :integer, :after => :third + assert_equal %w(first third second), conn.columns(:testings).map {|c| c.name } + end + + end + end +end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 1e68911ab3..30ee8a553a 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -10,2285 +10,1837 @@ require MIGRATIONS_ROOT + "/rename/1_we_need_things" require MIGRATIONS_ROOT + "/rename/2_rename_things" require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers" -if ActiveRecord::Base.connection.supports_migrations? - class BigNumber < ActiveRecord::Base; end +class BigNumber < ActiveRecord::Base; end - class Reminder < ActiveRecord::Base; end +class Reminder < ActiveRecord::Base; end - class Thing < ActiveRecord::Base; end +class Thing < ActiveRecord::Base; end - class ActiveRecord::Migration - class << self - attr_accessor :message_count - end - - def puts(text="") - ActiveRecord::Migration.message_count ||= 0 - ActiveRecord::Migration.message_count += 1 - end +class ActiveRecord::Migration + class << self + attr_accessor :message_count end - class MigrationTableAndIndexTest < ActiveRecord::TestCase - def test_add_schema_info_respects_prefix_and_suffix - conn = ActiveRecord::Base.connection - - conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name) - # Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters - ActiveRecord::Base.table_name_prefix = 'p_' - ActiveRecord::Base.table_name_suffix = '_s' - conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name) - - conn.initialize_schema_migrations_table - - assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name] - ensure - ActiveRecord::Base.table_name_prefix = "" - ActiveRecord::Base.table_name_suffix = "" - end + def puts(text="") + ActiveRecord::Migration.message_count ||= 0 + ActiveRecord::Migration.message_count += 1 end +end - class MigrationTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - - fixtures :people - - def setup - ActiveRecord::Migration.verbose = true - ActiveRecord::Migration.message_count = 0 - end - - def teardown - ActiveRecord::Base.connection.initialize_schema_migrations_table - ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}" - - %w(things awesome_things prefix_things_suffix prefix_awesome_things_suffix).each do |table| - Thing.connection.drop_table(table) rescue nil - end - Thing.reset_column_information - - %w(reminders people_reminders prefix_reminders_suffix).each do |table| - Reminder.connection.drop_table(table) rescue nil - end - Reminder.reset_column_information - - %w(last_name key bio age height wealth birthday favorite_day - moment_of_truth male administrator funny).each do |column| - Person.connection.remove_column('people', column) rescue nil - end - Person.connection.remove_column("people", "first_name") rescue nil - Person.connection.remove_column("people", "middle_name") rescue nil - Person.connection.add_column("people", "first_name", :string, :limit => 40) - Person.reset_column_information - end - - def test_add_index - # Limit size of last_name and key columns to support Firebird index limitations - Person.connection.add_column "people", "last_name", :string, :limit => 100 - Person.connection.add_column "people", "key", :string, :limit => 100 - Person.connection.add_column "people", "administrator", :boolean - - assert_nothing_raised { Person.connection.add_index("people", "last_name") } - assert_nothing_raised { Person.connection.remove_index("people", "last_name") } - - # Orcl nds shrt indx nms. Sybs 2. - # OpenBase does not have named indexes. You must specify a single column name - unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } - assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) } - # Oracle adapter cannot have specified index name larger than 30 characters - # Oracle adapter is shortening index name when just column list is given - unless current_adapter?(:OracleAdapter) - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } - assert_nothing_raised { Person.connection.remove_index("people", :name => :index_people_on_last_name_and_first_name) } - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } - assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") } - end - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } - assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } - assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) } - assert_nothing_raised { Person.connection.remove_index("people", "last_name") } - assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => {:last_name => 10}) } - assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) } - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => 10) } - assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20}) } - assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } - end - - # quoting - # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word - # OpenBase does not have named indexes. You must specify a single column name - unless current_adapter?(:OpenBaseAdapter) - Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'id'}" #some databases (including sqlite2 won't add a unique index if existing data non unique) - assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) } - assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) } - end - - # Sybase adapter does not support indexes on :boolean columns - # OpenBase does not have named indexes. You must specify a single column - unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) - assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") } - assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") } - end - - # Selected adapters support index sort order - if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter) - assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :order => {:last_name => :desc}) } - assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) } - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc}) } - assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc, :first_name => :asc}) } - assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } - assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => :desc) } - assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } - end - end - - def test_index_symbol_names - assert_nothing_raised { Person.connection.add_index :people, :primary_contact_id, :name => :symbol_index_name } - assert Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name) - assert_nothing_raised { Person.connection.remove_index :people, :name => :symbol_index_name } - assert !Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name) - end - - def test_add_index_length_limit - good_index_name = 'x' * Person.connection.index_name_length - too_long_index_name = good_index_name + 'x' - assert_raise(ArgumentError) { Person.connection.add_index("people", "first_name", :name => too_long_index_name) } - assert !Person.connection.index_name_exists?("people", too_long_index_name, false) - assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => good_index_name) } - assert Person.connection.index_name_exists?("people", good_index_name, false) - Person.connection.remove_index("people", :name => good_index_name) - end - - def test_remove_nonexistent_index - # we do this by name, so OpenBase is a wash as noted above - unless current_adapter?(:OpenBaseAdapter) - assert_raise(ArgumentError) { Person.connection.remove_index("people", "no_such_index") } - end - end +class MigrationTableAndIndexTest < ActiveRecord::TestCase + def test_add_schema_info_respects_prefix_and_suffix + conn = ActiveRecord::Base.connection - def test_rename_index - unless current_adapter?(:OpenBaseAdapter) - # keep the names short to make Oracle and similar behave - Person.connection.add_index('people', [:first_name], :name => 'old_idx') - assert_nothing_raised { Person.connection.rename_index('people', 'old_idx', 'new_idx') } - # if the adapter doesn't support the indexes call, pick defaults that let the test pass - assert !Person.connection.index_name_exists?('people', 'old_idx', false) - assert Person.connection.index_name_exists?('people', 'new_idx', true) - end - end + conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name) + # Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters + ActiveRecord::Base.table_name_prefix = 'p_' + ActiveRecord::Base.table_name_suffix = '_s' + conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name) - def test_double_add_index - unless current_adapter?(:OpenBaseAdapter) - Person.connection.add_index('people', [:first_name], :name => 'some_idx') - assert_raise(ArgumentError) { Person.connection.add_index('people', [:first_name], :name => 'some_idx') } - end - end + conn.initialize_schema_migrations_table - def test_index_exists - Person.connection.create_table :testings do |t| - t.column :foo, :string, :limit => 100 - t.column :bar, :string, :limit => 100 - end - Person.connection.add_index :testings, :foo + assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name] + ensure + ActiveRecord::Base.table_name_prefix = "" + ActiveRecord::Base.table_name_suffix = "" + end +end - assert Person.connection.index_exists?(:testings, :foo) - assert !Person.connection.index_exists?(:testings, :bar) - ensure - Person.connection.drop_table :testings rescue nil - end +class MigrationTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false - def test_index_exists_on_multiple_columns - Person.connection.create_table :testings do |t| - t.column :foo, :string, :limit => 100 - t.column :bar, :string, :limit => 100 - end - Person.connection.add_index :testings, [:foo, :bar] + fixtures :people - assert Person.connection.index_exists?(:testings, [:foo, :bar]) - ensure - Person.connection.drop_table :testings rescue nil - end + def setup + super + ActiveRecord::Migration.verbose = true + ActiveRecord::Migration.message_count = 0 + end - def test_unique_index_exists - Person.connection.create_table :testings do |t| - t.column :foo, :string, :limit => 100 - end - Person.connection.add_index :testings, :foo, :unique => true + def teardown + ActiveRecord::Base.connection.initialize_schema_migrations_table + ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::Migrator.schema_migrations_table_name}" - assert Person.connection.index_exists?(:testings, :foo, :unique => true) - ensure - Person.connection.drop_table :testings rescue nil + %w(things awesome_things prefix_things_suffix prefix_awesome_things_suffix).each do |table| + Thing.connection.drop_table(table) rescue nil end + Thing.reset_column_information - def test_named_index_exists - Person.connection.create_table :testings do |t| - t.column :foo, :string, :limit => 100 - end - Person.connection.add_index :testings, :foo, :name => "custom_index_name" - - assert Person.connection.index_exists?(:testings, :foo, :name => "custom_index_name") - ensure - Person.connection.drop_table :testings rescue nil + %w(reminders people_reminders prefix_reminders_suffix).each do |table| + Reminder.connection.drop_table(table) rescue nil end + Reminder.reset_column_information - def testing_table_with_only_foo_attribute - Person.connection.create_table :testings, :id => false do |t| - t.column :foo, :string - end - - yield Person.connection - ensure - Person.connection.drop_table :testings rescue nil + %w(last_name key bio age height wealth birthday favorite_day + moment_of_truth male administrator funny).each do |column| + Person.connection.remove_column('people', column) rescue nil end - protected :testing_table_with_only_foo_attribute + Person.connection.remove_column("people", "first_name") rescue nil + Person.connection.remove_column("people", "middle_name") rescue nil + Person.connection.add_column("people", "first_name", :string, :limit => 40) + Person.reset_column_information + end - def test_create_table_without_id - testing_table_with_only_foo_attribute do |connection| - assert_equal connection.columns(:testings).size, 1 + def test_add_index + # Limit size of last_name and key columns to support Firebird index limitations + Person.connection.add_column "people", "last_name", :string, :limit => 100 + Person.connection.add_column "people", "key", :string, :limit => 100 + Person.connection.add_column "people", "administrator", :boolean + + assert_nothing_raised { Person.connection.add_index("people", "last_name") } + assert_nothing_raised { Person.connection.remove_index("people", "last_name") } + + # Orcl nds shrt indx nms. Sybs 2. + # OpenBase does not have named indexes. You must specify a single column name + unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) } + # Oracle adapter cannot have specified index name larger than 30 characters + # Oracle adapter is shortening index name when just column list is given + unless current_adapter?(:OracleAdapter) + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.remove_index("people", :name => :index_people_on_last_name_and_first_name) } + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") } end + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => 10) } + assert_nothing_raised { Person.connection.remove_index("people", "last_name") } + assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :length => {:last_name => 10}) } + assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) } + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => 10) } + assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :length => {:last_name => 10, :first_name => 20}) } + assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } + end + + # quoting + # Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word + # OpenBase does not have named indexes. You must specify a single column name + unless current_adapter?(:OpenBaseAdapter) + Person.update_all "#{Person.connection.quote_column_name 'key'}=#{Person.connection.quote_column_name 'id'}" #some databases (including sqlite2 won't add a unique index if existing data non unique) + assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) } + assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) } + end + + # Sybase adapter does not support indexes on :boolean columns + # OpenBase does not have named indexes. You must specify a single column + unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) + assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") } + assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") } + end + + # Selected adapters support index sort order + if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter) + assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :order => {:last_name => :desc}) } + assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) } + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc}) } + assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc, :first_name => :asc}) } + assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => :desc) } + assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) } end + end - def test_add_column_with_primary_key_attribute - testing_table_with_only_foo_attribute do |connection| - assert_nothing_raised { connection.add_column :testings, :id, :primary_key } - assert_equal connection.columns(:testings).size, 2 - end - end + def test_index_symbol_names + assert_nothing_raised { Person.connection.add_index :people, :primary_contact_id, :name => :symbol_index_name } + assert Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name) + assert_nothing_raised { Person.connection.remove_index :people, :name => :symbol_index_name } + assert !Person.connection.index_exists?(:people, :primary_contact_id, :name => :symbol_index_name) + end - def test_create_table_adds_id - Person.connection.create_table :testings do |t| - t.column :foo, :string - end + def test_add_index_length_limit + good_index_name = 'x' * Person.connection.index_name_length + too_long_index_name = good_index_name + 'x' + assert_raise(ArgumentError) { Person.connection.add_index("people", "first_name", :name => too_long_index_name) } + assert !Person.connection.index_name_exists?("people", too_long_index_name, false) + assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => good_index_name) } + assert Person.connection.index_name_exists?("people", good_index_name, false) + Person.connection.remove_index("people", :name => good_index_name) + end - assert_equal %w(foo id), - Person.connection.columns(:testings).map { |c| c.name }.sort - ensure - Person.connection.drop_table :testings rescue nil + def test_remove_nonexistent_index + # we do this by name, so OpenBase is a wash as noted above + unless current_adapter?(:OpenBaseAdapter) + assert_raise(ArgumentError) { Person.connection.remove_index("people", "no_such_index") } end + end - def test_create_table_with_not_null_column - assert_nothing_raised do - Person.connection.create_table :testings do |t| - t.column :foo, :string, :null => false - end - end - - assert_raise(ActiveRecord::StatementInvalid) do - Person.connection.execute "insert into testings (foo) values (NULL)" - end - ensure - Person.connection.drop_table :testings rescue nil + def test_rename_index + unless current_adapter?(:OpenBaseAdapter) + # keep the names short to make Oracle and similar behave + Person.connection.add_index('people', [:first_name], :name => 'old_idx') + assert_nothing_raised { Person.connection.rename_index('people', 'old_idx', 'new_idx') } + # if the adapter doesn't support the indexes call, pick defaults that let the test pass + assert !Person.connection.index_name_exists?('people', 'old_idx', false) + assert Person.connection.index_name_exists?('people', 'new_idx', true) end + end - def test_create_table_with_defaults - # MySQL doesn't allow defaults on TEXT or BLOB columns. - mysql = current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter) - - Person.connection.create_table :testings do |t| - t.column :one, :string, :default => "hello" - t.column :two, :boolean, :default => true - t.column :three, :boolean, :default => false - t.column :four, :integer, :default => 1 - t.column :five, :text, :default => "hello" unless mysql - end - - columns = Person.connection.columns(:testings) - one = columns.detect { |c| c.name == "one" } - two = columns.detect { |c| c.name == "two" } - three = columns.detect { |c| c.name == "three" } - four = columns.detect { |c| c.name == "four" } - five = columns.detect { |c| c.name == "five" } unless mysql - - assert_equal "hello", one.default - assert_equal true, two.default - assert_equal false, three.default - assert_equal 1, four.default - assert_equal "hello", five.default unless mysql - - ensure - Person.connection.drop_table :testings rescue nil + def test_double_add_index + unless current_adapter?(:OpenBaseAdapter) + Person.connection.add_index('people', [:first_name], :name => 'some_idx') + assert_raise(ArgumentError) { Person.connection.add_index('people', [:first_name], :name => 'some_idx') } end + end - def test_create_table_with_limits - assert_nothing_raised do - Person.connection.create_table :testings do |t| - t.column :foo, :string, :limit => 255 - - t.column :default_int, :integer - - t.column :one_int, :integer, :limit => 1 - t.column :four_int, :integer, :limit => 4 - t.column :eight_int, :integer, :limit => 8 - t.column :eleven_int, :integer, :limit => 11 - end - end - - columns = Person.connection.columns(:testings) - foo = columns.detect { |c| c.name == "foo" } - assert_equal 255, foo.limit - - default = columns.detect { |c| c.name == "default_int" } - one = columns.detect { |c| c.name == "one_int" } - four = columns.detect { |c| c.name == "four_int" } - eight = columns.detect { |c| c.name == "eight_int" } - eleven = columns.detect { |c| c.name == "eleven_int" } - - if current_adapter?(:PostgreSQLAdapter) - assert_equal 'integer', default.sql_type - assert_equal 'smallint', one.sql_type - assert_equal 'integer', four.sql_type - assert_equal 'bigint', eight.sql_type - assert_equal 'integer', eleven.sql_type - elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) - assert_match 'int(11)', default.sql_type - assert_match 'tinyint', one.sql_type - assert_match 'int', four.sql_type - assert_match 'bigint', eight.sql_type - assert_match 'int(11)', eleven.sql_type - elsif current_adapter?(:OracleAdapter) - assert_equal 'NUMBER(38)', default.sql_type - assert_equal 'NUMBER(1)', one.sql_type - assert_equal 'NUMBER(4)', four.sql_type - assert_equal 'NUMBER(8)', eight.sql_type - end - ensure - Person.connection.drop_table :testings rescue nil + def test_create_table_with_force_true_does_not_drop_nonexisting_table + if Person.connection.table_exists?(:testings2) + Person.connection.drop_table :testings2 end - def test_create_table_with_primary_key_prefix_as_table_name_with_underscore - ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore - - Person.connection.create_table :testings do |t| - t.column :foo, :string - end - - assert_equal %w(foo testing_id), Person.connection.columns(:testings).map { |c| c.name }.sort - ensure - Person.connection.drop_table :testings rescue nil - ActiveRecord::Base.primary_key_prefix_type = nil + # using a copy as we need the drop_table method to + # continue to work for the ensure block of the test + temp_conn = Person.connection.dup + temp_conn.expects(:drop_table).never + temp_conn.create_table :testings2, :force => true do |t| + t.column :foo, :string end + ensure + Person.connection.drop_table :testings2 rescue nil + end - def test_create_table_with_primary_key_prefix_as_table_name - ActiveRecord::Base.primary_key_prefix_type = :table_name - - Person.connection.create_table :testings do |t| - t.column :foo, :string - end - - assert_equal %w(foo testingid), Person.connection.columns(:testings).map { |c| c.name }.sort - ensure - Person.connection.drop_table :testings rescue nil - ActiveRecord::Base.primary_key_prefix_type = nil - end + # We specifically do a manual INSERT here, and then test only the SELECT + # functionality. This allows us to more easily catch INSERT being broken, + # but SELECT actually working fine. + def test_native_decimal_insert_manual_vs_automatic + correct_value = '0012345678901234567890.0123456789'.to_d - def test_create_table_with_force_true_does_not_drop_nonexisting_table - if Person.connection.table_exists?(:testings2) - Person.connection.drop_table :testings2 - end + Person.delete_all + Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10' + Person.reset_column_information - # using a copy as we need the drop_table method to - # continue to work for the ensure block of the test - temp_conn = Person.connection.dup - temp_conn.expects(:drop_table).never - temp_conn.create_table :testings2, :force => true do |t| - t.column :foo, :string - end - ensure - Person.connection.drop_table :testings2 rescue nil + # Do a manual insertion + if current_adapter?(:OracleAdapter) + Person.connection.execute "insert into people (id, wealth, created_at, updated_at) values (people_seq.nextval, 12345678901234567890.0123456789, sysdate, sysdate)" + elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings + Person.connection.execute "insert into people (wealth, created_at, updated_at) values ('12345678901234567890.0123456789', 0, 0)" + elsif current_adapter?(:PostgreSQLAdapter) + Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, now(), now())" + else + Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, 0, 0)" end - def test_create_table_with_timestamps_should_create_datetime_columns - table_name = :testings - - Person.connection.create_table table_name do |t| - t.timestamps - end - created_columns = Person.connection.columns(table_name) - - created_at_column = created_columns.detect {|c| c.name == 'created_at' } - updated_at_column = created_columns.detect {|c| c.name == 'updated_at' } + # SELECT + row = Person.find(:first) + assert_kind_of BigDecimal, row.wealth - assert !created_at_column.null - assert !updated_at_column.null - ensure - Person.connection.drop_table table_name rescue nil + # If this assert fails, that means the SELECT is broken! + unless current_adapter?(:SQLite3Adapter) + assert_equal correct_value, row.wealth end - def test_create_table_with_timestamps_should_create_datetime_columns_with_options - table_name = :testings + # Reset to old state + Person.delete_all - Person.connection.create_table table_name do |t| - t.timestamps :null => false - end - created_columns = Person.connection.columns(table_name) + # Now use the Rails insertion + assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") } - created_at_column = created_columns.detect {|c| c.name == 'created_at' } - updated_at_column = created_columns.detect {|c| c.name == 'updated_at' } + # SELECT + row = Person.find(:first) + assert_kind_of BigDecimal, row.wealth - assert !created_at_column.null - assert !updated_at_column.null - ensure - Person.connection.drop_table table_name rescue nil + # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken! + unless current_adapter?(:SQLite3Adapter) + assert_equal correct_value, row.wealth end - def test_create_table_without_a_block - table_name = :testings - Person.connection.create_table table_name - ensure - Person.connection.drop_table table_name rescue nil - end - - # Sybase, and SQLite3 will not allow you to add a NOT NULL - # column to a table without a default value. - unless current_adapter?(:SybaseAdapter, :SQLite3Adapter) - def test_add_column_not_null_without_default - Person.connection.create_table :testings do |t| - t.column :foo, :string - end - Person.connection.add_column :testings, :bar, :string, :null => false - - assert_raise(ActiveRecord::StatementInvalid) do - Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)" - end - ensure - Person.connection.drop_table :testings rescue nil - end - end - - def test_add_column_not_null_with_default - Person.connection.create_table :testings do |t| - t.column :foo, :string - end + # Reset to old state + Person.connection.del_column "people", "wealth" rescue nil + Person.reset_column_information + end - con = Person.connection - Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter) - Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')" - Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter) - assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" } - - assert_raise(ActiveRecord::StatementInvalid) do - unless current_adapter?(:OpenBaseAdapter) - Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)" - else - Person.connection.insert("INSERT INTO testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) VALUES (2, 'hello', NULL)", - "Testing Insert","id",2) - end - end - ensure - Person.connection.drop_table :testings rescue nil - end + def test_add_column_with_precision_and_scale + Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7 + Person.reset_column_information - # We specifically do a manual INSERT here, and then test only the SELECT - # functionality. This allows us to more easily catch INSERT being broken, - # but SELECT actually working fine. - def test_native_decimal_insert_manual_vs_automatic - correct_value = '0012345678901234567890.0123456789'.to_d + wealth_column = Person.columns_hash['wealth'] + assert_equal 9, wealth_column.precision + assert_equal 7, wealth_column.scale + end + # Test SQLite adapter specifically for decimal types with precision and scale + # attributes, since these need to be maintained in schema but aren't actually + # used in SQLite itself + if current_adapter?(:SQLite3Adapter) + def test_change_column_with_new_precision_and_scale Person.delete_all - Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10' + Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7 Person.reset_column_information - # Do a manual insertion - if current_adapter?(:OracleAdapter) - Person.connection.execute "insert into people (id, wealth, created_at, updated_at) values (people_seq.nextval, 12345678901234567890.0123456789, sysdate, sysdate)" - elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings - Person.connection.execute "insert into people (wealth, created_at, updated_at) values ('12345678901234567890.0123456789', 0, 0)" - elsif current_adapter?(:PostgreSQLAdapter) - Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, now(), now())" - else - Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, 0, 0)" - end - - # SELECT - row = Person.find(:first) - assert_kind_of BigDecimal, row.wealth - - # If this assert fails, that means the SELECT is broken! - unless current_adapter?(:SQLite3Adapter) - assert_equal correct_value, row.wealth - end - - # Reset to old state - Person.delete_all - - # Now use the Rails insertion - assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") } - - # SELECT - row = Person.find(:first) - assert_kind_of BigDecimal, row.wealth - - # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken! - unless current_adapter?(:SQLite3Adapter) - assert_equal correct_value, row.wealth - end - - # Reset to old state - Person.connection.del_column "people", "wealth" rescue nil + Person.connection.change_column 'people', 'wealth', :decimal, :precision => 12, :scale => 8 Person.reset_column_information + + wealth_column = Person.columns_hash['wealth'] + assert_equal 12, wealth_column.precision + assert_equal 8, wealth_column.scale end - def test_add_column_with_precision_and_scale + def test_change_column_preserve_other_column_precision_and_scale + Person.delete_all + Person.connection.add_column 'people', 'last_name', :string Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7 Person.reset_column_information wealth_column = Person.columns_hash['wealth'] assert_equal 9, wealth_column.precision assert_equal 7, wealth_column.scale - end - - # Test SQLite adapter specifically for decimal types with precision and scale - # attributes, since these need to be maintained in schema but aren't actually - # used in SQLite itself - if current_adapter?(:SQLite3Adapter) - def test_change_column_with_new_precision_and_scale - Person.delete_all - Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7 - Person.reset_column_information - - Person.connection.change_column 'people', 'wealth', :decimal, :precision => 12, :scale => 8 - Person.reset_column_information - - wealth_column = Person.columns_hash['wealth'] - assert_equal 12, wealth_column.precision - assert_equal 8, wealth_column.scale - end - - def test_change_column_preserve_other_column_precision_and_scale - Person.delete_all - Person.connection.add_column 'people', 'last_name', :string - Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7 - Person.reset_column_information - - wealth_column = Person.columns_hash['wealth'] - assert_equal 9, wealth_column.precision - assert_equal 7, wealth_column.scale - - Person.connection.change_column 'people', 'last_name', :string, :null => false - Person.reset_column_information - wealth_column = Person.columns_hash['wealth'] - assert_equal 9, wealth_column.precision - assert_equal 7, wealth_column.scale - end - end - - def test_native_types - Person.delete_all - Person.connection.add_column "people", "last_name", :string - Person.connection.add_column "people", "bio", :text - Person.connection.add_column "people", "age", :integer - Person.connection.add_column "people", "height", :float - Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10' - Person.connection.add_column "people", "birthday", :datetime - Person.connection.add_column "people", "favorite_day", :date - Person.connection.add_column "people", "moment_of_truth", :datetime - Person.connection.add_column "people", "male", :boolean + Person.connection.change_column 'people', 'last_name', :string, :null => false Person.reset_column_information - assert_nothing_raised do - Person.create :first_name => 'bob', :last_name => 'bobsen', - :bio => "I was born ....", :age => 18, :height => 1.78, - :wealth => BigDecimal.new("12345678901234567890.0123456789"), - :birthday => 18.years.ago, :favorite_day => 10.days.ago, - :moment_of_truth => "1782-10-10 21:40:18", :male => true - end - - bob = Person.find(:first) - assert_equal 'bob', bob.first_name - assert_equal 'bobsen', bob.last_name - assert_equal "I was born ....", bob.bio - assert_equal 18, bob.age - - # Test for 30 significant digits (beyond the 16 of float), 10 of them - # after the decimal place. - - unless current_adapter?(:SQLite3Adapter) - assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth - end - - assert_equal true, bob.male? - - assert_equal String, bob.first_name.class - assert_equal String, bob.last_name.class - assert_equal String, bob.bio.class - assert_equal Fixnum, bob.age.class - assert_equal Time, bob.birthday.class - - if current_adapter?(:OracleAdapter, :SybaseAdapter) - # Sybase, and Oracle don't differentiate between date/time - assert_equal Time, bob.favorite_day.class - else - assert_equal Date, bob.favorite_day.class - end - - # Oracle adapter stores Time or DateTime with timezone value already in _before_type_cast column - # therefore no timezone change is done afterwards when default timezone is changed - unless current_adapter?(:OracleAdapter) - # Test DateTime column and defaults, including timezone. - # FIXME: moment of truth may be Time on 64-bit platforms. - if bob.moment_of_truth.is_a?(DateTime) - - with_env_tz 'US/Eastern' do - bob.reload - assert_equal DateTime.local_offset, bob.moment_of_truth.offset - assert_not_equal 0, bob.moment_of_truth.offset - assert_not_equal "Z", bob.moment_of_truth.zone - # US/Eastern is -5 hours from GMT - assert_equal Rational(-5, 24), bob.moment_of_truth.offset - assert_match(/\A-05:?00\Z/, bob.moment_of_truth.zone) #ruby 1.8.6 uses HH:MM, prior versions use HHMM - assert_equal DateTime::ITALY, bob.moment_of_truth.start - end - end - end - - assert_instance_of TrueClass, bob.male? - assert_kind_of BigDecimal, bob.wealth + wealth_column = Person.columns_hash['wealth'] + assert_equal 9, wealth_column.precision + assert_equal 7, wealth_column.scale end + end - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) - def test_unabstracted_database_dependent_types - Person.delete_all - - ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint - Person.reset_column_information - assert_match(/tinyint/, Person.columns_hash['intelligence_quotient'].sql_type) - ensure - ActiveRecord::Migration.remove_column :people, :intelligence_quotient rescue nil + def test_native_types + Person.delete_all + Person.connection.add_column "people", "last_name", :string + Person.connection.add_column "people", "bio", :text + Person.connection.add_column "people", "age", :integer + Person.connection.add_column "people", "height", :float + Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10' + Person.connection.add_column "people", "birthday", :datetime + Person.connection.add_column "people", "favorite_day", :date + Person.connection.add_column "people", "moment_of_truth", :datetime + Person.connection.add_column "people", "male", :boolean + Person.reset_column_information + + assert_nothing_raised do + Person.create :first_name => 'bob', :last_name => 'bobsen', + :bio => "I was born ....", :age => 18, :height => 1.78, + :wealth => BigDecimal.new("12345678901234567890.0123456789"), + :birthday => 18.years.ago, :favorite_day => 10.days.ago, + :moment_of_truth => "1782-10-10 21:40:18", :male => true + end + + bob = Person.find(:first) + assert_equal 'bob', bob.first_name + assert_equal 'bobsen', bob.last_name + assert_equal "I was born ....", bob.bio + assert_equal 18, bob.age + + # Test for 30 significant digits (beyond the 16 of float), 10 of them + # after the decimal place. + + unless current_adapter?(:SQLite3Adapter) + assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth + end + + assert_equal true, bob.male? + + assert_equal String, bob.first_name.class + assert_equal String, bob.last_name.class + assert_equal String, bob.bio.class + assert_equal Fixnum, bob.age.class + assert_equal Time, bob.birthday.class + + if current_adapter?(:OracleAdapter, :SybaseAdapter) + # Sybase, and Oracle don't differentiate between date/time + assert_equal Time, bob.favorite_day.class + else + assert_equal Date, bob.favorite_day.class + end + + # Oracle adapter stores Time or DateTime with timezone value already in _before_type_cast column + # therefore no timezone change is done afterwards when default timezone is changed + unless current_adapter?(:OracleAdapter) + # Test DateTime column and defaults, including timezone. + # FIXME: moment of truth may be Time on 64-bit platforms. + if bob.moment_of_truth.is_a?(DateTime) + + with_env_tz 'US/Eastern' do + bob.reload + assert_equal DateTime.local_offset, bob.moment_of_truth.offset + assert_not_equal 0, bob.moment_of_truth.offset + assert_not_equal "Z", bob.moment_of_truth.zone + # US/Eastern is -5 hours from GMT + assert_equal Rational(-5, 24), bob.moment_of_truth.offset + assert_match(/\A-05:?00\Z/, bob.moment_of_truth.zone) #ruby 1.8.6 uses HH:MM, prior versions use HHMM + assert_equal DateTime::ITALY, bob.moment_of_truth.start + end end end - def test_add_remove_single_field_using_string_arguments - assert !Person.column_methods_hash.include?(:last_name) - - ActiveRecord::Migration.add_column 'people', 'last_name', :string - - Person.reset_column_information - assert Person.column_methods_hash.include?(:last_name) + assert_instance_of TrueClass, bob.male? + assert_kind_of BigDecimal, bob.wealth + end - ActiveRecord::Migration.remove_column 'people', 'last_name' + if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + def test_unabstracted_database_dependent_types + Person.delete_all + ActiveRecord::Migration.add_column :people, :intelligence_quotient, :tinyint Person.reset_column_information - assert !Person.column_methods_hash.include?(:last_name) + assert_match(/tinyint/, Person.columns_hash['intelligence_quotient'].sql_type) + ensure + ActiveRecord::Migration.remove_column :people, :intelligence_quotient rescue nil end + end - def test_add_remove_single_field_using_symbol_arguments - assert !Person.column_methods_hash.include?(:last_name) - - ActiveRecord::Migration.add_column :people, :last_name, :string + def test_add_remove_single_field_using_string_arguments + assert !Person.column_methods_hash.include?(:last_name) - Person.reset_column_information - assert Person.column_methods_hash.include?(:last_name) + ActiveRecord::Migration.add_column 'people', 'last_name', :string - ActiveRecord::Migration.remove_column :people, :last_name + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) - Person.reset_column_information - assert !Person.column_methods_hash.include?(:last_name) - end + ActiveRecord::Migration.remove_column 'people', 'last_name' - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) - def testing_table_for_positioning - Person.connection.create_table :testings, :id => false do |t| - t.column :first, :integer - t.column :second, :integer - t.column :third, :integer - end + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) + end - yield Person.connection - ensure - Person.connection.drop_table :testings rescue nil - end - protected :testing_table_for_positioning + def test_add_remove_single_field_using_symbol_arguments + assert !Person.column_methods_hash.include?(:last_name) - def test_column_positioning - testing_table_for_positioning do |conn| - assert_equal %w(first second third), conn.columns(:testings).map {|c| c.name } - end - end + ActiveRecord::Migration.add_column :people, :last_name, :string - def test_add_column_with_positioning - testing_table_for_positioning do |conn| - conn.add_column :testings, :new_col, :integer - assert_equal %w(first second third new_col), conn.columns(:testings).map {|c| c.name } - end - testing_table_for_positioning do |conn| - conn.add_column :testings, :new_col, :integer, :first => true - assert_equal %w(new_col first second third), conn.columns(:testings).map {|c| c.name } - end - testing_table_for_positioning do |conn| - conn.add_column :testings, :new_col, :integer, :after => :first - assert_equal %w(first new_col second third), conn.columns(:testings).map {|c| c.name } - end - end + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) - def test_change_column_with_positioning - testing_table_for_positioning do |conn| - conn.change_column :testings, :second, :integer, :first => true - assert_equal %w(second first third), conn.columns(:testings).map {|c| c.name } - end - testing_table_for_positioning do |conn| - conn.change_column :testings, :second, :integer, :after => :third - assert_equal %w(first third second), conn.columns(:testings).map {|c| c.name } - end - end - end + ActiveRecord::Migration.remove_column :people, :last_name - def test_add_rename - Person.delete_all + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) + end - begin - Person.connection.add_column "people", "girlfriend", :string - Person.reset_column_information - Person.create :girlfriend => 'bobette' + def test_add_rename + Person.delete_all - Person.connection.rename_column "people", "girlfriend", "exgirlfriend" + begin + Person.connection.add_column "people", "girlfriend", :string + Person.reset_column_information + Person.create :girlfriend => 'bobette' - Person.reset_column_information - bob = Person.find(:first) + Person.connection.rename_column "people", "girlfriend", "exgirlfriend" - assert_equal "bobette", bob.exgirlfriend - ensure - Person.connection.remove_column("people", "girlfriend") rescue nil - Person.connection.remove_column("people", "exgirlfriend") rescue nil - end + Person.reset_column_information + bob = Person.find(:first) + assert_equal "bobette", bob.exgirlfriend + ensure + Person.connection.remove_column("people", "girlfriend") rescue nil + Person.connection.remove_column("people", "exgirlfriend") rescue nil end - def test_rename_column_using_symbol_arguments - begin - names_before = Person.find(:all).map(&:first_name) - Person.connection.rename_column :people, :first_name, :nick_name - Person.reset_column_information - assert Person.column_names.include?("nick_name") - assert_equal names_before, Person.find(:all).map(&:nick_name) - ensure - Person.connection.remove_column("people","nick_name") - Person.connection.add_column("people","first_name", :string) - end - end + end - def test_rename_column - begin - names_before = Person.find(:all).map(&:first_name) - Person.connection.rename_column "people", "first_name", "nick_name" - Person.reset_column_information - assert Person.column_names.include?("nick_name") - assert_equal names_before, Person.find(:all).map(&:nick_name) - ensure - Person.connection.remove_column("people","nick_name") - Person.connection.add_column("people","first_name", :string) - end + def test_rename_column_using_symbol_arguments + begin + names_before = Person.find(:all).map(&:first_name) + Person.connection.rename_column :people, :first_name, :nick_name + Person.reset_column_information + assert Person.column_names.include?("nick_name") + assert_equal names_before, Person.find(:all).map(&:nick_name) + ensure + Person.connection.remove_column("people","nick_name") + Person.connection.add_column("people","first_name", :string) end + end - def test_rename_column_preserves_default_value_not_null - begin - default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default - assert_equal 70000, default_before - Developer.connection.rename_column "developers", "salary", "anual_salary" - Developer.reset_column_information - assert Developer.column_names.include?("anual_salary") - default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default - assert_equal 70000, default_after - ensure - Developer.connection.rename_column "developers", "anual_salary", "salary" - Developer.reset_column_information - end + def test_rename_column + begin + names_before = Person.find(:all).map(&:first_name) + Person.connection.rename_column "people", "first_name", "nick_name" + Person.reset_column_information + assert Person.column_names.include?("nick_name") + assert_equal names_before, Person.find(:all).map(&:nick_name) + ensure + Person.connection.remove_column("people","nick_name") + Person.connection.add_column("people","first_name", :string) end + end - def test_rename_nonexistent_column - ActiveRecord::Base.connection.create_table(:hats) do |table| - table.column :hat_name, :string, :default => nil - end - exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) - ActiveRecord::StatementInvalid - else - ActiveRecord::ActiveRecordError - end - assert_raise(exception) do - Person.connection.rename_column "hats", "nonexistent", "should_fail" - end + def test_rename_column_preserves_default_value_not_null + begin + default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default + assert_equal 70000, default_before + Developer.connection.rename_column "developers", "salary", "anual_salary" + Developer.reset_column_information + assert Developer.column_names.include?("anual_salary") + default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default + assert_equal 70000, default_after ensure - ActiveRecord::Base.connection.drop_table(:hats) + Developer.connection.rename_column "developers", "anual_salary", "salary" + Developer.reset_column_information end + end - def test_rename_column_with_sql_reserved_word - begin - assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" } - Person.reset_column_information - assert Person.column_names.include?("group") - ensure - Person.connection.remove_column("people", "group") rescue nil - Person.connection.add_column("people", "first_name", :string) rescue nil - end + def test_rename_nonexistent_column + ActiveRecord::Base.connection.create_table(:hats) do |table| + table.column :hat_name, :string, :default => nil end - - def test_rename_column_with_an_index - ActiveRecord::Base.connection.create_table(:hats) do |table| - table.column :hat_name, :string, :limit => 100 - table.column :hat_size, :integer - end - Person.connection.add_index :hats, :hat_name - assert_nothing_raised do - Person.connection.rename_column "hats", "hat_name", "name" - end - ensure - ActiveRecord::Base.connection.drop_table(:hats) + exception = if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) + ActiveRecord::StatementInvalid + else + ActiveRecord::ActiveRecordError end - - def test_remove_column_with_index - ActiveRecord::Base.connection.create_table(:hats) do |table| - table.column :hat_name, :string, :limit => 100 - table.column :hat_size, :integer - end - ActiveRecord::Base.connection.add_index "hats", "hat_size" - - assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") } - ensure - ActiveRecord::Base.connection.drop_table(:hats) + assert_raise(exception) do + Person.connection.rename_column "hats", "nonexistent", "should_fail" end + ensure + ActiveRecord::Base.connection.drop_table(:hats) + end - def test_remove_column_with_multi_column_index - ActiveRecord::Base.connection.create_table(:hats) do |table| - table.column :hat_name, :string, :limit => 100 - table.column :hat_size, :integer - table.column :hat_style, :string, :limit => 100 - end - ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true - - assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") } + def test_rename_column_with_sql_reserved_word + begin + assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" } + Person.reset_column_information + assert Person.column_names.include?("group") ensure - ActiveRecord::Base.connection.drop_table(:hats) + Person.connection.remove_column("people", "group") rescue nil + Person.connection.add_column("people", "first_name", :string) rescue nil end + end - def test_remove_column_no_second_parameter_raises_exception - assert_raise(ArgumentError) { Person.connection.remove_column("funny") } + def test_rename_column_with_an_index + ActiveRecord::Base.connection.create_table(:hats) do |table| + table.column :hat_name, :string, :limit => 100 + table.column :hat_size, :integer end - - def test_change_type_of_not_null_column - assert_nothing_raised do - Topic.connection.change_column "topics", "written_on", :datetime, :null => false - Topic.reset_column_information - - Topic.connection.change_column "topics", "written_on", :datetime, :null => false - Topic.reset_column_information - - Topic.connection.change_column "topics", "written_on", :datetime, :null => true - Topic.reset_column_information - end + Person.connection.add_index :hats, :hat_name + assert_nothing_raised do + Person.connection.rename_column "hats", "hat_name", "name" end + ensure + ActiveRecord::Base.connection.drop_table(:hats) + end - if current_adapter?(:SQLite3Adapter) - def test_rename_table_for_sqlite_should_work_with_reserved_words - begin - assert_nothing_raised do - ActiveRecord::Base.connection.rename_table :references, :old_references - ActiveRecord::Base.connection.create_table :octopuses do |t| - t.column :url, :string - end - end - - assert_nothing_raised { ActiveRecord::Base.connection.rename_table :octopuses, :references } + def test_remove_column_with_index + ActiveRecord::Base.connection.create_table(:hats) do |table| + table.column :hat_name, :string, :limit => 100 + table.column :hat_size, :integer + end + ActiveRecord::Base.connection.add_index "hats", "hat_size" - # Using explicit id in insert for compatibility across all databases - con = ActiveRecord::Base.connection - assert_nothing_raised do - con.execute "INSERT INTO 'references' (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://rubyonrails.com')" - end - assert_equal 'http://rubyonrails.com', ActiveRecord::Base.connection.select_value("SELECT url FROM 'references' WHERE id=1") + assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") } + ensure + ActiveRecord::Base.connection.drop_table(:hats) + end - ensure - ActiveRecord::Base.connection.drop_table :references - ActiveRecord::Base.connection.rename_table :old_references, :references - end - end + def test_remove_column_with_multi_column_index + ActiveRecord::Base.connection.create_table(:hats) do |table| + table.column :hat_name, :string, :limit => 100 + table.column :hat_size, :integer + table.column :hat_style, :string, :limit => 100 end + ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true - def test_rename_table - begin - ActiveRecord::Base.connection.create_table :octopuses do |t| - t.column :url, :string - end - ActiveRecord::Base.connection.rename_table :octopuses, :octopi + assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") } + ensure + ActiveRecord::Base.connection.drop_table(:hats) + end - # Using explicit id in insert for compatibility across all databases - con = ActiveRecord::Base.connection - con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter) - assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" } - con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter) + def test_remove_column_no_second_parameter_raises_exception + assert_raise(ArgumentError) { Person.connection.remove_column("funny") } + end - assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1") + def test_change_type_of_not_null_column + assert_nothing_raised do + Topic.connection.change_column "topics", "written_on", :datetime, :null => false + Topic.reset_column_information - ensure - ActiveRecord::Base.connection.drop_table :octopuses rescue nil - ActiveRecord::Base.connection.drop_table :octopi rescue nil - end - end + Topic.connection.change_column "topics", "written_on", :datetime, :null => false + Topic.reset_column_information - def test_change_column_nullability - Person.delete_all - Person.connection.add_column "people", "funny", :boolean - Person.reset_column_information - assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls" - Person.connection.change_column "people", "funny", :boolean, :null => false, :default => true - Person.reset_column_information - assert !Person.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point" - Person.connection.change_column "people", "funny", :boolean, :null => true - Person.reset_column_information - assert Person.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point" + Topic.connection.change_column "topics", "written_on", :datetime, :null => true + Topic.reset_column_information end + end - def test_rename_table_with_an_index + if current_adapter?(:SQLite3Adapter) + def test_rename_table_for_sqlite_should_work_with_reserved_words begin - ActiveRecord::Base.connection.create_table :octopuses do |t| - t.column :url, :string + assert_nothing_raised do + ActiveRecord::Base.connection.rename_table :references, :old_references + ActiveRecord::Base.connection.create_table :octopuses do |t| + t.column :url, :string + end end - ActiveRecord::Base.connection.add_index :octopuses, :url - ActiveRecord::Base.connection.rename_table :octopuses, :octopi + assert_nothing_raised { ActiveRecord::Base.connection.rename_table :octopuses, :references } # Using explicit id in insert for compatibility across all databases con = ActiveRecord::Base.connection - con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter) - assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" } - con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter) + assert_nothing_raised do + con.execute "INSERT INTO 'references' (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://rubyonrails.com')" + end + assert_equal 'http://rubyonrails.com', ActiveRecord::Base.connection.select_value("SELECT url FROM 'references' WHERE id=1") - assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1") - assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url") ensure - ActiveRecord::Base.connection.drop_table :octopuses rescue nil - ActiveRecord::Base.connection.drop_table :octopi rescue nil + ActiveRecord::Base.connection.drop_table :references + ActiveRecord::Base.connection.rename_table :old_references, :references end end + end - def test_change_column - Person.connection.add_column 'people', 'age', :integer - label = "test_change_column Columns" - old_columns = Person.connection.columns(Person.table_name, label) - assert old_columns.find { |c| c.name == 'age' and c.type == :integer } - - assert_nothing_raised { Person.connection.change_column "people", "age", :string } - - new_columns = Person.connection.columns(Person.table_name, label) - assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer } - assert new_columns.find { |c| c.name == 'age' and c.type == :string } + def test_rename_table + begin + ActiveRecord::Base.connection.create_table :octopuses do |t| + t.column :url, :string + end + ActiveRecord::Base.connection.rename_table :octopuses, :octopi - old_columns = Topic.connection.columns(Topic.table_name, label) - assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true } - assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false } - new_columns = Topic.connection.columns(Topic.table_name, label) - assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true } - assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false } - assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true } - end + # Using explicit id in insert for compatibility across all databases + con = ActiveRecord::Base.connection + con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter) + assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" } + con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter) - def test_change_column_with_nil_default - Person.connection.add_column "people", "contributor", :boolean, :default => true - Person.reset_column_information - assert Person.new.contributor? + assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1") - assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil } - Person.reset_column_information - assert !Person.new.contributor? - assert_nil Person.new.contributor ensure - Person.connection.remove_column("people", "contributor") rescue nil - end - - def test_change_column_with_new_default - Person.connection.add_column "people", "administrator", :boolean, :default => true - Person.reset_column_information - assert Person.new.administrator? - - assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false } - Person.reset_column_information - assert !Person.new.administrator? - ensure - Person.connection.remove_column("people", "administrator") rescue nil + ActiveRecord::Base.connection.drop_table :octopuses rescue nil + ActiveRecord::Base.connection.drop_table :octopi rescue nil end + end - def test_change_column_default - Person.connection.change_column_default "people", "first_name", "Tester" - Person.reset_column_information - assert_equal "Tester", Person.new.first_name - end + def test_change_column_nullability + Person.delete_all + Person.connection.add_column "people", "funny", :boolean + Person.reset_column_information + assert Person.columns_hash["funny"].null, "Column 'funny' must initially allow nulls" + Person.connection.change_column "people", "funny", :boolean, :null => false, :default => true + Person.reset_column_information + assert !Person.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point" + Person.connection.change_column "people", "funny", :boolean, :null => true + Person.reset_column_information + assert Person.columns_hash["funny"].null, "Column 'funny' must allow nulls again at this point" + end - def test_change_column_quotes_column_names - Person.connection.create_table :testings do |t| - t.column :select, :string + def test_rename_table_with_an_index + begin + ActiveRecord::Base.connection.create_table :octopuses do |t| + t.column :url, :string end + ActiveRecord::Base.connection.add_index :octopuses, :url - assert_nothing_raised { Person.connection.change_column :testings, :select, :string, :limit => 10 } + ActiveRecord::Base.connection.rename_table :octopuses, :octopi - # Oracle needs primary key value from sequence - if current_adapter?(:OracleAdapter) - assert_nothing_raised { Person.connection.execute "insert into testings (id, #{Person.connection.quote_column_name('select')}) values (testings_seq.nextval, '7 chars')" } - else - assert_nothing_raised { Person.connection.execute "insert into testings (#{Person.connection.quote_column_name('select')}) values ('7 chars')" } - end - ensure - Person.connection.drop_table :testings rescue nil - end - - def test_keeping_default_and_notnull_constaint_on_change - Person.connection.create_table :testings do |t| - t.column :title, :string - end - person_klass = Class.new(Person) - person_klass.table_name = 'testings' - - person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99 - person_klass.reset_column_information - assert_equal 99, person_klass.columns_hash["wealth"].default - assert_equal false, person_klass.columns_hash["wealth"].null - # Oracle needs primary key value from sequence - if current_adapter?(:OracleAdapter) - assert_nothing_raised {person_klass.connection.execute("insert into testings (id, title) values (testings_seq.nextval, 'tester')")} - else - assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")} - end + # Using explicit id in insert for compatibility across all databases + con = ActiveRecord::Base.connection + con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter) + assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" } + con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter) - # change column default to see that column doesn't lose its not null definition - person_klass.connection.change_column_default "testings", "wealth", 100 - person_klass.reset_column_information - assert_equal 100, person_klass.columns_hash["wealth"].default - assert_equal false, person_klass.columns_hash["wealth"].null - - # rename column to see that column doesn't lose its not null and/or default definition - person_klass.connection.rename_column "testings", "wealth", "money" - person_klass.reset_column_information - assert_nil person_klass.columns_hash["wealth"] - assert_equal 100, person_klass.columns_hash["money"].default - assert_equal false, person_klass.columns_hash["money"].null - - # change column - person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000 - person_klass.reset_column_information - assert_equal 1000, person_klass.columns_hash["money"].default - assert_equal false, person_klass.columns_hash["money"].null - - # change column, make it nullable and clear default - person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil - person_klass.reset_column_information - assert_nil person_klass.columns_hash["money"].default - assert_equal true, person_klass.columns_hash["money"].null - - # change_column_null, make it not nullable and set null values to a default value - person_klass.connection.execute('UPDATE testings SET money = NULL') - person_klass.connection.change_column_null "testings", "money", false, 2000 - person_klass.reset_column_information - assert_nil person_klass.columns_hash["money"].default - assert_equal false, person_klass.columns_hash["money"].null - assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort + assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1") + assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url") ensure - Person.connection.drop_table :testings rescue nil + ActiveRecord::Base.connection.drop_table :octopuses rescue nil + ActiveRecord::Base.connection.drop_table :octopi rescue nil end + end - def test_change_column_default_to_null - Person.connection.change_column_default "people", "first_name", nil - Person.reset_column_information - assert_nil Person.new.first_name - end + def test_change_column + Person.connection.add_column 'people', 'age', :integer + label = "test_change_column Columns" + old_columns = Person.connection.columns(Person.table_name, label) + assert old_columns.find { |c| c.name == 'age' and c.type == :integer } + + assert_nothing_raised { Person.connection.change_column "people", "age", :string } + + new_columns = Person.connection.columns(Person.table_name, label) + assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer } + assert new_columns.find { |c| c.name == 'age' and c.type == :string } + + old_columns = Topic.connection.columns(Topic.table_name, label) + assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true } + assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false } + new_columns = Topic.connection.columns(Topic.table_name, label) + assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true } + assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false } + assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true } + end - def test_column_exists - Person.connection.create_table :testings do |t| - t.column :foo, :string - end + def test_change_column_with_nil_default + Person.connection.add_column "people", "contributor", :boolean, :default => true + Person.reset_column_information + assert Person.new.contributor? + + assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil } + Person.reset_column_information + assert !Person.new.contributor? + assert_nil Person.new.contributor + ensure + Person.connection.remove_column("people", "contributor") rescue nil + end - assert Person.connection.column_exists?(:testings, :foo) - assert !Person.connection.column_exists?(:testings, :bar) - ensure - Person.connection.drop_table :testings rescue nil - end + def test_change_column_with_new_default + Person.connection.add_column "people", "administrator", :boolean, :default => true + Person.reset_column_information + assert Person.new.administrator? - def test_column_exists_with_type - Person.connection.create_table :testings do |t| - t.column :foo, :string - t.column :bar, :decimal, :precision => 8, :scale => 2 - end + assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false } + Person.reset_column_information + assert !Person.new.administrator? + ensure + Person.connection.remove_column("people", "administrator") rescue nil + end - assert Person.connection.column_exists?(:testings, :foo, :string) - assert !Person.connection.column_exists?(:testings, :foo, :integer) - assert Person.connection.column_exists?(:testings, :bar, :decimal) - assert !Person.connection.column_exists?(:testings, :bar, :integer) - ensure - Person.connection.drop_table :testings rescue nil - end + def test_change_column_default + Person.connection.change_column_default "people", "first_name", "Tester" + Person.reset_column_information + assert_equal "Tester", Person.new.first_name + end - def test_column_exists_with_definition - Person.connection.create_table :testings do |t| - t.column :foo, :string, :limit => 100 - t.column :bar, :decimal, :precision => 8, :scale => 2 - end + def test_change_column_default_to_null + Person.connection.change_column_default "people", "first_name", nil + Person.reset_column_information + assert_nil Person.new.first_name + end - assert Person.connection.column_exists?(:testings, :foo, :string, :limit => 100) - assert !Person.connection.column_exists?(:testings, :foo, :string, :limit => 50) - assert Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 8, :scale => 2) - assert !Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 10, :scale => 2) - ensure - Person.connection.drop_table :testings rescue nil - end + def test_add_table + assert !Reminder.table_exists? - def test_column_exists_on_table_with_no_options_parameter_supplied - Person.connection.create_table :testings do |t| - t.string :foo - end - Person.connection.change_table :testings do |t| - assert t.column_exists?(:foo) - assert !(t.column_exists?(:bar)) - end - ensure - Person.connection.drop_table :testings rescue nil - end - - def test_add_table - assert !Reminder.table_exists? - - WeNeedReminders.up - - assert Reminder.create("content" => "hello world", "remind_at" => Time.now) - assert_equal "hello world", Reminder.find(:first).content - - WeNeedReminders.down - assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } - end - - def test_add_table_with_decimals - Person.connection.drop_table :big_numbers rescue nil - - assert !BigNumber.table_exists? - GiveMeBigNumbers.up - - assert BigNumber.create( - :bank_balance => 1586.43, - :big_bank_balance => BigDecimal("1000234000567.95"), - :world_population => 6000000000, - :my_house_population => 3, - :value_of_e => BigDecimal("2.7182818284590452353602875") - ) - - b = BigNumber.find(:first) - assert_not_nil b - - assert_not_nil b.bank_balance - assert_not_nil b.big_bank_balance - assert_not_nil b.world_population - assert_not_nil b.my_house_population - assert_not_nil b.value_of_e - - # TODO: set world_population >= 2**62 to cover 64-bit platforms and test - # is_a?(Bignum) - assert_kind_of Integer, b.world_population - assert_equal 6000000000, b.world_population - assert_kind_of Fixnum, b.my_house_population - assert_equal 3, b.my_house_population - assert_kind_of BigDecimal, b.bank_balance - assert_equal BigDecimal("1586.43"), b.bank_balance - assert_kind_of BigDecimal, b.big_bank_balance - assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance - - # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with - # precision/scale explicitly left out. By the SQL standard, numbers - # assigned to this field should be truncated but that's seldom respected. - if current_adapter?(:PostgreSQLAdapter) - # - PostgreSQL changes the SQL spec on columns declared simply as - # "decimal" to something more useful: instead of being given a scale - # of 0, they take on the compile-time limit for precision and scale, - # so the following should succeed unless you have used really wacky - # compilation options - # - SQLite2 has the default behavior of preserving all data sent in, - # so this happens there too - assert_kind_of BigDecimal, b.value_of_e - assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e - elsif current_adapter?(:SQLite3Adapter) - # - SQLite3 stores a float, in violation of SQL - assert_kind_of BigDecimal, b.value_of_e - assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001 - else - # - SQL standard is an integer - assert_kind_of Fixnum, b.value_of_e - assert_equal 2, b.value_of_e - end + WeNeedReminders.up - GiveMeBigNumbers.down - assert_raise(ActiveRecord::StatementInvalid) { BigNumber.find(:first) } - end + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content - def test_migrator - assert !Person.column_methods_hash.include?(:last_name) - assert !Reminder.table_exists? + WeNeedReminders.down + assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + end - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid") + def test_add_table_with_decimals + Person.connection.drop_table :big_numbers rescue nil + + assert !BigNumber.table_exists? + GiveMeBigNumbers.up + + assert BigNumber.create( + :bank_balance => 1586.43, + :big_bank_balance => BigDecimal("1000234000567.95"), + :world_population => 6000000000, + :my_house_population => 3, + :value_of_e => BigDecimal("2.7182818284590452353602875") + ) + + b = BigNumber.find(:first) + assert_not_nil b + + assert_not_nil b.bank_balance + assert_not_nil b.big_bank_balance + assert_not_nil b.world_population + assert_not_nil b.my_house_population + assert_not_nil b.value_of_e + + # TODO: set world_population >= 2**62 to cover 64-bit platforms and test + # is_a?(Bignum) + assert_kind_of Integer, b.world_population + assert_equal 6000000000, b.world_population + assert_kind_of Fixnum, b.my_house_population + assert_equal 3, b.my_house_population + assert_kind_of BigDecimal, b.bank_balance + assert_equal BigDecimal("1586.43"), b.bank_balance + assert_kind_of BigDecimal, b.big_bank_balance + assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance + + # This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with + # precision/scale explicitly left out. By the SQL standard, numbers + # assigned to this field should be truncated but that's seldom respected. + if current_adapter?(:PostgreSQLAdapter) + # - PostgreSQL changes the SQL spec on columns declared simply as + # "decimal" to something more useful: instead of being given a scale + # of 0, they take on the compile-time limit for precision and scale, + # so the following should succeed unless you have used really wacky + # compilation options + # - SQLite2 has the default behavior of preserving all data sent in, + # so this happens there too + assert_kind_of BigDecimal, b.value_of_e + assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e + elsif current_adapter?(:SQLite3Adapter) + # - SQLite3 stores a float, in violation of SQL + assert_kind_of BigDecimal, b.value_of_e + assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001 + else + # - SQL standard is an integer + assert_kind_of Fixnum, b.value_of_e + assert_equal 2, b.value_of_e + end + + GiveMeBigNumbers.down + assert_raise(ActiveRecord::StatementInvalid) { BigNumber.find(:first) } + end - assert_equal 3, ActiveRecord::Migrator.current_version - Person.reset_column_information - assert Person.column_methods_hash.include?(:last_name) - assert Reminder.create("content" => "hello world", "remind_at" => Time.now) - assert_equal "hello world", Reminder.find(:first).content + def test_migrator + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? - ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid") + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid") - assert_equal 0, ActiveRecord::Migrator.current_version - Person.reset_column_information - assert !Person.column_methods_hash.include?(:last_name) - assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } - end + assert_equal 3, ActiveRecord::Migrator.current_version + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content - def test_filtering_migrations - assert !Person.column_methods_hash.include?(:last_name) - assert !Reminder.table_exists? + ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid") - name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" } - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter) + assert_equal 0, ActiveRecord::Migrator.current_version + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) + assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + end - Person.reset_column_information - assert Person.column_methods_hash.include?(:last_name) - assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + def test_filtering_migrations + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? - ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter) + name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" } + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter) - Person.reset_column_information - assert !Person.column_methods_hash.include?(:last_name) - assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } - end + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } - class MockMigration < ActiveRecord::Migration - attr_reader :went_up, :went_down - def initialize - @went_up = false - @went_down = false - end + ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter) - def up - @went_up = true - super - end + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) + assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + end - def down - @went_down = true - super - end + class MockMigration < ActiveRecord::Migration + attr_reader :went_up, :went_down + def initialize + @went_up = false + @went_down = false end - def test_instance_based_migration_up - migration = MockMigration.new - assert !migration.went_up, 'have not gone up' - assert !migration.went_down, 'have not gone down' + def up + @went_up = true + super + end - migration.migrate :up - assert migration.went_up, 'have gone up' - assert !migration.went_down, 'have not gone down' + def down + @went_down = true + super end + end - def test_instance_based_migration_down - migration = MockMigration.new - assert !migration.went_up, 'have not gone up' - assert !migration.went_down, 'have not gone down' + def test_instance_based_migration_up + migration = MockMigration.new + assert !migration.went_up, 'have not gone up' + assert !migration.went_down, 'have not gone down' - migration.migrate :down - assert !migration.went_up, 'have gone up' - assert migration.went_down, 'have not gone down' - end + migration.migrate :up + assert migration.went_up, 'have gone up' + assert !migration.went_down, 'have not gone down' + end - def test_migrator_one_up - assert !Person.column_methods_hash.include?(:last_name) - assert !Reminder.table_exists? + def test_instance_based_migration_down + migration = MockMigration.new + assert !migration.went_up, 'have not gone up' + assert !migration.went_down, 'have not gone down' - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) + migration.migrate :down + assert !migration.went_up, 'have gone up' + assert migration.went_down, 'have not gone down' + end - Person.reset_column_information - assert Person.column_methods_hash.include?(:last_name) - assert !Reminder.table_exists? + def test_migrator_one_up + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2) + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) - assert Reminder.create("content" => "hello world", "remind_at" => Time.now) - assert_equal "hello world", Reminder.find(:first).content - end + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? - def test_migrator_one_down - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid") + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 2) - ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1) + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content + end - Person.reset_column_information - assert Person.column_methods_hash.include?(:last_name) - assert !Reminder.table_exists? - end + def test_migrator_one_down + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid") - def test_migrator_one_up_one_down - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) - ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0) + ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1) - assert !Person.column_methods_hash.include?(:last_name) - assert !Reminder.table_exists? - end + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + end - def test_migrator_double_up - assert_equal(0, ActiveRecord::Migrator.current_version) - ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) - assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) } - assert_equal(1, ActiveRecord::Migrator.current_version) - end + def test_migrator_one_up_one_down + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) + ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0) - def test_migrator_double_down - assert_equal(0, ActiveRecord::Migrator.current_version) - ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) - ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) - assert_nothing_raised { ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) } - assert_equal(0, ActiveRecord::Migrator.current_version) - end + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + end - if ActiveRecord::Base.connection.supports_ddl_transactions? - def test_migrator_one_up_with_exception_and_rollback - assert !Person.column_methods_hash.include?(:last_name) + def test_migrator_double_up + assert_equal(0, ActiveRecord::Migrator.current_version) + ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) + assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) } + assert_equal(1, ActiveRecord::Migrator.current_version) + end - e = assert_raise(StandardError) do - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100) - end + def test_migrator_double_down + assert_equal(0, ActiveRecord::Migrator.current_version) + ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/valid", 1) + ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) + assert_nothing_raised { ActiveRecord::Migrator.run(:down, MIGRATIONS_ROOT + "/valid", 1) } + assert_equal(0, ActiveRecord::Migrator.current_version) + end - assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message + if ActiveRecord::Base.connection.supports_ddl_transactions? + def test_migrator_one_up_with_exception_and_rollback + assert !Person.column_methods_hash.include?(:last_name) - Person.reset_column_information - assert !Person.column_methods_hash.include?(:last_name) + e = assert_raise(StandardError) do + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/broken", 100) end - end - def test_finds_migrations - migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations + assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message - [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i| - assert_equal migrations[i].version, pair.first - assert_equal migrations[i].name, pair.last - end + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) end + end - def test_finds_migrations_in_subdirectories - migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations + def test_finds_migrations + migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid").migrations - [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i| - assert_equal migrations[i].version, pair.first - assert_equal migrations[i].name, pair.last - end + [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i| + assert_equal migrations[i].version, pair.first + assert_equal migrations[i].name, pair.last end + end - def test_finds_migrations_from_two_directories - directories = [MIGRATIONS_ROOT + '/valid_with_timestamps', MIGRATIONS_ROOT + '/to_copy_with_timestamps'] - migrations = ActiveRecord::Migrator.new(:up, directories).migrations + def test_finds_migrations_in_subdirectories + migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations - [[20090101010101, "PeopleHaveHobbies"], - [20090101010202, "PeopleHaveDescriptions"], - [20100101010101, "ValidWithTimestampsPeopleHaveLastNames"], - [20100201010101, "ValidWithTimestampsWeNeedReminders"], - [20100301010101, "ValidWithTimestampsInnocentJointable"]].each_with_index do |pair, i| - assert_equal pair.first, migrations[i].version - assert_equal pair.last, migrations[i].name - end + [[1, 'ValidPeopleHaveLastNames'], [2, 'WeNeedReminders'], [3, 'InnocentJointable']].each_with_index do |pair, i| + assert_equal migrations[i].version, pair.first + assert_equal migrations[i].name, pair.last end + end - def test_dump_schema_information_outputs_lexically_ordered_versions - migration_path = MIGRATIONS_ROOT + '/valid_with_timestamps' - ActiveRecord::Migrator.run(:up, migration_path, 20100301010101) - ActiveRecord::Migrator.run(:up, migration_path, 20100201010101) + def test_finds_migrations_from_two_directories + directories = [MIGRATIONS_ROOT + '/valid_with_timestamps', MIGRATIONS_ROOT + '/to_copy_with_timestamps'] + migrations = ActiveRecord::Migrator.new(:up, directories).migrations - schema_info = ActiveRecord::Base.connection.dump_schema_information - assert_match(/20100201010101.*20100301010101/m, schema_info) + [[20090101010101, "PeopleHaveHobbies"], + [20090101010202, "PeopleHaveDescriptions"], + [20100101010101, "ValidWithTimestampsPeopleHaveLastNames"], + [20100201010101, "ValidWithTimestampsWeNeedReminders"], + [20100301010101, "ValidWithTimestampsInnocentJointable"]].each_with_index do |pair, i| + assert_equal pair.first, migrations[i].version + assert_equal pair.last, migrations[i].name end + end - def test_finds_pending_migrations - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1) - migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations + def test_dump_schema_information_outputs_lexically_ordered_versions + migration_path = MIGRATIONS_ROOT + '/valid_with_timestamps' + ActiveRecord::Migrator.run(:up, migration_path, 20100301010101) + ActiveRecord::Migrator.run(:up, migration_path, 20100201010101) - assert_equal 1, migrations.size - assert_equal migrations[0].version, 3 - assert_equal migrations[0].name, 'InterleavedInnocentJointable' - end + schema_info = ActiveRecord::Base.connection.dump_schema_information + assert_match(/20100201010101.*20100301010101/m, schema_info) + end - def test_relative_migrations - list = Dir.chdir(MIGRATIONS_ROOT) do - ActiveRecord::Migrator.up("valid/", 1) - end + def test_finds_pending_migrations + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1) + migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations + + assert_equal 1, migrations.size + assert_equal migrations[0].version, 3 + assert_equal migrations[0].name, 'InterleavedInnocentJointable' + end - migration_proxy = list.find { |item| - item.name == 'ValidPeopleHaveLastNames' - } - assert migration_proxy, 'should find pending migration' + def test_relative_migrations + list = Dir.chdir(MIGRATIONS_ROOT) do + ActiveRecord::Migrator.up("valid/", 1) end - def test_only_loads_pending_migrations - # migrate up to 1 - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) + migration_proxy = list.find { |item| + item.name == 'ValidPeopleHaveLastNames' + } + assert migration_proxy, 'should find pending migration' + end - proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil) + def test_only_loads_pending_migrations + # migrate up to 1 + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) - names = proxies.map(&:name) - assert !names.include?('ValidPeopleHaveLastNames') - assert names.include?('WeNeedReminders') - assert names.include?('InnocentJointable') - end + proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil) - def test_target_version_zero_should_run_only_once - # migrate up to 1 - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1) + names = proxies.map(&:name) + assert !names.include?('ValidPeopleHaveLastNames') + assert names.include?('WeNeedReminders') + assert names.include?('InnocentJointable') + end - # migrate down to 0 - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0) + def test_target_version_zero_should_run_only_once + # migrate up to 1 + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1) - # migrate down to 0 again - proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0) - assert_equal [], proxies - end + # migrate down to 0 + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0) - def test_migrator_db_has_no_schema_migrations_table - # Oracle adapter raises error if semicolon is present as last character - if current_adapter?(:OracleAdapter) - ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations") - else - ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;") - end - assert_nothing_raised do - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1) - end + # migrate down to 0 again + proxies = ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0) + assert_equal [], proxies + end + + def test_migrator_db_has_no_schema_migrations_table + # Oracle adapter raises error if semicolon is present as last character + if current_adapter?(:OracleAdapter) + ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations") + else + ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations;") + end + assert_nothing_raised do + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1) end + end - def test_migrator_verbosity - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) - assert_not_equal 0, ActiveRecord::Migration.message_count - ActiveRecord::Migration.message_count = 0 + def test_migrator_verbosity + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) + assert_not_equal 0, ActiveRecord::Migration.message_count + ActiveRecord::Migration.message_count = 0 - ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0) - assert_not_equal 0, ActiveRecord::Migration.message_count - ActiveRecord::Migration.message_count = 0 - end + ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0) + assert_not_equal 0, ActiveRecord::Migration.message_count + ActiveRecord::Migration.message_count = 0 + end - def test_migrator_verbosity_off - ActiveRecord::Migration.verbose = false - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) - assert_equal 0, ActiveRecord::Migration.message_count - ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0) - assert_equal 0, ActiveRecord::Migration.message_count - end + def test_migrator_verbosity_off + ActiveRecord::Migration.verbose = false + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) + assert_equal 0, ActiveRecord::Migration.message_count + ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0) + assert_equal 0, ActiveRecord::Migration.message_count + end - def test_migrator_going_down_due_to_version_target - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0) + def test_migrator_going_down_due_to_version_target + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 0) - assert !Person.column_methods_hash.include?(:last_name) - assert !Reminder.table_exists? + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid") + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid") - Person.reset_column_information - assert Person.column_methods_hash.include?(:last_name) - assert Reminder.create("content" => "hello world", "remind_at" => Time.now) - assert_equal "hello world", Reminder.find(:first).content - end + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content + end - def test_migrator_rollback - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid") - assert_equal(3, ActiveRecord::Migrator.current_version) + def test_migrator_rollback + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid") + assert_equal(3, ActiveRecord::Migrator.current_version) - ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") - assert_equal(2, ActiveRecord::Migrator.current_version) + ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") + assert_equal(2, ActiveRecord::Migrator.current_version) - ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") - assert_equal(1, ActiveRecord::Migrator.current_version) + ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") + assert_equal(1, ActiveRecord::Migrator.current_version) - ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") - assert_equal(0, ActiveRecord::Migrator.current_version) + ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") + assert_equal(0, ActiveRecord::Migrator.current_version) - ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") - assert_equal(0, ActiveRecord::Migrator.current_version) - end + ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") + assert_equal(0, ActiveRecord::Migrator.current_version) + end - def test_migrator_forward - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1) - assert_equal(1, ActiveRecord::Migrator.current_version) + def test_migrator_forward + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", 1) + assert_equal(1, ActiveRecord::Migrator.current_version) - ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid", 2) - assert_equal(3, ActiveRecord::Migrator.current_version) + ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid", 2) + assert_equal(3, ActiveRecord::Migrator.current_version) - ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid") - assert_equal(3, ActiveRecord::Migrator.current_version) - end + ActiveRecord::Migrator.forward(MIGRATIONS_ROOT + "/valid") + assert_equal(3, ActiveRecord::Migrator.current_version) + end - def test_get_all_versions - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid") - assert_equal([1,2,3], ActiveRecord::Migrator.get_all_versions) + def test_get_all_versions + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid") + assert_equal([1,2,3], ActiveRecord::Migrator.get_all_versions) - ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") - assert_equal([1,2], ActiveRecord::Migrator.get_all_versions) + ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") + assert_equal([1,2], ActiveRecord::Migrator.get_all_versions) - ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") - assert_equal([1], ActiveRecord::Migrator.get_all_versions) + ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") + assert_equal([1], ActiveRecord::Migrator.get_all_versions) - ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") - assert_equal([], ActiveRecord::Migrator.get_all_versions) - end + ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid") + assert_equal([], ActiveRecord::Migrator.get_all_versions) + end - def test_schema_migrations_table_name - ActiveRecord::Base.table_name_prefix = "prefix_" - ActiveRecord::Base.table_name_suffix = "_suffix" - Reminder.reset_table_name - assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name - ActiveRecord::Base.table_name_prefix = "" - ActiveRecord::Base.table_name_suffix = "" - Reminder.reset_table_name - assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name - ensure - ActiveRecord::Base.table_name_prefix = "" - ActiveRecord::Base.table_name_suffix = "" - end - - def test_proper_table_name - assert_equal "table", ActiveRecord::Migrator.proper_table_name('table') - assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table) - assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder) - Reminder.reset_table_name - assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder) - - # Use the model's own prefix/suffix if a model is given - ActiveRecord::Base.table_name_prefix = "ARprefix_" - ActiveRecord::Base.table_name_suffix = "_ARsuffix" - Reminder.table_name_prefix = 'prefix_' - Reminder.table_name_suffix = '_suffix' - Reminder.reset_table_name - assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder) - Reminder.table_name_prefix = '' - Reminder.table_name_suffix = '' - Reminder.reset_table_name - - # Use AR::Base's prefix/suffix if string or symbol is given - ActiveRecord::Base.table_name_prefix = "prefix_" - ActiveRecord::Base.table_name_suffix = "_suffix" - Reminder.reset_table_name - assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table') - assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table) - ActiveRecord::Base.table_name_prefix = "" - ActiveRecord::Base.table_name_suffix = "" - Reminder.reset_table_name - end - - def test_rename_table_with_prefix_and_suffix - assert !Thing.table_exists? - ActiveRecord::Base.table_name_prefix = 'prefix_' - ActiveRecord::Base.table_name_suffix = '_suffix' - Thing.reset_table_name - Thing.reset_sequence_name - WeNeedThings.up - - assert Thing.create("content" => "hello world") - assert_equal "hello world", Thing.find(:first).content - - RenameThings.up - Thing.table_name = "prefix_awesome_things_suffix" - - assert_equal "hello world", Thing.find(:first).content - ensure - ActiveRecord::Base.table_name_prefix = '' - ActiveRecord::Base.table_name_suffix = '' - Thing.reset_table_name - Thing.reset_sequence_name - end - - def test_add_drop_table_with_prefix_and_suffix - assert !Reminder.table_exists? - ActiveRecord::Base.table_name_prefix = 'prefix_' - ActiveRecord::Base.table_name_suffix = '_suffix' - Reminder.reset_table_name - Reminder.reset_sequence_name - WeNeedReminders.up - assert Reminder.create("content" => "hello world", "remind_at" => Time.now) - assert_equal "hello world", Reminder.find(:first).content - - WeNeedReminders.down - assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } - ensure - ActiveRecord::Base.table_name_prefix = '' - ActiveRecord::Base.table_name_suffix = '' - Reminder.reset_table_name - Reminder.reset_sequence_name - end + def test_schema_migrations_table_name + ActiveRecord::Base.table_name_prefix = "prefix_" + ActiveRecord::Base.table_name_suffix = "_suffix" + Reminder.reset_table_name + assert_equal "prefix_schema_migrations_suffix", ActiveRecord::Migrator.schema_migrations_table_name + ActiveRecord::Base.table_name_prefix = "" + ActiveRecord::Base.table_name_suffix = "" + Reminder.reset_table_name + assert_equal "schema_migrations", ActiveRecord::Migrator.schema_migrations_table_name + ensure + ActiveRecord::Base.table_name_prefix = "" + ActiveRecord::Base.table_name_suffix = "" + end - def test_create_table_with_binary_column - Person.connection.drop_table :binary_testings rescue nil + def test_proper_table_name + assert_equal "table", ActiveRecord::Migrator.proper_table_name('table') + assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table) + assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder) + Reminder.reset_table_name + assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder) + + # Use the model's own prefix/suffix if a model is given + ActiveRecord::Base.table_name_prefix = "ARprefix_" + ActiveRecord::Base.table_name_suffix = "_ARsuffix" + Reminder.table_name_prefix = 'prefix_' + Reminder.table_name_suffix = '_suffix' + Reminder.reset_table_name + assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder) + Reminder.table_name_prefix = '' + Reminder.table_name_suffix = '' + Reminder.reset_table_name + + # Use AR::Base's prefix/suffix if string or symbol is given + ActiveRecord::Base.table_name_prefix = "prefix_" + ActiveRecord::Base.table_name_suffix = "_suffix" + Reminder.reset_table_name + assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table') + assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table) + ActiveRecord::Base.table_name_prefix = "" + ActiveRecord::Base.table_name_suffix = "" + Reminder.reset_table_name + end - assert_nothing_raised { - Person.connection.create_table :binary_testings do |t| - t.column "data", :binary, :null => false - end - } + def test_rename_table_with_prefix_and_suffix + assert !Thing.table_exists? + ActiveRecord::Base.table_name_prefix = 'prefix_' + ActiveRecord::Base.table_name_suffix = '_suffix' + Thing.reset_table_name + Thing.reset_sequence_name + WeNeedThings.up + + assert Thing.create("content" => "hello world") + assert_equal "hello world", Thing.find(:first).content + + RenameThings.up + Thing.table_name = "prefix_awesome_things_suffix" + + assert_equal "hello world", Thing.find(:first).content + ensure + ActiveRecord::Base.table_name_prefix = '' + ActiveRecord::Base.table_name_suffix = '' + Thing.reset_table_name + Thing.reset_sequence_name + end - columns = Person.connection.columns(:binary_testings) - data_column = columns.detect { |c| c.name == "data" } + def test_add_drop_table_with_prefix_and_suffix + assert !Reminder.table_exists? + ActiveRecord::Base.table_name_prefix = 'prefix_' + ActiveRecord::Base.table_name_suffix = '_suffix' + Reminder.reset_table_name + Reminder.reset_sequence_name + WeNeedReminders.up + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content + + WeNeedReminders.down + assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + ensure + ActiveRecord::Base.table_name_prefix = '' + ActiveRecord::Base.table_name_suffix = '' + Reminder.reset_table_name + Reminder.reset_sequence_name + end + + def test_create_table_with_binary_column + Person.connection.drop_table :binary_testings rescue nil - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) - assert_equal '', data_column.default - else - assert_nil data_column.default + assert_nothing_raised { + Person.connection.create_table :binary_testings do |t| + t.column "data", :binary, :null => false end + } + + columns = Person.connection.columns(:binary_testings) + data_column = columns.detect { |c| c.name == "data" } - Person.connection.drop_table :binary_testings rescue nil + if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + assert_equal '', data_column.default + else + assert_nil data_column.default end - def test_migrator_with_duplicates - assert_raise(ActiveRecord::DuplicateMigrationVersionError) do - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil) - end + Person.connection.drop_table :binary_testings rescue nil + end + + def test_migrator_with_duplicates + assert_raise(ActiveRecord::DuplicateMigrationVersionError) do + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate", nil) end + end - def test_migrator_with_duplicate_names - assert_raise(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil) - end + def test_migrator_with_duplicate_names + assert_raise(ActiveRecord::DuplicateMigrationNameError, "Multiple migrations have the name Chunky") do + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/duplicate_names", nil) end + end - def test_migrator_with_missing_version_numbers - assert_raise(ActiveRecord::UnknownMigrationVersionError) do - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500) - end + def test_migrator_with_missing_version_numbers + assert_raise(ActiveRecord::UnknownMigrationVersionError) do + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/missing", 500) end + end - def test_create_table_with_custom_sequence_name - return unless current_adapter? :OracleAdapter + def test_create_table_with_custom_sequence_name + return unless current_adapter? :OracleAdapter - # table name is 29 chars, the standard sequence name will - # be 33 chars and should be shortened - assert_nothing_raised do - begin - Person.connection.create_table :table_with_name_thats_just_ok do |t| - t.column :foo, :string, :null => false - end - ensure - Person.connection.drop_table :table_with_name_thats_just_ok rescue nil + # table name is 29 chars, the standard sequence name will + # be 33 chars and should be shortened + assert_nothing_raised do + begin + Person.connection.create_table :table_with_name_thats_just_ok do |t| + t.column :foo, :string, :null => false end + ensure + Person.connection.drop_table :table_with_name_thats_just_ok rescue nil end + end - # should be all good w/ a custom sequence name - assert_nothing_raised do - begin - Person.connection.create_table :table_with_name_thats_just_ok, - :sequence_name => 'suitably_short_seq' do |t| - t.column :foo, :string, :null => false - end - - Person.connection.execute("select suitably_short_seq.nextval from dual") - - ensure - Person.connection.drop_table :table_with_name_thats_just_ok, - :sequence_name => 'suitably_short_seq' rescue nil + # should be all good w/ a custom sequence name + assert_nothing_raised do + begin + Person.connection.create_table :table_with_name_thats_just_ok, + :sequence_name => 'suitably_short_seq' do |t| + t.column :foo, :string, :null => false end - end - # confirm the custom sequence got dropped - assert_raise(ActiveRecord::StatementInvalid) do Person.connection.execute("select suitably_short_seq.nextval from dual") - end - end - protected - def with_env_tz(new_tz = 'US/Eastern') - old_tz, ENV['TZ'] = ENV['TZ'], new_tz - yield ensure - old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') + Person.connection.drop_table :table_with_name_thats_just_ok, + :sequence_name => 'suitably_short_seq' rescue nil end + end + # confirm the custom sequence got dropped + assert_raise(ActiveRecord::StatementInvalid) do + Person.connection.execute("select suitably_short_seq.nextval from dual") + end end - class MigrationLoggerTest < ActiveRecord::TestCase - def test_migration_should_be_run_without_logger - previous_logger = ActiveRecord::Base.logger - ActiveRecord::Base.logger = nil - assert_nothing_raised do - ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid") - end + protected + def with_env_tz(new_tz = 'US/Eastern') + old_tz, ENV['TZ'] = ENV['TZ'], new_tz + yield ensure - ActiveRecord::Base.logger = previous_logger + old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') end - end - class InterleavedMigrationsTest < ActiveRecord::TestCase - def test_migrator_interleaved_migrations - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1") - - assert_nothing_raised do - ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2") - end +end - Person.reset_column_information - assert Person.column_methods_hash.include?(:last_name) - - assert_nothing_raised do - proxies = ActiveRecord::Migrator.down( - MIGRATIONS_ROOT + "/interleaved/pass_3") - names = proxies.map(&:name) - assert names.include?('InterleavedPeopleHaveLastNames') - assert names.include?('InterleavedInnocentJointable') - end +class MigrationLoggerTest < ActiveRecord::TestCase + def test_migration_should_be_run_without_logger + previous_logger = ActiveRecord::Base.logger + ActiveRecord::Base.logger = nil + assert_nothing_raised do + ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid") end + ensure + ActiveRecord::Base.logger = previous_logger end +end - class ReservedWordsMigrationTest < ActiveRecord::TestCase - def test_drop_index_from_table_named_values - connection = Person.connection - connection.create_table :values, :force => true do |t| - t.integer :value - end - - assert_nothing_raised do - connection.add_index :values, :value - connection.remove_index :values, :column => :value - end +class InterleavedMigrationsTest < ActiveRecord::TestCase + def test_migrator_interleaved_migrations + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1") - connection.drop_table :values rescue nil + assert_nothing_raised do + ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2") end - end + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) - class ChangeTableMigrationsTest < ActiveRecord::TestCase - def setup - @connection = Person.connection - @connection.create_table :delete_me, :force => true do |t| - end + assert_nothing_raised do + proxies = ActiveRecord::Migrator.down( + MIGRATIONS_ROOT + "/interleaved/pass_3") + names = proxies.map(&:name) + assert names.include?('InterleavedPeopleHaveLastNames') + assert names.include?('InterleavedInnocentJointable') end + end +end - def teardown - Person.connection.drop_table :delete_me rescue nil +class ReservedWordsMigrationTest < ActiveRecord::TestCase + def test_drop_index_from_table_named_values + connection = Person.connection + connection.create_table :values, :force => true do |t| + t.integer :value end - def test_references_column_type_adds_id - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {}) - t.references :customer - end + assert_nothing_raised do + connection.add_index :values, :value + connection.remove_index :values, :column => :value end - def test_remove_references_column_type_removes_id - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, 'customer_id') - t.remove_references :customer - end + connection.drop_table :values rescue nil + end +end + + +class ChangeTableMigrationsTest < ActiveRecord::TestCase + def setup + @connection = Person.connection + @connection.create_table :delete_me, :force => true do |t| end + end - def test_add_belongs_to_works_like_add_references - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {}) - t.belongs_to :customer - end + def teardown + Person.connection.drop_table :delete_me rescue nil + end + + def test_references_column_type_adds_id + with_change_table do |t| + @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {}) + t.references :customer end + end - def test_remove_belongs_to_works_like_remove_references - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, 'customer_id') - t.remove_belongs_to :customer - end + def test_remove_references_column_type_removes_id + with_change_table do |t| + @connection.expects(:remove_column).with(:delete_me, 'customer_id') + t.remove_references :customer end + end - def test_references_column_type_with_polymorphic_adds_type - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {}) - @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {}) - t.references :taggable, :polymorphic => true - end + def test_add_belongs_to_works_like_add_references + with_change_table do |t| + @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {}) + t.belongs_to :customer end + end - def test_remove_references_column_type_with_polymorphic_removes_type - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, 'taggable_type') - @connection.expects(:remove_column).with(:delete_me, 'taggable_id') - t.remove_references :taggable, :polymorphic => true - end + def test_remove_belongs_to_works_like_remove_references + with_change_table do |t| + @connection.expects(:remove_column).with(:delete_me, 'customer_id') + t.remove_belongs_to :customer end + end - def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false}) - @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false}) - t.references :taggable, :polymorphic => true, :null => false - end + def test_references_column_type_with_polymorphic_adds_type + with_change_table do |t| + @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {}) + @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {}) + t.references :taggable, :polymorphic => true end + end - def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, 'taggable_type') - @connection.expects(:remove_column).with(:delete_me, 'taggable_id') - t.remove_references :taggable, :polymorphic => true, :null => false - end + def test_remove_references_column_type_with_polymorphic_removes_type + with_change_table do |t| + @connection.expects(:remove_column).with(:delete_me, 'taggable_type') + @connection.expects(:remove_column).with(:delete_me, 'taggable_id') + t.remove_references :taggable, :polymorphic => true end + end - def test_timestamps_creates_updated_at_and_created_at - with_change_table do |t| - @connection.expects(:add_timestamps).with(:delete_me) - t.timestamps - end + def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag + with_change_table do |t| + @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false}) + @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false}) + t.references :taggable, :polymorphic => true, :null => false end + end - def test_remove_timestamps_creates_updated_at_and_created_at - with_change_table do |t| - @connection.expects(:remove_timestamps).with(:delete_me) - t.remove_timestamps - end + def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag + with_change_table do |t| + @connection.expects(:remove_column).with(:delete_me, 'taggable_type') + @connection.expects(:remove_column).with(:delete_me, 'taggable_id') + t.remove_references :taggable, :polymorphic => true, :null => false end + end - def string_column - if current_adapter?(:PostgreSQLAdapter) - "character varying(255)" - elsif current_adapter?(:OracleAdapter) - 'VARCHAR2(255)' - else - 'varchar(255)' - end + def test_timestamps_creates_updated_at_and_created_at + with_change_table do |t| + @connection.expects(:add_timestamps).with(:delete_me) + t.timestamps end + end - def integer_column - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) - 'int(11)' - elsif current_adapter?(:OracleAdapter) - 'NUMBER(38)' - else - 'integer' - end + def test_remove_timestamps_creates_updated_at_and_created_at + with_change_table do |t| + @connection.expects(:remove_timestamps).with(:delete_me) + t.remove_timestamps end + end - def test_integer_creates_integer_column - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, :foo, integer_column, {}) - @connection.expects(:add_column).with(:delete_me, :bar, integer_column, {}) - t.integer :foo, :bar - end + def string_column + if current_adapter?(:PostgreSQLAdapter) + "character varying(255)" + elsif current_adapter?(:OracleAdapter) + 'VARCHAR2(255)' + else + 'varchar(255)' end + end - def test_string_creates_string_column - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, :foo, string_column, {}) - @connection.expects(:add_column).with(:delete_me, :bar, string_column, {}) - t.string :foo, :bar - end + def integer_column + if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + 'int(11)' + elsif current_adapter?(:OracleAdapter) + 'NUMBER(38)' + else + 'integer' end + end - def test_column_creates_column - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, :bar, :integer, {}) - t.column :bar, :integer - end + def test_integer_creates_integer_column + with_change_table do |t| + @connection.expects(:add_column).with(:delete_me, :foo, integer_column, {}) + @connection.expects(:add_column).with(:delete_me, :bar, integer_column, {}) + t.integer :foo, :bar end + end - def test_column_creates_column_with_options - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false}) - t.column :bar, :integer, :null => false - end + def test_string_creates_string_column + with_change_table do |t| + @connection.expects(:add_column).with(:delete_me, :foo, string_column, {}) + @connection.expects(:add_column).with(:delete_me, :bar, string_column, {}) + t.string :foo, :bar end + end - def test_index_creates_index - with_change_table do |t| - @connection.expects(:add_index).with(:delete_me, :bar, {}) - t.index :bar - end + def test_column_creates_column + with_change_table do |t| + @connection.expects(:add_column).with(:delete_me, :bar, :integer, {}) + t.column :bar, :integer end + end - def test_index_creates_index_with_options - with_change_table do |t| - @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true}) - t.index :bar, :unique => true - end + def test_column_creates_column_with_options + with_change_table do |t| + @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false}) + t.column :bar, :integer, :null => false end + end - def test_index_exists - with_change_table do |t| - @connection.expects(:index_exists?).with(:delete_me, :bar, {}) - t.index_exists?(:bar) - end + def test_index_creates_index + with_change_table do |t| + @connection.expects(:add_index).with(:delete_me, :bar, {}) + t.index :bar end + end - def test_index_exists_with_options - with_change_table do |t| - @connection.expects(:index_exists?).with(:delete_me, :bar, {:unique => true}) - t.index_exists?(:bar, :unique => true) - end + def test_index_creates_index_with_options + with_change_table do |t| + @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true}) + t.index :bar, :unique => true end + end - def test_change_changes_column - with_change_table do |t| - @connection.expects(:change_column).with(:delete_me, :bar, :string, {}) - t.change :bar, :string - end + def test_index_exists + with_change_table do |t| + @connection.expects(:index_exists?).with(:delete_me, :bar, {}) + t.index_exists?(:bar) end + end - def test_change_changes_column_with_options - with_change_table do |t| - @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true}) - t.change :bar, :string, :null => true - end + def test_index_exists_with_options + with_change_table do |t| + @connection.expects(:index_exists?).with(:delete_me, :bar, {:unique => true}) + t.index_exists?(:bar, :unique => true) end + end - def test_change_default_changes_column - with_change_table do |t| - @connection.expects(:change_column_default).with(:delete_me, :bar, :string) - t.change_default :bar, :string - end + def test_change_changes_column + with_change_table do |t| + @connection.expects(:change_column).with(:delete_me, :bar, :string, {}) + t.change :bar, :string end + end - def test_remove_drops_single_column - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, [:bar]) - t.remove :bar - end + def test_change_changes_column_with_options + with_change_table do |t| + @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true}) + t.change :bar, :string, :null => true end + end - def test_remove_drops_multiple_columns - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, [:bar, :baz]) - t.remove :bar, :baz - end + def test_change_default_changes_column + with_change_table do |t| + @connection.expects(:change_column_default).with(:delete_me, :bar, :string) + t.change_default :bar, :string end + end - def test_remove_index_removes_index_with_options - with_change_table do |t| - @connection.expects(:remove_index).with(:delete_me, {:unique => true}) - t.remove_index :unique => true - end + def test_remove_drops_single_column + with_change_table do |t| + @connection.expects(:remove_column).with(:delete_me, [:bar]) + t.remove :bar end + end - def test_rename_renames_column - with_change_table do |t| - @connection.expects(:rename_column).with(:delete_me, :bar, :baz) - t.rename :bar, :baz - end + def test_remove_drops_multiple_columns + with_change_table do |t| + @connection.expects(:remove_column).with(:delete_me, [:bar, :baz]) + t.remove :bar, :baz end + end - protected - def with_change_table - Person.connection.change_table :delete_me do |t| - yield t - end + def test_remove_index_removes_index_with_options + with_change_table do |t| + @connection.expects(:remove_index).with(:delete_me, {:unique => true}) + t.remove_index :unique => true end end - if ActiveRecord::Base.connection.supports_bulk_alter? - class BulkAlterTableMigrationsTest < ActiveRecord::TestCase - def setup - @connection = Person.connection - @connection.create_table(:delete_me, :force => true) {|t| } - end + def test_rename_renames_column + with_change_table do |t| + @connection.expects(:rename_column).with(:delete_me, :bar, :baz) + t.rename :bar, :baz + end + end - def teardown - Person.connection.drop_table(:delete_me) rescue nil - end + protected + def with_change_table + Person.connection.change_table :delete_me do |t| + yield t + end + end +end - def test_adding_multiple_columns - assert_queries(1) do - with_bulk_change_table do |t| - t.column :name, :string - t.string :qualification, :experience - t.integer :age, :default => 0 - t.date :birthdate - t.timestamps - end - end +if ActiveRecord::Base.connection.supports_bulk_alter? + class BulkAlterTableMigrationsTest < ActiveRecord::TestCase + def setup + @connection = Person.connection + @connection.create_table(:delete_me, :force => true) {|t| } + end - assert_equal 8, columns.size - [:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type } - assert_equal 0, column(:age).default - end + def teardown + Person.connection.drop_table(:delete_me) rescue nil + end - def test_removing_columns + def test_adding_multiple_columns + assert_queries(1) do with_bulk_change_table do |t| + t.column :name, :string t.string :qualification, :experience + t.integer :age, :default => 0 + t.date :birthdate + t.timestamps end + end - [:qualification, :experience].each {|c| assert column(c) } - - assert_queries(1) do - with_bulk_change_table do |t| - t.remove :qualification, :experience - t.string :qualification_experience - end - end + assert_equal 8, columns.size + [:name, :qualification, :experience].each {|s| assert_equal :string, column(s).type } + assert_equal 0, column(:age).default + end - [:qualification, :experience].each {|c| assert ! column(c) } - assert column(:qualification_experience) + def test_removing_columns + with_bulk_change_table do |t| + t.string :qualification, :experience end - def test_adding_indexes - with_bulk_change_table do |t| - t.string :username - t.string :name - t.integer :age - end + [:qualification, :experience].each {|c| assert column(c) } - # Adding an index fires a query every time to check if an index already exists or not - assert_queries(3) do - with_bulk_change_table do |t| - t.index :username, :unique => true, :name => :awesome_username_index - t.index [:name, :age] - end + assert_queries(1) do + with_bulk_change_table do |t| + t.remove :qualification, :experience + t.string :qualification_experience end + end - assert_equal 2, indexes.size - - name_age_index = index(:index_delete_me_on_name_and_age) - assert_equal ['name', 'age'].sort, name_age_index.columns.sort - assert ! name_age_index.unique + [:qualification, :experience].each {|c| assert ! column(c) } + assert column(:qualification_experience) + end - assert index(:awesome_username_index).unique + def test_adding_indexes + with_bulk_change_table do |t| + t.string :username + t.string :name + t.integer :age end - def test_removing_index + # Adding an index fires a query every time to check if an index already exists or not + assert_queries(3) do with_bulk_change_table do |t| - t.string :name - t.index :name + t.index :username, :unique => true, :name => :awesome_username_index + t.index [:name, :age] end + end - assert index(:index_delete_me_on_name) + assert_equal 2, indexes.size - assert_queries(3) do - with_bulk_change_table do |t| - t.remove_index :name - t.index :name, :name => :new_name_index, :unique => true - end - end + name_age_index = index(:index_delete_me_on_name_and_age) + assert_equal ['name', 'age'].sort, name_age_index.columns.sort + assert ! name_age_index.unique - assert ! index(:index_delete_me_on_name) + assert index(:awesome_username_index).unique + end - new_name_index = index(:new_name_index) - assert new_name_index.unique + def test_removing_index + with_bulk_change_table do |t| + t.string :name + t.index :name end - def test_changing_columns + assert index(:index_delete_me_on_name) + + assert_queries(3) do with_bulk_change_table do |t| - t.string :name - t.date :birthdate + t.remove_index :name + t.index :name, :name => :new_name_index, :unique => true end + end - assert ! column(:name).default - assert_equal :date, column(:birthdate).type + assert ! index(:index_delete_me_on_name) - # One query for columns (delete_me table) - # One query for primary key (delete_me table) - # One query to do the bulk change - assert_queries(3) do - with_bulk_change_table do |t| - t.change :name, :string, :default => 'NONAME' - t.change :birthdate, :datetime - end - end + new_name_index = index(:new_name_index) + assert new_name_index.unique + end - assert_equal 'NONAME', column(:name).default - assert_equal :datetime, column(:birthdate).type + def test_changing_columns + with_bulk_change_table do |t| + t.string :name + t.date :birthdate end - protected + assert ! column(:name).default + assert_equal :date, column(:birthdate).type - def with_bulk_change_table - # Reset columns/indexes cache as we're changing the table - @columns = @indexes = nil - - Person.connection.change_table(:delete_me, :bulk => true) do |t| - yield t + # One query for columns (delete_me table) + # One query for primary key (delete_me table) + # One query to do the bulk change + assert_queries(3) do + with_bulk_change_table do |t| + t.change :name, :string, :default => 'NONAME' + t.change :birthdate, :datetime end end - def column(name) - columns.detect {|c| c.name == name.to_s } - end + assert_equal 'NONAME', column(:name).default + assert_equal :datetime, column(:birthdate).type + end - def columns - @columns ||= Person.connection.columns('delete_me') - end + protected - def index(name) - indexes.detect {|i| i.name == name.to_s } - end + def with_bulk_change_table + # Reset columns/indexes cache as we're changing the table + @columns = @indexes = nil - def indexes - @indexes ||= Person.connection.indexes('delete_me') + Person.connection.change_table(:delete_me, :bulk => true) do |t| + yield t end - end # AlterTableMigrationsTest + end - end + def column(name) + columns.detect {|c| c.name == name.to_s } + end - class CopyMigrationsTest < ActiveRecord::TestCase - def setup + def columns + @columns ||= Person.connection.columns('delete_me') end - def clear - ActiveRecord::Base.timestamped_migrations = true - to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations - File.delete(*to_delete) + def index(name) + indexes.detect {|i| i.name == name.to_s } end - def test_copying_migrations_without_timestamps - ActiveRecord::Base.timestamped_migrations = false - @migrations_path = MIGRATIONS_ROOT + "/valid" - @existing_migrations = Dir[@migrations_path + "/*.rb"] + def indexes + @indexes ||= Person.connection.indexes('delete_me') + end + end # AlterTableMigrationsTest + +end + +class CopyMigrationsTest < ActiveRecord::TestCase + def setup + end - copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) - assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb") - assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename) + def clear + ActiveRecord::Base.timestamped_migrations = true + to_delete = Dir[@migrations_path + "/*.rb"] - @existing_migrations + File.delete(*to_delete) + end - expected = "# This migration comes from bukkits (originally 1)" - assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp + def test_copying_migrations_without_timestamps + ActiveRecord::Base.timestamped_migrations = false + @migrations_path = MIGRATIONS_ROOT + "/valid" + @existing_migrations = Dir[@migrations_path + "/*.rb"] + + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) + assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb") + assert_equal [@migrations_path + "/4_people_have_hobbies.bukkits.rb", @migrations_path + "/5_people_have_descriptions.bukkits.rb"], copied.map(&:filename) + + expected = "# This migration comes from bukkits (originally 1)" + assert_equal expected, IO.readlines(@migrations_path + "/4_people_have_hobbies.bukkits.rb")[0].chomp + + files_count = Dir[@migrations_path + "/*.rb"].length + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) + assert_equal files_count, Dir[@migrations_path + "/*.rb"].length + assert copied.empty? + ensure + clear + end + + def test_copying_migrations_without_timestamps_from_2_sources + ActiveRecord::Base.timestamped_migrations = false + @migrations_path = MIGRATIONS_ROOT + "/valid" + @existing_migrations = Dir[@migrations_path + "/*.rb"] + + sources = ActiveSupport::OrderedHash.new + sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy" + sources[:omg] = MIGRATIONS_ROOT + "/to_copy2" + ActiveRecord::Migration.copy(@migrations_path, sources) + assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb") + assert File.exists?(@migrations_path + "/6_create_articles.omg.rb") + assert File.exists?(@migrations_path + "/7_create_comments.omg.rb") + + files_count = Dir[@migrations_path + "/*.rb"].length + ActiveRecord::Migration.copy(@migrations_path, sources) + assert_equal files_count, Dir[@migrations_path + "/*.rb"].length + ensure + clear + end + + def test_copying_migrations_with_timestamps + @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" + @existing_migrations = Dir[@migrations_path + "/*.rb"] + + Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") + expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb", + @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"] + assert_equal expected, copied.map(&:filename) files_count = Dir[@migrations_path + "/*.rb"].length - copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) assert_equal files_count, Dir[@migrations_path + "/*.rb"].length assert copied.empty? - ensure - clear end + ensure + clear + end - def test_copying_migrations_without_timestamps_from_2_sources - ActiveRecord::Base.timestamped_migrations = false - @migrations_path = MIGRATIONS_ROOT + "/valid" - @existing_migrations = Dir[@migrations_path + "/*.rb"] + def test_copying_migrations_with_timestamps_from_2_sources + @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" + @existing_migrations = Dir[@migrations_path + "/*.rb"] - sources = ActiveSupport::OrderedHash.new - sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy" - sources[:omg] = MIGRATIONS_ROOT + "/to_copy2" - ActiveRecord::Migration.copy(@migrations_path, sources) - assert File.exists?(@migrations_path + "/4_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/5_people_have_descriptions.bukkits.rb") - assert File.exists?(@migrations_path + "/6_create_articles.omg.rb") - assert File.exists?(@migrations_path + "/7_create_comments.omg.rb") + sources = ActiveSupport::OrderedHash.new + sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2" + + Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do + copied = ActiveRecord::Migration.copy(@migrations_path, sources) + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101012_create_articles.omg.rb") + assert File.exists?(@migrations_path + "/20100726101013_create_comments.omg.rb") + assert_equal 4, copied.length files_count = Dir[@migrations_path + "/*.rb"].length ActiveRecord::Migration.copy(@migrations_path, sources) assert_equal files_count, Dir[@migrations_path + "/*.rb"].length - ensure - clear end + ensure + clear + end - def test_copying_migrations_with_timestamps - @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" - @existing_migrations = Dir[@migrations_path + "/*.rb"] + def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future + @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" + @existing_migrations = Dir[@migrations_path + "/*.rb"] - Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do - copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") - expected = [@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb", - @migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb"] - assert_equal expected, copied.map(&:filename) + Time.travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do + ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) + assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb") - files_count = Dir[@migrations_path + "/*.rb"].length - copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert_equal files_count, Dir[@migrations_path + "/*.rb"].length - assert copied.empty? - end - ensure - clear + files_count = Dir[@migrations_path + "/*.rb"].length + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) + assert_equal files_count, Dir[@migrations_path + "/*.rb"].length + assert copied.empty? end + ensure + clear + end - def test_copying_migrations_with_timestamps_from_2_sources - @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" - @existing_migrations = Dir[@migrations_path + "/*.rb"] + def test_skipping_migrations + @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" + @existing_migrations = Dir[@migrations_path + "/*.rb"] - sources = ActiveSupport::OrderedHash.new - sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" - sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2" + sources = ActiveSupport::OrderedHash.new + sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision" - Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do - copied = ActiveRecord::Migration.copy(@migrations_path, sources) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") - assert File.exists?(@migrations_path + "/20100726101012_create_articles.omg.rb") - assert File.exists?(@migrations_path + "/20100726101013_create_comments.omg.rb") - assert_equal 4, copied.length + skipped = [] + on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" } + copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) + assert_equal 2, copied.length - files_count = Dir[@migrations_path + "/*.rb"].length - ActiveRecord::Migration.copy(@migrations_path, sources) - assert_equal files_count, Dir[@migrations_path + "/*.rb"].length - end - ensure - clear - end + assert_equal 1, skipped.length + assert_equal ["omg PeopleHaveHobbies"], skipped + ensure + clear + end - def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_future - @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" - @existing_migrations = Dir[@migrations_path + "/*.rb"] + def test_skip_is_not_called_if_migrations_are_from_the_same_plugin + @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" + @existing_migrations = Dir[@migrations_path + "/*.rb"] - Time.travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do - ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.bukkits.rb") + sources = ActiveSupport::OrderedHash.new + sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" - files_count = Dir[@migrations_path + "/*.rb"].length - copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert_equal files_count, Dir[@migrations_path + "/*.rb"].length - assert copied.empty? - end - ensure - clear - end + skipped = [] + on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" } + copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) + ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) - def test_skipping_migrations - @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" - @existing_migrations = Dir[@migrations_path + "/*.rb"] + assert_equal 2, copied.length + assert_equal 0, skipped.length + ensure + clear + end - sources = ActiveSupport::OrderedHash.new - sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" - sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_name_collision" + def test_copying_migrations_to_non_existing_directory + @migrations_path = MIGRATIONS_ROOT + "/non_existing" + @existing_migrations = [] - skipped = [] - on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" } - copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) + Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") assert_equal 2, copied.length - - assert_equal 1, skipped.length - assert_equal ["omg PeopleHaveHobbies"], skipped - ensure - clear end + ensure + clear + Dir.delete(@migrations_path) + end - def test_skip_is_not_called_if_migrations_are_from_the_same_plugin - @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" - @existing_migrations = Dir[@migrations_path + "/*.rb"] - - sources = ActiveSupport::OrderedHash.new - sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" - - skipped = [] - on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" } - copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) - ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) + def test_copying_migrations_to_empty_directory + @migrations_path = MIGRATIONS_ROOT + "/empty" + @existing_migrations = [] + Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") assert_equal 2, copied.length - assert_equal 0, skipped.length - ensure - clear - end - - def test_copying_migrations_to_non_existing_directory - @migrations_path = MIGRATIONS_ROOT + "/non_existing" - @existing_migrations = [] - - Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do - copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") - assert_equal 2, copied.length - end - ensure - clear - Dir.delete(@migrations_path) - end - - def test_copying_migrations_to_empty_directory - @migrations_path = MIGRATIONS_ROOT + "/empty" - @existing_migrations = [] - - Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do - copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) - assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.bukkits.rb") - assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.bukkits.rb") - assert_equal 2, copied.length - end - ensure - clear end + ensure + clear end end diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index 8b4638b161..52dfea8fac 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -421,6 +421,12 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal expected, received end + def test_order_after_reorder_combines_orders + expected = Developer.order('name DESC, id DESC').collect { |dev| [dev.name, dev.id] } + received = Developer.order('name ASC').reorder('name DESC').order('id DESC').collect { |dev| [dev.name, dev.id] } + assert_equal expected, received + end + def test_nested_exclusive_scope expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary } received = DeveloperOrderedBySalary.send(:with_exclusive_scope, :find => { :limit => 100 }) do @@ -527,7 +533,7 @@ class DefaultScopingTest < ActiveRecord::TestCase def test_default_scope_is_threadsafe if in_memory_db? - return skip "in memory db can't share a db between threads" + skip "in memory db can't share a db between threads" end threads = [] diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 15cb7aec07..e9a3b0419c 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -20,7 +20,7 @@ module ActiveRecord end def test_single_values - assert_equal [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq].map(&:to_s).sort, + assert_equal [:limit, :offset, :lock, :readonly, :from, :reordering, :reverse_order, :uniq].map(&:to_s).sort, Relation::SINGLE_VALUE_METHODS.map(&:to_s).sort end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index dd6d7e52d5..724632489b 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -3,6 +3,7 @@ require "cases/helper" class SchemaDumperTest < ActiveRecord::TestCase def setup + super @stream = StringIO.new end diff --git a/activerecord/test/cases/session_store/session_test.rb b/activerecord/test/cases/session_store/session_test.rb index bcacbb9b5f..a3b8ab74d9 100644 --- a/activerecord/test/cases/session_store/session_test.rb +++ b/activerecord/test/cases/session_store/session_test.rb @@ -7,10 +7,13 @@ module ActiveRecord class SessionTest < ActiveRecord::TestCase self.use_transactional_fixtures = false + attr_reader :session_klass + def setup super ActiveRecord::Base.connection.schema_cache.clear! Session.drop_table! if Session.table_exists? + @session_klass = Class.new(Session) end def test_data_column_name @@ -61,8 +64,8 @@ module ActiveRecord def test_find_by_session_id Session.create_table! session_id = "10" - s = Session.create!(:data => 'world', :session_id => session_id) - t = Session.find_by_session_id(session_id) + s = session_klass.create!(:data => 'world', :session_id => session_id) + t = session_klass.find_by_session_id(session_id) assert_equal s, t assert_equal s.data, t.data Session.drop_table! diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb index 382ad0a06a..79442d68b0 100644 --- a/activerecord/test/cases/validations/uniqueness_validation_test.rb +++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb @@ -45,6 +45,18 @@ class UniquenessValidationTest < ActiveRecord::TestCase assert t2.save, "Should now save t2 as unique" end + def test_validates_uniqueness_with_nil_value + Topic.validates_uniqueness_of(:title) + + t = Topic.new("title" => nil) + assert t.save, "Should save t as unique" + + t2 = Topic.new("title" => nil) + assert !t2.valid?, "Shouldn't be valid" + assert !t2.save, "Shouldn't save t2 as unique" + assert_equal ["has already been taken"], t2.errors[:title] + end + def test_validates_uniqueness_with_validates Topic.validates :title, :uniqueness => true Topic.create!('title' => 'abc') @@ -80,6 +92,30 @@ class UniquenessValidationTest < ActiveRecord::TestCase assert r3.valid?, "Saving r3" end + def test_validate_uniqueness_with_object_scope + Reply.validates_uniqueness_of(:content, :scope => :topic) + + t = Topic.create("title" => "I'm unique!") + + r1 = t.replies.create "title" => "r1", "content" => "hello world" + assert r1.valid?, "Saving r1" + + r2 = t.replies.create "title" => "r2", "content" => "hello world" + assert !r2.valid?, "Saving r2 first time" + end + + def test_validate_uniqueness_with_object_arg + Reply.validates_uniqueness_of(:topic) + + t = Topic.create("title" => "I'm unique!") + + r1 = t.replies.create "title" => "r1", "content" => "hello world" + assert r1.valid?, "Saving r1" + + r2 = t.replies.create "title" => "r2", "content" => "hello world" + assert !r2.valid?, "Saving r2 first time" + end + def test_validate_uniqueness_scoped_to_defining_class t = Topic.create("title" => "What, me worry?") diff --git a/activerecord/test/cases/yaml_serialization_test.rb b/activerecord/test/cases/yaml_serialization_test.rb index 2b4ec81199..302913e095 100644 --- a/activerecord/test/cases/yaml_serialization_test.rb +++ b/activerecord/test/cases/yaml_serialization_test.rb @@ -1,4 +1,4 @@ -require "cases/helper" +require 'cases/helper' require 'models/topic' class YamlSerializationTest < ActiveRecord::TestCase @@ -36,22 +36,17 @@ class YamlSerializationTest < ActiveRecord::TestCase assert_equal({'attributes' => topic.attributes}, coder) end - begin - require 'psych' - - def test_psych_roundtrip - topic = Topic.first - assert topic - t = Psych.load Psych.dump topic - assert_equal topic, t - end - - def test_psych_roundtrip_new_object - topic = Topic.new - assert topic - t = Psych.load Psych.dump topic - assert_equal topic.attributes, t.attributes - end - rescue LoadError + def test_psych_roundtrip + topic = Topic.first + assert topic + t = Psych.load Psych.dump topic + assert_equal topic, t + end + + def test_psych_roundtrip_new_object + topic = Topic.new + assert topic + t = Psych.load Psych.dump topic + assert_equal topic.attributes, t.attributes end end diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 1a1a18166a..8bcb9df8a8 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -80,6 +80,11 @@ class Topic < ActiveRecord::Base after_initialize :set_email_address + class_attribute :after_initialize_called + after_initialize do + self.class.after_initialize_called = true + end + def approved=(val) @custom_approved = val write_attribute(:approved, val) diff --git a/activeresource/test/abstract_unit.rb b/activeresource/test/abstract_unit.rb index 9c1e9a526d..c68625df4f 100644 --- a/activeresource/test/abstract_unit.rb +++ b/activeresource/test/abstract_unit.rb @@ -3,15 +3,14 @@ require File.expand_path('../../../load_paths', __FILE__) lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") $:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) -require 'test/unit' +require 'minitest/autorun' require 'active_resource' require 'active_support' require 'active_support/test_case' - require 'setter_trap' +require 'active_support/logger' -require 'logger' -ActiveResource::Base.logger = Logger.new("#{File.dirname(__FILE__)}/debug.log") +ActiveResource::Base.logger = ActiveSupport::Logger.new("#{File.dirname(__FILE__)}/debug.log") def setup_response matz_hash = { 'person' => { :id => 1, :name => 'Matz' } } diff --git a/activeresource/test/cases/authorization_test.rb b/activeresource/test/cases/authorization_test.rb index dabc40dfe7..0185e5432d 100644 --- a/activeresource/test/cases/authorization_test.rb +++ b/activeresource/test/cases/authorization_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class AuthorizationTest < Test::Unit::TestCase +class AuthorizationTest < ActiveSupport::TestCase Response = Struct.new(:code) def setup diff --git a/activeresource/test/cases/base/custom_methods_test.rb b/activeresource/test/cases/base/custom_methods_test.rb index 3eaa9b1c5b..f7aa7a4a09 100644 --- a/activeresource/test/cases/base/custom_methods_test.rb +++ b/activeresource/test/cases/base/custom_methods_test.rb @@ -3,7 +3,7 @@ require 'fixtures/person' require 'fixtures/street_address' require 'active_support/core_ext/hash/conversions' -class CustomMethodsTest < Test::Unit::TestCase +class CustomMethodsTest < ActiveSupport::TestCase def setup @matz = { :person => { :id => 1, :name => 'Matz' } }.to_json @matz_deep = { :person => { :id => 1, :name => 'Matz', :other => 'other' } }.to_json diff --git a/activeresource/test/cases/base/equality_test.rb b/activeresource/test/cases/base/equality_test.rb index 84f1a7b998..fffd8b75c3 100644 --- a/activeresource/test/cases/base/equality_test.rb +++ b/activeresource/test/cases/base/equality_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require "fixtures/person" require "fixtures/street_address" -class BaseEqualityTest < Test::Unit::TestCase +class BaseEqualityTest < ActiveSupport::TestCase def setup @new = Person.new @one = Person.new(:id => 1) diff --git a/activeresource/test/cases/base/load_test.rb b/activeresource/test/cases/base/load_test.rb index 784e7dd036..f07e1ea16b 100644 --- a/activeresource/test/cases/base/load_test.rb +++ b/activeresource/test/cases/base/load_test.rb @@ -32,7 +32,7 @@ module Highrise end -class BaseLoadTest < Test::Unit::TestCase +class BaseLoadTest < ActiveSupport::TestCase def setup @matz = { :id => 1, :name => 'Matz' } diff --git a/activeresource/test/cases/base_errors_test.rb b/activeresource/test/cases/base_errors_test.rb index 5063916d10..aacbeeb83c 100644 --- a/activeresource/test/cases/base_errors_test.rb +++ b/activeresource/test/cases/base_errors_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require "fixtures/person" -class BaseErrorsTest < Test::Unit::TestCase +class BaseErrorsTest < ActiveSupport::TestCase def setup ActiveResource::HttpMock.respond_to do |mock| mock.post "/people.xml", {}, %q(<?xml version="1.0" encoding="UTF-8"?><errors><error>Age can't be blank</error><error>Name can't be blank</error><error>Name must start with a letter</error><error>Person quota full for today.</error></errors>), 422, {'Content-Type' => 'application/xml; charset=utf-8'} diff --git a/activeresource/test/cases/base_test.rb b/activeresource/test/cases/base_test.rb index 7b42f64a35..c3b963844c 100644 --- a/activeresource/test/cases/base_test.rb +++ b/activeresource/test/cases/base_test.rb @@ -12,7 +12,7 @@ require 'active_support/ordered_hash' require 'active_support/core_ext/hash/conversions' require 'mocha' -class BaseTest < Test::Unit::TestCase +class BaseTest < ActiveSupport::TestCase def setup setup_response # find me in abstract_unit @original_person_site = Person.site diff --git a/activeresource/test/cases/connection_test.rb b/activeresource/test/cases/connection_test.rb index 535107aeef..653912f000 100644 --- a/activeresource/test/cases/connection_test.rb +++ b/activeresource/test/cases/connection_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class ConnectionTest < Test::Unit::TestCase +class ConnectionTest < ActiveSupport::TestCase ResponseCodeStub = Struct.new(:code) RedirectResponseStub = Struct.new(:code, :Location) diff --git a/activeresource/test/cases/finder_test.rb b/activeresource/test/cases/finder_test.rb index 5fbbfeef6e..3e8550d356 100644 --- a/activeresource/test/cases/finder_test.rb +++ b/activeresource/test/cases/finder_test.rb @@ -6,7 +6,7 @@ require "fixtures/beast" require "fixtures/proxy" require 'active_support/core_ext/hash/conversions' -class FinderTest < Test::Unit::TestCase +class FinderTest < ActiveSupport::TestCase def setup setup_response # find me in abstract_unit end diff --git a/activeresource/test/cases/format_test.rb b/activeresource/test/cases/format_test.rb index 174142ec52..21fdc24832 100644 --- a/activeresource/test/cases/format_test.rb +++ b/activeresource/test/cases/format_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require "fixtures/person" require "fixtures/street_address" -class FormatTest < Test::Unit::TestCase +class FormatTest < ActiveSupport::TestCase def setup @matz = { :id => 1, :name => 'Matz' } @david = { :id => 2, :name => 'David' } diff --git a/activeresource/test/cases/observing_test.rb b/activeresource/test/cases/observing_test.rb index 58d3d389ff..b2371a1bdf 100644 --- a/activeresource/test/cases/observing_test.rb +++ b/activeresource/test/cases/observing_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'fixtures/person' require 'active_support/core_ext/hash/conversions' -class ObservingTest < Test::Unit::TestCase +class ObservingTest < ActiveSupport::TestCase cattr_accessor :history class PersonObserver < ActiveModel::Observer diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb index 8f8deb9692..e97bb25b9f 100644 --- a/activesupport/lib/active_support/backtrace_cleaner.rb +++ b/activesupport/lib/active_support/backtrace_cleaner.rb @@ -1,11 +1,11 @@ module ActiveSupport - # Backtraces often include many lines that are not relevant for the context under review. This makes it hard to find the + # Backtraces often include many lines that are not relevant for the context under review. This makes it hard to find the # signal amongst the backtrace noise, and adds debugging time. With a BacktraceCleaner, filters and silencers are used to # remove the noisy lines, so that only the most relevant lines remain. # # Filters are used to modify lines of data, while silencers are used to remove lines entirely. The typical filter use case - # is to remove lengthy path information from the start of each line, and view file paths relevant to the app directory - # instead of the file system root. The typical silencer use case is to exclude the output of a noisy library from the + # is to remove lengthy path information from the start of each line, and view file paths relevant to the app directory + # instead of the file system root. The typical silencer use case is to exclude the output of a noisy library from the # backtrace, so that you can focus on the rest. # # ==== Example: @@ -15,9 +15,9 @@ module ActiveSupport # bc.add_silencer { |line| line =~ /mongrel|rubygems/ } # bc.clean(exception.backtrace) # will strip the Rails.root prefix and skip any lines from mongrel or rubygems # - # To reconfigure an existing BacktraceCleaner (like the default one in Rails) and show as much data as possible, you can - # always call <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the backtrace to a pristine state. If you - # need to reconfigure an existing BacktraceCleaner so that it does not filter or modify the paths of any lines of the + # To reconfigure an existing BacktraceCleaner (like the default one in Rails) and show as much data as possible, you can + # always call <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the backtrace to a pristine state. If you + # need to reconfigure an existing BacktraceCleaner so that it does not filter or modify the paths of any lines of the # backtrace, you can call BacktraceCleaner#remove_filters! These two methods will give you a completely untouched backtrace. # # Inspired by the Quiet Backtrace gem by Thoughtbot. @@ -50,7 +50,7 @@ module ActiveSupport @filters << block end - # Adds a silencer from the block provided. If the silencer returns true for a given line, it will be excluded from + # Adds a silencer from the block provided. If the silencer returns true for a given line, it will be excluded from # the clean backtrace. # # Example: diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index df3aeb6b8a..f1d00aab6d 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -1,6 +1,5 @@ require 'active_support/concern' require 'active_support/descendants_tracker' -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/kernel/singleton_class' @@ -77,8 +76,8 @@ module ActiveSupport # save # end # - def run_callbacks(kind, key = nil, &block) - self.class.__run_callbacks(key, kind, self, &block) + def run_callbacks(kind, *args, &block) + send("_run_#{kind}_callbacks", *args, &block) end private @@ -121,12 +120,12 @@ module ActiveSupport end def normalize_options!(options) - options[:if] = Array.wrap(options[:if]) - options[:unless] = Array.wrap(options[:unless]) + options[:if] = Array(options[:if]) + options[:unless] = Array(options[:unless]) options[:per_key] ||= {} - options[:per_key][:if] = Array.wrap(options[:per_key][:if]) - options[:per_key][:unless] = Array.wrap(options[:per_key][:unless]) + options[:per_key][:if] = Array(options[:per_key][:if]) + options[:per_key][:unless] = Array(options[:per_key][:unless]) end def name @@ -166,19 +165,10 @@ module ActiveSupport RUBY_EVAL end - # This will supply contents for before and around filters, and no - # contents for after filters (for the forward pass). - def start(key=nil, object=nil) - return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?") - - # options[0] is the compiled form of supplied conditions - # options[1] is the "end" for the conditional - # + # Wraps code with filter + def apply(code, key=nil, object=nil) case @kind when :before - # if condition # before_save :filter_name, :if => :condition - # filter_name - # end <<-RUBY_EVAL if !halted && #{@compiled_options} # This double assignment is to prevent warnings in 1.9.3 as @@ -190,62 +180,64 @@ module ActiveSupport halted_callback_hook(#{@raw_filter.inspect.inspect}) end end + #{code} RUBY_EVAL - when :around - # Compile around filters with conditions into proxy methods - # that contain the conditions. - # - # For `around_save :filter_name, :if => :condition': - # - # def _conditional_callback_save_17 - # if condition - # filter_name do - # yield self - # end - # else - # yield self - # end - # end - # - name = "_conditional_callback_#{@kind}_#{next_id}" - @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 - def #{name}(halted) - if #{@compiled_options} && !halted - #{@filter} do - yield self - end - else - yield self - end - end - RUBY_EVAL - "#{name}(halted) do" - end - end - - # This will supply contents for around and after filters, but not - # before filters (for the backward pass). - def end(key=nil, object=nil) - return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?") - - case @kind when :after - # after_save :filter_name, :if => :condition <<-RUBY_EVAL + #{code} if #{@compiled_options} #{@filter} end RUBY_EVAL when :around + name = define_conditional_callback <<-RUBY_EVAL + #{name}(halted) do + #{code} value end RUBY_EVAL end end + + def one_time_conditions_valid?(object) + object.send("_one_time_conditions_valid_#{@callback_id}?") + end + private + # Compile around filters with conditions into proxy methods + # that contain the conditions. + # + # For `around_save :filter_name, :if => :condition': + # + # def _conditional_callback_save_17 + # if condition + # filter_name do + # yield self + # end + # else + # yield self + # end + # end + # + def define_conditional_callback + name = "_conditional_callback_#{@kind}_#{next_id}" + @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def #{name}(halted) + if #{@compiled_options} && !halted + #{@filter} do + yield self + end + else + yield self + end + end + RUBY_EVAL + name + end + # Options support the same options as filters themselves (and support # symbols, string, procs, and objects), so compile a conditional # expression based on the options @@ -253,11 +245,11 @@ module ActiveSupport conditions = ["true"] unless options[:if].empty? - conditions << Array.wrap(_compile_filter(options[:if])) + conditions << Array(_compile_filter(options[:if])) end unless options[:unless].empty? - conditions << Array.wrap(_compile_filter(options[:unless])).map {|f| "!#{f}"} + conditions << Array(_compile_filter(options[:unless])).map {|f| "!#{f}"} end conditions.flatten.join(" && ") @@ -302,7 +294,7 @@ module ActiveSupport @klass.send(:define_method, "#{method_name}_object") { filter } _normalize_legacy_filter(kind, filter) - scopes = Array.wrap(chain.config[:scope]) + scopes = Array(chain.config[:scope]) method_to_call = scopes.map{ |s| s.is_a?(Symbol) ? send(s) : s }.join("_") @klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 @@ -348,10 +340,20 @@ module ActiveSupport method << "value = nil" method << "halted = false" - each do |callback| - method << callback.start(key, object) + callbacks = yielding + applicable_callbacks_for(key, object).reverse_each do |callback| + callbacks = callback.apply(callbacks, key, object) end + method << callbacks + method << "raise rescued_error if rescued_error" if config[:rescuable] + method << "halted ? false : (block_given? ? value : true)" + method.flatten.compact.join("\n") + end + + # Returns part of method that evaluates the callback block + def yielding + method = [] if config[:rescuable] method << "rescued_error = nil" method << "begin" @@ -364,24 +366,37 @@ module ActiveSupport method << "rescued_error = e" method << "end" end + method.join("\n") + end - reverse_each do |callback| - method << callback.end(key, object) + # Selects callbacks that have valid <tt>:per_key</tt> condition + def applicable_callbacks_for(key, object) + return self unless key + select do |callback| + callback.one_time_conditions_valid?(object) end - - method << "raise rescued_error if rescued_error" if config[:rescuable] - method << "halted ? false : (block_given? ? value : true)" - method.compact.join("\n") end end module ClassMethods + # Generate the internal runner method called by +run_callbacks+. + def __define_runner(symbol) #:nodoc: + runner_method = "_run_#{symbol}_callbacks" + unless private_method_defined?(runner_method) + class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def #{runner_method}(key = nil, &blk) + self.class.__run_callback(key, :#{symbol}, self, &blk) + end + private :#{runner_method} + RUBY_EVAL + end + end # This method calls the callback method for the given key. # If this called first time it creates a new callback method for the key, # calculating which callbacks can be omitted because of per_key conditions. # - def __run_callbacks(key, kind, object, &blk) #:nodoc: + def __run_callback(key, kind, object, &blk) #:nodoc: name = __callback_runner_name(key, kind) unless object.respond_to?(name) str = send("_#{kind}_callbacks").compile(key, object) @@ -606,6 +621,7 @@ module ActiveSupport callbacks.each do |callback| class_attribute "_#{callback}_callbacks" send("_#{callback}_callbacks=", CallbackChain.new(callback, config)) + __define_runner(callback) end end end diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb index 391bdc925d..3ec7e576c8 100644 --- a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb +++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb @@ -1,29 +1,9 @@ require 'bigdecimal' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' class BigDecimal - YAML_TAG = 'tag:yaml.org,2002:float' YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' } - # This emits the number without any scientific notation. - # This is better than self.to_f.to_s since it doesn't lose precision. - # - # Note that reconstituting YAML floats to native floats may lose precision. - def to_yaml(opts = {}) - return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - - YAML.quick_emit(nil, opts) do |out| - string = to_s - out.scalar(YAML_TAG, YAML_MAPPING[string] || string, :plain) - end - end - def encode_with(coder) string = to_s coder.represent_scalar(nil, YAML_MAPPING[string] || string) diff --git a/activesupport/lib/active_support/core_ext/class/subclasses.rb b/activesupport/lib/active_support/core_ext/class/subclasses.rb index 46e9daaa8f..74ea047c24 100644 --- a/activesupport/lib/active_support/core_ext/class/subclasses.rb +++ b/activesupport/lib/active_support/core_ext/class/subclasses.rb @@ -7,7 +7,7 @@ class Class #:nodoc: def descendants descendants = [] - ObjectSpace.each_object(class << self; self; end) do |k| + ObjectSpace.each_object(singleton_class) do |k| descendants.unshift k unless k == self end descendants diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb index 1a3cf66a1b..6dd321ecf9 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -79,29 +79,6 @@ class DateTime change(:hour => 23, :min => 59, :sec => 59) end - # 1.9.3 defines + and - on DateTime, < 1.9.3 do not. - if DateTime.public_instance_methods(false).include?(:+) - def plus_with_duration(other) #:nodoc: - if ActiveSupport::Duration === other - other.since(self) - else - plus_without_duration(other) - end - end - alias_method :plus_without_duration, :+ - alias_method :+, :plus_with_duration - - def minus_with_duration(other) #:nodoc: - if ActiveSupport::Duration === other - plus_with_duration(-other) - else - minus_without_duration(other) - end - end - alias_method :minus_without_duration, :- - alias_method :-, :minus_with_duration - end - # Adjusts DateTime to UTC by adding its offset value; offset is set to 0 # # Example: diff --git a/activesupport/lib/active_support/core_ext/object/instance_variables.rb b/activesupport/lib/active_support/core_ext/object/instance_variables.rb index 66caf9bec8..91fdf93eb2 100644 --- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb +++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb @@ -10,7 +10,7 @@ class Object # # C.new(0, 1).instance_values # => {"x" => 0, "y" => 1} def instance_values #:nodoc: - Hash[instance_variables.map { |name| [name.to_s[1..-1], instance_variable_get(name)] }] + Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }] end # Returns an array of instance variable names including "@". They are strings diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb index d478ee0ef6..1a34e88a87 100644 --- a/activesupport/lib/active_support/core_ext/string/filters.rb +++ b/activesupport/lib/active_support/core_ext/string/filters.rb @@ -36,14 +36,13 @@ class String # "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)") # # => "And they f... (continued)" def truncate(length, options = {}) - text = self.dup - options[:omission] ||= "..." + return self.dup unless self.length > length - length_with_room_for_omission = length - options[:omission].mb_chars.length - chars = text.mb_chars + options[:omission] ||= "..." + length_with_room_for_omission = length - options[:omission].length stop = options[:separator] ? - (chars.rindex(options[:separator].mb_chars, length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission + (rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission - (chars.length > length ? chars[0...stop] + options[:omission] : text).to_s + self[0...stop] + options[:omission] end end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 6cb2ea68b3..73aa7dd89a 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -136,11 +136,6 @@ module ActiveSupport #:nodoc: coder.represent_scalar nil, to_str end - def to_yaml(*args) - return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - to_str.to_yaml(*args) - end - UNSAFE_STRING_METHODS.each do |unsafe_method| if 'String'.respond_to?(unsafe_method) class_eval <<-EOT, __FILE__, __LINE__ + 1 diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index f3235d11bb..5e433f5dd9 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -78,7 +78,7 @@ class Time options[:hour] || hour, options[:min] || (options[:hour] ? 0 : min), options[:sec] || ((options[:hour] || options[:min]) ? 0 : sec), - options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : usec) + options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000)) ) end diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb index f9505a247c..94f8d7133e 100644 --- a/activesupport/lib/active_support/deprecation/behaviors.rb +++ b/activesupport/lib/active_support/deprecation/behaviors.rb @@ -1,5 +1,4 @@ require "active_support/notifications" -require "active_support/core_ext/array/wrap" module ActiveSupport module Deprecation @@ -19,7 +18,7 @@ module ActiveSupport # ActiveSupport::Deprecation.behavior = :stderr # ActiveSupport::Deprecation.behavior = [:stderr, :log] def behavior=(behavior) - @behavior = Array.wrap(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b } + @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b } end end @@ -34,8 +33,8 @@ module ActiveSupport if defined?(Rails) && Rails.logger Rails.logger else - require 'logger' - Logger.new($stderr) + require 'active_support/logger' + ActiveSupport::Logger.new($stderr) end logger.warn message logger.debug callstack.join("\n ") if debug diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb index a4ad2da137..2ede084e95 100644 --- a/activesupport/lib/active_support/file_update_checker.rb +++ b/activesupport/lib/active_support/file_update_checker.rb @@ -1,4 +1,3 @@ -require "active_support/core_ext/array/wrap" require "active_support/core_ext/array/extract_options" module ActiveSupport @@ -113,7 +112,7 @@ module ActiveSupport end def compile_ext(array) #:nodoc: - array = Array.wrap(array) + array = Array(array) return if array.empty? ".{#{array.join(",")}}" end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 07b6a940c6..0e1bf4c40b 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -5,7 +5,6 @@ require 'active_support/ordered_hash' require 'bigdecimal' require 'active_support/core_ext/big_decimal/conversions' # for #to_s -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/object/instance_variables' @@ -228,9 +227,9 @@ class Hash # create a subset of the hash by applying :only or :except subset = if options if attrs = options[:only] - slice(*Array.wrap(attrs)) + slice(*Array(attrs)) elsif attrs = options[:except] - except(*Array.wrap(attrs)) + except(*Array(attrs)) else self end diff --git a/activesupport/lib/active_support/multibyte.rb b/activesupport/lib/active_support/multibyte.rb index 57e8e24bf4..5efe13c537 100644 --- a/activesupport/lib/active_support/multibyte.rb +++ b/activesupport/lib/active_support/multibyte.rb @@ -1,9 +1,5 @@ -# encoding: utf-8 -require 'active_support/core_ext/module/attribute_accessors' - module ActiveSupport #:nodoc: module Multibyte - autoload :EncodingError, 'active_support/multibyte/exceptions' autoload :Chars, 'active_support/multibyte/chars' autoload :Unicode, 'active_support/multibyte/unicode' @@ -21,24 +17,5 @@ module ActiveSupport #:nodoc: def self.proxy_class @proxy_class ||= ActiveSupport::Multibyte::Chars end - - # Regular expressions that describe valid byte sequences for a character - VALID_CHARACTER = { - # Borrowed from the Kconv library by Shinji KONO - (also as seen on the W3C site) - 'UTF-8' => /\A(?: - [\x00-\x7f] | - [\xc2-\xdf] [\x80-\xbf] | - \xe0 [\xa0-\xbf] [\x80-\xbf] | - [\xe1-\xef] [\x80-\xbf] [\x80-\xbf] | - \xf0 [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] | - [\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] | - \xf4 [\x80-\x8f] [\x80-\xbf] [\x80-\xbf])\z /xn, - # Quick check for valid Shift-JIS characters, disregards the odd-even pairing - 'Shift_JIS' => /\A(?: - [\x00-\x7e\xa1-\xdf] | - [\x81-\x9f\xe0-\xef] [\x40-\x7e\x80-\x9e\x9f-\xfc])\z /xn - } end -end - -require 'active_support/multibyte/utils'
\ No newline at end of file +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index dcc176e93f..ac61870871 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -1,6 +1,7 @@ # encoding: utf-8 require 'active_support/core_ext/string/access' require 'active_support/core_ext/string/behavior' +require 'active_support/core_ext/module/delegation' module ActiveSupport #:nodoc: module Multibyte #:nodoc: @@ -34,10 +35,13 @@ module ActiveSupport #:nodoc: # # ActiveSupport::Multibyte.proxy_class = CharsForUTF32 class Chars + include Comparable attr_reader :wrapped_string alias to_s wrapped_string alias to_str wrapped_string + delegate :<=>, :=~, :acts_like_string?, :to => :wrapped_string + # Creates a new Chars instance by wrapping _string_. def initialize(string) @wrapped_string = string @@ -47,8 +51,8 @@ module ActiveSupport #:nodoc: # Forward all undefined methods to the wrapped string. def method_missing(method, *args, &block) if method.to_s =~ /!$/ - @wrapped_string.__send__(method, *args, &block) - self + result = @wrapped_string.__send__(method, *args, &block) + self if result else result = @wrapped_string.__send__(method, *args, &block) result.kind_of?(String) ? chars(result) : result @@ -61,35 +65,9 @@ module ActiveSupport #:nodoc: super || @wrapped_string.respond_to?(method, include_private) end - # Enable more predictable duck-typing on String-like classes. See Object#acts_like?. - def acts_like_string? - true - end - # Returns +true+ when the proxy class can handle the string. Returns +false+ otherwise. def self.consumes?(string) - # Unpack is a little bit faster than regular expressions. - string.unpack('U*') - true - rescue ArgumentError - false - end - - include Comparable - - # Returns -1, 0, or 1, depending on whether the Chars object is to be sorted before, - # equal or after the object on the right side of the operation. It accepts any object - # that implements +to_s+: - # - # 'é'.mb_chars <=> 'ü'.mb_chars # => -1 - # - # See <tt>String#<=></tt> for more details. - def <=>(other) - @wrapped_string <=> other.to_s - end - - def =~(other) - @wrapped_string =~ other + string.encoding == Encoding::UTF_8 end # Works just like <tt>String#split</tt>, with the exception that the items in the resulting list are Chars @@ -101,45 +79,10 @@ module ActiveSupport #:nodoc: @wrapped_string.split(*args).map { |i| i.mb_chars } end - # Like <tt>String#[]=</tt>, except instead of byte offsets you specify character offsets. - # - # Example: - # - # s = "Müller" - # s.mb_chars[2] = "e" # Replace character with offset 2 - # s - # # => "Müeler" - # - # s = "Müller" - # s.mb_chars[1, 2] = "ö" # Replace 2 characters at character offset 1 - # s - # # => "Möler" - def []=(*args) - replace_by = args.pop - # Indexed replace with regular expressions already works - if args.first.is_a?(Regexp) - @wrapped_string[*args] = replace_by - else - result = Unicode.u_unpack(@wrapped_string) - case args.first - when Fixnum - raise IndexError, "index #{args[0]} out of string" if args[0] >= result.length - min = args[0] - max = args[1].nil? ? min : (min + args[1] - 1) - range = Range.new(min, max) - replace_by = [replace_by].pack('U') if replace_by.is_a?(Fixnum) - when Range - raise RangeError, "#{args[0]} out of range" if args[0].min >= result.length - range = args[0] - else - needle = args[0].to_s - min = index(needle) - max = min + Unicode.u_unpack(needle).length - 1 - range = Range.new(min, max) - end - result[range] = Unicode.u_unpack(replace_by) - @wrapped_string.replace(result.pack('U*')) - end + # Works like like <tt>String#slice!</tt>, but returns an instance of Chars, or nil if the string was not + # modified. + def slice!(*args) + chars(@wrapped_string.slice!(*args)) end # Reverses all characters in the string. @@ -147,38 +90,10 @@ module ActiveSupport #:nodoc: # Example: # 'Café'.mb_chars.reverse.to_s # => 'éfaC' def reverse - chars(Unicode.g_unpack(@wrapped_string).reverse.flatten.pack('U*')) - end - - # Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that - # character. - # - # Example: - # 'こんにちは'.mb_chars.slice(2..3).to_s # => "にち" - def slice(*args) - if args.size > 2 - raise ArgumentError, "wrong number of arguments (#{args.size} for 1)" # Do as if we were native - elsif (args.size == 2 && !(args.first.is_a?(Numeric) || args.first.is_a?(Regexp))) - raise TypeError, "cannot convert #{args.first.class} into Integer" # Do as if we were native - elsif (args.size == 2 && !args[1].is_a?(Numeric)) - raise TypeError, "cannot convert #{args[1].class} into Integer" # Do as if we were native - elsif args[0].kind_of? Range - cps = Unicode.u_unpack(@wrapped_string).slice(*args) - result = cps.nil? ? nil : cps.pack('U*') - elsif args[0].kind_of? Regexp - result = @wrapped_string.slice(*args) - elsif args.size == 1 && args[0].kind_of?(Numeric) - character = Unicode.u_unpack(@wrapped_string)[args[0]] - result = character && [character].pack('U') - else - cps = Unicode.u_unpack(@wrapped_string).slice(*args) - result = cps && cps.pack('U*') - end - result && chars(result) + chars(Unicode.unpack_graphemes(@wrapped_string).reverse.flatten.pack('U*')) end - alias_method :[], :slice - # Limit the byte size of the string to a number of bytes without breaking characters. Usable + # Limits the byte size of the string to a number of bytes without breaking characters. Usable # when the storage for a string is limited for some reason. # # Example: @@ -187,20 +102,28 @@ module ActiveSupport #:nodoc: slice(0...translate_offset(limit)) end - # Convert characters in the string to uppercase. + # Converts characters in the string to uppercase. # # Example: # 'Laurent, où sont les tests ?'.mb_chars.upcase.to_s # => "LAURENT, OÙ SONT LES TESTS ?" def upcase - chars(Unicode.apply_mapping @wrapped_string, :uppercase_mapping) + chars Unicode.upcase(@wrapped_string) end - # Convert characters in the string to lowercase. + # Converts characters in the string to lowercase. # # Example: # 'VĚDA A VÝZKUM'.mb_chars.downcase.to_s # => "věda a výzkum" def downcase - chars(Unicode.apply_mapping @wrapped_string, :lowercase_mapping) + chars Unicode.downcase(@wrapped_string) + end + + # Converts characters in the string to the opposite case. + # + # Example: + # 'El Cañón".mb_chars.swapcase.to_s # => "eL cAÑÓN" + def swapcase + chars Unicode.swapcase(@wrapped_string) end # Converts the first character to uppercase and the remainder to lowercase. @@ -217,7 +140,7 @@ module ActiveSupport #:nodoc: # "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró" # "日本語".mb_chars.titleize # => "日本語" def titleize - chars(downcase.to_s.gsub(/\b('?[\S])/u) { Unicode.apply_mapping $1, :uppercase_mapping }) + chars(downcase.to_s.gsub(/\b('?[\S])/u) { Unicode.upcase($1)}) end alias_method :titlecase, :titleize @@ -237,7 +160,7 @@ module ActiveSupport #:nodoc: # 'é'.length # => 2 # 'é'.mb_chars.decompose.to_s.length # => 3 def decompose - chars(Unicode.decompose_codepoints(:canonical, Unicode.u_unpack(@wrapped_string)).pack('U*')) + chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack('U*')) end # Performs composition on all the characters. @@ -246,16 +169,16 @@ module ActiveSupport #:nodoc: # 'é'.length # => 3 # 'é'.mb_chars.compose.to_s.length # => 2 def compose - chars(Unicode.compose_codepoints(Unicode.u_unpack(@wrapped_string)).pack('U*')) + chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack('U*')) end # Returns the number of grapheme clusters in the string. # # Example: # 'क्षि'.mb_chars.length # => 4 - # 'क्षि'.mb_chars.g_length # => 3 - def g_length - Unicode.g_unpack(@wrapped_string).length + # 'क्षि'.mb_chars.grapheme_length # => 3 + def grapheme_length + Unicode.unpack_graphemes(@wrapped_string).length end # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string. @@ -265,14 +188,10 @@ module ActiveSupport #:nodoc: chars(Unicode.tidy_bytes(@wrapped_string, force)) end - %w(capitalize downcase lstrip reverse rstrip slice strip tidy_bytes upcase).each do |method| - # Only define a corresponding bang method for methods defined in the proxy; On 1.9 the proxy will - # exclude lstrip!, rstrip! and strip! because they are already work as expected on multibyte strings. - if public_method_defined?(method) - define_method("#{method}!") do |*args| - @wrapped_string = send(args.nil? ? method : method, *args).to_s - self - end + %w(capitalize downcase reverse tidy_bytes upcase).each do |method| + define_method("#{method}!") do |*args| + @wrapped_string = send(method, *args).to_s + self end end @@ -282,41 +201,14 @@ module ActiveSupport #:nodoc: return nil if byte_offset.nil? return 0 if @wrapped_string == '' - @wrapped_string = @wrapped_string.dup.force_encoding(Encoding::ASCII_8BIT) - begin - @wrapped_string[0...byte_offset].unpack('U*').length + @wrapped_string.byteslice(0...byte_offset).unpack('U*').length rescue ArgumentError byte_offset -= 1 retry end end - def justify(integer, way, padstr=' ') #:nodoc: - raise ArgumentError, "zero width padding" if padstr.length == 0 - padsize = integer - size - padsize = padsize > 0 ? padsize : 0 - case way - when :right - result = @wrapped_string.dup.insert(0, padding(padsize, padstr)) - when :left - result = @wrapped_string.dup.insert(-1, padding(padsize, padstr)) - when :center - lpad = padding((padsize / 2.0).floor, padstr) - rpad = padding((padsize / 2.0).ceil, padstr) - result = @wrapped_string.dup.insert(0, lpad).insert(-1, rpad) - end - chars(result) - end - - def padding(padsize, padstr=' ') #:nodoc: - if padsize != 0 - chars(padstr * ((padsize / Unicode.u_unpack(padstr).size) + 1)).slice(0, padsize) - else - '' - end - end - def chars(string) #:nodoc: self.class.new(string) end diff --git a/activesupport/lib/active_support/multibyte/exceptions.rb b/activesupport/lib/active_support/multibyte/exceptions.rb deleted file mode 100644 index 62066e3c71..0000000000 --- a/activesupport/lib/active_support/multibyte/exceptions.rb +++ /dev/null @@ -1,8 +0,0 @@ -# encoding: utf-8 - -module ActiveSupport #:nodoc: - module Multibyte #:nodoc: - # Raised when a problem with the encoding was found. - class EncodingError < StandardError; end - end -end
\ No newline at end of file diff --git a/activesupport/lib/active_support/multibyte/unicode.rb b/activesupport/lib/active_support/multibyte/unicode.rb index 754ca9290b..a0a8f3c97e 100644 --- a/activesupport/lib/active_support/multibyte/unicode.rb +++ b/activesupport/lib/active_support/multibyte/unicode.rb @@ -10,7 +10,7 @@ module ActiveSupport NORMALIZATION_FORMS = [:c, :kc, :d, :kd] # The Unicode version that is supported by the implementation - UNICODE_VERSION = '5.2.0' + UNICODE_VERSION = '6.0.0' # The default normalization used for operations that require normalization. It can be set to any of the # normalizations in NORMALIZATION_FORMS. @@ -61,19 +61,6 @@ module ActiveSupport TRAILERS_PAT = /(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+\Z/u LEADERS_PAT = /\A(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+/u - # Unpack the string at codepoints boundaries. Raises an EncodingError when the encoding of the string isn't - # valid UTF-8. - # - # Example: - # Unicode.u_unpack('Café') # => [67, 97, 102, 233] - def u_unpack(string) - begin - string.unpack 'U*' - rescue ArgumentError - raise EncodingError, 'malformed UTF-8 character' - end - end - # Detect whether the codepoint is in a certain character class. Returns +true+ when it's in the specified # character class and +false+ otherwise. Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>, # <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>. @@ -86,10 +73,10 @@ module ActiveSupport # Unpack the string at grapheme boundaries. Returns a list of character lists. # # Example: - # Unicode.g_unpack('क्षि') # => [[2325, 2381], [2359], [2367]] - # Unicode.g_unpack('Café') # => [[67], [97], [102], [233]] - def g_unpack(string) - codepoints = u_unpack(string) + # Unicode.unpack_graphemes('क्षि') # => [[2325, 2381], [2359], [2367]] + # Unicode.unpack_graphemes('Café') # => [[67], [97], [102], [233]] + def unpack_graphemes(string) + codepoints = string.codepoints.to_a unpacked = [] pos = 0 marker = 0 @@ -118,12 +105,12 @@ module ActiveSupport unpacked end - # Reverse operation of g_unpack. + # Reverse operation of unpack_graphemes. # # Example: - # Unicode.g_pack(Unicode.g_unpack('क्षि')) # => 'क्षि' - def g_pack(unpacked) - (unpacked.flatten).pack('U*') + # Unicode.pack_graphemes(Unicode.unpack_graphemes('क्षि')) # => 'क्षि' + def pack_graphemes(unpacked) + unpacked.flatten.pack('U*') end # Re-order codepoints so the string becomes canonical. @@ -143,7 +130,7 @@ module ActiveSupport end # Decompose composed characters to the decomposed form. - def decompose_codepoints(type, codepoints) + def decompose(type, codepoints) codepoints.inject([]) do |decomposed, cp| # if it's a hangul syllable starter character if HANGUL_SBASE <= cp and cp < HANGUL_SLAST @@ -156,7 +143,7 @@ module ActiveSupport decomposed.concat ncp # if the codepoint is decomposable in with the current decomposition type elsif (ncp = database.codepoints[cp].decomp_mapping) and (!database.codepoints[cp].decomp_type || type == :compatability) - decomposed.concat decompose_codepoints(type, ncp.dup) + decomposed.concat decompose(type, ncp.dup) else decomposed << cp end @@ -164,7 +151,7 @@ module ActiveSupport end # Compose decomposed characters to the composed form. - def compose_codepoints(codepoints) + def compose(codepoints) pos = 0 eoa = codepoints.length - 1 starter_pos = 0 @@ -283,35 +270,40 @@ module ActiveSupport def normalize(string, form=nil) form ||= @default_normalization_form # See http://www.unicode.org/reports/tr15, Table 1 - codepoints = u_unpack(string) + codepoints = string.codepoints.to_a case form when :d - reorder_characters(decompose_codepoints(:canonical, codepoints)) + reorder_characters(decompose(:canonical, codepoints)) when :c - compose_codepoints(reorder_characters(decompose_codepoints(:canonical, codepoints))) + compose(reorder_characters(decompose(:canonical, codepoints))) when :kd - reorder_characters(decompose_codepoints(:compatability, codepoints)) + reorder_characters(decompose(:compatability, codepoints)) when :kc - compose_codepoints(reorder_characters(decompose_codepoints(:compatability, codepoints))) + compose(reorder_characters(decompose(:compatability, codepoints))) else raise ArgumentError, "#{form} is not a valid normalization variant", caller end.pack('U*') end - def apply_mapping(string, mapping) #:nodoc: - u_unpack(string).map do |codepoint| - cp = database.codepoints[codepoint] - if cp and (ncp = cp.send(mapping)) and ncp > 0 - ncp - else - codepoint - end - end.pack('U*') + def downcase(string) + apply_mapping string, :lowercase_mapping + end + + def upcase(string) + apply_mapping string, :uppercase_mapping + end + + def swapcase(string) + apply_mapping string, :swapcase_mapping end # Holds data about a codepoint in the Unicode database class Codepoint attr_accessor :code, :combining_class, :decomp_type, :decomp_mapping, :uppercase_mapping, :lowercase_mapping + + def swapcase_mapping + uppercase_mapping > 0 ? uppercase_mapping : lowercase_mapping + end end # Holds static data from the Unicode database @@ -374,6 +366,17 @@ module ActiveSupport private + def apply_mapping(string, mapping) #:nodoc: + string.each_codepoint.map do |codepoint| + cp = database.codepoints[codepoint] + if cp and (ncp = cp.send(mapping)) and ncp > 0 + ncp + else + codepoint + end + end.pack('U*') + end + def tidy_byte(byte) if byte < 160 [database.cp1252[byte] || byte].pack("U").unpack("C*") diff --git a/activesupport/lib/active_support/multibyte/utils.rb b/activesupport/lib/active_support/multibyte/utils.rb deleted file mode 100644 index bd6d4bad41..0000000000 --- a/activesupport/lib/active_support/multibyte/utils.rb +++ /dev/null @@ -1,27 +0,0 @@ -# encoding: utf-8 - -module ActiveSupport #:nodoc: - module Multibyte #:nodoc: - # Returns a regular expression that matches valid characters in the current encoding - def self.valid_character - VALID_CHARACTER[Encoding.default_external.to_s] - end - - # Verifies the encoding of a string - def self.verify(string) - string.valid_encoding? - end - - # Verifies the encoding of the string and raises an exception when it's not valid - def self.verify!(string) - raise EncodingError.new("Found characters with invalid encoding") unless verify(string) - end - - # Removes all invalid characters from the string. - # - # Note: this method is a no-op in Ruby 1.9 - def self.clean(string) - string - end - end -end diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index d4f309fbd7..8edd3960c7 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -1,8 +1,3 @@ -begin - require 'psych' -rescue LoadError -end - require 'yaml' YAML.add_builtin_type("omap") do |type, val| @@ -29,20 +24,6 @@ module ActiveSupport coder.represent_seq '!omap', map { |k,v| { k => v } } end - def to_yaml(opts = {}) - if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? - return super - end - - YAML.quick_emit(self, opts) do |out| - out.seq(taguri) do |seq| - each do |k, v| - seq.add(k => v) - end - end - end - end - def nested_under_indifferent_access self end diff --git a/activesupport/lib/active_support/string_inquirer.rb b/activesupport/lib/active_support/string_inquirer.rb index e6b1f39225..f3f3909a90 100644 --- a/activesupport/lib/active_support/string_inquirer.rb +++ b/activesupport/lib/active_support/string_inquirer.rb @@ -11,8 +11,8 @@ module ActiveSupport # class StringInquirer < String def method_missing(method_name, *arguments) - if method_name.to_s[-1,1] == "?" - self == method_name.to_s[0..-2] + if method_name[-1, 1] == "?" + self == method_name[0..-2] else super end diff --git a/activesupport/lib/active_support/tagged_logging.rb b/activesupport/lib/active_support/tagged_logging.rb index 8eae43188d..dc3ca25938 100644 --- a/activesupport/lib/active_support/tagged_logging.rb +++ b/activesupport/lib/active_support/tagged_logging.rb @@ -19,7 +19,7 @@ module ActiveSupport def tagged(*new_tags) tags = current_tags - new_tags = Array.wrap(new_tags).flatten.reject(&:blank?) + new_tags = Array(new_tags).flatten.reject(&:blank?) tags.concat new_tags yield ensure diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index 707544e594..4169557286 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -1,4 +1,4 @@ -require 'test/unit/testcase' +require 'minitest/spec' require 'active_support/testing/setup_and_teardown' require 'active_support/testing/assertions' require 'active_support/testing/deprecation' @@ -9,7 +9,19 @@ require 'active_support/testing/mochaing' require 'active_support/core_ext/kernel/reporting' module ActiveSupport - class TestCase < ::Test::Unit::TestCase + class TestCase < ::MiniTest::Spec + + if MiniTest::Unit::VERSION < '2.6.1' + class << self + alias :name :to_s + end + end + + # Use AS::TestCase for the base class when describing a model + register_spec_type(self) do |desc| + desc < ActiveRecord::Model + end + Assertion = MiniTest::Assertion alias_method :method_name, :name if method_defined? :name alias_method :method_name, :__name__ if method_defined? :__name__ @@ -19,10 +31,27 @@ module ActiveSupport yield if $tags[tag] end + # FIXME: we have tests that depend on run order, we should fix that and + # remove this method. + def self.test_order # :nodoc: + :sorted + end + include ActiveSupport::Testing::SetupAndTeardown include ActiveSupport::Testing::Assertions include ActiveSupport::Testing::Deprecation include ActiveSupport::Testing::Pending extend ActiveSupport::Testing::Declarative + + # test/unit backwards compatibility methods + alias :assert_raise :assert_raises + alias :assert_not_nil :refute_nil + alias :assert_not_equal :refute_equal + alias :assert_no_match :refute_match + alias :assert_not_same :refute_same + + def assert_nothing_raised(*args) + yield + end end end diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb index 4e1a58a801..d84595fa8f 100644 --- a/activesupport/lib/active_support/testing/assertions.rb +++ b/activesupport/lib/active_support/testing/assertions.rb @@ -1,4 +1,3 @@ -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/object/blank' module ActiveSupport @@ -45,7 +44,7 @@ module ActiveSupport # post :delete, :id => ... # end def assert_difference(expression, difference = 1, message = nil, &block) - expressions = Array.wrap expression + expressions = Array(expression) exps = expressions.map { |e| e.respond_to?(:call) ? e : lambda { eval(e, block.binding) } diff --git a/activesupport/lib/active_support/testing/deprecation.rb b/activesupport/lib/active_support/testing/deprecation.rb index 0135185a47..a8342904dc 100644 --- a/activesupport/lib/active_support/testing/deprecation.rb +++ b/activesupport/lib/active_support/testing/deprecation.rb @@ -34,22 +34,3 @@ module ActiveSupport end end end - -begin - require 'test/unit/error' -rescue LoadError - # Using miniunit, ignore. -else - module Test - module Unit - class Error #:nodoc: - # Silence warnings when reporting test errors. - def message_with_silenced_deprecation - ActiveSupport::Deprecation.silence { message_without_silenced_deprecation } - end - alias_method :message_without_silenced_deprecation, :message - alias_method :message, :message_with_silenced_deprecation - end - end - end -end diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb index 6b29ba4c10..c896b955fb 100644 --- a/activesupport/lib/active_support/testing/isolation.rb +++ b/activesupport/lib/active_support/testing/isolation.rb @@ -38,11 +38,7 @@ module ActiveSupport end def self.included(base) - if defined?(::MiniTest) && base < ::MiniTest::Unit::TestCase - base.send :include, MiniTest - elsif defined?(Test::Unit) - base.send :include, TestUnit - end + base.send :include, MiniTest end def _run_class_setup # class setup method should only happen in parent @@ -52,30 +48,6 @@ module ActiveSupport end end - module TestUnit - def run(result) - _run_class_setup - - yield(Test::Unit::TestCase::STARTED, name) - - @_result = result - - 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 - module MiniTest def run(runner) _run_class_setup diff --git a/activesupport/lib/active_support/testing/pending.rb b/activesupport/lib/active_support/testing/pending.rb index feac7bc347..510f80f32c 100644 --- a/activesupport/lib/active_support/testing/pending.rb +++ b/activesupport/lib/active_support/testing/pending.rb @@ -11,39 +11,7 @@ module ActiveSupport @@at_exit = false def pending(description = "", &block) - if defined?(::MiniTest) - skip(description.blank? ? nil : description) - else - if description.is_a?(Symbol) - is_pending = $tags[description] - return block.call unless is_pending - end - - if block_given? - failed = false - - begin - block.call - rescue Exception - failed = true - end - - flunk("<#{description}> did not fail.") unless failed - end - - caller[0] =~ (/(.*):(.*):in `(.*)'/) - @@pending_cases << "#{$3} at #{$1}, line #{$2}" - print "P" - - @@at_exit ||= begin - at_exit do - puts "\nPending Cases:" - @@pending_cases.each do |test_case| - puts test_case - end - end - end - end + skip(description.blank? ? nil : description) end end diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb index 40b781485e..772c7b4209 100644 --- a/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -10,7 +10,6 @@ module ActiveSupport include ActiveSupport::Callbacks define_callbacks :setup, :teardown - include ForMiniTest end module ClassMethods @@ -23,24 +22,22 @@ module ActiveSupport end end - module ForMiniTest - def run(runner) - result = '.' + def run(runner) + result = '.' + begin + run_callbacks :setup do + result = super + end + rescue Exception => e + result = runner.puke(self.class, method_name, e) + ensure begin - run_callbacks :setup do - result = super - end + run_callbacks :teardown rescue Exception => e result = runner.puke(self.class, method_name, e) - ensure - begin - run_callbacks :teardown - rescue Exception => e - result = runner.puke(self.class, method_name, e) - end end - result end + result end end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index d3adf671a0..1cb71012ef 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -1,4 +1,4 @@ -require "active_support/values/time_zone" +require 'active_support/values/time_zone' require 'active_support/core_ext/object/acts_like' require 'active_support/core_ext/object/inclusion' @@ -146,12 +146,6 @@ module ActiveSupport end end - def to_yaml(options = {}) - return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck? - - utc.to_yaml(options) - end - def httpdate utc.httpdate end diff --git a/activesupport/lib/active_support/values/unicode_tables.dat b/activesupport/lib/active_support/values/unicode_tables.dat Binary files differindex 4fe0268cca..7edc4663e8 100644 --- a/activesupport/lib/active_support/values/unicode_tables.dat +++ b/activesupport/lib/active_support/values/unicode_tables.dat diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index 504ac3e9b9..40e25ce0cd 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -18,7 +18,7 @@ silence_warnings do Encoding.default_external = "UTF-8" end -require 'test/unit' +require 'minitest/autorun' require 'empty_bool' silence_warnings { require 'mocha' } @@ -37,4 +37,4 @@ def uses_memcached(test_name) end # Show backtraces for deprecated behavior for quicker cleanup. -ActiveSupport::Deprecation.debug = true
\ No newline at end of file +ActiveSupport::Deprecation.debug = true diff --git a/activesupport/test/buffered_logger_test.rb b/activesupport/test/buffered_logger_test.rb index b9891c74c8..615635607c 100644 --- a/activesupport/test/buffered_logger_test.rb +++ b/activesupport/test/buffered_logger_test.rb @@ -3,10 +3,9 @@ require 'multibyte_test_helpers' require 'stringio' require 'fileutils' require 'tempfile' -require 'active_support/buffered_logger' require 'active_support/testing/deprecation' -class BufferedLoggerTest < Test::Unit::TestCase +class BufferedLoggerTest < ActiveSupport::TestCase include MultibyteTestHelpers include ActiveSupport::Testing::Deprecation diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index aa6fb14e7b..3454c378d3 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -681,7 +681,7 @@ uses_memcached 'memcached backed store' do @data = @cache.instance_variable_get(:@data) @cache.clear @cache.silence! - @cache.logger = Logger.new("/dev/null") + @cache.logger = ActiveSupport::Logger.new("/dev/null") end include CacheStoreBehavior @@ -786,7 +786,7 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase @cache = ActiveSupport::Cache.lookup_store(:memory_store) @buffer = StringIO.new - @cache.logger = Logger.new(@buffer) + @cache.logger = ActiveSupport::Logger.new(@buffer) end def test_logging diff --git a/activesupport/test/callback_inheritance_test.rb b/activesupport/test/callback_inheritance_test.rb index 06259c648c..b5ad34c204 100644 --- a/activesupport/test/callback_inheritance_test.rb +++ b/activesupport/test/callback_inheritance_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'test/unit' class GrandParent include ActiveSupport::Callbacks @@ -105,7 +104,7 @@ end class CountingChild < CountingParent end -class BasicCallbacksTest < Test::Unit::TestCase +class BasicCallbacksTest < ActiveSupport::TestCase def setup @index = GrandParent.new("index").dispatch @update = GrandParent.new("update").dispatch @@ -126,7 +125,7 @@ class BasicCallbacksTest < Test::Unit::TestCase end end -class InheritedCallbacksTest < Test::Unit::TestCase +class InheritedCallbacksTest < ActiveSupport::TestCase def setup @index = Parent.new("index").dispatch @update = Parent.new("update").dispatch @@ -147,7 +146,7 @@ class InheritedCallbacksTest < Test::Unit::TestCase end end -class InheritedCallbacksTest2 < Test::Unit::TestCase +class InheritedCallbacksTest2 < ActiveSupport::TestCase def setup @update1 = Child.new("update", :open).dispatch @update2 = Child.new("update", :closed).dispatch @@ -162,7 +161,7 @@ class InheritedCallbacksTest2 < Test::Unit::TestCase end end -class DynamicInheritedCallbacks < Test::Unit::TestCase +class DynamicInheritedCallbacks < ActiveSupport::TestCase def test_callbacks_looks_to_the_superclass_before_running child = EmptyChild.new.dispatch assert !child.performed? diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index e723121bb4..2c2a420619 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'test/unit' module CallbacksTest class Phone @@ -158,7 +157,7 @@ module CallbacksTest end end - class OneTimeCompileTest < Test::Unit::TestCase + class OneTimeCompileTest < ActiveSupport::TestCase def test_optimized_first_compile around = OneTimeCompile.new around.save @@ -177,7 +176,7 @@ module CallbacksTest end end - class AfterSaveConditionalPersonCallbackTest < Test::Unit::TestCase + class AfterSaveConditionalPersonCallbackTest < ActiveSupport::TestCase def test_after_save_runs_in_the_reverse_order person = AfterSaveConditionalPerson.new person.save @@ -345,7 +344,7 @@ module CallbacksTest end end - class AroundCallbacksTest < Test::Unit::TestCase + class AroundCallbacksTest < ActiveSupport::TestCase def test_save_around around = AroundPerson.new around.save @@ -364,7 +363,7 @@ module CallbacksTest end end - class AroundCallbackResultTest < Test::Unit::TestCase + class AroundCallbackResultTest < ActiveSupport::TestCase def test_save_around around = AroundPersonResult.new around.save @@ -372,7 +371,7 @@ module CallbacksTest end end - class SkipCallbacksTest < Test::Unit::TestCase + class SkipCallbacksTest < ActiveSupport::TestCase def test_skip_person person = PersonSkipper.new assert_equal [], person.history @@ -391,7 +390,7 @@ module CallbacksTest end end - class CallbacksTest < Test::Unit::TestCase + class CallbacksTest < ActiveSupport::TestCase def test_save_phone phone = Phone.new assert_raise RuntimeError do @@ -419,7 +418,7 @@ module CallbacksTest end end - class ConditionalCallbackTest < Test::Unit::TestCase + class ConditionalCallbackTest < ActiveSupport::TestCase def test_save_conditional_person person = ConditionalPerson.new person.save @@ -437,7 +436,7 @@ module CallbacksTest - class ResetCallbackTest < Test::Unit::TestCase + class ResetCallbackTest < ActiveSupport::TestCase def test_save_conditional_person person = CleanPerson.new person.save @@ -567,7 +566,7 @@ module CallbacksTest end end - class UsingObjectTest < Test::Unit::TestCase + class UsingObjectTest < ActiveSupport::TestCase def test_before_object u = UsingObjectBefore.new u.save @@ -592,7 +591,7 @@ module CallbacksTest end end - class CallbackTerminatorTest < Test::Unit::TestCase + class CallbackTerminatorTest < ActiveSupport::TestCase def test_termination terminator = CallbackTerminator.new terminator.save @@ -612,7 +611,7 @@ module CallbacksTest end end - class HyphenatedKeyTest < Test::Unit::TestCase + class HyphenatedKeyTest < ActiveSupport::TestCase def test_save obj = HyphenatedCallbacks.new obj.save @@ -625,7 +624,7 @@ module CallbacksTest skip_callback :save, :before, :before_save_method, :if => lambda {self.age > 21} end - class WriterCallbacksTest < Test::Unit::TestCase + class WriterCallbacksTest < ActiveSupport::TestCase def test_skip_writer writer = WriterSkipper.new writer.age = 18 diff --git a/activesupport/test/clean_logger_test.rb b/activesupport/test/clean_logger_test.rb index 178c7c0b23..02693a97dc 100644 --- a/activesupport/test/clean_logger_test.rb +++ b/activesupport/test/clean_logger_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'stringio' require 'active_support/logger' -class CleanLoggerTest < Test::Unit::TestCase +class CleanLoggerTest < ActiveSupport::TestCase def setup @out = StringIO.new @logger = ActiveSupport::Logger.new(@out) diff --git a/activesupport/test/concern_test.rb b/activesupport/test/concern_test.rb index 0b0920ee03..912ce30c29 100644 --- a/activesupport/test/concern_test.rb +++ b/activesupport/test/concern_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/concern' -class ConcernTest < Test::Unit::TestCase +class ConcernTest < ActiveSupport::TestCase module Baz extend ActiveSupport::Concern diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb index 278734027a..58835c0ac5 100644 --- a/activesupport/test/core_ext/array_ext_test.rb +++ b/activesupport/test/core_ext/array_ext_test.rb @@ -6,7 +6,7 @@ require 'active_support/core_ext/object/conversions' require 'active_support/core_ext' # FIXME: pulling in all to_xml extensions require 'active_support/hash_with_indifferent_access' -class ArrayExtAccessTests < Test::Unit::TestCase +class ArrayExtAccessTests < ActiveSupport::TestCase def test_from assert_equal %w( a b c d ), %w( a b c d ).from(0) assert_equal %w( c d ), %w( a b c d ).from(2) @@ -30,7 +30,7 @@ class ArrayExtAccessTests < Test::Unit::TestCase end end -class ArrayExtToParamTests < Test::Unit::TestCase +class ArrayExtToParamTests < ActiveSupport::TestCase class ToParam < String def to_param "#{self}1" @@ -52,7 +52,7 @@ class ArrayExtToParamTests < Test::Unit::TestCase end end -class ArrayExtToSentenceTests < Test::Unit::TestCase +class ArrayExtToSentenceTests < ActiveSupport::TestCase def test_plain_array_to_sentence assert_equal "", [].to_sentence assert_equal "one", ['one'].to_sentence @@ -92,7 +92,7 @@ class ArrayExtToSentenceTests < Test::Unit::TestCase end end -class ArrayExtToSTests < Test::Unit::TestCase +class ArrayExtToSTests < ActiveSupport::TestCase def test_to_s_db collection = [ Class.new { def id() 1 end }.new, @@ -105,7 +105,7 @@ class ArrayExtToSTests < Test::Unit::TestCase end end -class ArrayExtGroupingTests < Test::Unit::TestCase +class ArrayExtGroupingTests < ActiveSupport::TestCase def test_in_groups_of_with_perfect_fit groups = [] ('a'..'i').to_a.in_groups_of(3) do |group| @@ -188,7 +188,7 @@ class ArrayExtGroupingTests < Test::Unit::TestCase end end -class ArraySplitTests < Test::Unit::TestCase +class ArraySplitTests < ActiveSupport::TestCase def test_split_with_empty_array assert_equal [[]], [].split(0) end @@ -209,7 +209,7 @@ class ArraySplitTests < Test::Unit::TestCase end end -class ArrayToXmlTests < Test::Unit::TestCase +class ArrayToXmlTests < ActiveSupport::TestCase def test_to_xml xml = [ { :name => "David", :age => 26, :age_in_millis => 820497600000 }, @@ -299,7 +299,7 @@ class ArrayToXmlTests < Test::Unit::TestCase end end -class ArrayExtractOptionsTests < Test::Unit::TestCase +class ArrayExtractOptionsTests < ActiveSupport::TestCase class HashSubclass < Hash end @@ -341,7 +341,7 @@ class ArrayExtractOptionsTests < Test::Unit::TestCase end end -class ArrayUniqByTests < Test::Unit::TestCase +class ArrayUniqByTests < ActiveSupport::TestCase def test_uniq_by ActiveSupport::Deprecation.silence do assert_equal [1,2], [1,2,3,4].uniq_by { |i| i.odd? } @@ -371,7 +371,7 @@ class ArrayUniqByTests < Test::Unit::TestCase end end -class ArrayWrapperTests < Test::Unit::TestCase +class ArrayWrapperTests < ActiveSupport::TestCase class FakeCollection def to_ary ["foo", "bar"] @@ -446,7 +446,7 @@ class ArrayWrapperTests < Test::Unit::TestCase end end -class ArrayPrependAppendTest < Test::Unit::TestCase +class ArrayPrependAppendTest < ActiveSupport::TestCase def test_append assert_equal [1, 2], [1].append(2) end diff --git a/activesupport/test/core_ext/bigdecimal_test.rb b/activesupport/test/core_ext/bigdecimal_test.rb index b38e08a9f4..e24a089650 100644 --- a/activesupport/test/core_ext/bigdecimal_test.rb +++ b/activesupport/test/core_ext/bigdecimal_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'bigdecimal' require 'active_support/core_ext/big_decimal' -class BigDecimalTest < Test::Unit::TestCase +class BigDecimalTest < ActiveSupport::TestCase def test_to_yaml assert_match("--- 100000.30020320320000000000000000000000000000001\n", BigDecimal.new('100000.30020320320000000000000000000000000000001').to_yaml) assert_match("--- .Inf\n", BigDecimal.new('Infinity').to_yaml) diff --git a/activesupport/test/core_ext/blank_test.rb b/activesupport/test/core_ext/blank_test.rb index a2cf298905..a68c074777 100644 --- a/activesupport/test/core_ext/blank_test.rb +++ b/activesupport/test/core_ext/blank_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' require 'active_support/core_ext/object/blank' -class BlankTest < Test::Unit::TestCase +class BlankTest < ActiveSupport::TestCase BLANK = [ EmptyTrue.new, nil, false, '', ' ', " \n\t \r ", ' ', [], {} ] NOT = [ EmptyFalse.new, Object.new, true, 0, 1, 'a', [nil], { nil => 0 } ] diff --git a/activesupport/test/core_ext/class/attribute_accessor_test.rb b/activesupport/test/core_ext/class/attribute_accessor_test.rb index 6b50f8db37..3822e7af66 100644 --- a/activesupport/test/core_ext/class/attribute_accessor_test.rb +++ b/activesupport/test/core_ext/class/attribute_accessor_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/class/attribute_accessors' -class ClassAttributeAccessorTest < Test::Unit::TestCase +class ClassAttributeAccessorTest < ActiveSupport::TestCase def setup @class = Class.new do cattr_accessor :foo diff --git a/activesupport/test/core_ext/class/delegating_attributes_test.rb b/activesupport/test/core_ext/class/delegating_attributes_test.rb index cbfb290c48..148f82946c 100644 --- a/activesupport/test/core_ext/class/delegating_attributes_test.rb +++ b/activesupport/test/core_ext/class/delegating_attributes_test.rb @@ -20,7 +20,7 @@ module DelegatingFixtures end end -class DelegatingAttributesTest < Test::Unit::TestCase +class DelegatingAttributesTest < ActiveSupport::TestCase include DelegatingFixtures attr_reader :single_class diff --git a/activesupport/test/core_ext/class_test.rb b/activesupport/test/core_ext/class_test.rb index 60ba3b8f88..9c6c579ef7 100644 --- a/activesupport/test/core_ext/class_test.rb +++ b/activesupport/test/core_ext/class_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'active_support/core_ext/class' require 'set' -class ClassTest < Test::Unit::TestCase +class ClassTest < ActiveSupport::TestCase class Parent; end class Foo < Parent; end class Bar < Foo; end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index 09d4765390..6e91fdedce 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -444,7 +444,7 @@ class DateExtCalculationsTest < ActiveSupport::TestCase end end -class DateExtBehaviorTest < Test::Unit::TestCase +class DateExtBehaviorTest < ActiveSupport::TestCase def test_date_acts_like_date assert Date.new.acts_like_date? end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 0087163faf..433dafde83 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/time' -class DateTimeExtCalculationsTest < Test::Unit::TestCase +class DateTimeExtCalculationsTest < ActiveSupport::TestCase def test_to_s datetime = DateTime.new(2005, 2, 21, 14, 30, 0, 0) assert_equal "2005-02-21 14:30:00", datetime.to_s(:db) diff --git a/activesupport/test/core_ext/duplicable_test.rb b/activesupport/test/core_ext/duplicable_test.rb index e48e6a7c45..3e54266051 100644 --- a/activesupport/test/core_ext/duplicable_test.rb +++ b/activesupport/test/core_ext/duplicable_test.rb @@ -3,7 +3,7 @@ require 'bigdecimal' require 'active_support/core_ext/object/duplicable' require 'active_support/core_ext/numeric/time' -class DuplicableTest < Test::Unit::TestCase +class DuplicableTest < ActiveSupport::TestCase RAISE_DUP = [nil, false, true, :symbol, 1, 2.3, BigDecimal.new('4.56'), 5.seconds] YES = ['1', Object.new, /foo/, [], {}, Time.now] NO = [Class.new, Module.new] @@ -22,7 +22,7 @@ class DuplicableTest < Test::Unit::TestCase end RAISE_DUP.each do |v| - assert_raises(TypeError) do + assert_raises(TypeError, v.class.name) do v.dup end end diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index f10e6c82e4..0bf48dd378 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -7,7 +7,7 @@ class SummablePayment < Payment def +(p) self.class.new(price + p.price) end end -class EnumerableTests < Test::Unit::TestCase +class EnumerableTests < ActiveSupport::TestCase Enumerator = [].each.class class GenericEnumerable diff --git a/activesupport/test/core_ext/file_test.rb b/activesupport/test/core_ext/file_test.rb index 26be694176..50c9c57aa6 100644 --- a/activesupport/test/core_ext/file_test.rb +++ b/activesupport/test/core_ext/file_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/file' -class AtomicWriteTest < Test::Unit::TestCase +class AtomicWriteTest < ActiveSupport::TestCase def test_atomic_write_without_errors contents = "Atomic Text" File.atomic_write(file_name, Dir.pwd) do |file| diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index dfa0cdb478..a0f261ebdb 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -6,7 +6,7 @@ require 'active_support/ordered_hash' require 'active_support/core_ext/object/conversions' require 'active_support/inflections' -class HashExtTest < Test::Unit::TestCase +class HashExtTest < ActiveSupport::TestCase class IndifferentHash < HashWithIndifferentAccess end @@ -523,7 +523,7 @@ class IWriteMyOwnXML end end -class HashExtToParamTests < Test::Unit::TestCase +class HashExtToParamTests < ActiveSupport::TestCase class ToParam < String def to_param "#{self}-1" @@ -554,7 +554,7 @@ class HashExtToParamTests < Test::Unit::TestCase end end -class HashToXmlTest < Test::Unit::TestCase +class HashToXmlTest < ActiveSupport::TestCase def setup @xml_options = { :root => :person, :skip_instruct => true, :indent => 0 } end diff --git a/activesupport/test/core_ext/integer_ext_test.rb b/activesupport/test/core_ext/integer_ext_test.rb index b1f5f70a70..bfbb2260c6 100644 --- a/activesupport/test/core_ext/integer_ext_test.rb +++ b/activesupport/test/core_ext/integer_ext_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/integer' -class IntegerExtTest < Test::Unit::TestCase +class IntegerExtTest < ActiveSupport::TestCase PRIME = 22953686867719691230002707821868552601124472329079 def test_multiple_of diff --git a/activesupport/test/core_ext/kernel_test.rb b/activesupport/test/core_ext/kernel_test.rb index 73a7179872..e90b9d454f 100644 --- a/activesupport/test/core_ext/kernel_test.rb +++ b/activesupport/test/core_ext/kernel_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/kernel' -class KernelTest < Test::Unit::TestCase +class KernelTest < ActiveSupport::TestCase def test_silence_warnings silence_warnings { assert_nil $VERBOSE } assert_equal 1234, silence_warnings { 1234 } @@ -54,7 +54,7 @@ class KernelTest < Test::Unit::TestCase end end -class KernelSuppressTest < Test::Unit::TestCase +class KernelSuppressTest < ActiveSupport::TestCase def test_reraise assert_raise(LoadError) do suppress(ArgumentError) { raise LoadError } @@ -85,7 +85,7 @@ class MockStdErr end end -class KernelDebuggerTest < Test::Unit::TestCase +class KernelDebuggerTest < ActiveSupport::TestCase def test_debugger_not_available_message_to_stderr old_stderr = $stderr $stderr = MockStdErr.new diff --git a/activesupport/test/core_ext/load_error_test.rb b/activesupport/test/core_ext/load_error_test.rb index d7b8f602ca..31863d0aca 100644 --- a/activesupport/test/core_ext/load_error_test.rb +++ b/activesupport/test/core_ext/load_error_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/load_error' -class TestMissingSourceFile < Test::Unit::TestCase +class TestMissingSourceFile < ActiveSupport::TestCase def test_with_require assert_raise(MissingSourceFile) { require 'no_this_file_don\'t_exist' } end @@ -16,7 +16,7 @@ class TestMissingSourceFile < Test::Unit::TestCase end end -class TestLoadError < Test::Unit::TestCase +class TestLoadError < ActiveSupport::TestCase def test_with_require assert_raise(LoadError) { require 'no_this_file_don\'t_exist' } end diff --git a/activesupport/test/core_ext/module/attr_internal_test.rb b/activesupport/test/core_ext/module/attr_internal_test.rb index 93578c9610..2aea14cf2b 100644 --- a/activesupport/test/core_ext/module/attr_internal_test.rb +++ b/activesupport/test/core_ext/module/attr_internal_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/module/attr_internal' -class AttrInternalTest < Test::Unit::TestCase +class AttrInternalTest < ActiveSupport::TestCase def setup @target = Class.new @instance = @target.new diff --git a/activesupport/test/core_ext/module/attribute_accessor_test.rb b/activesupport/test/core_ext/module/attribute_accessor_test.rb index 29889b51e0..6a2ad2f241 100644 --- a/activesupport/test/core_ext/module/attribute_accessor_test.rb +++ b/activesupport/test/core_ext/module/attribute_accessor_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/module/attribute_accessors' -class ModuleAttributeAccessorTest < Test::Unit::TestCase +class ModuleAttributeAccessorTest < ActiveSupport::TestCase def setup m = @module = Module.new do mattr_accessor :foo diff --git a/activesupport/test/core_ext/module/attribute_aliasing_test.rb b/activesupport/test/core_ext/module/attribute_aliasing_test.rb index 065c3531e0..29c3053b47 100644 --- a/activesupport/test/core_ext/module/attribute_aliasing_test.rb +++ b/activesupport/test/core_ext/module/attribute_aliasing_test.rb @@ -24,7 +24,7 @@ module AttributeAliasing end end -class AttributeAliasingTest < Test::Unit::TestCase +class AttributeAliasingTest < ActiveSupport::TestCase def test_attribute_alias e = AttributeAliasing::Email.new diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index f11bf3dc69..950ef82a3c 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -68,7 +68,7 @@ class Name end end -class ModuleTest < Test::Unit::TestCase +class ModuleTest < ActiveSupport::TestCase def setup @david = Someone.new("David", Somewhere.new("Paulina", "Chicago")) end @@ -245,7 +245,7 @@ module BarMethods end end -class MethodAliasingTest < Test::Unit::TestCase +class MethodAliasingTest < ActiveSupport::TestCase def setup Object.const_set :FooClassWithBarMethod, Class.new { def bar() 'bar' end } @instance = FooClassWithBarMethod.new diff --git a/activesupport/test/core_ext/name_error_test.rb b/activesupport/test/core_ext/name_error_test.rb index 6352484d04..03ce09f22a 100644 --- a/activesupport/test/core_ext/name_error_test.rb +++ b/activesupport/test/core_ext/name_error_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/name_error' -class NameErrorTest < Test::Unit::TestCase +class NameErrorTest < ActiveSupport::TestCase def test_name_error_should_set_missing_name SomeNameThatNobodyWillUse____Really ? 1 : 0 flunk "?!?!" diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb index 3a2452b4b0..1cb1e25d4c 100644 --- a/activesupport/test/core_ext/numeric_ext_test.rb +++ b/activesupport/test/core_ext/numeric_ext_test.rb @@ -3,7 +3,7 @@ require 'active_support/time' require 'active_support/core_ext/numeric' require 'active_support/core_ext/integer' -class NumericExtTimeAndDateTimeTest < Test::Unit::TestCase +class NumericExtTimeAndDateTimeTest < ActiveSupport::TestCase def setup @now = Time.local(2005,2,10,15,30,45) @dtnow = DateTime.civil(2005,2,10,15,30,45) @@ -128,7 +128,7 @@ class NumericExtTimeAndDateTimeTest < Test::Unit::TestCase end end -class NumericExtDateTest < Test::Unit::TestCase +class NumericExtDateTest < ActiveSupport::TestCase def setup @today = Date.today end @@ -151,7 +151,7 @@ class NumericExtDateTest < Test::Unit::TestCase end end -class NumericExtSizeTest < Test::Unit::TestCase +class NumericExtSizeTest < ActiveSupport::TestCase def test_unit_in_terms_of_another relationships = { 1024.bytes => 1.kilobyte, diff --git a/activesupport/test/core_ext/object/inclusion_test.rb b/activesupport/test/core_ext/object/inclusion_test.rb index 568ebe9aab..22888333f5 100644 --- a/activesupport/test/core_ext/object/inclusion_test.rb +++ b/activesupport/test/core_ext/object/inclusion_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/object/inclusion' -class InTest < Test::Unit::TestCase +class InTest < ActiveSupport::TestCase def test_in_multiple_args assert :b.in?(:a,:b) assert !:c.in?(:a,:b) diff --git a/activesupport/test/core_ext/object/to_param_test.rb b/activesupport/test/core_ext/object/to_param_test.rb index c3efefddb5..bd7c6c422a 100644 --- a/activesupport/test/core_ext/object/to_param_test.rb +++ b/activesupport/test/core_ext/object/to_param_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/object/to_param' -class ToParamTest < Test::Unit::TestCase +class ToParamTest < ActiveSupport::TestCase def test_object foo = Object.new def foo.to_s; 'foo' end diff --git a/activesupport/test/core_ext/object/to_query_test.rb b/activesupport/test/core_ext/object/to_query_test.rb index c146f6cc9b..6a26e1fa4f 100644 --- a/activesupport/test/core_ext/object/to_query_test.rb +++ b/activesupport/test/core_ext/object/to_query_test.rb @@ -3,7 +3,7 @@ require 'active_support/ordered_hash' require 'active_support/core_ext/object/to_query' require 'active_support/core_ext/string/output_safety.rb' -class ToQueryTest < Test::Unit::TestCase +class ToQueryTest < ActiveSupport::TestCase def test_simple_conversion assert_query_equal 'a=10', :a => 10 end diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb index 782a01213d..b027fccab3 100644 --- a/activesupport/test/core_ext/object_and_class_ext_test.rb +++ b/activesupport/test/core_ext/object_and_class_ext_test.rb @@ -59,7 +59,7 @@ class ObjectTests < ActiveSupport::TestCase end end -class ObjectInstanceVariableTest < Test::Unit::TestCase +class ObjectInstanceVariableTest < ActiveSupport::TestCase def setup @source, @dest = Object.new, Object.new @source.instance_variable_set(:@bar, 'bar') @@ -91,7 +91,7 @@ class ObjectInstanceVariableTest < Test::Unit::TestCase end end -class ObjectTryTest < Test::Unit::TestCase +class ObjectTryTest < ActiveSupport::TestCase def setup @string = "Hello" end diff --git a/activesupport/test/core_ext/proc_test.rb b/activesupport/test/core_ext/proc_test.rb index dc7b2c957d..690bfd3bf8 100644 --- a/activesupport/test/core_ext/proc_test.rb +++ b/activesupport/test/core_ext/proc_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/proc' -class ProcTests < Test::Unit::TestCase +class ProcTests < ActiveSupport::TestCase def test_bind_returns_method_with_changed_self block = Proc.new { self } assert_equal self, block.call diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index e50b6c132a..8a91f6d69c 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'active_support/time' require 'active_support/core_ext/range' -class RangeTest < Test::Unit::TestCase +class RangeTest < ActiveSupport::TestCase def test_to_s_from_dates date_range = Date.new(2005, 12, 10)..Date.new(2005, 12, 12) assert_equal "BETWEEN '2005-12-10' AND '2005-12-12'", date_range.to_s(:db) diff --git a/activesupport/test/core_ext/regexp_ext_test.rb b/activesupport/test/core_ext/regexp_ext_test.rb index 68b089d5b4..c2398d31bd 100644 --- a/activesupport/test/core_ext/regexp_ext_test.rb +++ b/activesupport/test/core_ext/regexp_ext_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/regexp' -class RegexpExtAccessTests < Test::Unit::TestCase +class RegexpExtAccessTests < ActiveSupport::TestCase def test_multiline assert_equal true, //m.multiline? assert_equal false, //.multiline? diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 2e44cbe247..6c2828b74e 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -17,7 +17,7 @@ module Ace end end -class StringInflectionsTest < Test::Unit::TestCase +class StringInflectionsTest < ActiveSupport::TestCase include InflectorTestCases include ConstantizeTestCases @@ -297,7 +297,7 @@ class StringInflectionsTest < Test::Unit::TestCase end end -class StringBehaviourTest < Test::Unit::TestCase +class StringBehaviourTest < ActiveSupport::TestCase def test_acts_like_string assert 'Bambi'.acts_like_string? end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 6cc63851e9..cfd5a27f08 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -491,6 +491,11 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.utc(2013,10,17,20,22,19), Time.utc(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :weeks => 2, :days => 5, :hours => 5, :minutes => 7, :seconds => 9) end + def test_advance_with_nsec + t = Time.at(0, Rational(108635108, 1000)) + assert_equal t, t.advance(:months => 0) + end + def test_prev_week with_env_tz 'US/Eastern' do assert_equal Time.local(2005,2,21), Time.local(2005,3,1,15,15,10).prev_week @@ -829,7 +834,7 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end end -class TimeExtMarshalingTest < Test::Unit::TestCase +class TimeExtMarshalingTest < ActiveSupport::TestCase def test_marshaling_with_utc_instance t = Time.utc(2000) unmarshaled = Marshal.load(Marshal.dump(t)) diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index 04f5ea85a8..7cf3842a16 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'active_support/time' require 'active_support/json' -class TimeWithZoneTest < Test::Unit::TestCase +class TimeWithZoneTest < ActiveSupport::TestCase def setup @utc = Time.utc(2000, 1, 1, 0) @@ -736,7 +736,7 @@ class TimeWithZoneTest < Test::Unit::TestCase end end -class TimeWithZoneMethodsForTimeAndDateTimeTest < Test::Unit::TestCase +class TimeWithZoneMethodsForTimeAndDateTimeTest < ActiveSupport::TestCase def setup @t, @dt = Time.utc(2000), DateTime.civil(2000) end diff --git a/activesupport/test/core_ext/uri_ext_test.rb b/activesupport/test/core_ext/uri_ext_test.rb index d988837603..4a6cbb8801 100644 --- a/activesupport/test/core_ext/uri_ext_test.rb +++ b/activesupport/test/core_ext/uri_ext_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' require 'uri' require 'active_support/core_ext/uri' -class URIExtTest < Test::Unit::TestCase +class URIExtTest < ActiveSupport::TestCase def test_uri_decode_handle_multibyte str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese. diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 7039f90499..081e6a16fd 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -14,7 +14,7 @@ module ModuleWithConstant InheritedConstant = "Hello" end -class DependenciesTest < Test::Unit::TestCase +class DependenciesTest < ActiveSupport::TestCase def teardown ActiveSupport::Dependencies.clear end @@ -413,7 +413,7 @@ class DependenciesTest < Test::Unit::TestCase assert ActiveSupport::Dependencies.qualified_const_defined?("Object") assert ActiveSupport::Dependencies.qualified_const_defined?("::Object") assert ActiveSupport::Dependencies.qualified_const_defined?("::Object::Kernel") - assert ActiveSupport::Dependencies.qualified_const_defined?("::Test::Unit::TestCase") + assert ActiveSupport::Dependencies.qualified_const_defined?("::ActiveSupport::TestCase") end def test_qualified_const_defined_should_not_call_const_missing diff --git a/activesupport/test/deprecation/proxy_wrappers_test.rb b/activesupport/test/deprecation/proxy_wrappers_test.rb index aa887f274d..e4f0f0f7c2 100644 --- a/activesupport/test/deprecation/proxy_wrappers_test.rb +++ b/activesupport/test/deprecation/proxy_wrappers_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/deprecation' -class ProxyWrappersTest < Test::Unit::TestCase +class ProxyWrappersTest < ActiveSupport::TestCase Waffles = false NewWaffles = :hamburgers diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb index d77a62f108..e821a285d7 100644 --- a/activesupport/test/deprecation_test.rb +++ b/activesupport/test/deprecation_test.rb @@ -120,7 +120,7 @@ class DeprecationTest < ActiveSupport::TestCase ActiveSupport::Deprecation.warn 'abc' ActiveSupport::Deprecation.warn 'def' end - rescue Test::Unit::AssertionFailedError + rescue MiniTest::Assertion flunk 'assert_deprecated should match any warning in block, not just the last one' end @@ -166,22 +166,4 @@ class DeprecationTest < ActiveSupport::TestCase def test_deprecation_with_explicit_message assert_deprecated(/you now need to do something extra for this one/) { @dtc.d } end - - unless defined?(::MiniTest) - def test_assertion_failed_error_doesnt_spout_deprecation_warnings - error_class = Class.new(StandardError) do - def message - ActiveSupport::Deprecation.warn 'warning in error message' - super - end - end - - raise error_class.new('hmm') - - rescue => e - error = Test::Unit::Error.new('testing ur doodz', e) - assert_not_deprecated { error.message } - assert_nil @last_message - end - end end diff --git a/activesupport/test/descendants_tracker_with_autoloading_test.rb b/activesupport/test/descendants_tracker_with_autoloading_test.rb index ae18a56f44..9180f1f977 100644 --- a/activesupport/test/descendants_tracker_with_autoloading_test.rb +++ b/activesupport/test/descendants_tracker_with_autoloading_test.rb @@ -1,10 +1,9 @@ require 'abstract_unit' -require 'test/unit' require 'active_support/descendants_tracker' require 'active_support/dependencies' require 'descendants_tracker_test_cases' -class DescendantsTrackerWithAutoloadingTest < Test::Unit::TestCase +class DescendantsTrackerWithAutoloadingTest < ActiveSupport::TestCase include DescendantsTrackerTestCases def test_clear_with_autoloaded_parent_children_and_granchildren @@ -32,4 +31,4 @@ class DescendantsTrackerWithAutoloadingTest < Test::Unit::TestCase assert_equal [], Child2.descendants end end -end
\ No newline at end of file +end diff --git a/activesupport/test/descendants_tracker_without_autoloading_test.rb b/activesupport/test/descendants_tracker_without_autoloading_test.rb index 1f0c32dc3f..74669aaca1 100644 --- a/activesupport/test/descendants_tracker_without_autoloading_test.rb +++ b/activesupport/test/descendants_tracker_without_autoloading_test.rb @@ -1,8 +1,7 @@ require 'abstract_unit' -require 'test/unit' require 'active_support/descendants_tracker' require 'descendants_tracker_test_cases' -class DescendantsTrackerWithoutAutoloadingTest < Test::Unit::TestCase +class DescendantsTrackerWithoutAutoloadingTest < ActiveSupport::TestCase include DescendantsTrackerTestCases -end
\ No newline at end of file +end diff --git a/activesupport/test/file_update_checker_test.rb b/activesupport/test/file_update_checker_test.rb index dd19b58aa2..dd2483287b 100644 --- a/activesupport/test/file_update_checker_test.rb +++ b/activesupport/test/file_update_checker_test.rb @@ -1,10 +1,9 @@ require 'abstract_unit' -require 'test/unit' require 'fileutils' MTIME_FIXTURES_PATH = File.expand_path("../fixtures", __FILE__) -class FileUpdateCheckerWithEnumerableTest < Test::Unit::TestCase +class FileUpdateCheckerWithEnumerableTest < ActiveSupport::TestCase FILES = %w(1.txt 2.txt 3.txt) def setup @@ -80,4 +79,4 @@ class FileUpdateCheckerWithEnumerableTest < Test::Unit::TestCase assert !checker.execute_if_updated assert_equal 0, i end -end
\ No newline at end of file +end diff --git a/activesupport/test/gzip_test.rb b/activesupport/test/gzip_test.rb index 626981dc9d..75a0505899 100644 --- a/activesupport/test/gzip_test.rb +++ b/activesupport/test/gzip_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/object/blank' -class GzipTest < Test::Unit::TestCase +class GzipTest < ActiveSupport::TestCase def test_compress_should_decompress_to_the_same_value assert_equal "Hello World", ActiveSupport::Gzip.decompress(ActiveSupport::Gzip.compress("Hello World")) end diff --git a/activesupport/test/i18n_test.rb b/activesupport/test/i18n_test.rb index 34825c9b8f..4f2027f4eb 100644 --- a/activesupport/test/i18n_test.rb +++ b/activesupport/test/i18n_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'active_support/time' require 'active_support/core_ext/array/conversions' -class I18nTest < Test::Unit::TestCase +class I18nTest < ActiveSupport::TestCase def setup @date = Date.parse("2008-7-2") @time = Time.utc(2008, 7, 2, 16, 47, 1) diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index 6b7e839e43..3311d58254 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -4,7 +4,7 @@ require 'active_support/inflector' require 'inflector_test_cases' require 'constantize_test_cases' -class InflectorTest < Test::Unit::TestCase +class InflectorTest < ActiveSupport::TestCase include InflectorTestCases include ConstantizeTestCases diff --git a/activesupport/test/isolation_test.rb b/activesupport/test/isolation_test.rb deleted file mode 100644 index 2c2986ea28..0000000000 --- a/activesupport/test/isolation_test.rb +++ /dev/null @@ -1,182 +0,0 @@ -require 'abstract_unit' -require 'rbconfig' - -if defined?(MiniTest) || defined?(Test::Unit::TestResultFailureSupport) - $stderr.puts "Isolation tests can test test-unit 1 only" - -elsif 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 - - def setup - @instance = "HELLO" - end - - def teardown - raise if @boom - end - - test "runs the test" do - assert true - end - - test "captures errors" do - raise - end - - test "captures failures" do - assert false - end - - test "first runs in isolation" do - assert_nil $x - $x = 1 - end - - test "second runs in isolation" do - assert_nil $x - $x = 2 - end - - test "runs with slow tests" do - sleep 0.3 - assert true - sleep 0.2 - end - - test "runs setup" do - assert "HELLO", @instance - end - - test "runs teardown" do - @boom = true - end - - test "resets requires one" do - assert !defined?(Custom) - assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/custom/).size - require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "custom")) - end - - test "resets requires two" do - assert !defined?(Custom) - assert_equal 0, $LOADED_FEATURES.grep(/fixtures\/custom/).size - require File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "custom")) - end - 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 - defined?(::MiniTest) ? parse_minitest : parse_testunit - end - - 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 - - # 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 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') - - @results[$1] = val - 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} failed" - end - - def assert_passing(name) - assert_equal :success, @results[name.to_s], "Test #{name} passed" - end - - def assert_erroring(name) - assert_equal :error, @results[name.to_s], "Test #{name} errored" - 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 diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index bebad18e99..a2e61d88d5 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' require 'active_support/core_ext/string/inflections' require 'active_support/json' -class TestJSONEncoding < Test::Unit::TestCase +class TestJSONEncoding < ActiveSupport::TestCase class Foo def initialize(a, b) @a, @b = a, b diff --git a/activesupport/test/load_paths_test.rb b/activesupport/test/load_paths_test.rb index a2d8da726a..979e25bdf3 100644 --- a/activesupport/test/load_paths_test.rb +++ b/activesupport/test/load_paths_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class LoadPathsTest < Test::Unit::TestCase +class LoadPathsTest < ActiveSupport::TestCase def test_uniq_load_paths load_paths_count = $LOAD_PATH.inject({}) { |paths, path| expanded_path = File.expand_path(path) diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 20e56e2c81..63e7a35c01 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -7,9 +7,10 @@ class String def __method_for_multibyte_testing_with_integer_result; 1; end def __method_for_multibyte_testing; 'result'; end def __method_for_multibyte_testing!; 'result'; end + def __method_for_multibyte_testing_that_returns_nil!; end end -class MultibyteCharsTest < Test::Unit::TestCase +class MultibyteCharsTest < ActiveSupport::TestCase include MultibyteTestHelpers def setup @@ -36,11 +37,15 @@ class MultibyteCharsTest < Test::Unit::TestCase assert_not_equal @chars.object_id, @chars.__method_for_multibyte_testing.object_id end - def test_forwarded_bang_method_calls_should_return_the_original_chars_instance + def test_forwarded_bang_method_calls_should_return_the_original_chars_instance_when_result_is_not_nil assert_kind_of @proxy_class, @chars.__method_for_multibyte_testing! assert_equal @chars.object_id, @chars.__method_for_multibyte_testing!.object_id end + def test_forwarded_bang_method_calls_should_return_nil_when_result_is_nil + assert_nil @chars.__method_for_multibyte_testing_that_returns_nil! + end + def test_methods_are_forwarded_to_wrapped_string_for_byte_strings assert_equal BYTE_STRING.class, BYTE_STRING.mb_chars.class end @@ -67,17 +72,6 @@ class MultibyteCharsTest < Test::Unit::TestCase assert !@proxy_class.consumes?(BYTE_STRING) end - def test_unpack_utf8_strings - assert_equal 4, ActiveSupport::Multibyte::Unicode.u_unpack(UNICODE_STRING).length - assert_equal 5, ActiveSupport::Multibyte::Unicode.u_unpack(ASCII_STRING).length - end - - def test_unpack_raises_encoding_error_on_broken_strings - assert_raise(ActiveSupport::Multibyte::EncodingError) do - ActiveSupport::Multibyte::Unicode.u_unpack(BYTE_STRING) - end - end - def test_concatenation_should_return_a_proxy_class_instance assert_equal ActiveSupport::Multibyte.proxy_class, ('a'.mb_chars + 'b').class assert_equal ActiveSupport::Multibyte.proxy_class, ('a'.mb_chars << 'b').class @@ -96,7 +90,7 @@ class MultibyteCharsTest < Test::Unit::TestCase end -class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase +class MultibyteCharsUTF8BehaviourTest < ActiveSupport::TestCase include MultibyteTestHelpers def setup @@ -112,15 +106,11 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase end end - def test_indexed_insert_accepts_fixnums - @chars[2] = 32 - assert_equal 'こに わ', @chars - end - - %w{capitalize downcase lstrip reverse rstrip strip upcase}.each do |method| + %w{capitalize downcase lstrip reverse rstrip swapcase upcase}.each do |method| class_eval(<<-EOTESTS) - def test_#{method}_bang_should_return_self - assert_equal @chars.object_id, @chars.send("#{method}!").object_id + def test_#{method}_bang_should_return_self_when_modifying_wrapped_string + chars = ' él piDió Un bUen café ' + assert_equal chars.object_id, chars.send("#{method}!").object_id end def test_#{method}_bang_should_change_wrapped_string @@ -171,6 +161,7 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert chars('').decompose.kind_of?(ActiveSupport::Multibyte.proxy_class) assert chars('').compose.kind_of?(ActiveSupport::Multibyte.proxy_class) assert chars('').tidy_bytes.kind_of?(ActiveSupport::Multibyte.proxy_class) + assert chars('').swapcase.kind_of?(ActiveSupport::Multibyte.proxy_class) end def test_should_be_equal_to_the_wrapped_string @@ -419,7 +410,7 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase def test_slice_bang_removes_the_slice_from_the_receiver chars = 'úüù'.mb_chars chars.slice!(0,2) - assert_equal 'úü', chars + assert_equal 'ù', chars end def test_slice_should_throw_exceptions_on_invalid_arguments @@ -442,6 +433,11 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert_equal 'abc', 'aBc'.mb_chars.downcase end + def test_swapcase_should_swap_ascii_characters + assert_equal '', ''.mb_chars.swapcase + assert_equal 'AbC', 'aBc'.mb_chars.swapcase + end + def test_capitalize_should_work_on_ascii_characters assert_equal '', ''.mb_chars.capitalize assert_equal 'Abc', 'abc'.mb_chars.capitalize @@ -467,7 +463,7 @@ end # The default Multibyte Chars proxy has more features than the normal string implementation. Tests # for the implementation of these features should run on all Ruby versions and shouldn't be tested # through the proxy methods. -class MultibyteCharsExtrasTest < Test::Unit::TestCase +class MultibyteCharsExtrasTest < ActiveSupport::TestCase include MultibyteTestHelpers def test_upcase_should_be_unicode_aware @@ -476,10 +472,15 @@ class MultibyteCharsExtrasTest < Test::Unit::TestCase end def test_downcase_should_be_unicode_aware - assert_equal "абвгд\0f", chars("аБвгд\0f").downcase + assert_equal "абвгд\0f", chars("аБвгд\0F").downcase assert_equal 'こにちわ', chars('こにちわ').downcase end + def test_swapcase_should_be_unicode_aware + assert_equal "аaéÜ\0f", chars("АAÉü\0F").swapcase + assert_equal 'こにちわ', chars('こにちわ').swapcase + end + def test_capitalize_should_be_unicode_aware { 'аБвг аБвг' => 'Абвг абвг', 'аБвг АБВГ' => 'Абвг абвг', @@ -506,7 +507,7 @@ class MultibyteCharsExtrasTest < Test::Unit::TestCase def test_limit_should_work_on_a_multibyte_string example = chars(UNICODE_STRING) - bytesize = UNICODE_STRING.respond_to?(:bytesize) ? UNICODE_STRING.bytesize : UNICODE_STRING.size + bytesize = UNICODE_STRING.bytesize assert_equal UNICODE_STRING, example.limit(bytesize) assert_equal '', example.limit(0) @@ -605,7 +606,7 @@ class MultibyteCharsExtrasTest < Test::Unit::TestCase else str = input end - assert_equal expected_length, chars(str).g_length + assert_equal expected_length, chars(str).grapheme_length end end diff --git a/activesupport/test/multibyte_conformance.rb b/activesupport/test/multibyte_conformance.rb index b3b477bb75..2baf724da4 100644 --- a/activesupport/test/multibyte_conformance.rb +++ b/activesupport/test/multibyte_conformance.rb @@ -25,7 +25,7 @@ class Downloader end end -class MultibyteConformanceTest < Test::Unit::TestCase +class MultibyteConformanceTest < ActiveSupport::TestCase include MultibyteTestHelpers UNIDATA_URL = "http://www.unicode.org/Public/#{ActiveSupport::Multibyte::Unicode::UNICODE_VERSION}/ucd" diff --git a/activesupport/test/multibyte_unicode_database_test.rb b/activesupport/test/multibyte_unicode_database_test.rb index 26a41579c2..bec65daf50 100644 --- a/activesupport/test/multibyte_unicode_database_test.rb +++ b/activesupport/test/multibyte_unicode_database_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' -class MultibyteUnicodeDatabaseTest < Test::Unit::TestCase +class MultibyteUnicodeDatabaseTest < ActiveSupport::TestCase include ActiveSupport::Multibyte::Unicode diff --git a/activesupport/test/multibyte_utils_test.rb b/activesupport/test/multibyte_utils_test.rb deleted file mode 100644 index f807492be0..0000000000 --- a/activesupport/test/multibyte_utils_test.rb +++ /dev/null @@ -1,93 +0,0 @@ -# encoding: utf-8 - -require 'abstract_unit' -require 'multibyte_test_helpers' - -class MultibyteUtilsTest < ActiveSupport::TestCase - include MultibyteTestHelpers - - test "valid_character returns an expression for the current encoding" do - with_encoding('None') do - assert_nil ActiveSupport::Multibyte.valid_character - end - with_encoding('UTF8') do - assert_equal ActiveSupport::Multibyte::VALID_CHARACTER['UTF-8'], ActiveSupport::Multibyte.valid_character - end - with_encoding('SJIS') do - assert_equal ActiveSupport::Multibyte::VALID_CHARACTER['Shift_JIS'], ActiveSupport::Multibyte.valid_character - end - end - - test "verify verifies ASCII strings are properly encoded" do - with_encoding('None') do - examples.each do |example| - assert ActiveSupport::Multibyte.verify(example) - end - end - end - - test "verify verifies UTF-8 strings are properly encoded" do - with_encoding('UTF8') do - assert ActiveSupport::Multibyte.verify(example('valid UTF-8')) - assert !ActiveSupport::Multibyte.verify(example('invalid UTF-8')) - end - end - - test "verify verifies Shift-JIS strings are properly encoded" do - with_encoding('SJIS') do - assert ActiveSupport::Multibyte.verify(example('valid Shift-JIS')) - assert !ActiveSupport::Multibyte.verify(example('invalid Shift-JIS')) - end - end - - test "verify! raises an exception when it finds an invalid character" do - with_encoding('UTF8') do - assert_raises(ActiveSupport::Multibyte::EncodingError) do - ActiveSupport::Multibyte.verify!(example('invalid UTF-8')) - end - end - end - - test "verify! doesn't raise an exception when the encoding is valid" do - with_encoding('UTF8') do - assert_nothing_raised do - ActiveSupport::Multibyte.verify!(example('valid UTF-8')) - end - end - end - - test "clean is a no-op" do - with_encoding('UTF8') do - assert_equal example('invalid Shift-JIS'), ActiveSupport::Multibyte.clean(example('invalid Shift-JIS')) - end - end - - private - - STRINGS = { - 'valid ASCII' => [65, 83, 67, 73, 73].pack('C*'), - 'invalid ASCII' => [128].pack('C*'), - 'valid UTF-8' => [227, 129, 147, 227, 129, 171, 227, 129, 161, 227, 130, 143].pack('C*'), - 'invalid UTF-8' => [184, 158, 8, 136, 165].pack('C*'), - 'valid Shift-JIS' => [131, 122, 129, 91, 131, 128].pack('C*'), - 'invalid Shift-JIS' => [184, 158, 8, 0, 255, 136, 165].pack('C*') - } - - def example(key) - STRINGS[key].force_encoding(Encoding.default_external) - end - - def examples - STRINGS.values.map { |s| s.force_encoding(Encoding.default_external) } - end - - KCODE_TO_ENCODING = Hash.new(Encoding::BINARY). - update('UTF8' => Encoding::UTF_8, 'SJIS' => Encoding::Shift_JIS) - - def with_encoding(enc) - before = Encoding.default_external - silence_warnings { Encoding.default_external = KCODE_TO_ENCODING[enc] } - yield - silence_warnings { Encoding.default_external = before } - end -end diff --git a/activesupport/test/option_merger_test.rb b/activesupport/test/option_merger_test.rb index 2bdd3034e5..9d139b61b8 100644 --- a/activesupport/test/option_merger_test.rb +++ b/activesupport/test/option_merger_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/core_ext/object/with_options' -class OptionMergerTest < Test::Unit::TestCase +class OptionMergerTest < ActiveSupport::TestCase def setup @options = {:hello => 'world'} end diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index 8119b36491..e8defd396b 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -3,7 +3,7 @@ require 'active_support/json' require 'active_support/core_ext/object/to_json' require 'active_support/core_ext/hash/indifferent_access' -class OrderedHashTest < Test::Unit::TestCase +class OrderedHashTest < ActiveSupport::TestCase def setup @keys = %w( blue green red pink orange ) @values = %w( 000099 009900 aa0000 cc0066 cc6633 ) @@ -291,21 +291,16 @@ class OrderedHashTest < Test::Unit::TestCase assert_equal @ordered_hash.values, @deserialized_ordered_hash.values end - begin - require 'psych' + def test_psych_serialize + @deserialized_ordered_hash = Psych.load(Psych.dump(@ordered_hash)) - def test_psych_serialize - @deserialized_ordered_hash = Psych.load(Psych.dump(@ordered_hash)) - - values = @deserialized_ordered_hash.map { |_, value| value } - assert_equal @values, values - end + values = @deserialized_ordered_hash.map { |_, value| value } + assert_equal @values, values + end - def test_psych_serialize_tag - yaml = Psych.dump(@ordered_hash) - assert_match '!omap', yaml - end - rescue LoadError + def test_psych_serialize_tag + yaml = Psych.dump(@ordered_hash) + assert_match '!omap', yaml end def test_has_yaml_tag diff --git a/activesupport/test/ordered_options_test.rb b/activesupport/test/ordered_options_test.rb index b215b60df3..0eee991e20 100644 --- a/activesupport/test/ordered_options_test.rb +++ b/activesupport/test/ordered_options_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class OrderedOptionsTest < Test::Unit::TestCase +class OrderedOptionsTest < ActiveSupport::TestCase def test_usage a = ActiveSupport::OrderedOptions.new diff --git a/activesupport/test/rescuable_test.rb b/activesupport/test/rescuable_test.rb index c28ffa50f2..3f8d09c18e 100644 --- a/activesupport/test/rescuable_test.rb +++ b/activesupport/test/rescuable_test.rb @@ -70,7 +70,7 @@ class CoolStargate < Stargate end -class RescuableTest < Test::Unit::TestCase +class RescuableTest < ActiveSupport::TestCase def setup @stargate = Stargate.new @cool_stargate = CoolStargate.new diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 8f77999d25..2fde07995b 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -1,9 +1,4 @@ require 'abstract_unit' -begin - require 'psych' -rescue LoadError -end - require 'active_support/core_ext/string/inflections' require 'yaml' @@ -96,13 +91,20 @@ class SafeBufferTest < ActiveSupport::TestCase assert !@buffer.dup.html_safe? end + test "Should return safe buffer when added with another safe buffer" do + clean = "<script>".html_safe + result_buffer = @buffer + clean + assert result_buffer.html_safe? + assert_equal "<script>", result_buffer + end + test "Should raise an error when safe_concat is called on dirty buffers" do @buffer.gsub!('', '<>') assert_raise ActiveSupport::SafeBuffer::SafeConcatError do @buffer.safe_concat "BUSTED" end end - + test "should not fail if the returned object is not a string" do assert_kind_of NilClass, @buffer.slice("chipchop") end diff --git a/activesupport/test/string_inquirer_test.rb b/activesupport/test/string_inquirer_test.rb index 7f11f667df..bb15916e9e 100644 --- a/activesupport/test/string_inquirer_test.rb +++ b/activesupport/test/string_inquirer_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -class StringInquirerTest < Test::Unit::TestCase +class StringInquirerTest < ActiveSupport::TestCase def test_match assert ActiveSupport::StringInquirer.new("production").production? end diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index 756d21b3e4..e5b5547478 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -18,44 +18,50 @@ module ActiveSupport end end - if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions - def test_callback_with_exception - tc = Class.new(TestCase) do - setup :bad_callback - def bad_callback; raise 'oh noes' end - def test_true; assert true end + def test_callback_with_exception + tc = Class.new(TestCase) do + def self.name + nil end - test_name = 'test_true' - fr = FakeRunner.new + setup :bad_callback + def bad_callback; raise 'oh noes' end + def test_true; assert true end + end - test = tc.new test_name - test.run fr - klass, name, exception = *fr.puked.first + test_name = 'test_true' + fr = FakeRunner.new - assert_equal tc, klass - assert_equal test_name, name - assert_equal 'oh noes', exception.message - end + test = tc.new test_name + test.run fr + klass, name, exception = *fr.puked.first + + assert_equal tc, klass + assert_equal test_name, name + assert_equal 'oh noes', exception.message + end - def test_teardown_callback_with_exception - tc = Class.new(TestCase) do - teardown :bad_callback - def bad_callback; raise 'oh noes' end - def test_true; assert true end + def test_teardown_callback_with_exception + tc = Class.new(TestCase) do + def self.name + nil end - test_name = 'test_true' - fr = FakeRunner.new + teardown :bad_callback + def bad_callback; raise 'oh noes' end + def test_true; assert true end + end - test = tc.new test_name - test.run fr - klass, name, exception = *fr.puked.first + test_name = 'test_true' + fr = FakeRunner.new - assert_equal tc, klass - assert_equal test_name, name - assert_equal 'oh noes', exception.message - end + test = tc.new test_name + test.run fr + klass, name, exception = *fr.puked.first + + assert_equal tc, klass + assert_equal test_name, name + assert_equal 'oh noes', exception.message end end end diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb index f880052786..11506554a9 100644 --- a/activesupport/test/test_test.rb +++ b/activesupport/test/test_test.rb @@ -61,24 +61,19 @@ class AssertDifferenceTest < ActiveSupport::TestCase end def test_array_of_expressions_identify_failure - assert_difference ['@object.num', '1 + 1'] do - @object.increment + assert_raises(MiniTest::Assertion) do + assert_difference ['@object.num', '1 + 1'] do + @object.increment + end end - fail 'should not get to here' - rescue Exception => e - assert_match(/didn't change by/, e.message) - assert_match(/expected but was/, e.message) end def test_array_of_expressions_identify_failure_when_message_provided - assert_difference ['@object.num', '1 + 1'], 1, 'something went wrong' do - @object.increment + assert_raises(MiniTest::Assertion) do + assert_difference ['@object.num', '1 + 1'], 1, 'something went wrong' do + @object.increment + end end - fail 'should not get to here' - rescue Exception => e - assert_match(/something went wrong/, e.message) - assert_match(/didn't change by/, e.message) - assert_match(/expected but was/, e.message) end else def default_test; end diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 3575175517..e26256f9c6 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/time' -class TimeZoneTest < Test::Unit::TestCase +class TimeZoneTest < ActiveSupport::TestCase def test_utc_to_local zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] assert_equal Time.utc(1999, 12, 31, 19), zone.utc_to_local(Time.utc(2000, 1)) # standard offset -0500 diff --git a/activesupport/test/transliterate_test.rb b/activesupport/test/transliterate_test.rb index 08e11d4f38..b7076e9e58 100644 --- a/activesupport/test/transliterate_test.rb +++ b/activesupport/test/transliterate_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' require 'active_support/inflector/transliterate' require 'active_support/core_ext/object/inclusion' -class TransliterateTest < Test::Unit::TestCase +class TransliterateTest < ActiveSupport::TestCase def test_transliterate_should_not_change_ascii_chars (0..127).each do |byte| diff --git a/activesupport/test/ts_isolated.rb b/activesupport/test/ts_isolated.rb index 58710e0165..1d96c20bb6 100644 --- a/activesupport/test/ts_isolated.rb +++ b/activesupport/test/ts_isolated.rb @@ -1,10 +1,11 @@ $:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') -require 'test/unit' +require 'minitest/autorun' +require 'active_support/test_case' require 'rbconfig' require 'active_support/core_ext/kernel/reporting' -class TestIsolated < Test::Unit::TestCase +class TestIsolated < ActiveSupport::TestCase ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) Dir["#{File.dirname(__FILE__)}/**/*_test.rb"].each do |file| diff --git a/activesupport/test/xml_mini/jdom_engine_test.rb b/activesupport/test/xml_mini/jdom_engine_test.rb index 7f809e7898..f77d78d42c 100644 --- a/activesupport/test/xml_mini/jdom_engine_test.rb +++ b/activesupport/test/xml_mini/jdom_engine_test.rb @@ -3,7 +3,7 @@ if RUBY_PLATFORM =~ /java/ require 'active_support/xml_mini' require 'active_support/core_ext/hash/conversions' - class JDOMEngineTest < Test::Unit::TestCase + class JDOMEngineTest < ActiveSupport::TestCase include ActiveSupport def setup diff --git a/activesupport/test/xml_mini/libxml_engine_test.rb b/activesupport/test/xml_mini/libxml_engine_test.rb index 83d03bccc6..5debb2fd59 100644 --- a/activesupport/test/xml_mini/libxml_engine_test.rb +++ b/activesupport/test/xml_mini/libxml_engine_test.rb @@ -8,7 +8,7 @@ rescue LoadError # Skip libxml tests else -class LibxmlEngineTest < Test::Unit::TestCase +class LibxmlEngineTest < ActiveSupport::TestCase include ActiveSupport def setup diff --git a/activesupport/test/xml_mini/libxmlsax_engine_test.rb b/activesupport/test/xml_mini/libxmlsax_engine_test.rb index 864810099e..94250d48ec 100644 --- a/activesupport/test/xml_mini/libxmlsax_engine_test.rb +++ b/activesupport/test/xml_mini/libxmlsax_engine_test.rb @@ -8,7 +8,7 @@ rescue LoadError # Skip libxml tests else -class LibXMLSAXEngineTest < Test::Unit::TestCase +class LibXMLSAXEngineTest < ActiveSupport::TestCase include ActiveSupport def setup diff --git a/activesupport/test/xml_mini/nokogiri_engine_test.rb b/activesupport/test/xml_mini/nokogiri_engine_test.rb index db0d7c5b02..3f37c7cbb6 100644 --- a/activesupport/test/xml_mini/nokogiri_engine_test.rb +++ b/activesupport/test/xml_mini/nokogiri_engine_test.rb @@ -8,7 +8,7 @@ rescue LoadError # Skip nokogiri tests else -class NokogiriEngineTest < Test::Unit::TestCase +class NokogiriEngineTest < ActiveSupport::TestCase include ActiveSupport def setup diff --git a/activesupport/test/xml_mini/nokogirisax_engine_test.rb b/activesupport/test/xml_mini/nokogirisax_engine_test.rb index 1149d0fecc..d6ae7f12ae 100644 --- a/activesupport/test/xml_mini/nokogirisax_engine_test.rb +++ b/activesupport/test/xml_mini/nokogirisax_engine_test.rb @@ -8,7 +8,7 @@ rescue LoadError # Skip nokogiri tests else -class NokogiriSAXEngineTest < Test::Unit::TestCase +class NokogiriSAXEngineTest < ActiveSupport::TestCase include ActiveSupport def setup diff --git a/activesupport/test/xml_mini/rexml_engine_test.rb b/activesupport/test/xml_mini/rexml_engine_test.rb index 57bb35254a..c4770405f2 100644 --- a/activesupport/test/xml_mini/rexml_engine_test.rb +++ b/activesupport/test/xml_mini/rexml_engine_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'active_support/xml_mini' -class REXMLEngineTest < Test::Unit::TestCase +class REXMLEngineTest < ActiveSupport::TestCase include ActiveSupport def test_default_is_rexml diff --git a/activesupport/test/xml_mini_test.rb b/activesupport/test/xml_mini_test.rb index dde17ea403..504fc96493 100644 --- a/activesupport/test/xml_mini_test.rb +++ b/activesupport/test/xml_mini_test.rb @@ -3,7 +3,7 @@ require 'active_support/xml_mini' require 'active_support/builder' module XmlMiniTest - class RenameKeyTest < Test::Unit::TestCase + class RenameKeyTest < ActiveSupport::TestCase def test_rename_key_dasherizes_by_default assert_equal "my-key", ActiveSupport::XmlMini.rename_key("my_key") end diff --git a/railties/guides/source/3_2_release_notes.textile b/railties/guides/source/3_2_release_notes.textile index 927abc7944..0e58f2012e 100644 --- a/railties/guides/source/3_2_release_notes.textile +++ b/railties/guides/source/3_2_release_notes.textile @@ -7,19 +7,45 @@ Highlights in Rails 3.2: * Automatic Query Explains * Tagged Logging -These release notes cover the major changes, but don't include every little bug fix and change. If you want to see everything, check out the "list of commits":https://github.com/rails/rails/commits/3-2-stable in the main Rails repository on GitHub. +These release notes cover the major changes, but do not include each bug-fix and changes. If you want to see everything, check out the "list of commits":https://github.com/rails/rails/commits/3-2-stable in the main Rails repository on GitHub. endprologue. h3. Upgrading to Rails 3.2 -If you're upgrading an existing application, it's a great idea to have good test coverage before going in. You should also first upgrade to Rails 3.1 in case you haven't and make sure your application still runs as expected before attempting to update to Rails 3.2. Then take heed of the following changes: +If you're upgrading an existing application, it's a great idea to have good test coverage before going in. You should also first upgrade to Rails 3.1 in case you haven't and make sure your application still runs as expected before attempting an update to Rails 3.2. Then take heed of the following changes: + +h4. What to update in your apps + +* Update your Gemfile to depend on rails = 3.2.0 +* Update your Gemfile to depend on sass-rails ~> 3.2.3 +* Update your Gemfile to depend on coffee-rails ~> 3.2.1 + +* Start moving any remaining Rails 2.3-style vendor/plugins/==*==. These have been finally deprecated and will be removed in Rails 4.0. Instead, extract your vendor/plugins to their own gems and bundle them in your Gemfile. If you think they're not worthy of being a gem, move them into lib/my_plugin/==*==. You'll also need to add an appropriate initializer in config/initializers/my_plugin.rb. + +* There are a couple of new configuration changes you'd want to add in <tt>config/environments/development.rb</tt>: + +<ruby> +# Raise exception on mass assignment protection for Active Record models +config.active_record.mass_assignment_sanitizer = :strict + +# Log the query plan for queries taking more than this (works +# with SQLite, MySQL, and PostgreSQL) +config.active_record.auto_explain_threshold_in_seconds = 0.5 +</ruby> + +The last configuration from above also needs to be added in <tt>config/environments/test.rb</tt>: + +<ruby> +# Raise exception on mass assignment protection for Active Record models +config.active_record.mass_assignment_sanitizer = :strict +</ruby> h4. Rails 3.2 requires at least Ruby 1.8.7 Rails 3.2 requires Ruby 1.8.7 or higher. Support for all of the previous Ruby versions has been dropped officially and you should upgrade as early as possible. Rails 3.2 is also compatible with Ruby 1.9.2. -TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults, so if you want to use 1.9.x, jump on 1.9.2 or 1.9.3 for smooth sailing. +TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails. Ruby Enterprise Edition has these fixed since the release of 1.8.7-2010.02. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults, so if you want to use 1.9.x, jump on to 1.9.2 or 1.9.3 for smooth sailing. h3. Creating a Rails 3.2 application diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb index ef7e733ce4..6f9a200aa9 100644 --- a/railties/lib/rails/application/routes_reloader.rb +++ b/railties/lib/rails/application/routes_reloader.rb @@ -42,7 +42,7 @@ module Rails def finalize! route_sets.each do |routes| - ActiveSupport.on_load(:action_controller) { routes.finalize! } + routes.finalize! end end diff --git a/railties/lib/rails/backtrace_cleaner.rb b/railties/lib/rails/backtrace_cleaner.rb index 36fd9aea19..cc26db849d 100644 --- a/railties/lib/rails/backtrace_cleaner.rb +++ b/railties/lib/rails/backtrace_cleaner.rb @@ -26,17 +26,4 @@ module Rails add_filter { |line| line.sub(gems_regexp, '\2 (\3) \4') } end end - - # For installing the BacktraceCleaner in the test/unit - module BacktraceFilterForTestUnit #:nodoc: - def self.included(klass) - klass.send :alias_method_chain, :filter_backtrace, :cleaning - end - - def filter_backtrace_with_cleaning(backtrace, prefix=nil) - backtrace = filter_backtrace_without_cleaning(backtrace, prefix) - backtrace = backtrace.first.split("\n") if backtrace.size == 1 - Rails.backtrace_cleaner.clean(backtrace) - end - end end diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb index d425c9db6c..6fc127efae 100644 --- a/railties/lib/rails/commands/dbconsole.rb +++ b/railties/lib/rails/commands/dbconsole.rb @@ -1,10 +1,4 @@ require 'erb' - -begin - require 'psych' -rescue LoadError -end - require 'yaml' require 'optparse' require 'rbconfig' diff --git a/railties/lib/rails/console/app.rb b/railties/lib/rails/console/app.rb index 23d57379ba..ee8bb55f38 100644 --- a/railties/lib/rails/console/app.rb +++ b/railties/lib/rails/console/app.rb @@ -3,7 +3,6 @@ require 'active_support/test_case' require 'action_controller' # work around the at_exit hook in test/unit, which kills IRB -Test::Unit.run = true if Test::Unit.respond_to?(:run=) module Rails module ConsoleMethods diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index ce62ea463d..45f55a2a0a 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -1,6 +1,5 @@ require 'open-uri' require 'rbconfig' -require 'active_support/core_ext/array/wrap' module Rails module Generators @@ -92,7 +91,7 @@ module Rails if options[:env].nil? inject_into_file 'config/application.rb', "\n #{data}", :after => sentinel, :verbose => false else - Array.wrap(options[:env]).each do |env| + Array(options[:env]).each do |env| inject_into_file "config/environments/#{env}.rb", "\n #{data}", :after => env_file_sentinel, :verbose => false end end @@ -244,7 +243,7 @@ module Rails # def route(routing_code) log :route, routing_code - sentinel = /\.routes\.draw do(?:\s*\|map\|)?\s*$/ + sentinel = /\.routes\.draw do\s*$/ in_root do inject_into_file 'config/routes.rb', "\n #{routing_code}\n", { :after => sentinel, :verbose => false } diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index cd7d51e628..0e900a34bb 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -133,6 +133,16 @@ task :default => :test end chmod "script", 0755, :verbose => false end + + def gemfile_entry + return unless inside_application? + + gemfile_in_app_path = File.join(rails_app_path, "Gemfile") + if File.exist? gemfile_in_app_path + entry = "gem '#{name}', :path => '#{relative_path}'" + append_file gemfile_in_app_path, entry + end + end end module Generators @@ -153,6 +163,10 @@ task :default => :test class_option :skip_gemspec, :type => :boolean, :default => false, :desc => "Skip gemspec file" + class_option :skip_gemfile_entry, :type => :boolean, :default => false, + :desc => "If creating plugin in application's directory " + + "skip adding entry to Gemfile" + def initialize(*args) raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank? @@ -208,6 +222,10 @@ task :default => :test create_dummy_app end + def update_gemfile + build(:gemfile_entry) unless options[:skip_gemfile_entry] + end + def finish_template build(:leftovers) end @@ -313,6 +331,19 @@ end def mute(&block) shell.mute(&block) end + + def rails_app_path + APP_PATH.sub("/config/application", "") if defined?(APP_PATH) + end + + def inside_application? + rails_app_path && app_path =~ /^#{rails_app_path}/ + end + + def relative_path + return unless inside_application? + app_path.sub(/^#{rails_app_path}\//, '') + end end end end diff --git a/railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb b/railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb index 2ca36a1e44..e82e321914 100644 --- a/railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb +++ b/railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb @@ -1,3 +1,3 @@ require 'rubygems' -require 'test/unit' +require 'minitest/autorun' require 'active_support' diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index 2286e0477a..684beb32a3 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -22,7 +22,7 @@ class SourceAnnotationExtractor # If +options+ has a flag <tt>:tag</tt> the tag is shown as in the example above. # Otherwise the string contains just line and text. def to_s(options={}) - s = "[%3d] " % line + s = "[#{line.to_s.rjust(options[:indent])}]" s << "[#{tag}] " if options[:tag] s << text end @@ -93,6 +93,7 @@ class SourceAnnotationExtractor # Prints the mapping from filenames to annotations in +results+ ordered by filename. # The +options+ hash is passed to each annotation's +to_s+. def display(results, options={}) + options[:indent] = results.map { |f, a| a.map(&:line) }.flatten.max.to_s.size results.keys.sort.each do |file| puts "#{file}:" results[file].each do |note| diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 8d0d8cacac..11e4353c87 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -2,31 +2,19 @@ # so fixtures aren't loaded into that environment abort("Abort testing: Your Rails environment is running in production mode!") if Rails.env.production? -require 'test/unit' +require 'minitest/autorun' require 'active_support/test_case' require 'action_controller/test_case' require 'action_dispatch/testing/integration' -if defined?(Test::Unit::Util::BacktraceFilter) && ENV['BACKTRACE'].nil? - require 'rails/backtrace_cleaner' - Test::Unit::Util::BacktraceFilter.module_eval { include Rails::BacktraceFilterForTestUnit } -end - -if defined?(MiniTest) - # Enable turn if it is available - begin - require 'turn' - - if MiniTest::Unit.respond_to?(:use_natural_language_case_names=) - MiniTest::Unit.use_natural_language_case_names = true - end - rescue LoadError - end +# Enable turn if it is available +begin + require 'turn' + MiniTest::Unit.use_natural_language_case_names = true +rescue LoadError end if defined?(ActiveRecord::Base) - require 'active_record/test_case' - class ActiveSupport::TestCase include ActiveRecord::TestFixtures self.fixture_path = "#{Rails.root}/test/fixtures/" diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb index 400068d94c..29ebdc6511 100644 --- a/railties/test/abstract_unit.rb +++ b/railties/test/abstract_unit.rb @@ -1,7 +1,7 @@ require File.expand_path("../../../load_paths", __FILE__) require 'stringio' -require 'test/unit' +require 'minitest/autorun' require 'fileutils' require 'active_support' diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb index 1b99af22a4..a2a7f184b8 100644 --- a/railties/test/application/asset_debugging_test.rb +++ b/railties/test/application/asset_debugging_test.rb @@ -2,7 +2,7 @@ require 'isolation/abstract_unit' require 'rack/test' module ApplicationTests - class AssetDebuggingTest < Test::Unit::TestCase + class AssetDebuggingTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation include Rack::Test::Methods diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index cc5695091b..460c921ec3 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -4,7 +4,7 @@ require 'active_support/core_ext/kernel/reporting' require 'rack/test' module ApplicationTests - class AssetsTest < Test::Unit::TestCase + class AssetsTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation include Rack::Test::Methods @@ -17,10 +17,6 @@ module ApplicationTests teardown_app end - def app - @app ||= Rails.application - end - def precompile! quietly do Dir.chdir(app_path){ `bundle exec rake assets:precompile` } @@ -427,6 +423,12 @@ module ApplicationTests assert_equal "NoPost;\n", File.read("#{app_path}/public/assets/application.js") end + test "initialization on the assets group should set assets_dir" do + require "#{app_path}/config/application" + Rails.application.initialize!(:assets) + assert_not_nil Rails.application.config.action_controller.assets_dir + end + test "enhancements to assets:precompile should only run once" do app_file "lib/tasks/enhance.rake", "Rake::Task['assets:precompile'].enhance { puts 'enhancement' }" output = precompile! diff --git a/railties/test/application/build_original_fullpath_test.rb b/railties/test/application/build_original_fullpath_test.rb index 7a679ea04e..647ffb097a 100644 --- a/railties/test/application/build_original_fullpath_test.rb +++ b/railties/test/application/build_original_fullpath_test.rb @@ -1,7 +1,7 @@ require "abstract_unit" module ApplicationTests - class BuildOriginalPathTest < Test::Unit::TestCase + class BuildOriginalPathTest < ActiveSupport::TestCase def test_include_original_PATH_info_in_ORIGINAL_FULLPATH env = { 'PATH_INFO' => '/foo/' } assert_equal "/foo/", Rails.application.send(:build_original_fullpath, env) diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 0d64a136f8..397f4da8fc 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -14,7 +14,7 @@ end class ::MyOtherMailObserver < ::MyMailObserver; end module ApplicationTests - class ConfigurationTest < Test::Unit::TestCase + class ConfigurationTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation include Rack::Test::Methods diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb index fa2652a6d3..f372afa51c 100644 --- a/railties/test/application/console_test.rb +++ b/railties/test/application/console_test.rb @@ -1,6 +1,6 @@ require 'isolation/abstract_unit' -class ConsoleTest < Test::Unit::TestCase +class ConsoleTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index 4365d00b1f..bf58bb3f74 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class GeneratorsTest < Test::Unit::TestCase + class GeneratorsTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/initializers/boot_test.rb b/railties/test/application/initializers/boot_test.rb index b1e01dc13f..04c46058cb 100644 --- a/railties/test/application/initializers/boot_test.rb +++ b/railties/test/application/initializers/boot_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class GemBooting < Test::Unit::TestCase + class GemBooting < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index a0417360a1..8812685620 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class FrameworksTest < Test::Unit::TestCase + class FrameworksTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/initializers/hooks_test.rb b/railties/test/application/initializers/hooks_test.rb index 8c7726339c..7b3e6844fd 100644 --- a/railties/test/application/initializers/hooks_test.rb +++ b/railties/test/application/initializers/hooks_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class InitializersTest < Test::Unit::TestCase + class InitializersTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb index 305ae7eb0a..abb277dc1d 100644 --- a/railties/test/application/initializers/i18n_test.rb +++ b/railties/test/application/initializers/i18n_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class I18nTest < Test::Unit::TestCase + class I18nTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb index 644b8208a9..31811e7f92 100644 --- a/railties/test/application/initializers/load_path_test.rb +++ b/railties/test/application/initializers/load_path_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class LoadPathTest < Test::Unit::TestCase + class LoadPathTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/initializers/notifications_test.rb b/railties/test/application/initializers/notifications_test.rb index b72c14eaf0..d866a63fe0 100644 --- a/railties/test/application/initializers/notifications_test.rb +++ b/railties/test/application/initializers/notifications_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class NotificationsTest < Test::Unit::TestCase + class NotificationsTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index c4c93cce22..457e81e174 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -1,6 +1,6 @@ require 'isolation/abstract_unit' -class LoadingTest < Test::Unit::TestCase +class LoadingTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/middleware/best_practices_test.rb b/railties/test/application/middleware/best_practices_test.rb index 1c88b9bf06..f6783c6ca2 100644 --- a/railties/test/application/middleware/best_practices_test.rb +++ b/railties/test/application/middleware/best_practices_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class BestPracticesTest < Test::Unit::TestCase + class BestPracticesTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb index 790c5b2d53..561b020707 100644 --- a/railties/test/application/middleware/cache_test.rb +++ b/railties/test/application/middleware/cache_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class RoutingTest < Test::Unit::TestCase + class RoutingTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/middleware/cookies_test.rb b/railties/test/application/middleware/cookies_test.rb index 13556cbed2..18af7abafc 100644 --- a/railties/test/application/middleware/cookies_test.rb +++ b/railties/test/application/middleware/cookies_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class CookiesTest < Test::Unit::TestCase + class CookiesTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def new_app diff --git a/railties/test/application/middleware/exceptions_test.rb b/railties/test/application/middleware/exceptions_test.rb index aedc4fe648..a80898092d 100644 --- a/railties/test/application/middleware/exceptions_test.rb +++ b/railties/test/application/middleware/exceptions_test.rb @@ -3,7 +3,7 @@ require 'isolation/abstract_unit' require 'rack/test' module ApplicationTests - class MiddlewareExceptionsTest < Test::Unit::TestCase + class MiddlewareExceptionsTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation include Rack::Test::Methods diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb index da291f061c..066f0c1c84 100644 --- a/railties/test/application/middleware/remote_ip_test.rb +++ b/railties/test/application/middleware/remote_ip_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class RemoteIpTest < Test::Unit::TestCase + class RemoteIpTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb index d2ad2668bb..0591386a87 100644 --- a/railties/test/application/middleware/sendfile_test.rb +++ b/railties/test/application/middleware/sendfile_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class SendfileTest < Test::Unit::TestCase + class SendfileTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 9e02ef9c66..2f1df1fa59 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -3,7 +3,7 @@ require 'stringio' require 'rack/test' module ApplicationTests - class MiddlewareTest < Test::Unit::TestCase + class MiddlewareTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb index 84f4408147..55f5a349de 100644 --- a/railties/test/application/paths_test.rb +++ b/railties/test/application/paths_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class PathsTest < Test::Unit::TestCase + class PathsTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/rack/logger_test.rb b/railties/test/application/rack/logger_test.rb index 387eb25525..a77c6f472c 100644 --- a/railties/test/application/rack/logger_test.rb +++ b/railties/test/application/rack/logger_test.rb @@ -4,7 +4,7 @@ require "rack/test" module ApplicationTests module RackTests - class LoggerTest < Test::Unit::TestCase + class LoggerTest < ActiveSupport::TestCase include ActiveSupport::LogSubscriber::TestHelper include Rack::Test::Methods diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb index 86e1995def..49ac9fc66c 100644 --- a/railties/test/application/rackup_test.rb +++ b/railties/test/application/rackup_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class RackupTest < Test::Unit::TestCase + class RackupTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def rackup diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb index 7982c42d8f..301e516192 100644 --- a/railties/test/application/rake/migrations_test.rb +++ b/railties/test/application/rake/migrations_test.rb @@ -2,7 +2,7 @@ require "isolation/abstract_unit" module ApplicationTests module RakeTests - class RakeMigrationsTest < Test::Unit::TestCase + class RakeMigrationsTest < ActiveSupport::TestCase def setup build_app boot_rails diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb index 659cbfec0f..e121d6f1ab 100644 --- a/railties/test/application/rake/notes_test.rb +++ b/railties/test/application/rake/notes_test.rb @@ -2,7 +2,7 @@ require "isolation/abstract_unit" module ApplicationTests module RakeTests - class RakeNotesTest < Test::Unit::TestCase + class RakeNotesTest < ActiveSupport::TestCase def setup build_app require "rails/all" @@ -17,6 +17,7 @@ module ApplicationTests app_file "app/views/home/index.html.erb", "<% # TODO: note in erb %>" app_file "app/views/home/index.html.haml", "-# TODO: note in haml" app_file "app/views/home/index.html.slim", "/ TODO: note in slim" + app_file "app/controllers/application_controller.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in ruby" boot_rails require 'rake' @@ -27,10 +28,18 @@ module ApplicationTests Dir.chdir(app_path) do output = `bundle exec rake notes` + lines = output.scan(/\[([0-9\s]+)\]/).flatten assert_match /note in erb/, output assert_match /note in haml/, output assert_match /note in slim/, output + assert_match /note in ruby/, output + + assert_equal 4, lines.size + assert_equal 4, lines[0].size + assert_equal 4, lines[1].size + assert_equal 4, lines[2].size + assert_equal 4, lines[3].size end end diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 1d90671e44..ff12b3e9fc 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -2,7 +2,7 @@ require "isolation/abstract_unit" module ApplicationTests - class RakeTest < Test::Unit::TestCase + class RakeTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup @@ -128,7 +128,7 @@ module ApplicationTests `bundle exec rake db:migrate db:test:clone test` end - assert_match(/7 tests, 10 assertions, 0 failures, 0 errors/, content) + assert_match(/\d+ tests, \d+ assertions, 0 failures, 0 errors/, content) end def test_rake_dump_structure_should_respect_db_structure_env_variable diff --git a/railties/test/application/route_inspect_test.rb b/railties/test/application/route_inspect_test.rb index 6503251b9f..fcfa87e395 100644 --- a/railties/test/application/route_inspect_test.rb +++ b/railties/test/application/route_inspect_test.rb @@ -1,10 +1,10 @@ -require 'test/unit' +require 'minitest/autorun' require 'rails/application/route_inspector' require 'action_controller' require 'rails/engine' module ApplicationTests - class RouteInspectTest < Test::Unit::TestCase + class RouteInspectTest < ActiveSupport::TestCase def setup @set = ActionDispatch::Routing::RouteSet.new @inspector = Rails::Application::RouteInspector.new diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb index a05e39658d..28ce3beea9 100644 --- a/railties/test/application/routing_test.rb +++ b/railties/test/application/routing_test.rb @@ -2,7 +2,7 @@ require 'isolation/abstract_unit' require 'rack/test' module ApplicationTests - class RoutingTest < Test::Unit::TestCase + class RoutingTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation include Rack::Test::Methods diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb index 4468fa295e..e1d283a7fd 100644 --- a/railties/test/application/runner_test.rb +++ b/railties/test/application/runner_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class RunnerTest < Test::Unit::TestCase + class RunnerTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index aa55a3cf1e..f6bcaa466a 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class TestTest < Test::Unit::TestCase + class TestTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup diff --git a/railties/test/application/url_generation_test.rb b/railties/test/application/url_generation_test.rb index 2b6ec26cd0..85a8a15fcc 100644 --- a/railties/test/application/url_generation_test.rb +++ b/railties/test/application/url_generation_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class UrlGenerationTest < Test::Unit::TestCase + class UrlGenerationTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def app diff --git a/railties/test/backtrace_cleaner_test.rb b/railties/test/backtrace_cleaner_test.rb index 80077378db..cbe7d35f6d 100644 --- a/railties/test/backtrace_cleaner_test.rb +++ b/railties/test/backtrace_cleaner_test.rb @@ -1,34 +1,6 @@ require 'abstract_unit' require 'rails/backtrace_cleaner' -if defined? Test::Unit::Util::BacktraceFilter - class TestWithBacktrace - include Test::Unit::Util::BacktraceFilter - include Rails::BacktraceFilterForTestUnit - end - - class BacktraceCleanerFilterTest < ActiveSupport::TestCase - def setup - @test = TestWithBacktrace.new - @backtrace = [ './test/rails/benchmark_test.rb', './test/rails/dependencies.rb', '/opt/local/lib/ruby/kernel.rb' ] - end - - test "test with backtrace should use the rails backtrace cleaner to clean" do - Rails.stubs(:backtrace_cleaner).returns(stub(:clean)) - Rails.backtrace_cleaner.expects(:clean).with(@backtrace, nil) - @test.send(:filter_backtrace, @backtrace) - end - - test "filter backtrace should have the same arity as Test::Unit::Util::BacktraceFilter" do - assert_nothing_raised do - @test.send(:filter_backtrace, @backtrace, '/opt/local/lib') - end - end - end -else - $stderr.puts 'No BacktraceFilter for minitest' -end - if defined? Gem class BacktraceCleanerVendorGemTest < ActiveSupport::TestCase def setup diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index b62bd4b131..f0164ed667 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -241,7 +241,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_file "spec/dummy/config/application.rb" assert_no_file "test" end - + def test_ensure_that_gitignore_can_be_generated_from_a_template_for_dummy_path FileUtils.cd(Rails.root) run_generator([destination_root, "--dummy_path", "spec/dummy" "--skip-test-unit"]) @@ -263,6 +263,37 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_no_file "bukkits.gemspec" end + def test_creating_plugin_in_app_directory_adds_gemfile_entry + # simulate application existance + gemfile_path = "#{Rails.root}/Gemfile" + Object.const_set('APP_PATH', Rails.root) + FileUtils.touch gemfile_path + + run_generator [destination_root] + + assert_file gemfile_path, /gem 'bukkits', :path => 'tmp\/bukkits'/ + ensure + Object.send(:remove_const, 'APP_PATH') + FileUtils.rm gemfile_path + end + + def test_skipping_gemfile_entry + # simulate application existance + gemfile_path = "#{Rails.root}/Gemfile" + Object.const_set('APP_PATH', Rails.root) + FileUtils.touch gemfile_path + + run_generator [destination_root, "--skip-gemfile-entry"] + + assert_file gemfile_path do |contents| + assert_no_match(/gem 'bukkits', :path => 'tmp\/bukkits'/, contents) + end + ensure + Object.send(:remove_const, 'APP_PATH') + FileUtils.rm gemfile_path + end + + protected def action(*args, &block) diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index f57737172d..72588af631 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -8,8 +8,9 @@ # Rails booted up. require 'fileutils' -require 'test/unit' require 'rubygems' +require 'minitest/autorun' +require 'active_support/test_case' # TODO: Remove setting this magic constant RAILS_FRAMEWORK_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../..") @@ -256,7 +257,7 @@ module TestHelpers end end -class Test::Unit::TestCase +class ActiveSupport::TestCase include TestHelpers::Paths include TestHelpers::Rack include TestHelpers::Generation diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 2813f689c5..5ed923a484 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -4,7 +4,7 @@ require "stringio" require "rack/test" module RailtiesTest - class EngineTest < Test::Unit::TestCase + class EngineTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation include SharedTests diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb index 0491fc2174..2bb9df6b64 100644 --- a/railties/test/railties/mounted_engine_test.rb +++ b/railties/test/railties/mounted_engine_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' module ApplicationTests - class ApplicationRoutingTest < Test::Unit::TestCase + class ApplicationRoutingTest < ActiveSupport::TestCase require 'rack/test' include Rack::Test::Methods include ActiveSupport::Testing::Isolation diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb index 55f85c7202..cd495320b5 100644 --- a/railties/test/railties/railtie_test.rb +++ b/railties/test/railties/railtie_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module RailtiesTest - class RailtieTest < Test::Unit::TestCase + class RailtieTest < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation def setup |