diff options
216 files changed, 1689 insertions, 1447 deletions
@@ -1,21 +1,38 @@ -Gem.sources.each { |uri| source uri } +clear_sources +source 'http://gemcutter.org' + +gem "rake", ">= 0.8.7" +gem "mocha", ">= 0.9.8" gem "rails", "3.0.pre", :vendored_at => "railties" -%w( - activesupport - activemodel - actionpack - actionmailer - activerecord - activeresource -).each do |lib| +%w(activesupport activemodel actionpack actionmailer activerecord activeresource).each do |lib| gem lib, '3.0.pre', :vendored_at => lib end -gem "rack", "1.0.1" -gem "rack-mount", :git => "git://github.com/rails/rack-mount.git" -gem "rack-test", "~> 0.5.0" -gem "erubis", "~> 2.6.0" -gem "arel", :git => "git://github.com/rails/arel.git" -gem "mocha" -gem "sqlite3-ruby" -gem "RedCloth" + +# AR +gem "arel", "0.2.pre", :git => "git://github.com/rails/arel.git" +gem "sqlite3-ruby", ">= 1.2.5" + +# AP +gem "rack", "1.0.1", :git => "git://github.com/rails/rack.git" +gem "rack-mount", :git => "git://github.com/rails/rack-mount.git" +gem "rack-test", ">= 0.5.0" +gem "erubis", ">= 2.6.5" +gem "RedCloth", ">= 4.2.2" + +if ENV['CI'] + disable_system_gems + + gem "nokogiri", ">= 1.4.0" + gem "memcache-client", ">= 1.7.6" + gem "pg", ">= 0.8.0" + gem "mysql", ">= 2.8.1" + + # fcgi gem doesn't compile on 1.9 + # avoid minitest strangeness on 1.9 + if RUBY_VERSION < '1.9.0' + gem "fcgi", ">= 0.8.7" + else + gem "test-unit", ">= 2.0.5" + end +end @@ -10,9 +10,9 @@ Dir["#{File.dirname(__FILE__)}/*/lib/*/version.rb"].each do |version_path| end desc 'Run all tests by default' -task :default => :test +task :default => %w(test test:isolated) -%w(test isolated_test rdoc pgem package release gem gemspec).each do |task_name| +%w(test test:isolated rdoc pgem package release gem gemspec).each do |task_name| desc "Run #{task_name} task for all projects" task task_name do errors = [] diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index 96c84b986e..1a7ece5068 100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -24,14 +24,16 @@ Rake::TestTask.new { |t| t.libs << "test" t.pattern = 'test/*_test.rb' t.verbose = true - t.warning = false + t.warning = true } -task :isolated_test do - ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) - Dir.glob("test/*_test.rb").all? do |file| - system(ruby, '-Ilib:test', file) - end or raise "Failures" +namespace :test do + task :isolated do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + Dir.glob("test/*_test.rb").all? do |file| + system(ruby, '-Ilib:test', file) + end or raise "Failures" + end end # Generate the RDoc documentation diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 293af01bbf..bef9bb8e79 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -452,6 +452,8 @@ module ActionMailer #:nodoc: # remain uninitialized (useful when you only need to invoke the "receive" # method, for instance). def initialize(method_name=nil, *parameters) #:nodoc: + @_response_body = nil + super() create!(method_name, *parameters) if method_name end @@ -465,8 +467,8 @@ module ActionMailer #:nodoc: create_parts # Set the subject if not set yet - @subject ||= I18n.t(method_name, :scope => [:actionmailer, :subjects, mailer_name], - :default => method_name.humanize) + @subject ||= I18n.t(:subject, :scope => [:actionmailer, mailer_name, method_name], + :default => method_name.humanize) # build the mail object itself @mail = create_mail diff --git a/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/parser.rb b/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/parser.rb index ab1a828471..0ddc525213 100644 --- a/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/parser.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/parser.rb @@ -43,6 +43,7 @@ module Racc class Parser + old_verbose, $VERBOSE = $VERBOSE, nil Racc_Runtime_Version = '1.4.5' Racc_Runtime_Revision = '$Revision: 1.7 $'.split[1] @@ -71,6 +72,7 @@ module Racc Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R Racc_Runtime_Type = 'ruby' end + $VERBOSE = old_verbose def Parser.racc_runtime_type Racc_Runtime_Type diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index fcbaa9e186..e84b3b0d23 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -4,9 +4,11 @@ begin rescue LoadError $:.unshift("#{root}/activesupport/lib") $:.unshift("#{root}/actionpack/lib") - $:.unshift("#{root}/actionmailer/lib") end +lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") +$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) + require 'rubygems' require 'test/unit' diff --git a/actionmailer/test/mail_service_test.rb b/actionmailer/test/mail_service_test.rb index f9365ea90c..c98f0a7601 100644 --- a/actionmailer/test/mail_service_test.rb +++ b/actionmailer/test/mail_service_test.rb @@ -402,7 +402,7 @@ class ActionMailerTest < Test::Unit::TestCase assert_nothing_raised { TestMailer.deliver_subject_with_i18n(@recipient) } assert_equal "Subject with i18n", ActionMailer::Base.deliveries.first.subject - I18n.backend.store_translations('en', :actionmailer => {:subjects => {:test_mailer => {:subject_with_i18n => "New Subject!"}}}) + I18n.backend.store_translations('en', :actionmailer => {:test_mailer => {:subject_with_i18n => {:subject => "New Subject!"}}}) assert_nothing_raised { TestMailer.deliver_subject_with_i18n(@recipient) } assert_equal "New Subject!", ActionMailer::Base.deliveries.last.subject end diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index 1930416358..ae5985120e 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -16,8 +16,10 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', '= 3.0.pre') s.add_dependency('activemodel', '= 3.0.pre') - s.add_dependency('rack', '~> 1.0.0') - s.add_dependency('rack-test', '~> 0.5.0') + s.add_dependency('rack', '~> 1.0.1') + s.add_dependency('rack-test', '~> 0.5.0') + s.add_dependency('rack-mount', '~> 0.0.1') + s.add_dependency('erubis', '~> 2.6.0') s.require_path = 'lib' s.autorequire = 'action_controller' diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb index 8293e79b0a..c71cef42b2 100644 --- a/actionpack/lib/abstract_controller/layouts.rb +++ b/actionpack/lib/abstract_controller/layouts.rb @@ -89,7 +89,7 @@ module AbstractController # ==== Returns # String:: A template name def _implied_layout_name - name.underscore + name && name.underscore end # Takes the specified layout and creates a _layout method to be called @@ -100,7 +100,7 @@ module AbstractController # name, return that string. Otherwise, use the superclass' # layout (which might also be implied) def _write_layout_method - case @_layout + case defined?(@_layout) ? @_layout : nil when String self.class_eval %{def _layout(details) #{@_layout.inspect} end} when Symbol @@ -119,17 +119,19 @@ module AbstractController when true raise ArgumentError, "Layouts must be specified as a String, Symbol, false, or nil" when nil - self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def _layout(details) - self.class.cache_layout(details) do - if template_exists?("#{_implied_layout_name}", details, :_prefix => "layouts") - "#{_implied_layout_name}" - else - super + if name + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def _layout(details) + self.class.cache_layout(details) do + if template_exists?("#{_implied_layout_name}", details, :_prefix => "layouts") + "#{_implied_layout_name}" + else + super + end end end - end - RUBY + RUBY + end end self.class_eval { private :_layout } end diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb index 0aae2b18e9..7054b9cf26 100644 --- a/actionpack/lib/abstract_controller/rendering_controller.rb +++ b/actionpack/lib/abstract_controller/rendering_controller.rb @@ -12,6 +12,12 @@ module AbstractController self._view_paths ||= ActionView::PathSet.new end + # Initialize controller with nil formats. + def initialize(*) #:nodoc: + @_formats = nil + super + end + # An instance of a view class. The default view class is ActionView::Base # # The view class must have the following methods: diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index 6f89bf5d67..60b3f9a89b 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -49,7 +49,7 @@ module ActionController # and response object available. You might wish to control the # environment and response manually for performance reasons. - attr_internal :status, :headers, :content_type, :app, :response + attr_internal :status, :headers, :content_type, :response def initialize(*) @_headers = {} @@ -69,7 +69,7 @@ module ActionController end # :api: private - def call(name, env) + def dispatch(name, env) @_env = env process(name) to_a @@ -95,7 +95,7 @@ module ActionController end def call(env) - controller = @controller.new.call(@action, env) + @controller.new.dispatch(@action, env) end end diff --git a/actionpack/lib/action_controller/metal/rack_convenience.rb b/actionpack/lib/action_controller/metal/rack_convenience.rb index a80569c530..131d20114d 100644 --- a/actionpack/lib/action_controller/metal/rack_convenience.rb +++ b/actionpack/lib/action_controller/metal/rack_convenience.rb @@ -8,7 +8,7 @@ module ActionController attr_internal :request end - def call(name, env) + def dispatch(action, env) @_request = ActionDispatch::Request.new(env) @_response = ActionDispatch::Response.new @_response.request = request diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb index 4761763a26..43c661bef4 100644 --- a/actionpack/lib/action_controller/metal/streaming.rb +++ b/actionpack/lib/action_controller/metal/streaming.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/string/bytesize' - module ActionController #:nodoc: # Methods for sending arbitrary data and for streaming files to the browser, # instead of rendering. diff --git a/actionpack/lib/action_controller/middleware.rb b/actionpack/lib/action_controller/middleware.rb index fac0ed2645..17275793b7 100644 --- a/actionpack/lib/action_controller/middleware.rb +++ b/actionpack/lib/action_controller/middleware.rb @@ -1,34 +1,34 @@ module ActionController class Middleware < Metal class ActionMiddleware - def initialize(controller) - @controller = controller + def initialize(controller, app) + @controller, @app = controller, app end def call(env) - controller = @controller.allocate - controller.send(:initialize) - controller.app = @app - controller._call(env) + @controller.build(@app).dispatch(:index, env) end + end + + class << self + alias build new - def app=(app) - @app = app + def new(app) + ActionMiddleware.new(self, app) end end - - def self.new(app) - middleware = ActionMiddleware.new(self) - middleware.app = app - middleware + + attr_internal :app + + def process(action) + response = super + self.status, self.headers, self.response_body = response if response.is_a?(Array) + response end - - def _call(env) - @_env = env - @_request = ActionDispatch::Request.new(env) - @_response = ActionDispatch::Response.new - @_response.request = @_request - process(:index) + + def initialize(app) + super() + @_app = app end def index diff --git a/actionpack/lib/action_controller/translation.rb b/actionpack/lib/action_controller/translation.rb index 9bb63cdb15..65e9eddb0a 100644 --- a/actionpack/lib/action_controller/translation.rb +++ b/actionpack/lib/action_controller/translation.rb @@ -1,12 +1,12 @@ module ActionController module Translation def translate(*args) - I18n.translate *args + I18n.translate(*args) end alias :t :translate def localize(*args) - I18n.localize *args + I18n.localize(*args) end alias :l :localize end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 75be2cc260..b3bb8c623f 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -5,7 +5,7 @@ require 'strscan' require 'active_support/memoizable' require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/hash/indifferent_access' -require 'active_support/core_ext/object/tap' +require 'active_support/core_ext/string/access' module ActionDispatch class Request < Rack::Request @@ -166,7 +166,7 @@ module ActionDispatch @env["action_dispatch.request.formats"] ||= if parameters[:format] - [Mime[parameters[:format]]] + Array.wrap(Mime[parameters[:format]]) elsif xhr? || (accept && !accept.include?(?,)) accepts else diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index 4f71ea6165..3b27309f58 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -1,3 +1,5 @@ +require "active_support/inflector/methods" + module ActionDispatch class MiddlewareStack < Array class Middleware @@ -32,7 +34,7 @@ module ActionDispatch elsif @klass.respond_to?(:call) @klass.call else - @klass.to_s.constantize + ActiveSupport::Inflector.constantize(@klass.to_s) end end @@ -53,7 +55,7 @@ module ActionDispatch when Class klass == middleware else - klass == middleware.to_s.constantize + klass == ActiveSupport::Inflector.constantize(middleware.to_s) end end diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index b9c377db2c..68ed1e3340 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -1,6 +1,4 @@ -require 'active_support/core_ext/object/conversions' -require 'active_support/core_ext/boolean/conversions' -require 'active_support/core_ext/nil/conversions' +require 'active_support/core_ext/object/to_param' require 'active_support/core_ext/regexp' module ActionDispatch diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index d6d822842b..ebfb4c9be2 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -20,15 +20,20 @@ module ActionDispatch return self end - controller(resource) do + singular = resource.to_s + plural = singular.pluralize + + controller(plural) do namespace(resource) do with_scope_level(:resource) do yield if block_given? - get "", :to => :show + get "", :to => :show, :as => "#{singular}" post "", :to => :create put "", :to => :update - delete "", :to => :destory + delete "", :to => :destroy + get "new", :to => :new, :as => "new_#{singular}" + get "edit", :to => :edit, :as => "edit_#{singular}" end end end @@ -54,22 +59,25 @@ module ActionDispatch return self end + plural = resource.to_s + singular = plural.singularize + controller(resource) do namespace(resource) do with_scope_level(:resources) do yield if block_given? member do - get "", :to => :show + get "", :to => :show, :as => "#{singular}" put "", :to => :update - delete "", :to => :destory - get "edit", :to => :edit + delete "", :to => :destroy + get "edit", :to => :edit, :as => "edit_#{singular}" end collection do - get "", :to => :index + get "", :to => :index, :as => "#{plural}" post "", :to => :create - get "new", :to => :new + get "new", :to => :new, :as => "new_#{singular}" end end end @@ -221,6 +229,10 @@ module ActionDispatch map_method(:delete, *args, &block) end + def root(options = {}) + match '/', options.merge(:as => :root) + end + def match(*args) options = args.last.is_a?(Hash) ? args.pop : {} diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 93617e826d..28e5b806da 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -20,7 +20,12 @@ module ActionDispatch params = env[PARAMETERS_KEY] merge_default_action!(params) split_glob_param!(params) if @glob_param - params.each { |key, value| params[key] = URI.unescape(value) if value.is_a?(String) } + params.each do |key, value| + if value.is_a?(String) + value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding) + params[key] = URI.unescape(value) + end + end if env['action_controller.recognize'] [200, {}, params] diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb index 96f08f2355..0e4a92048f 100644 --- a/actionpack/lib/action_dispatch/testing/assertions.rb +++ b/actionpack/lib/action_dispatch/testing/assertions.rb @@ -1,8 +1,21 @@ module ActionDispatch module Assertions - %w(response selector tag dom routing model).each do |kind| - require "action_dispatch/testing/assertions/#{kind}" - include const_get("#{kind.camelize}Assertions") + autoload :DomAssertions, 'action_dispatch/testing/assertions/dom' + autoload :ModelAssertions, 'action_dispatch/testing/assertions/model' + autoload :ResponseAssertions, 'action_dispatch/testing/assertions/response' + autoload :RoutingAssertions, 'action_dispatch/testing/assertions/routing' + autoload :SelectorAssertions, 'action_dispatch/testing/assertions/selector' + autoload :TagAssertions, 'action_dispatch/testing/assertions/tag' + + extend ActiveSupport::Concern + + included do + include DomAssertions + include ModelAssertions + include ResponseAssertions + include RoutingAssertions + include SelectorAssertions + include TagAssertions end end end diff --git a/actionpack/lib/action_view/erb/util.rb b/actionpack/lib/action_view/erb/util.rb index f767a5e27e..aef859b3ac 100644 --- a/actionpack/lib/action_view/erb/util.rb +++ b/actionpack/lib/action_view/erb/util.rb @@ -23,6 +23,7 @@ class ERB end end + undef :h alias h html_escape module_function :html_escape diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb index 4aed10f640..564f12c955 100644 --- a/actionpack/lib/action_view/helpers/translation_helper.rb +++ b/actionpack/lib/action_view/helpers/translation_helper.rb @@ -21,7 +21,7 @@ module ActionView # Delegates to I18n.localize with no additional functionality. def localize(*args) - I18n.localize *args + I18n.localize(*args) end alias :l :localize diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index fc89726670..7006a5b968 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -71,12 +71,10 @@ module ActionView # In this case, the layout would receive the block passed into <tt>render :layout</tt>, # and the Struct specified in the layout would be passed into the block. The result # would be <html>Hello David</html>. - def _layout_for(name = nil) + def _layout_for(name = nil, &block) return @_content_for[name || :layout] if !block_given? || name - with_output_buffer do - return yield - end + capture(&block) end def _render_inline(inline, layout, options) diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index 8beda24aba..86bbad822d 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -120,6 +120,7 @@ module ActionView def _view view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller) view.class.send :include, _helpers + view.output_buffer = self.output_buffer view end diff --git a/actionpack/test/abstract/helper_test.rb b/actionpack/test/abstract/helper_test.rb index 6c28f01fa4..efcd68e5c8 100644 --- a/actionpack/test/abstract/helper_test.rb +++ b/actionpack/test/abstract/helper_test.rb @@ -40,7 +40,7 @@ module AbstractController class AbstractHelpersBlock < ControllerWithHelpers helper do - include HelperyTest + include ::AbstractController::Testing::HelperyTest end end diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index 9c29696ad5..ae2f1bf1f2 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -212,7 +212,7 @@ module AbstractControllerTests end test "when the layout is specified as a symbol and the method doesn't exist, raise an exception" do - assert_raises(NoMethodError, /:nilz/) { WithSymbolAndNoMethod.new.process(:index) } + assert_raises(NoMethodError) { WithSymbolAndNoMethod.new.process(:index) } end test "when the layout is specified as a symbol and the method returns something besides a string/false/nil, raise an exception" do diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 214d79cd87..775cfc82bf 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -6,17 +6,13 @@ rescue LoadError $:.unshift "#{root}/activemodel/lib" end -$:.unshift(File.dirname(__FILE__) + '/../lib') +lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") +$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) + $:.unshift(File.dirname(__FILE__) + '/lib') $:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') $:.unshift(File.dirname(__FILE__) + '/fixtures/alternate_helpers') -begin - %w( rack rack/test sqlite3 ).each { |lib| require lib } -rescue LoadError => e - abort e.message -end - ENV['TMPDIR'] = File.join(File.dirname(__FILE__), 'tmp') require 'test/unit' diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index 2da97a9d86..8445428e8f 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'active_support/core_ext/symbol' class ActionController::Base class << self diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index 12539739aa..b9be163904 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -3,12 +3,6 @@ require 'active_support/core_ext/kernel/reporting' ActionController::Base.helpers_dir = File.dirname(__FILE__) + '/../fixtures/helpers' -class TestController < ActionController::Base - attr_accessor :delegate_attr - def delegate_method() end - def rescue_action(e) raise end -end - module Fun class GamesController < ActionController::Base def render_hello_world @@ -38,6 +32,12 @@ module LocalAbcHelper end class HelperTest < Test::Unit::TestCase + class TestController < ActionController::Base + attr_accessor :delegate_attr + def delegate_method() end + def rescue_action(e) raise end + end + def setup # Increment symbol counter. @symbol = (@@counter ||= 'A0').succ!.dup diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index d6e2a5a974..624b14e69b 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -390,7 +390,7 @@ class IntegrationProcessTest < ActionController::IntegrationTest def with_test_route_set with_routing do |set| set.draw do |map| - match ':action', :to => IntegrationController + match ':action', :to => ::IntegrationProcessTest::IntegrationController end yield end diff --git a/actionpack/test/controller/new_base/render_action_test.rb b/actionpack/test/controller/new_base/render_action_test.rb index ecd29c4530..239f68659c 100644 --- a/actionpack/test/controller/new_base/render_action_test.rb +++ b/actionpack/test/controller/new_base/render_action_test.rb @@ -86,7 +86,7 @@ module RenderAction describe "Both <controller_path>.html.erb and application.html.erb are missing" test "rendering with layout => true" do - assert_raise(ArgumentError, /no default layout for RenderAction::BasicController in/) do + assert_raise(ArgumentError) do get "/render_action/basic/hello_world_with_layout", {}, "action_dispatch.show_exceptions" => false end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index ac8dad7c42..b32325fa20 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -860,7 +860,7 @@ class RenderTest < ActionController::TestCase # :ported: def test_access_to_controller_name_in_view get :accessing_controller_name_in_template - assert_equal "test", @response.body # name is explicitly set to 'test' inside the controller. + assert_equal "test", @response.body # name is explicitly set in the controller. end # :ported: diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index 2b1f532b8d..37367eaafc 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -343,9 +343,9 @@ class RescueTest < ActionController::IntegrationTest def with_test_routing with_routing do |set| set.draw do |map| - match 'foo', :to => TestController.action(:foo) - match 'invalid', :to => TestController.action(:invalid) - match 'b00m', :to => TestController.action(:b00m) + match 'foo', :to => ::RescueTest::TestController.action(:foo) + match 'invalid', :to => ::RescueTest::TestController.action(:invalid) + match 'b00m', :to => ::RescueTest::TestController.action(:b00m) end yield end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 308e2a85b1..3971aacadb 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -450,6 +450,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase assert_equal({:controller => "content", :action => 'show_page', :id => 'foo'}, rs.recognize_path("/page/foo")) token = "\321\202\320\265\320\272\321\201\321\202" # 'text' in russian + token.force_encoding(Encoding::BINARY) if token.respond_to?(:force_encoding) escaped_token = CGI::escape(token) assert_equal '/page/' + escaped_token, rs.generate(:controller => 'content', :action => 'show_page', :id => token) @@ -1644,6 +1645,58 @@ class RouteSetTest < ActiveSupport::TestCase assert_uri_equal '/foo?x=hello+world', default_route_set.generate({:controller => 'foo', :x => 'hello world'}) end + def test_generate_with_default_params + set.draw do |map| + map.connect 'dummy/page/:page', :controller => 'dummy' + map.connect 'dummy/dots/page.:page', :controller => 'dummy', :action => 'dots' + map.connect 'ibocorp/:page', :controller => 'ibocorp', + :requirements => { :page => /\d+/ }, + :defaults => { :page => 1 } + + map.connect ':controller/:action/:id' + end + + pending do + assert_equal '/ibocorp', set.generate({:controller => 'ibocorp', :page => 1}) + end + end + + def test_generate_with_optional_params_recalls_last_request + set.draw do |map| + map.connect "blog/", :controller => "blog", :action => "index" + + map.connect "blog/:year/:month/:day", + :controller => "blog", + :action => "show_date", + :requirements => { :year => /(19|20)\d\d/, :month => /[01]?\d/, :day => /[0-3]?\d/ }, + :day => nil, :month => nil + + map.connect "blog/show/:id", :controller => "blog", :action => "show", :id => /\d+/ + map.connect "blog/:controller/:action/:id" + map.connect "*anything", :controller => "blog", :action => "unknown_request" + end + + assert_equal({:controller => "blog", :action => "index"}, set.recognize_path("/blog")) + assert_equal({:controller => "blog", :action => "show", :id => "123"}, set.recognize_path("/blog/show/123")) + assert_equal({:controller => "blog", :action => "show_date", :year => "2004"}, set.recognize_path("/blog/2004")) + assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :month => "12"}, set.recognize_path("/blog/2004/12")) + assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :month => "12", :day => "25"}, set.recognize_path("/blog/2004/12/25")) + assert_equal({:controller => "articles", :action => "edit", :id => "123"}, set.recognize_path("/blog/articles/edit/123")) + assert_equal({:controller => "articles", :action => "show_stats"}, set.recognize_path("/blog/articles/show_stats")) + assert_equal({:controller => "blog", :action => "unknown_request", :anything => ["blog", "wibble"]}, set.recognize_path("/blog/wibble")) + assert_equal({:controller => "blog", :action => "unknown_request", :anything => ["junk"]}, set.recognize_path("/junk")) + + last_request = set.recognize_path("/blog/2006/07/28").freeze + assert_equal({:controller => "blog", :action => "show_date", :year => "2006", :month => "07", :day => "28"}, last_request) + assert_equal("/blog/2006/07/25", set.generate({:day => 25}, last_request)) + assert_equal("/blog/2005", set.generate({:year => 2005}, last_request)) + assert_equal("/blog/show/123", set.generate({:action => "show" , :id => 123}, last_request)) + pending do + assert_equal("/blog/2006/07/28", set.generate({:year => 2006}, last_request)) + end + assert_equal("/blog/2006", set.generate({:year => 2006, :month => nil}, last_request)) + end + private def assert_uri_equal(expected, actual) assert_equal(sort_query_string_params(expected), sort_query_string_params(actual)) diff --git a/actionpack/test/controller/verification_test.rb b/actionpack/test/controller/verification_test.rb index 63e8cf3e61..11d0d10897 100644 --- a/actionpack/test/controller/verification_test.rb +++ b/actionpack/test/controller/verification_test.rb @@ -126,7 +126,7 @@ class VerificationTest < ActionController::TestCase with_routing do |set| set.draw do |map| match 'foo', :to => 'test#foo', :as => :foo - match 'verification_test/:action', :to => TestController + match 'verification_test/:action', :to => ::VerificationTest::TestController end get :guarded_one_for_named_route_test, :two => "not one" assert_redirected_to '/foo' diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb index 3c2408de5f..d3308f73cc 100644 --- a/actionpack/test/dispatch/request/json_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb @@ -57,7 +57,7 @@ class JsonParamsParsingTest < ActionController::IntegrationTest def with_test_routing with_routing do |set| set.draw do |map| - match ':action', :to => TestController + match ':action', :to => ::JsonParamsParsingTest::TestController end yield end diff --git a/actionpack/test/dispatch/request/query_string_parsing_test.rb b/actionpack/test/dispatch/request/query_string_parsing_test.rb index b764478d87..071d80c5b0 100644 --- a/actionpack/test/dispatch/request/query_string_parsing_test.rb +++ b/actionpack/test/dispatch/request/query_string_parsing_test.rb @@ -109,12 +109,12 @@ class QueryStringParsingTest < ActionController::IntegrationTest def assert_parses(expected, actual) with_routing do |set| set.draw do |map| - match ':action', :to => TestController + match ':action', :to => ::QueryStringParsingTest::TestController end get "/parse", actual assert_response :ok - assert_equal(expected, TestController.last_query_parameters) + assert_equal(expected, ::QueryStringParsingTest::TestController.last_query_parameters) end end end diff --git a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb index e98a49980e..69dbd7f528 100644 --- a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb @@ -130,7 +130,7 @@ class UrlEncodedParamsParsingTest < ActionController::IntegrationTest def with_test_routing with_routing do |set| set.draw do |map| - match ':action', :to => TestController + match ':action', :to => ::UrlEncodedParamsParsingTest::TestController end yield end diff --git a/actionpack/test/dispatch/request/xml_params_parsing_test.rb b/actionpack/test/dispatch/request/xml_params_parsing_test.rb index 0dc47ed9d5..96189e4ca2 100644 --- a/actionpack/test/dispatch/request/xml_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/xml_params_parsing_test.rb @@ -84,7 +84,7 @@ class XmlParamsParsingTest < ActionController::IntegrationTest def with_test_routing with_routing do |set| set.draw do |map| - match ':action', :to => TestController + match ':action', :to => ::XmlParamsParsingTest::TestController end yield end @@ -100,4 +100,4 @@ class LegacyXmlParamsParsingTest < XmlParamsParsingTest def default_headers {'HTTP_X_POST_DATA_FORMAT' => 'xml'} end -end
\ No newline at end of file +end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 239fda98e0..b62df9a6b2 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -432,6 +432,10 @@ class RequestTest < ActiveSupport::TestCase request = stub_request request.expects(:parameters).at_least_once.returns({ :format => :txt }) assert_equal with_set(Mime::TEXT), request.formats + + request = stub_request + request.expects(:parameters).at_least_once.returns({ :format => :unknown }) + assert request.formats.empty? end test "negotiate_mime" do diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 74e6c8e72d..ca07bc7a28 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -37,7 +37,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get 'admin', :to => "queenbee#index" end - constraints IpRestrictor do + constraints ::TestRoutingMapper::IpRestrictor do get 'admin/accounts', :to => "queenbee#accounts" end @@ -80,7 +80,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - match 'sprockets.js', :to => SprocketsApp + match 'sprockets.js', :to => ::TestRoutingMapper::SprocketsApp match 'people/:id/update', :to => 'people#update', :as => :update_person match '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person @@ -190,8 +190,21 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_projects with_test_routes do + get '/projects' + assert_equal 'projects#index', @response.body + assert_equal '/projects', projects_path + + get '/projects/new' + assert_equal 'projects#new', @response.body + assert_equal '/projects/new', new_project_path + get '/projects/1' assert_equal 'projects#show', @response.body + assert_equal '/projects/1', project_path(:id => '1') + + get '/projects/1/edit' + assert_equal 'projects#edit', @response.body + assert_equal '/projects/1/edit', edit_project_path(:id => '1') end end @@ -231,7 +244,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'people#index', @response.body get '/projects/1/companies/1/avatar' - assert_equal 'avatar#show', @response.body + assert_equal 'avatars#show', @response.body end end @@ -254,7 +267,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'people#show', @response.body get '/projects/1/people/1/7a2dec8/avatar' - assert_equal 'avatar#show', @response.body + assert_equal 'avatars#show', @response.body put '/projects/1/people/1/accessible_projects' assert_equal 'people#accessible_projects', @response.body @@ -282,7 +295,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'posts#preview', @response.body get '/projects/1/posts/1/subscription' - assert_equal 'subscription#show', @response.body + assert_equal 'subscriptions#show', @response.body get '/projects/1/posts/1/comments' assert_equal 'comments#index', @response.body @@ -329,13 +342,13 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest def test_account_namespace with_test_routes do get '/account/subscription' - assert_equal 'subscription#show', @response.body + assert_equal 'subscriptions#show', @response.body get '/account/credit' - assert_equal 'credit#show', @response.body + assert_equal 'credits#show', @response.body get '/account/credit_card' - assert_equal 'credit_card#show', @response.body + assert_equal 'credit_cards#show', @response.body end end diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index edfc303d3d..ab7b9bc31b 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -219,7 +219,7 @@ class CookieStoreTest < ActionController::IntegrationTest def with_test_route_set(options = {}) with_routing do |set| set.draw do |map| - match ':action', :to => TestController + match ':action', :to => ::CookieStoreTest::TestController end options = {:key => SessionKey, :secret => SessionSecret}.merge(options) @app = ActionDispatch::Session::CookieStore.new(set, options) diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb index afc9d91d50..5a1dcb4dab 100644 --- a/actionpack/test/dispatch/session/mem_cache_store_test.rb +++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb @@ -112,7 +112,7 @@ class MemCacheStoreTest < ActionController::IntegrationTest def with_test_route_set with_routing do |set| set.draw do |map| - match ':action', :to => TestController + match ':action', :to => ::MemCacheStoreTest::TestController end @app = ActionDispatch::Session::MemCacheStore.new(set, :key => '_session_id') yield diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb index b2006a0d2f..5da02b2ea6 100644 --- a/actionpack/test/dispatch/test_request_test.rb +++ b/actionpack/test/dispatch/test_request_test.rb @@ -5,7 +5,7 @@ class TestRequestTest < ActiveSupport::TestCase env = ActionDispatch::TestRequest.new.env assert_equal "GET", env.delete("REQUEST_METHOD") - assert_equal nil, env.delete("HTTPS") + assert_equal "off", env.delete("HTTPS") assert_equal "http", env.delete("rack.url_scheme") assert_equal "example.org", env.delete("SERVER_NAME") assert_equal "80", env.delete("SERVER_PORT") diff --git a/actionpack/test/fixtures/layouts/block_with_layout.erb b/actionpack/test/fixtures/layouts/block_with_layout.erb index 6a8b41914b..f25b41271d 100644 --- a/actionpack/test/fixtures/layouts/block_with_layout.erb +++ b/actionpack/test/fixtures/layouts/block_with_layout.erb @@ -1,3 +1,3 @@ -<% render(:layout => "layout_for_partial", :locals => { :name => "Anthony" }) do %>Inside from first block in layout<% end %> +<% render(:layout => "layout_for_partial", :locals => { :name => "Anthony" }) do %>Inside from first block in layout<% "Return value should be discarded" %><% end %> <%= yield %> <% render(:layout => "layout_for_partial", :locals => { :name => "Ramm" }) do %>Inside from second block in layout<% end %> diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 85a97d570c..0a2b82bd89 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -88,7 +88,7 @@ class NumberHelperTest < ActionView::TestCase assert_equal("111.00", number_with_precision(111, :precision => 2)) assert_equal("111.235", number_with_precision("111.2346")) assert_equal("31.83", number_with_precision("31.825", :precision => 2)) - assert_equal("3268", number_with_precision((32.675 * 100.00), :precision => 0)) + assert_equal("3268", number_with_precision((32.6751 * 100.00), :precision => 0)) assert_equal("112", number_with_precision(111.50, :precision => 0)) assert_equal("1234567892", number_with_precision(1234567891.50, :precision => 0)) diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index ca72c13ffa..05a409d05a 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -24,7 +24,7 @@ module ActionView test_case.class_eval do test "helpers defined on ActionView::TestCase are available" do assert test_case.ancestors.include?(ASharedTestHelper) - assert 'Holla!', from_shared_helper + assert_equal 'Holla!', from_shared_helper end end end @@ -38,10 +38,15 @@ module ActionView assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy')) end + test "can render a layout with block" do + assert_equal "Before (ChrisCruft)\n!\nAfter", + render(:layout => "test/layout_for_partial", :locals => {:name => "ChrisCruft"}) {"!"} + end + helper AnotherTestHelper test "additional helper classes can be specified as in a controller" do assert test_case.ancestors.include?(AnotherTestHelper) - assert 'Howdy!', from_another_helper + assert_equal 'Howdy!', from_another_helper end end @@ -58,14 +63,14 @@ module ActionView helper AnotherTestHelper test "additional helper classes can be specified as in a controller" do assert test_case.ancestors.include?(AnotherTestHelper) - assert 'Howdy!', from_another_helper + assert_equal 'Howdy!', from_another_helper test_case.helper_class.module_eval do def render_from_helper from_another_helper end end - assert 'Howdy!', render(:partial => 'test/from_helper') + assert_equal 'Howdy!', render(:partial => 'test/from_helper') end end diff --git a/actionpack/test/ts_isolated.rb b/actionpack/test/ts_isolated.rb index 21d62f6aa7..5670d93613 100644 --- a/actionpack/test/ts_isolated.rb +++ b/actionpack/test/ts_isolated.rb @@ -10,8 +10,8 @@ class TestIsolated < Test::Unit::TestCase Dir["#{File.dirname(__FILE__)}/{abstract,controller,dispatch,template}/**/*_test.rb"].each do |file| define_method("test #{file}") do command = "#{ruby} -Ilib:test #{file}" - silence_stderr { `#{command}` } - assert_equal 0, $?.to_i, command + result = silence_stderr { `#{command}` } + assert_block("#{command}\n#{result}") { $?.to_i.zero? } end end end diff --git a/activemodel/Rakefile b/activemodel/Rakefile index 8897987518..1f4a8466c9 100755 --- a/activemodel/Rakefile +++ b/activemodel/Rakefile @@ -1,4 +1,5 @@ -require File.join(File.dirname(__FILE__), 'lib', 'active_model', 'version') +dir = File.dirname(__FILE__) +require "#{dir}/lib/active_model/version" PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' PKG_NAME = 'activemodel' @@ -12,17 +13,19 @@ require 'rake/testtask' task :default => :test Rake::TestTask.new do |t| - t.libs << "test" - t.test_files = Dir.glob("test/cases/**/*_test.rb").sort + t.libs << "#{dir}/test" + t.test_files = Dir.glob("#{dir}/test/cases/**/*_test.rb").sort t.verbose = true t.warning = true end -task :isolated_test do - ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) - Dir.glob("test/**/*_test.rb").all? do |file| - system(ruby, '-w', '-Ilib:test', file) - end or raise "Failures" +namespace :test do + task :isolated do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + Dir.glob("#{dir}/test/**/*_test.rb").all? do |file| + system(ruby, '-w', "-I#{dir}/lib", "-I#{dir}/test", file) + end or raise "Failures" + end end @@ -30,20 +33,20 @@ require 'rake/rdoctask' # Generate the RDoc documentation Rake::RDocTask.new do |rdoc| - rdoc.rdoc_dir = 'doc' + rdoc.rdoc_dir = "#{dir}/doc" rdoc.title = "Active Model" rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object' rdoc.options << '--charset' << 'utf-8' rdoc.template = ENV['template'] ? "#{ENV['template']}.rb" : '../doc/template/horo' - rdoc.rdoc_files.include('README', 'CHANGES') - rdoc.rdoc_files.include('lib/**/*.rb') + rdoc.rdoc_files.include("#{dir}/README", "#{dir}/CHANGES") + rdoc.rdoc_files.include("#{dir}/lib/**/*.rb") end require 'rake/packagetask' require 'rake/gempackagetask' -spec = eval(File.read('activemodel.gemspec')) +spec = eval(File.read("#{dir}/activemodel.gemspec")) Rake::GemPackageTask.new(spec) do |p| p.gem_spec = spec diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb index 49783c2735..c1a3f6a4a7 100644 --- a/activemodel/test/cases/helper.rb +++ b/activemodel/test/cases/helper.rb @@ -3,9 +3,11 @@ begin require "#{root}/vendor/gems/environment" rescue LoadError $:.unshift("#{root}/activesupport/lib") - $:.unshift("#{root}/activemodel/lib") end +lib = File.expand_path("#{File.dirname(__FILE__)}/../../lib") +$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) + require 'config' require 'active_model' diff --git a/activerecord/Rakefile b/activerecord/Rakefile index f7585f789b..2511f13fed 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -49,11 +49,13 @@ task :test do run_without_aborting(*tasks) end -task :isolated_test do - tasks = defined?(JRUBY_VERSION) ? - %w(isolated_test_jdbcmysql isolated_test_jdbcsqlite3 isolated_test_jdbcpostgresql) : - %w(isolated_test_mysql isolated_test_sqlite3 isolated_test_postgresql) - run_without_aborting(*tasks) +namespace :test do + task :isolated do + tasks = defined?(JRUBY_VERSION) ? + %w(isolated_test_jdbcmysql isolated_test_jdbcsqlite3 isolated_test_jdbcpostgresql) : + %w(isolated_test_mysql isolated_test_sqlite3 isolated_test_postgresql) + run_without_aborting(*tasks) + end end %w( mysql postgresql sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter| diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index 204cddde47..c84a3ac5a9 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.add_dependency('activesupport', '= 3.0.pre') s.add_dependency('activemodel', '= 3.0.pre') - s.add_dependency('arel', '~> 0.1.1') + s.add_dependency('arel', '= 0.2.pre') s.require_path = 'lib' s.autorequire = 'active_record' diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 0888c41396..3a5f3ed030 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1480,7 +1480,7 @@ module ActiveRecord if reflection.options.include?(:dependent) # Add polymorphic type if the :as option is present dependent_conditions = [] - dependent_conditions << "#{reflection.primary_key_name} = \#{record.quoted_id}" + dependent_conditions << "#{reflection.primary_key_name} = \#{record.#{reflection.name}.send(:owner_quoted_id)}" dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as] dependent_conditions << sanitize_sql(reflection.options[:conditions], reflection.quoted_table_name) if reflection.options[:conditions] dependent_conditions << extra_conditions if extra_conditions @@ -1724,7 +1724,7 @@ module ActiveRecord if (ids_array = select_limited_ids_array(options, join_dependency)).empty? throw :invalid_query else - Arel::In.new( + Arel::Predicates::In.new( Arel::SqlLiteral.new("#{connection.quote_table_name table_name}.#{primary_key}"), ids_array ) diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index 4672b0723e..c646fe488b 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -84,7 +84,7 @@ module ActiveRecord else relation = arel_table(@reflection.options[:join_table]) relation.conditions(relation[@reflection.primary_key_name].eq(@owner.id). - and(Arel::In.new(relation[@reflection.association_foreign_key], records.map(&:id))) + and(Arel::Predicates::In.new(relation[@reflection.association_foreign_key], records.map(&:id))) ).delete end end diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 29ba84ee37..cd31b0e211 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -71,7 +71,7 @@ module ActiveRecord else relation = arel_table(@reflection.table_name) relation.conditions(relation[@reflection.primary_key_name].eq(@owner.id). - and(Arel::In.new(relation[@reflection.klass.primary_key], records.map(&:id))) + and(Arel::Predicates::In.new(relation[@reflection.klass.primary_key], records.map(&:id))) ).update(relation[@reflection.primary_key_name] => nil) @owner.class.update_counters(@owner.id, cached_counter_attribute_name => -records.size) if has_cached_counter? diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 4df0f1af69..4a3ab9ea82 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/object/tap' - module ActiveRecord module AttributeMethods module Dirty diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 4e6090458a..056f29f029 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -12,7 +12,6 @@ require 'active_support/core_ext/hash/deep_merge' require 'active_support/core_ext/hash/indifferent_access' require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/string/behavior' -require 'active_support/core_ext/symbol' require 'active_support/core_ext/object/metaclass' module ActiveRecord #:nodoc: diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index edcf547e01..ca3110a374 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -250,6 +250,8 @@ module ActiveRecord assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes) end }, __FILE__, __LINE__ + + add_autosave_association_callbacks(reflection) else raise ArgumentError, "No association found for name `#{association_name}'. Has it been defined yet?" end diff --git a/activerecord/lib/active_record/notifications.rb b/activerecord/lib/active_record/notifications.rb index a5ce7ac524..562a5b91f4 100644 --- a/activerecord/lib/active_record/notifications.rb +++ b/activerecord/lib/active_record/notifications.rb @@ -1,5 +1,5 @@ require 'active_support/notifications' -ActiveSupport::Notifications.subscribe("sql") do |event| - ActiveRecord::Base.connection.log_info(event.payload[:sql], event.payload[:name], event.duration) +ActiveSupport::Notifications.subscribe("sql") do |name, before, after, result, instrumenter_id, payload| + ActiveRecord::Base.connection.log_info(payload[:sql], name, after - before) end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 6bc56ecf15..5f0eec754f 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -110,19 +110,17 @@ module ActiveRecord end def respond_to?(method) - if @relation.respond_to?(method) || Array.instance_methods.include?(method.to_s) - true - else - super - end + @relation.respond_to?(method) || Array.method_defined?(method) || super end private def method_missing(method, *args, &block) if @relation.respond_to?(method) @relation.send(method, *args, &block) - elsif Array.instance_methods.include?(method.to_s) + elsif Array.method_defined?(method) to_a.send(method, *args, &block) + else + super end end end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 0365cb592f..e8a2a72735 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/integer/even_odd' - module ActiveRecord # Raised by <tt>save!</tt> and <tt>create!</tt> when the record is invalid. Use the # +record+ method to retrieve the record which did not validate. diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index b193f8d8ba..86d14c9c81 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -659,6 +659,18 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal 1, Client.find_all_by_client_of(firm.id).size end + def test_delete_all_association_with_primary_key_deletes_correct_records + firm = Firm.find(:first) + # break the vanilla firm_id foreign key + assert_equal 2, firm.clients.count + firm.clients.first.update_attribute(:firm_id, nil) + assert_equal 1, firm.clients(true).count + assert_equal 1, firm.clients_using_primary_key_with_delete_all.count + old_record = firm.clients_using_primary_key_with_delete_all.first + firm = Firm.find(:first) + firm.destroy + assert Client.find_by_id(old_record.id).nil? + end def test_creation_respects_hash_condition ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 871cfa6468..25613da912 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -3,9 +3,11 @@ begin require "#{root}/vendor/gems/environment" rescue LoadError $:.unshift("#{root}/activesupport/lib") - $:.unshift("#{root}/activerecord/lib") end +lib = File.expand_path("#{File.dirname(__FILE__)}/../../lib") +$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) + require 'config' require 'rubygems' diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb index f9eea3d118..2529a33dab 100644 --- a/activerecord/test/cases/pooled_connections_test.rb +++ b/activerecord/test/cases/pooled_connections_test.rb @@ -105,7 +105,7 @@ class PooledConnectionsTest < ActiveRecord::TestCase Thread.new do ActiveRecord::Base.connection.rollback_db_transaction ActiveRecord::Base.connection_pool.release_connection - end.join rescue nil + end add_record('three') end diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index 99e248743a..acd214eb5a 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -176,8 +176,8 @@ class ReflectionTest < ActiveRecord::TestCase def test_reflection_of_all_associations # FIXME these assertions bust a lot - assert_equal 36, Firm.reflect_on_all_associations.size - assert_equal 26, Firm.reflect_on_all_associations(:has_many).size + assert_equal 37, Firm.reflect_on_all_associations.size + assert_equal 27, Firm.reflect_on_all_associations(:has_many).size assert_equal 10, Firm.reflect_on_all_associations(:has_one).size assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size end diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 4833d04aff..1a2c8030fb 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -78,7 +78,7 @@ class RelationTest < ActiveRecord::TestCase relation = Topic.all ["map", "uniq", "sort", "insert", "delete", "update"].each do |method| - assert relation.respond_to?(method) + assert relation.respond_to?(method), "Topic.all should respond to #{method.inspect}" end end diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index 469f5399ae..7e93fda1eb 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -68,6 +68,8 @@ class Firm < Company has_many :readonly_clients, :class_name => 'Client', :readonly => true has_many :clients_using_primary_key, :class_name => 'Client', :primary_key => 'name', :foreign_key => 'firm_name' + has_many :clients_using_primary_key_with_delete_all, :class_name => 'Client', + :primary_key => 'name', :foreign_key => 'firm_name', :dependent => :delete_all has_many :clients_grouped_by_firm_id, :class_name => "Client", :group => "firm_id", :select => "firm_id" has_many :clients_grouped_by_name, :class_name => "Client", :group => "name", :select => "name" diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb index 05c5b666ae..f2c05dd48f 100644 --- a/activerecord/test/models/pirate.rb +++ b/activerecord/test/models/pirate.rb @@ -18,7 +18,7 @@ class Pirate < ActiveRecord::Base has_many :treasure_estimates, :through => :treasures, :source => :price_estimates # These both have :autosave enabled because accepts_nested_attributes_for is used on them. - has_one :ship, :validate => true + has_one :ship has_one :non_validated_ship, :class_name => 'Ship' has_many :birds has_many :birds_with_method_callbacks, :class_name => "Bird", diff --git a/activerecord/test/models/ship.rb b/activerecord/test/models/ship.rb index d0df951622..06759d64b8 100644 --- a/activerecord/test/models/ship.rb +++ b/activerecord/test/models/ship.rb @@ -1,7 +1,7 @@ class Ship < ActiveRecord::Base self.record_timestamps = false - belongs_to :pirate, :validate => true + belongs_to :pirate has_many :parts, :class_name => 'ShipPart', :autosave => true accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? } diff --git a/activeresource/Rakefile b/activeresource/Rakefile index 834d4c0c59..6566e84d4c 100644 --- a/activeresource/Rakefile +++ b/activeresource/Rakefile @@ -35,15 +35,16 @@ Rake::TestTask.new { |t| t.warning = true } -task :isolated_test do - ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) - activesupport_path = "#{File.dirname(__FILE__)}/../activesupport/lib" - Dir.glob("test/**/*_test.rb").all? do |file| - system(ruby, '-w', "-Ilib:test:#{activesupport_path}", file) - end or raise "Failures" +namespace :test do + task :isolated do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + activesupport_path = "#{File.dirname(__FILE__)}/../activesupport/lib" + Dir.glob("test/**/*_test.rb").all? do |file| + system(ruby, '-w', "-Ilib:test:#{activesupport_path}", file) + end or raise "Failures" + end end - # Generate the RDoc documentation Rake::RDocTask.new { |rdoc| diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index ae627c365d..18105e8887 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -8,6 +8,7 @@ require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/module/aliasing' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/misc' +require 'active_support/core_ext/object/to_query' require 'set' require 'uri' @@ -273,8 +274,8 @@ module ActiveResource @site = nil else @site = create_site_uri_from(site) - @user = URI.decode(@site.user) if @site.user - @password = URI.decode(@site.password) if @site.password + @user = uri_parser.unescape(@site.user) if @site.user + @password = uri_parser.unescape(@site.password) if @site.password end end @@ -736,12 +737,12 @@ module ActiveResource # Accepts a URI and creates the site URI from that. def create_site_uri_from(site) - site.is_a?(URI) ? site.dup : URI.parse(site) + site.is_a?(URI) ? site.dup : uri_parser.parse(site) end # Accepts a URI and creates the proxy URI from that. def create_proxy_uri_from(proxy) - proxy.is_a?(URI) ? proxy.dup : URI.parse(proxy) + proxy.is_a?(URI) ? proxy.dup : uri_parser.parse(proxy) end # contains a set of the current prefix parameters. @@ -766,6 +767,10 @@ module ActiveResource [ prefix_options, query_options ] end + + def uri_parser + @uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI + end end attr_accessor :attributes #:nodoc: @@ -1151,15 +1156,16 @@ module ActiveResource def respond_to?(method, include_priv = false) method_name = method.to_s if attributes.nil? - return super + super elsif attributes.has_key?(method_name) - return true - elsif ['?','='].include?(method_name.last) && attributes.has_key?(method_name.first(-1)) - return true + true + elsif method_name =~ /(?:=|\?)$/ && attributes.include?($`) + true + else + # super must be called at the end of the method, because the inherited respond_to? + # would return true for generated readers, even if the attribute wasn't present + super end - # super must be called at the end of the method, because the inherited respond_to? - # would return true for generated readers, even if the attribute wasn't present - super end protected @@ -1248,13 +1254,15 @@ module ActiveResource def method_missing(method_symbol, *arguments) #:nodoc: method_name = method_symbol.to_s - case method_name.last + if method_name =~ /(=|\?)$/ + case $1 when "=" - attributes[method_name.first(-1)] = arguments.first + attributes[$`] = arguments.first when "?" - attributes[method_name.first(-1)] - else - attributes.has_key?(method_name) ? attributes[method_name] : super + attributes[$`] + end + else + attributes.include?(method_name) ? attributes[method_name] : super end end end diff --git a/activeresource/lib/active_resource/connection.rb b/activeresource/lib/active_resource/connection.rb index 98cb1a932b..193be89a82 100644 --- a/activeresource/lib/active_resource/connection.rb +++ b/activeresource/lib/active_resource/connection.rb @@ -31,20 +31,21 @@ module ActiveResource def initialize(site, format = ActiveResource::Formats::XmlFormat) raise ArgumentError, 'Missing site URI' unless site @user = @password = nil + @uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI self.site = site self.format = format end # Set URI for remote service. def site=(site) - @site = site.is_a?(URI) ? site : URI.parse(site) - @user = URI.decode(@site.user) if @site.user - @password = URI.decode(@site.password) if @site.password + @site = site.is_a?(URI) ? site : @uri_parser.parse(site) + @user = @uri_parser.unescape(@site.user) if @site.user + @password = @uri_parser.unescape(@site.password) if @site.password end # Set the proxy for remote service. def proxy=(proxy) - @proxy = proxy.is_a?(URI) ? proxy : URI.parse(proxy) + @proxy = proxy.is_a?(URI) ? proxy : @uri_parser.parse(proxy) end # Sets the user for remote service. diff --git a/activeresource/test/abstract_unit.rb b/activeresource/test/abstract_unit.rb index ee12f785b5..10849be20c 100644 --- a/activeresource/test/abstract_unit.rb +++ b/activeresource/test/abstract_unit.rb @@ -3,9 +3,11 @@ begin require "#{root}/vendor/gems/environment" rescue LoadError $:.unshift("#{root}/activesupport/lib") - $:.unshift("#{root}/activeresource/lib") end +lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") +$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) + require 'rubygems' require 'test/unit' require 'active_support' diff --git a/activeresource/test/cases/base/load_test.rb b/activeresource/test/cases/base/load_test.rb index 189a4d81fe..7745a9439b 100644 --- a/activeresource/test/cases/base/load_test.rb +++ b/activeresource/test/cases/base/load_test.rb @@ -1,7 +1,6 @@ require 'abstract_unit' require "fixtures/person" require "fixtures/street_address" -require 'active_support/core_ext/symbol' require 'active_support/core_ext/hash/conversions' module Highrise diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 818983fdd6..f2d957f154 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -1,13 +1,9 @@ require 'benchmark' +require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/benchmark' require 'active_support/core_ext/exception' require 'active_support/core_ext/class/attribute_accessors' - -%w(hash nil string time date date_time array big_decimal range object boolean).each do |library| - require "active_support/core_ext/#{library}/conversions" -end - -# require 'active_support/core_ext' # FIXME: pulling in all to_param extensions +require 'active_support/core_ext/object/to_param' module ActiveSupport # See ActiveSupport::Cache::Store for documentation. @@ -48,7 +44,7 @@ module ActiveSupport # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new) # # => returns MyOwnCacheStore.new def self.lookup_store(*store_option) - store, *parameters = *([ store_option ].flatten) + store, *parameters = *Array.wrap(store_option).flatten case store when Symbol diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index c53cf3f530..db140225e8 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -40,22 +40,6 @@ class Array end end - - # Calls <tt>to_param</tt> on all its elements and joins the result with - # slashes. This is used by <tt>url_for</tt> in Action Pack. - def to_param - collect { |e| e.to_param }.join '/' - end - - # Converts an array into a string suitable for use as a URL query string, - # using the given +key+ as the param name. - # - # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding" - def to_query(key) - prefix = "#{key}[]" - collect { |value| value.to_query(prefix) }.join '&' - end - # Converts a collection of elements into a formatted string by calling # <tt>to_s</tt> on all elements and joining them: # diff --git a/activesupport/lib/active_support/core_ext/boolean.rb b/activesupport/lib/active_support/core_ext/boolean.rb deleted file mode 100644 index be834288f2..0000000000 --- a/activesupport/lib/active_support/core_ext/boolean.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_support/core_ext/boolean/conversions'
\ No newline at end of file diff --git a/activesupport/lib/active_support/core_ext/boolean/conversions.rb b/activesupport/lib/active_support/core_ext/boolean/conversions.rb deleted file mode 100644 index 534ebb7118..0000000000 --- a/activesupport/lib/active_support/core_ext/boolean/conversions.rb +++ /dev/null @@ -1,11 +0,0 @@ -class TrueClass - def to_param - self - end -end - -class FalseClass - def to_param - self - end -end diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index ce3bebc25a..3dd61334d0 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -1,4 +1,5 @@ require 'active_support/duration' +require 'active_support/core_ext/time/zones' class Date class << self diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb index 54facf4430..b41ad5b686 100644 --- a/activesupport/lib/active_support/core_ext/date/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date/conversions.rb @@ -1,6 +1,7 @@ require 'active_support/inflector' require 'active_support/core_ext/time/conversions' require 'active_support/core_ext/date_time/conversions' +require 'active_support/values/time_zone' class Date DATE_FORMATS = { 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 41cf020f94..e93abfa4a3 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -1,4 +1,4 @@ -require 'rational' +require 'rational' unless RUBY_VERSION >= '1.9.2' class DateTime class << self diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb index 15a303cf04..b11c916f61 100644 --- a/activesupport/lib/active_support/core_ext/enumerable.rb +++ b/activesupport/lib/active_support/core_ext/enumerable.rb @@ -101,15 +101,6 @@ module Enumerable size = block_given? ? select(&block).size : self.size size > 1 end - - # Returns true if none of the elements match the given block. - # - # success = responses.none? {|r| r.status / 100 == 5 } - # - # This is a builtin method in Ruby 1.8.7 and later. - def none?(&block) - !any?(&block) - end unless [].respond_to?(:none?) end class Range #:nodoc: diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index bd9419e1a2..35ccec5df4 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -1,6 +1,5 @@ require 'active_support/time' -require 'active_support/core_ext/object/conversions' -require 'active_support/core_ext/array/conversions' +require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/hash/reverse_merge' class Hash @@ -68,21 +67,6 @@ class Hash ) end - # Converts a hash into a string suitable for use as a URL query string. An optional <tt>namespace</tt> can be - # passed to enclose the param names (see example below). - # - # ==== Examples - # { :name => 'David', :nationality => 'Danish' }.to_query # => "name=David&nationality=Danish" - # - # { :name => 'David', :nationality => 'Danish' }.to_query('user') # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish" - def to_query(namespace = nil) - collect do |key, value| - value.to_query(namespace ? "#{namespace}[#{key}]" : key) - end.sort * '&' - end - - alias_method :to_param, :to_query - def to_xml(options = {}) require 'builder' unless defined?(Builder) @@ -155,7 +139,7 @@ class Hash case value.class.to_s when 'Hash' if value['type'] == 'array' - child_key, entries = value.detect { |k,v| k != 'type' } # child_key is throwaway + child_key, entries = Array.wrap(value.detect { |k,v| k != 'type' }) # child_key is throwaway if entries.nil? || (c = value['__content__'] && c.blank?) [] else diff --git a/activesupport/lib/active_support/core_ext/integer.rb b/activesupport/lib/active_support/core_ext/integer.rb index 7ba018ed7f..a44a1b4c74 100644 --- a/activesupport/lib/active_support/core_ext/integer.rb +++ b/activesupport/lib/active_support/core_ext/integer.rb @@ -1,3 +1,3 @@ -require 'active_support/core_ext/integer/even_odd' +require 'active_support/core_ext/integer/multiple' require 'active_support/core_ext/integer/inflections' require 'active_support/core_ext/integer/time' diff --git a/activesupport/lib/active_support/core_ext/integer/even_odd.rb b/activesupport/lib/active_support/core_ext/integer/even_odd.rb deleted file mode 100644 index 8f9a97b44c..0000000000 --- a/activesupport/lib/active_support/core_ext/integer/even_odd.rb +++ /dev/null @@ -1,16 +0,0 @@ -class Integer - # Check whether the integer is evenly divisible by the argument. - def multiple_of?(number) - self % number == 0 - end - - # Is the integer a multiple of 2? - def even? - multiple_of? 2 - end unless method_defined?(:even?) - - # Is the integer not a multiple of 2? - def odd? - !even? - end unless method_defined?(:odd?) -end diff --git a/activesupport/lib/active_support/core_ext/integer/multiple.rb b/activesupport/lib/active_support/core_ext/integer/multiple.rb new file mode 100644 index 0000000000..40bea54c67 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/integer/multiple.rb @@ -0,0 +1,6 @@ +class Integer + # Check whether the integer is evenly divisible by the argument. + def multiple_of?(number) + self % number == 0 + end +end diff --git a/activesupport/lib/active_support/core_ext/kernel/debugger.rb b/activesupport/lib/active_support/core_ext/kernel/debugger.rb index 0813a51383..59e03e3df7 100644 --- a/activesupport/lib/active_support/core_ext/kernel/debugger.rb +++ b/activesupport/lib/active_support/core_ext/kernel/debugger.rb @@ -7,6 +7,7 @@ module Kernel end end + undef :breakpoint if respond_to?(:breakpoint) def breakpoint message = "\n***** The 'breakpoint' command has been renamed 'debugger' -- please change *****\n" defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message) diff --git a/activesupport/lib/active_support/core_ext/nil.rb b/activesupport/lib/active_support/core_ext/nil.rb deleted file mode 100644 index e9f63c4802..0000000000 --- a/activesupport/lib/active_support/core_ext/nil.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_support/core_ext/nil/conversions'
\ No newline at end of file diff --git a/activesupport/lib/active_support/core_ext/nil/conversions.rb b/activesupport/lib/active_support/core_ext/nil/conversions.rb deleted file mode 100644 index 6ceb500a2a..0000000000 --- a/activesupport/lib/active_support/core_ext/nil/conversions.rb +++ /dev/null @@ -1,5 +0,0 @@ -class NilClass - def to_param - self - end -end diff --git a/activesupport/lib/active_support/core_ext/object/conversions.rb b/activesupport/lib/active_support/core_ext/object/conversions.rb index 638f0decc1..540f7aadb0 100644 --- a/activesupport/lib/active_support/core_ext/object/conversions.rb +++ b/activesupport/lib/active_support/core_ext/object/conversions.rb @@ -1,18 +1,4 @@ +require 'active_support/core_ext/object/to_param' +require 'active_support/core_ext/object/to_query' require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/hash/conversions' - -class Object - # Alias of <tt>to_s</tt>. - def to_param - to_s - end - - # Converts an object into a string suitable for use as a URL query string, using the given <tt>key</tt> as the - # param name. - # - # Note: This method is defined as a default implementation for all Objects for Hash#to_query to work. - def to_query(key) - require 'cgi' unless defined?(CGI) && defined?(CGI::escape) - "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}" - end -end diff --git a/activesupport/lib/active_support/core_ext/object/extending.rb b/activesupport/lib/active_support/core_ext/object/extending.rb index bbf6f8563b..0cc74c8298 100644 --- a/activesupport/lib/active_support/core_ext/object/extending.rb +++ b/activesupport/lib/active_support/core_ext/object/extending.rb @@ -50,31 +50,4 @@ class Object def extend_with_included_modules_from(object) #:nodoc: object.extended_by.each { |mod| extend mod } end - - unless defined? instance_exec # 1.9 - module InstanceExecMethods #:nodoc: - end - include InstanceExecMethods - - # Evaluate the block with the given arguments within the context of - # this object, so self is set to the method receiver. - # - # From Mauricio's http://eigenclass.org/hiki/bounded+space+instance_exec - def instance_exec(*args, &block) - begin - old_critical, Thread.critical = Thread.critical, true - n = 0 - n += 1 while respond_to?(method_name = "__instance_exec#{n}") - InstanceExecMethods.module_eval { define_method(method_name, &block) } - ensure - Thread.critical = old_critical - end - - begin - send(method_name, *args) - ensure - InstanceExecMethods.module_eval { remove_method(method_name) } rescue nil - end - end - end end 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 4ecaab3bbb..866317b17a 100644 --- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb +++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb @@ -1,11 +1,4 @@ class Object - # Available in 1.8.6 and later. - unless respond_to?(:instance_variable_defined?) - def instance_variable_defined?(variable) - instance_variables.include?(variable.to_s) - end - end - # Returns a hash that maps instance variable names without "@" to their # corresponding values. Keys are strings both in Ruby 1.8 and 1.9. # diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb index 80011dfbed..3e3af03cc5 100644 --- a/activesupport/lib/active_support/core_ext/object/misc.rb +++ b/activesupport/lib/active_support/core_ext/object/misc.rb @@ -1,3 +1,2 @@ require 'active_support/core_ext/object/returning' -require 'active_support/core_ext/object/tap' require 'active_support/core_ext/object/with_options' diff --git a/activesupport/lib/active_support/core_ext/object/tap.rb b/activesupport/lib/active_support/core_ext/object/tap.rb deleted file mode 100644 index db7e715e2d..0000000000 --- a/activesupport/lib/active_support/core_ext/object/tap.rb +++ /dev/null @@ -1,16 +0,0 @@ -class Object - # Yields <code>x</code> to the block, and then returns <code>x</code>. - # The primary purpose of this method is to "tap into" a method chain, - # in order to perform operations on intermediate results within the chain. - # - # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a. - # tap { |x| puts "array: #{x.inspect}" }. - # select { |x| x%2 == 0 }. - # tap { |x| puts "evens: #{x.inspect}" }. - # map { |x| x*x }. - # tap { |x| puts "squares: #{x.inspect}" } - def tap - yield self - self - end unless Object.respond_to?(:tap) -end diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb new file mode 100644 index 0000000000..a5e2260791 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/object/to_param.rb @@ -0,0 +1,47 @@ +class Object + # Alias of <tt>to_s</tt>. + def to_param + to_s + end +end + +class NilClass + def to_param + self + end +end + +class TrueClass + def to_param + self + end +end + +class FalseClass + def to_param + self + end +end + +class Array + # Calls <tt>to_param</tt> on all its elements and joins the result with + # slashes. This is used by <tt>url_for</tt> in Action Pack. + def to_param + collect { |e| e.to_param }.join '/' + end +end + +class Hash + # Converts a hash into a string suitable for use as a URL query string. An optional <tt>namespace</tt> can be + # passed to enclose the param names (see example below). + # + # ==== Examples + # { :name => 'David', :nationality => 'Danish' }.to_query # => "name=David&nationality=Danish" + # + # { :name => 'David', :nationality => 'Danish' }.to_query('user') # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish" + def to_param(namespace = nil) + collect do |key, value| + value.to_query(namespace ? "#{namespace}[#{key}]" : key) + end.sort * '&' + end +end diff --git a/activesupport/lib/active_support/core_ext/object/to_query.rb b/activesupport/lib/active_support/core_ext/object/to_query.rb new file mode 100644 index 0000000000..3f1540f685 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/object/to_query.rb @@ -0,0 +1,27 @@ +require 'active_support/core_ext/object/to_param' + +class Object + # Converts an object into a string suitable for use as a URL query string, using the given <tt>key</tt> as the + # param name. + # + # Note: This method is defined as a default implementation for all Objects for Hash#to_query to work. + def to_query(key) + require 'cgi' unless defined?(CGI) && defined?(CGI::escape) + "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}" + end +end + +class Array + # Converts an array into a string suitable for use as a URL query string, + # using the given +key+ as the param name. + # + # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding" + def to_query(key) + prefix = "#{key}[]" + collect { |value| value.to_query(prefix) }.join '&' + end +end + +class Hash + alias_method :to_query, :to_param +end diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb index 6c52f12712..0365b6af1c 100644 --- a/activesupport/lib/active_support/core_ext/string.rb +++ b/activesupport/lib/active_support/core_ext/string.rb @@ -4,7 +4,6 @@ require 'active_support/core_ext/string/multibyte' require 'active_support/core_ext/string/starts_ends_with' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/string/access' -require 'active_support/core_ext/string/iterators' require 'active_support/core_ext/string/xchar' require 'active_support/core_ext/string/behavior' require 'active_support/core_ext/string/interpolation' diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb index 57385d86d2..182b3e745d 100644 --- a/activesupport/lib/active_support/core_ext/string/access.rb +++ b/activesupport/lib/active_support/core_ext/string/access.rb @@ -1,3 +1,5 @@ +require "active_support/multibyte" + class String unless '1.9'.respond_to?(:force_encoding) # Returns the character at the +position+ treating the string as an array (where 0 is the first character). diff --git a/activesupport/lib/active_support/core_ext/string/bytesize.rb b/activesupport/lib/active_support/core_ext/string/bytesize.rb deleted file mode 100644 index ed051b921e..0000000000 --- a/activesupport/lib/active_support/core_ext/string/bytesize.rb +++ /dev/null @@ -1,5 +0,0 @@ -unless '1.9'.respond_to?(:bytesize) - class String - alias :bytesize :size - end -end diff --git a/activesupport/lib/active_support/core_ext/string/interpolation.rb b/activesupport/lib/active_support/core_ext/string/interpolation.rb index d9159b690a..41a061c1a4 100644 --- a/activesupport/lib/active_support/core_ext/string/interpolation.rb +++ b/activesupport/lib/active_support/core_ext/string/interpolation.rb @@ -6,7 +6,6 @@ =end if RUBY_VERSION < '1.9' - require 'active_support/core_ext/string/bytesize' # KeyError is raised by String#% when the string contains a named placeholder # that is not contained in the given arguments hash. Ruby 1.9 includes and diff --git a/activesupport/lib/active_support/core_ext/string/iterators.rb b/activesupport/lib/active_support/core_ext/string/iterators.rb deleted file mode 100644 index 2f8aa84024..0000000000 --- a/activesupport/lib/active_support/core_ext/string/iterators.rb +++ /dev/null @@ -1,13 +0,0 @@ -unless '1.9'.respond_to?(:each_char) - class String - # Yields a single-character string for each character in the string. - # When $KCODE = 'UTF8', multi-byte characters are yielded appropriately. - def each_char - require 'strscan' unless defined? ::StringScanner - scanner, char = ::StringScanner.new(self), /./mu - while c = scanner.scan(char) - yield c - end - end - end -end diff --git a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb index f65bb8f75b..641acf62d0 100644 --- a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb +++ b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb @@ -1,18 +1,4 @@ class String - unless '1.8.7 and up'.respond_to?(:start_with?) - # Does the string start with the specified +prefix+? - def start_with?(prefix) - prefix = prefix.to_s - self[0, prefix.length] == prefix - end - - # Does the string end with the specified +suffix+? - def end_with?(suffix) - suffix = suffix.to_s - self[-suffix.length, suffix.length] == suffix - end - end - alias_method :starts_with?, :start_with? alias_method :ends_with?, :end_with? end diff --git a/activesupport/lib/active_support/core_ext/symbol.rb b/activesupport/lib/active_support/core_ext/symbol.rb deleted file mode 100644 index c103cd9dcf..0000000000 --- a/activesupport/lib/active_support/core_ext/symbol.rb +++ /dev/null @@ -1 +0,0 @@ -require 'active_support/core_ext/symbol/to_proc' diff --git a/activesupport/lib/active_support/core_ext/symbol/to_proc.rb b/activesupport/lib/active_support/core_ext/symbol/to_proc.rb deleted file mode 100644 index 520369452b..0000000000 --- a/activesupport/lib/active_support/core_ext/symbol/to_proc.rb +++ /dev/null @@ -1,14 +0,0 @@ -class Symbol - # Turns the symbol into a simple proc, which is especially useful for enumerations. Examples: - # - # # The same as people.collect { |p| p.name } - # people.collect(&:name) - # - # # The same as people.select { |p| p.manager? }.collect { |p| p.salary } - # people.select(&:manager?).collect(&:salary) - # - # This is a builtin method in Ruby 1.8.7 and later. - def to_proc - Proc.new { |*args| args.shift.__send__(self, *args) } - end unless :to_proc.respond_to?(:to_proc) -end diff --git a/activesupport/lib/active_support/core_ext/uri.rb b/activesupport/lib/active_support/core_ext/uri.rb index 9a1c61d99b..ca1be8b7e9 100644 --- a/activesupport/lib/active_support/core_ext/uri.rb +++ b/activesupport/lib/active_support/core_ext/uri.rb @@ -4,7 +4,8 @@ if RUBY_VERSION >= '1.9' str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese. str.force_encoding(Encoding::UTF_8) if str.respond_to?(:force_encoding) - unless str == URI.unescape(URI.escape(str)) + parser = URI::Parser.new + unless str == parser.unescape(parser.escape(str)) URI::Parser.class_eval do remove_method :unescape def unescape(str, escaped = @regexp[:ESCAPED]) diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index 7f6f012721..e858bcdc80 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -339,7 +339,7 @@ module ActiveSupport #:nodoc: next end [ nesting_camel ] - end.flatten.compact.uniq + end.compact.flatten.compact.uniq end # Search for a file in load_paths matching the provided suffix. diff --git a/activesupport/lib/active_support/deprecated_callbacks.rb b/activesupport/lib/active_support/deprecated_callbacks.rb index 20fb03cbeb..f56fef0b6d 100644 --- a/activesupport/lib/active_support/deprecated_callbacks.rb +++ b/activesupport/lib/active_support/deprecated_callbacks.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/array/extract_options' +require 'active_support/core_ext/array/wrap' module ActiveSupport # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic @@ -194,8 +195,8 @@ module ActiveSupport end def should_run_callback?(*args) - [options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } && - ![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) } + Array.wrap(options[:if]).flatten.compact.all? { |a| evaluate_method(a, *args) } && + !Array.wrap(options[:unless]).flatten.compact.any? { |a| evaluate_method(a, *args) } end end diff --git a/activesupport/lib/active_support/inflector.rb b/activesupport/lib/active_support/inflector.rb index 67aea2782f..215a60eba7 100644 --- a/activesupport/lib/active_support/inflector.rb +++ b/activesupport/lib/active_support/inflector.rb @@ -1,410 +1,7 @@ -# encoding: utf-8 -require 'iconv' -require 'active_support/core_ext/object/blank' -require 'active_support/core_ext/string/access' -require 'active_support/core_ext/string/multibyte' - -module ActiveSupport - # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without, - # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept - # in inflections.rb. - # - # The Rails core team has stated patches for the inflections library will not be accepted - # in order to avoid breaking legacy applications which may be relying on errant inflections. - # If you discover an incorrect inflection and require it for your application, you'll need - # to correct it yourself (explained below). - module Inflector - extend self - - # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional - # inflection rules. Examples: - # - # ActiveSupport::Inflector.inflections do |inflect| - # inflect.plural /^(ox)$/i, '\1\2en' - # inflect.singular /^(ox)en/i, '\1' - # - # inflect.irregular 'octopus', 'octopi' - # - # inflect.uncountable "equipment" - # end - # - # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the - # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may - # already have been loaded. - class Inflections - def self.instance - @__instance__ ||= new - end - - attr_reader :plurals, :singulars, :uncountables, :humans - - def initialize - @plurals, @singulars, @uncountables, @humans = [], [], [], [] - end - - # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression. - # The replacement should always be a string that may include references to the matched data from the rule. - def plural(rule, replacement) - @uncountables.delete(rule) if rule.is_a?(String) - @uncountables.delete(replacement) - @plurals.insert(0, [rule, replacement]) - end - - # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. - # The replacement should always be a string that may include references to the matched data from the rule. - def singular(rule, replacement) - @uncountables.delete(rule) if rule.is_a?(String) - @uncountables.delete(replacement) - @singulars.insert(0, [rule, replacement]) - end - - # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used - # for strings, not regular expressions. You simply pass the irregular in singular and plural form. - # - # Examples: - # irregular 'octopus', 'octopi' - # irregular 'person', 'people' - def irregular(singular, plural) - @uncountables.delete(singular) - @uncountables.delete(plural) - if singular[0,1].upcase == plural[0,1].upcase - plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1]) - plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1]) - singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1]) - else - plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) - plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) - plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) - plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) - singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1]) - singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1]) - end - end - - # Add uncountable words that shouldn't be attempted inflected. - # - # Examples: - # uncountable "money" - # uncountable "money", "information" - # uncountable %w( money information rice ) - def uncountable(*words) - (@uncountables << words).flatten! - end - - # Specifies a humanized form of a string by a regular expression rule or by a string mapping. - # When using a regular expression based replacement, the normal humanize formatting is called after the replacement. - # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name') - # - # Examples: - # human /_cnt$/i, '\1_count' - # human "legacy_col_person_name", "Name" - def human(rule, replacement) - @humans.insert(0, [rule, replacement]) - end - - # Clears the loaded inflections within a given scope (default is <tt>:all</tt>). - # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>, - # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>. - # - # Examples: - # clear :all - # clear :plurals - def clear(scope = :all) - case scope - when :all - @plurals, @singulars, @uncountables = [], [], [] - else - instance_variable_set "@#{scope}", [] - end - end - end - - # Yields a singleton instance of Inflector::Inflections so you can specify additional - # inflector rules. - # - # Example: - # ActiveSupport::Inflector.inflections do |inflect| - # inflect.uncountable "rails" - # end - def inflections - if block_given? - yield Inflections.instance - else - Inflections.instance - end - end - - # Returns the plural form of the word in the string. - # - # Examples: - # "post".pluralize # => "posts" - # "octopus".pluralize # => "octopi" - # "sheep".pluralize # => "sheep" - # "words".pluralize # => "words" - # "CamelOctopus".pluralize # => "CamelOctopi" - def pluralize(word) - result = word.to_s.dup - - if word.empty? || inflections.uncountables.include?(result.downcase) - result - else - inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } - result - end - end - - # The reverse of +pluralize+, returns the singular form of a word in a string. - # - # Examples: - # "posts".singularize # => "post" - # "octopi".singularize # => "octopus" - # "sheep".singularize # => "sheep" - # "word".singularize # => "word" - # "CamelOctopi".singularize # => "CamelOctopus" - def singularize(word) - result = word.to_s.dup - - if inflections.uncountables.include?(result.downcase) - result - else - inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } - result - end - end - - # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+ - # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase. - # - # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces. - # - # Examples: - # "active_record".camelize # => "ActiveRecord" - # "active_record".camelize(:lower) # => "activeRecord" - # "active_record/errors".camelize # => "ActiveRecord::Errors" - # "active_record/errors".camelize(:lower) # => "activeRecord::Errors" - def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true) - if first_letter_in_uppercase - lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } - else - lower_case_and_underscored_word.to_s.first.downcase + camelize(lower_case_and_underscored_word)[1..-1] - end - end - - # Capitalizes all the words and replaces some characters in the string to create - # a nicer looking title. +titleize+ is meant for creating pretty output. It is not - # used in the Rails internals. - # - # +titleize+ is also aliased as as +titlecase+. - # - # Examples: - # "man from the boondocks".titleize # => "Man From The Boondocks" - # "x-men: the last stand".titleize # => "X Men: The Last Stand" - def titleize(word) - humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize } - end - - # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string. - # - # Changes '::' to '/' to convert namespaces to paths. - # - # Examples: - # "ActiveRecord".underscore # => "active_record" - # "ActiveRecord::Errors".underscore # => active_record/errors - def underscore(camel_cased_word) - camel_cased_word.to_s.gsub(/::/, '/'). - gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). - gsub(/([a-z\d])([A-Z])/,'\1_\2'). - tr("-", "_"). - downcase - end - - # Replaces underscores with dashes in the string. - # - # Example: - # "puni_puni" # => "puni-puni" - def dasherize(underscored_word) - underscored_word.gsub(/_/, '-') - end - - # Capitalizes the first word and turns underscores into spaces and strips a - # trailing "_id", if any. Like +titleize+, this is meant for creating pretty output. - # - # Examples: - # "employee_salary" # => "Employee salary" - # "author_id" # => "Author" - def humanize(lower_case_and_underscored_word) - result = lower_case_and_underscored_word.to_s.dup - - inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } - result.gsub(/_id$/, "").gsub(/_/, " ").capitalize - end - - # Removes the module part from the expression in the string. - # - # Examples: - # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections" - # "Inflections".demodulize # => "Inflections" - def demodulize(class_name_in_module) - class_name_in_module.to_s.gsub(/^.*::/, '') - end - - # Replaces special characters in a string so that it may be used as part of a 'pretty' URL. - # - # ==== Examples - # - # class Person - # def to_param - # "#{id}-#{name.parameterize}" - # end - # end - # - # @person = Person.find(1) - # # => #<Person id: 1, name: "Donald E. Knuth"> - # - # <%= link_to(@person.name, person_path(@person)) %> - # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a> - def parameterize(string, sep = '-') - # replace accented chars with their ascii equivalents - parameterized_string = transliterate(string) - # Turn unwanted chars into the separator - parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep) - unless sep.blank? - re_sep = Regexp.escape(sep) - # No more than one of the separator in a row. - parameterized_string.gsub!(/#{re_sep}{2,}/, sep) - # Remove leading/trailing separator. - parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '') - end - parameterized_string.downcase - end - - - # Replaces accented characters with their ascii equivalents. - def transliterate(string) - Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s - end - - if RUBY_VERSION >= '1.9' - undef_method :transliterate - def transliterate(string) - warn "Ruby 1.9 doesn't support Unicode normalization yet" - string.dup - end - - # The iconv transliteration code doesn't function correctly - # on some platforms, but it's very fast where it does function. - elsif "foo" != (Inflector.transliterate("föö") rescue nil) - undef_method :transliterate - def transliterate(string) - string.mb_chars.normalize(:kd). # Decompose accented characters - gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics). - end - end - - # Create the name of a table like Rails does for models to table names. This method - # uses the +pluralize+ method on the last word in the string. - # - # Examples - # "RawScaledScorer".tableize # => "raw_scaled_scorers" - # "egg_and_ham".tableize # => "egg_and_hams" - # "fancyCategory".tableize # => "fancy_categories" - def tableize(class_name) - pluralize(underscore(class_name)) - end - - # Create a class name from a plural table name like Rails does for table names to models. - # Note that this returns a string and not a Class. (To convert to an actual class - # follow +classify+ with +constantize+.) - # - # Examples: - # "egg_and_hams".classify # => "EggAndHam" - # "posts".classify # => "Post" - # - # Singular names are not handled correctly: - # "business".classify # => "Busines" - def classify(table_name) - # strip out any leading schema name - camelize(singularize(table_name.to_s.sub(/.*\./, ''))) - end - - # Creates a foreign key name from a class name. - # +separate_class_name_and_id_with_underscore+ sets whether - # the method should put '_' between the name and 'id'. - # - # Examples: - # "Message".foreign_key # => "message_id" - # "Message".foreign_key(false) # => "messageid" - # "Admin::Post".foreign_key # => "post_id" - def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) - underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id") - end - - # Ruby 1.9 introduces an inherit argument for Module#const_get and - # #const_defined? and changes their default behavior. - if Module.method(:const_get).arity == 1 - # Tries to find a constant with the name specified in the argument string: - # - # "Module".constantize # => Module - # "Test::Unit".constantize # => Test::Unit - # - # The name is assumed to be the one of a top-level constant, no matter whether - # it starts with "::" or not. No lexical context is taken into account: - # - # C = 'outside' - # module M - # C = 'inside' - # C # => 'inside' - # "C".constantize # => 'outside', same as ::C - # end - # - # NameError is raised when the name is not in CamelCase or the constant is - # unknown. - def constantize(camel_cased_word) - names = camel_cased_word.split('::') - names.shift if names.empty? || names.first.empty? - - constant = Object - names.each do |name| - constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name) - end - constant - end - else - def constantize(camel_cased_word) #:nodoc: - names = camel_cased_word.split('::') - names.shift if names.empty? || names.first.empty? - - constant = Object - names.each do |name| - constant = constant.const_get(name, false) || constant.const_missing(name) - end - constant - end - end - - # Turns a number into an ordinal string used to denote the position in an - # ordered sequence such as 1st, 2nd, 3rd, 4th. - # - # Examples: - # ordinalize(1) # => "1st" - # ordinalize(2) # => "2nd" - # ordinalize(1002) # => "1002nd" - # ordinalize(1003) # => "1003rd" - def ordinalize(number) - if (11..13).include?(number.to_i % 100) - "#{number}th" - else - case number.to_i % 10 - when 1; "#{number}st" - when 2; "#{number}nd" - when 3; "#{number}rd" - else "#{number}th" - end - end - end - end -end - # in case active_support/inflector is required without the rest of active_support +require 'active_support/inflector/inflections' +require 'active_support/inflector/transliterate' +require 'active_support/inflector/methods' + require 'active_support/inflections' require 'active_support/core_ext/string/inflections' diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb new file mode 100644 index 0000000000..785e245ea4 --- /dev/null +++ b/activesupport/lib/active_support/inflector/inflections.rb @@ -0,0 +1,211 @@ +module ActiveSupport + module Inflector + # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional + # inflection rules. Examples: + # + # ActiveSupport::Inflector.inflections do |inflect| + # inflect.plural /^(ox)$/i, '\1\2en' + # inflect.singular /^(ox)en/i, '\1' + # + # inflect.irregular 'octopus', 'octopi' + # + # inflect.uncountable "equipment" + # end + # + # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the + # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may + # already have been loaded. + class Inflections + def self.instance + @__instance__ ||= new + end + + attr_reader :plurals, :singulars, :uncountables, :humans + + def initialize + @plurals, @singulars, @uncountables, @humans = [], [], [], [] + end + + # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression. + # The replacement should always be a string that may include references to the matched data from the rule. + def plural(rule, replacement) + @uncountables.delete(rule) if rule.is_a?(String) + @uncountables.delete(replacement) + @plurals.insert(0, [rule, replacement]) + end + + # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. + # The replacement should always be a string that may include references to the matched data from the rule. + def singular(rule, replacement) + @uncountables.delete(rule) if rule.is_a?(String) + @uncountables.delete(replacement) + @singulars.insert(0, [rule, replacement]) + end + + # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used + # for strings, not regular expressions. You simply pass the irregular in singular and plural form. + # + # Examples: + # irregular 'octopus', 'octopi' + # irregular 'person', 'people' + def irregular(singular, plural) + @uncountables.delete(singular) + @uncountables.delete(plural) + if singular[0,1].upcase == plural[0,1].upcase + plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1]) + plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1]) + singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1]) + else + plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) + plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) + plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) + plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) + singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1]) + singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1]) + end + end + + # Add uncountable words that shouldn't be attempted inflected. + # + # Examples: + # uncountable "money" + # uncountable "money", "information" + # uncountable %w( money information rice ) + def uncountable(*words) + (@uncountables << words).flatten! + end + + # Specifies a humanized form of a string by a regular expression rule or by a string mapping. + # When using a regular expression based replacement, the normal humanize formatting is called after the replacement. + # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name') + # + # Examples: + # human /_cnt$/i, '\1_count' + # human "legacy_col_person_name", "Name" + def human(rule, replacement) + @humans.insert(0, [rule, replacement]) + end + + # Clears the loaded inflections within a given scope (default is <tt>:all</tt>). + # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>, + # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>. + # + # Examples: + # clear :all + # clear :plurals + def clear(scope = :all) + case scope + when :all + @plurals, @singulars, @uncountables = [], [], [] + else + instance_variable_set "@#{scope}", [] + end + end + end + + # Yields a singleton instance of Inflector::Inflections so you can specify additional + # inflector rules. + # + # Example: + # ActiveSupport::Inflector.inflections do |inflect| + # inflect.uncountable "rails" + # end + def inflections + if block_given? + yield Inflections.instance + else + Inflections.instance + end + end + + # Returns the plural form of the word in the string. + # + # Examples: + # "post".pluralize # => "posts" + # "octopus".pluralize # => "octopi" + # "sheep".pluralize # => "sheep" + # "words".pluralize # => "words" + # "CamelOctopus".pluralize # => "CamelOctopi" + def pluralize(word) + result = word.to_s.dup + + if word.empty? || inflections.uncountables.include?(result.downcase) + result + else + inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } + result + end + end + + # The reverse of +pluralize+, returns the singular form of a word in a string. + # + # Examples: + # "posts".singularize # => "post" + # "octopi".singularize # => "octopus" + # "sheep".singularize # => "sheep" + # "word".singularize # => "word" + # "CamelOctopi".singularize # => "CamelOctopus" + def singularize(word) + result = word.to_s.dup + + if inflections.uncountables.include?(result.downcase) + result + else + inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } + result + end + end + + # Capitalizes the first word and turns underscores into spaces and strips a + # trailing "_id", if any. Like +titleize+, this is meant for creating pretty output. + # + # Examples: + # "employee_salary" # => "Employee salary" + # "author_id" # => "Author" + def humanize(lower_case_and_underscored_word) + result = lower_case_and_underscored_word.to_s.dup + + inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } + result.gsub(/_id$/, "").gsub(/_/, " ").capitalize + end + + # Capitalizes all the words and replaces some characters in the string to create + # a nicer looking title. +titleize+ is meant for creating pretty output. It is not + # used in the Rails internals. + # + # +titleize+ is also aliased as as +titlecase+. + # + # Examples: + # "man from the boondocks".titleize # => "Man From The Boondocks" + # "x-men: the last stand".titleize # => "X Men: The Last Stand" + def titleize(word) + humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize } + end + + # Create the name of a table like Rails does for models to table names. This method + # uses the +pluralize+ method on the last word in the string. + # + # Examples + # "RawScaledScorer".tableize # => "raw_scaled_scorers" + # "egg_and_ham".tableize # => "egg_and_hams" + # "fancyCategory".tableize # => "fancy_categories" + def tableize(class_name) + pluralize(underscore(class_name)) + end + + # Create a class name from a plural table name like Rails does for table names to models. + # Note that this returns a string and not a Class. (To convert to an actual class + # follow +classify+ with +constantize+.) + # + # Examples: + # "egg_and_hams".classify # => "EggAndHam" + # "posts".classify # => "Post" + # + # Singular names are not handled correctly: + # "business".classify # => "Busines" + def classify(table_name) + # strip out any leading schema name + camelize(singularize(table_name.to_s.sub(/.*\./, ''))) + end + end +end diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb new file mode 100644 index 0000000000..41277893e3 --- /dev/null +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -0,0 +1,139 @@ +module ActiveSupport + # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without, + # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept + # in inflections.rb. + # + # The Rails core team has stated patches for the inflections library will not be accepted + # in order to avoid breaking legacy applications which may be relying on errant inflections. + # If you discover an incorrect inflection and require it for your application, you'll need + # to correct it yourself (explained below). + module Inflector + extend self + + # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+ + # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase. + # + # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces. + # + # Examples: + # "active_record".camelize # => "ActiveRecord" + # "active_record".camelize(:lower) # => "activeRecord" + # "active_record/errors".camelize # => "ActiveRecord::Errors" + # "active_record/errors".camelize(:lower) # => "activeRecord::Errors" + def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true) + if first_letter_in_uppercase + lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } + else + lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1] + end + end + + # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string. + # + # Changes '::' to '/' to convert namespaces to paths. + # + # Examples: + # "ActiveRecord".underscore # => "active_record" + # "ActiveRecord::Errors".underscore # => active_record/errors + def underscore(camel_cased_word) + camel_cased_word.to_s.gsub(/::/, '/'). + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + tr("-", "_"). + downcase + end + + # Replaces underscores with dashes in the string. + # + # Example: + # "puni_puni" # => "puni-puni" + def dasherize(underscored_word) + underscored_word.gsub(/_/, '-') + end + + # Removes the module part from the expression in the string. + # + # Examples: + # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections" + # "Inflections".demodulize # => "Inflections" + def demodulize(class_name_in_module) + class_name_in_module.to_s.gsub(/^.*::/, '') + end + + # Creates a foreign key name from a class name. + # +separate_class_name_and_id_with_underscore+ sets whether + # the method should put '_' between the name and 'id'. + # + # Examples: + # "Message".foreign_key # => "message_id" + # "Message".foreign_key(false) # => "messageid" + # "Admin::Post".foreign_key # => "post_id" + def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) + underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id") + end + + # Ruby 1.9 introduces an inherit argument for Module#const_get and + # #const_defined? and changes their default behavior. + if Module.method(:const_get).arity == 1 + # Tries to find a constant with the name specified in the argument string: + # + # "Module".constantize # => Module + # "Test::Unit".constantize # => Test::Unit + # + # The name is assumed to be the one of a top-level constant, no matter whether + # it starts with "::" or not. No lexical context is taken into account: + # + # C = 'outside' + # module M + # C = 'inside' + # C # => 'inside' + # "C".constantize # => 'outside', same as ::C + # end + # + # NameError is raised when the name is not in CamelCase or the constant is + # unknown. + def constantize(camel_cased_word) + names = camel_cased_word.split('::') + names.shift if names.empty? || names.first.empty? + + constant = Object + names.each do |name| + constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name) + end + constant + end + else + def constantize(camel_cased_word) #:nodoc: + names = camel_cased_word.split('::') + names.shift if names.empty? || names.first.empty? + + constant = Object + names.each do |name| + constant = constant.const_get(name, false) || constant.const_missing(name) + end + constant + end + end + + # Turns a number into an ordinal string used to denote the position in an + # ordered sequence such as 1st, 2nd, 3rd, 4th. + # + # Examples: + # ordinalize(1) # => "1st" + # ordinalize(2) # => "2nd" + # ordinalize(1002) # => "1002nd" + # ordinalize(1003) # => "1003rd" + def ordinalize(number) + if (11..13).include?(number.to_i % 100) + "#{number}th" + else + case number.to_i % 10 + when 1; "#{number}st" + when 2; "#{number}nd" + when 3; "#{number}rd" + else "#{number}th" + end + end + end + end +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb new file mode 100644 index 0000000000..30a9072ee1 --- /dev/null +++ b/activesupport/lib/active_support/inflector/transliterate.rb @@ -0,0 +1,61 @@ +# encoding: utf-8 +require 'iconv' +require 'active_support/core_ext/string/multibyte' + +module ActiveSupport + module Inflector + extend self + + # Replaces accented characters with their ascii equivalents. + def transliterate(string) + Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s + end + + if RUBY_VERSION >= '1.9' + undef_method :transliterate + def transliterate(string) + warn "Ruby 1.9 doesn't support Unicode normalization yet" + string.dup + end + + # The iconv transliteration code doesn't function correctly + # on some platforms, but it's very fast where it does function. + elsif "foo" != (Inflector.transliterate("föö") rescue nil) + undef_method :transliterate + def transliterate(string) + string.mb_chars.normalize(:kd). # Decompose accented characters + gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics). + end + end + + # Replaces special characters in a string so that it may be used as part of a 'pretty' URL. + # + # ==== Examples + # + # class Person + # def to_param + # "#{id}-#{name.parameterize}" + # end + # end + # + # @person = Person.find(1) + # # => #<Person id: 1, name: "Donald E. Knuth"> + # + # <%= link_to(@person.name, person_path(@person)) %> + # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a> + def parameterize(string, sep = '-') + # replace accented chars with their ascii equivalents + parameterized_string = transliterate(string) + # Turn unwanted chars into the separator + parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep) + unless sep.nil? || sep.empty? + re_sep = Regexp.escape(sep) + # No more than one of the separator in a row. + parameterized_string.gsub!(/#{re_sep}{2,}/, sep) + # Remove leading/trailing separator. + parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '') + end + parameterized_string.downcase + end + end +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb index c6c17a3c4e..cfe28d7bb9 100644 --- a/activesupport/lib/active_support/json/backends/jsongem.rb +++ b/activesupport/lib/active_support/json/backends/jsongem.rb @@ -23,15 +23,18 @@ module ActiveSupport private def convert_dates_from(data) case data - when DATE_REGEX - DateTime.parse(data) - when Array - data.map! { |d| convert_dates_from(d) } - when Hash - data.each do |key, value| - data[key] = convert_dates_from(value) - end - else data + when nil + nil + when DATE_REGEX + DateTime.parse(data) + when Array + data.map! { |d| convert_dates_from(d) } + when Hash + data.each do |key, value| + data[key] = convert_dates_from(value) + end + else + data end end end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index f440d6ce58..8e8f9022c1 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -6,10 +6,7 @@ require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/object/instance_variables' require 'active_support/deprecation' -require 'active_support/core_ext/date_time/conversions' -require 'active_support/core_ext/time/conversions' require 'active_support/time_with_zone' -require 'active_support/values/time_zone' # Hack to load json gem first so we can overwrite its to_json. begin diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb index 282346b1a6..87e4b1ad33 100644 --- a/activesupport/lib/active_support/message_verifier.rb +++ b/activesupport/lib/active_support/message_verifier.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/string/bytesize' - module ActiveSupport # MessageVerifier makes it easy to generate and verify messages which are signed # to prevent tampering. diff --git a/activesupport/lib/active_support/multibyte.rb b/activesupport/lib/active_support/multibyte.rb index 6f2016a409..7e6f7d754b 100644 --- a/activesupport/lib/active_support/multibyte.rb +++ b/activesupport/lib/active_support/multibyte.rb @@ -4,6 +4,12 @@ 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 :UnicodeDatabase, 'active_support/multibyte/unicode_database' + autoload :Codepoint, 'active_support/multibyte/unicode_database' + autoload :UCD, 'active_support/multibyte/unicode_database' + # A list of all available normalization forms. See http://www.unicode.org/reports/tr15/tr15-29.html for more # information about normalization. NORMALIZATION_FORMS = [:c, :kc, :d, :kd] @@ -53,7 +59,4 @@ module ActiveSupport #:nodoc: end end -require 'active_support/multibyte/chars' -require 'active_support/multibyte/exceptions' -require 'active_support/multibyte/unicode_database' -require 'active_support/multibyte/utils' +require 'active_support/multibyte/utils'
\ 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 579ccc124d..c7225fec06 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -1,4 +1,5 @@ # encoding: utf-8 +require 'active_support/core_ext/string/access' require 'active_support/core_ext/string/behavior' module ActiveSupport #:nodoc: @@ -197,7 +198,7 @@ module ActiveSupport #:nodoc: # 'Café périferôl'.mb_chars.index('ô') #=> 12 # 'Café périferôl'.mb_chars.index(/\w/u) #=> 0 def index(needle, offset=0) - wrapped_offset = self.first(offset).wrapped_string.length + wrapped_offset = first(offset).wrapped_string.length index = @wrapped_string.index(needle, wrapped_offset) index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil end @@ -211,7 +212,7 @@ module ActiveSupport #:nodoc: # 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13 def rindex(needle, offset=nil) offset ||= length - wrapped_offset = self.first(offset).wrapped_string.length + wrapped_offset = first(offset).wrapped_string.length index = @wrapped_string.rindex(needle, wrapped_offset) index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil end @@ -321,7 +322,7 @@ module ActiveSupport #:nodoc: # Example: # 'Café'.mb_chars.reverse.to_s #=> 'éfaC' def reverse - chars(self.class.u_unpack(@wrapped_string).reverse.pack('U*')) + chars(self.class.g_unpack(@wrapped_string).reverse.flatten.pack('U*')) end # Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that @@ -363,6 +364,16 @@ module ActiveSupport #:nodoc: slice end + # Limit 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: + # s = 'こんにちは' + # s.mb_chars.limit(7) #=> "こに" + def limit(limit) + slice(0...translate_offset(limit)) + end + # Returns the codepoint of the first character in the string. # # Example: @@ -651,24 +662,20 @@ module ActiveSupport #:nodoc: end protected - + def translate_offset(byte_offset) #:nodoc: return nil if byte_offset.nil? return 0 if @wrapped_string == '' - chunk = @wrapped_string[0..byte_offset] + + if @wrapped_string.respond_to?(:force_encoding) + @wrapped_string = @wrapped_string.dup.force_encoding(Encoding::ASCII_8BIT) + end + begin - begin - chunk.unpack('U*').length - 1 - rescue ArgumentError => e - chunk = @wrapped_string[0..(byte_offset+=1)] - # Stop retrying at the end of the string - raise e unless byte_offset < chunk.length - # We damaged a character, retry - retry - end - # Catch the ArgumentError so we can throw our own - rescue ArgumentError - raise EncodingError, 'malformed UTF-8 character' + @wrapped_string[0...byte_offset].unpack('U*').length + rescue ArgumentError => e + byte_offset -= 1 + retry end end diff --git a/activesupport/lib/active_support/multibyte/utils.rb b/activesupport/lib/active_support/multibyte/utils.rb index 8e47763d39..b243df46d8 100644 --- a/activesupport/lib/active_support/multibyte/utils.rb +++ b/activesupport/lib/active_support/multibyte/utils.rb @@ -26,11 +26,11 @@ module ActiveSupport #:nodoc: else def self.verify(string) if expression = valid_character - for c in string.split(//) - return false unless expression.match(c) - end + # Splits the string on character boundaries, which are determined based on $KCODE. + string.split(//).all? { |c| expression.match(c) } + else + true end - true end end @@ -49,9 +49,8 @@ module ActiveSupport #:nodoc: else def self.clean(string) if expression = valid_character - stripped = []; for c in string.split(//) - stripped << c if expression.match(c) - end; stripped.join + # Splits the string on character boundaries, which are determined based on $KCODE. + string.split(//).grep(expression).join else string end diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index 9eae3bebe2..6304f496f5 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -111,7 +111,7 @@ module ActiveSupport def subscribe @queue.subscribe(@pattern) do |*args| - yield *args + yield(*args) end end end diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb index 4324e40cbb..b492648610 100644 --- a/activesupport/lib/active_support/ordered_hash.rb +++ b/activesupport/lib/active_support/ordered_hash.rb @@ -120,6 +120,13 @@ module ActiveSupport dup.merge!(other_hash) end + # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not. + def replace(other) + super + @keys = other.keys + self + end + def inspect "#<OrderedHash #{super}>" end diff --git a/activesupport/lib/active_support/ruby/shim.rb b/activesupport/lib/active_support/ruby/shim.rb index 37c57c485a..f811239077 100644 --- a/activesupport/lib/active_support/ruby/shim.rb +++ b/activesupport/lib/active_support/ruby/shim.rb @@ -4,21 +4,15 @@ # Date next_year, next_month # DateTime to_date, to_datetime, xmlschema # Enumerable group_by, each_with_object, none? -# Integer even?, odd? -# Object tap # Process Process.daemon # REXML security fix # String ord -# Symbol to_proc # Time to_date, to_time, to_datetime require 'active_support' require 'active_support/core_ext/date/calculations' require 'active_support/core_ext/date_time/conversions' require 'active_support/core_ext/enumerable' -require 'active_support/core_ext/integer/even_odd' -require 'active_support/core_ext/object/tap' require 'active_support/core_ext/process/daemon' require 'active_support/core_ext/string/conversions' require 'active_support/core_ext/rexml' -require 'active_support/core_ext/symbol/to_proc' require 'active_support/core_ext/time/conversions' diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb index 7952eb50c3..0e998d2dbe 100644 --- a/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -21,12 +21,12 @@ module ActiveSupport run_callbacks :setup result = super rescue Exception => e - result = runner.puke(self.class, self.name, e) + result = runner.puke(self.class, method_name, e) ensure begin run_callbacks :teardown, :enumerator => :reverse_each rescue Exception => e - result = runner.puke(self.class, self.name, e) + result = runner.puke(self.class, method_name, e) end end result diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 4907fae9d6..a64128e49e 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -1,4 +1,5 @@ require 'active_support/duration' +require 'active_support/values/time_zone' require 'active_support/core_ext/numeric/time' require 'active_support/core_ext/integer/time' require 'active_support/core_ext/time/conversions' diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 53a4c7acf5..e7583bef1b 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/object/blank' require 'active_support/core_ext/time' require 'active_support/core_ext/date' require 'active_support/core_ext/date_time' diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index f390c66838..dda139372e 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -1,22 +1,15 @@ ORIG_ARGV = ARGV.dup -root = File.expand_path('../../..', __FILE__) + begin - require "#{root}/vendor/gems/environment" + require File.expand_path('../../../vendor/gems/environment', __FILE__) rescue LoadError - $:.unshift("#{root}/activesupport/lib") - $:.unshift("#{root}/activerecord/lib") end +lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") +$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) require 'test/unit' - -begin - require 'mocha' -rescue LoadError - $stderr.puts 'Loading rubygems' - require 'rubygems' - require 'mocha' -end +require 'mocha' ENV['NO_RELOAD'] = '1' require 'active_support' diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 892aa97ad7..6a51ce9402 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -154,13 +154,13 @@ class FileStoreTest < ActiveSupport::TestCase File.stubs(:mtime).returns(time) @cache.write('foo', 'bar') - cache_read = lambda { @cache.read('foo', :expires_in => 1.minute) } + cache_read = lambda { @cache.read('foo', :expires_in => 60) } assert_equal 'bar', cache_read.call - Time.stubs(:now).returns(time + 30.seconds) + Time.stubs(:now).returns(time + 30) assert_equal 'bar', cache_read.call - Time.stubs(:now).returns(time + 2.minutes) + Time.stubs(:now).returns(time + 120) assert_nil cache_read.call end end diff --git a/activesupport/test/core_ext/boolean_ext_test.rb b/activesupport/test/core_ext/boolean_ext_test.rb deleted file mode 100644 index 9439716efb..0000000000 --- a/activesupport/test/core_ext/boolean_ext_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'abstract_unit' -require 'active_support/core_ext/boolean/conversions' - -class BooleanExtAccessTests < Test::Unit::TestCase - def test_to_param_on_true - assert_equal true, true.to_param - end - - def test_to_param_on_false - assert_equal false, false.to_param - end -end diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb index 4170de3dce..66f5f9fbde 100644 --- a/activesupport/test/core_ext/enumerable_test.rb +++ b/activesupport/test/core_ext/enumerable_test.rb @@ -1,6 +1,5 @@ require 'abstract_unit' require 'active_support/core_ext/array' -require 'active_support/core_ext/symbol' require 'active_support/core_ext/enumerable' Payment = Struct.new(:price) @@ -90,15 +89,4 @@ class EnumerableTests < Test::Unit::TestCase assert ![ 1, 2 ].many? {|x| x > 1 } assert [ 1, 2, 2 ].many? {|x| x > 1 } end - - def test_none - assert [].none? - assert [nil, false].none? - assert ![1].none? - - assert [].none? {|x| x > 1 } - assert ![ 2 ].none? {|x| x > 1 } - assert ![ 1, 2 ].none? {|x| x > 1 } - assert [ 1, 1 ].none? {|x| x > 1 } - end end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index eb4c37aaf0..4642bb1330 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -899,42 +899,6 @@ class HashToXmlTest < Test::Unit::TestCase # :builder, etc, shouldn't be added to options assert_equal({:skip_instruct => true}, options) end -end - -class QueryTest < Test::Unit::TestCase - def test_simple_conversion - assert_query_equal 'a=10', :a => 10 - end - - def test_cgi_escaping - assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d' - end - - def test_nil_parameter_value - empty = Object.new - def empty.to_param; nil end - assert_query_equal 'a=', 'a' => empty - end - - def test_nested_conversion - assert_query_equal 'person%5Blogin%5D=seckar&person%5Bname%5D=Nicholas', - :person => {:name => 'Nicholas', :login => 'seckar'} - end - - def test_multiple_nested - assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10', - :person => {:id => 10}, :account => {:person => {:id => 20}} - end - - def test_array_values - assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20', - :person => {:id => [10, 20]} - end - - def test_array_values_are_not_sorted - assert_query_equal 'person%5Bid%5D%5B%5D=20&person%5Bid%5D%5B%5D=10', - :person => {:id => [20, 10]} - end def test_expansion_count_is_limited expected = { @@ -962,9 +926,4 @@ class QueryTest < Test::Unit::TestCase Hash.from_xml(attack_xml) end end - - private - def assert_query_equal(expected, actual, message = nil) - assert_equal expected.split('&'), actual.to_query.split('&') - end end diff --git a/activesupport/test/core_ext/integer_ext_test.rb b/activesupport/test/core_ext/integer_ext_test.rb index 956ae5189d..e1591089f5 100644 --- a/activesupport/test/core_ext/integer_ext_test.rb +++ b/activesupport/test/core_ext/integer_ext_test.rb @@ -2,22 +2,6 @@ require 'abstract_unit' require 'active_support/core_ext/integer' class IntegerExtTest < Test::Unit::TestCase - def test_even - assert [ -2, 0, 2, 4 ].all? { |i| i.even? } - assert ![ -1, 1, 3 ].all? { |i| i.even? } - - assert 22953686867719691230002707821868552601124472329079.odd? - assert !22953686867719691230002707821868552601124472329079.even? - assert 22953686867719691230002707821868552601124472329080.even? - assert !22953686867719691230002707821868552601124472329080.odd? - end - - def test_odd - assert ![ -2, 0, 2, 4 ].all? { |i| i.odd? } - assert [ -1, 1, 3 ].all? { |i| i.odd? } - assert 1000000000000000000000000000000000000000000000000000000001.odd? - end - def test_multiple_of [ -7, 0, 7, 14 ].each { |i| assert i.multiple_of?(7) } [ -7, 7, 14 ].each { |i| assert ! i.multiple_of?(6) } diff --git a/activesupport/test/core_ext/nil_ext_test.rb b/activesupport/test/core_ext/nil_ext_test.rb deleted file mode 100644 index 1062676d65..0000000000 --- a/activesupport/test/core_ext/nil_ext_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'abstract_unit' -require 'active_support/core_ext/nil/conversions' - -class NilExtAccessTests < Test::Unit::TestCase - def test_to_param - assert_nil nil.to_param - end -end diff --git a/activesupport/test/core_ext/object/to_param_test.rb b/activesupport/test/core_ext/object/to_param_test.rb new file mode 100644 index 0000000000..c3efefddb5 --- /dev/null +++ b/activesupport/test/core_ext/object/to_param_test.rb @@ -0,0 +1,19 @@ +require 'abstract_unit' +require 'active_support/core_ext/object/to_param' + +class ToParamTest < Test::Unit::TestCase + def test_object + foo = Object.new + def foo.to_s; 'foo' end + assert_equal 'foo', foo.to_param + end + + def test_nil + assert_nil nil.to_param + end + + def test_boolean + assert_equal true, true.to_param + assert_equal false, false.to_param + end +end diff --git a/activesupport/test/core_ext/object/to_query_test.rb b/activesupport/test/core_ext/object/to_query_test.rb new file mode 100644 index 0000000000..0fb15be654 --- /dev/null +++ b/activesupport/test/core_ext/object/to_query_test.rb @@ -0,0 +1,43 @@ +require 'abstract_unit' +require 'active_support/core_ext/object/to_query' + +class ToQueryTest < Test::Unit::TestCase + def test_simple_conversion + assert_query_equal 'a=10', :a => 10 + end + + def test_cgi_escaping + assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d' + end + + def test_nil_parameter_value + empty = Object.new + def empty.to_param; nil end + assert_query_equal 'a=', 'a' => empty + end + + def test_nested_conversion + assert_query_equal 'person%5Blogin%5D=seckar&person%5Bname%5D=Nicholas', + :person => {:name => 'Nicholas', :login => 'seckar'} + end + + def test_multiple_nested + assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10', + :person => {:id => 10}, :account => {:person => {:id => 20}} + end + + def test_array_values + assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20', + :person => {:id => [10, 20]} + end + + def test_array_values_are_not_sorted + assert_query_equal 'person%5Bid%5D%5B%5D=20&person%5Bid%5D%5B%5D=10', + :person => {:id => [20, 10]} + end + + private + def assert_query_equal(expected, actual, message = nil) + assert_equal expected.split('&'), actual.to_query.split('&') + end +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 f0121b862d..e6fbdb637b 100644 --- a/activesupport/test/core_ext/object_and_class_ext_test.rb +++ b/activesupport/test/core_ext/object_and_class_ext_test.rb @@ -182,13 +182,6 @@ class ObjectInstanceVariableTest < Test::Unit::TestCase assert_equal %w(@bar @baz), @source.instance_variable_names.sort end - def test_instance_variable_defined - assert @source.instance_variable_defined?('@bar') - assert @source.instance_variable_defined?(:@bar) - assert !@source.instance_variable_defined?(:@foo) - assert !@source.instance_variable_defined?('@foo') - end - def test_copy_instance_variables_from_without_explicit_excludes assert_equal [], @dest.instance_variables @dest.copy_instance_variables_from(@source) diff --git a/activesupport/test/core_ext/object_ext_test.rb b/activesupport/test/core_ext/object_ext_test.rb deleted file mode 100644 index 484eecaab6..0000000000 --- a/activesupport/test/core_ext/object_ext_test.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'abstract_unit' -require 'active_support/core_ext/object/metaclass' -require 'active_support/core_ext/object/conversions' - -class ObjectExtTest < Test::Unit::TestCase - def test_tap_yields_and_returns_self - foo = Object.new - assert_equal foo, foo.tap { |x| assert_equal foo, x; :bar } - end - - def test_to_param - foo = Object.new - foo.class_eval("def to_s; 'foo'; end") - assert_equal 'foo', foo.to_param - end -end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 584a41b631..1e8a1c4f08 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -5,6 +5,7 @@ require 'inflector_test_cases' require 'active_support/core_ext/string' require 'active_support/core_ext/time' +require 'active_support/core_ext/kernel/reporting' class StringInflectionsTest < Test::Unit::TestCase include InflectorTestCases @@ -185,17 +186,9 @@ class StringInflectionsTest < Test::Unit::TestCase assert s.starts_with?('hel') assert !s.starts_with?('el') - assert s.start_with?('h') - assert s.start_with?('hel') - assert !s.start_with?('el') - assert s.ends_with?('o') assert s.ends_with?('lo') assert !s.ends_with?('el') - - assert s.end_with?('o') - assert s.end_with?('lo') - assert !s.end_with?('el') end def test_string_squish @@ -214,17 +207,6 @@ class StringInflectionsTest < Test::Unit::TestCase # And changes the original string: assert_equal original, expected end - - if RUBY_VERSION < '1.9' - def test_each_char_with_utf8_string_when_kcode_is_utf8 - with_kcode('UTF8') do - '€2.99'.each_char do |char| - assert_not_equal 1, char.length - break - end - end - end - end end class StringBehaviourTest < Test::Unit::TestCase @@ -350,13 +332,6 @@ class TestGetTextString < Test::Unit::TestCase end end -class StringBytesizeTest < Test::Unit::TestCase - def test_bytesize - assert_respond_to 'foo', :bytesize - assert_equal 3, 'foo'.bytesize - end -end - class OutputSafetyTest < ActiveSupport::TestCase def setup @string = "hello" diff --git a/activesupport/test/core_ext/symbol_test.rb b/activesupport/test/core_ext/symbol_test.rb deleted file mode 100644 index 1eaccb9965..0000000000 --- a/activesupport/test/core_ext/symbol_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'abstract_unit' - -class SymbolTests < Test::Unit::TestCase - def test_to_proc - assert_equal %w(one two three), [:one, :two, :three].map(&:to_s) - assert_equal(%w(one two three), - {1 => "one", 2 => "two", 3 => "three"}.sort_by(&:first).map(&:last)) - end -end diff --git a/activesupport/test/core_ext/uri_ext_test.rb b/activesupport/test/core_ext/uri_ext_test.rb index 2d4f38d095..e4a242abc4 100644 --- a/activesupport/test/core_ext/uri_ext_test.rb +++ b/activesupport/test/core_ext/uri_ext_test.rb @@ -7,7 +7,11 @@ class URIExtTest < Test::Unit::TestCase str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese. str.force_encoding(Encoding::UTF_8) if str.respond_to?(:force_encoding) - assert_equal str, URI.unescape(URI.escape(str)) - assert_equal str, URI.decode(URI.escape(str)) + if URI.const_defined?(:Parser) + parser = URI::Parser.new + assert_equal str, parser.unescape(parser.escape(str)) + else + assert_equal str, URI.unescape(URI.escape(str)) + end end end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 97d70cf8c4..0fcf1eaf00 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -3,7 +3,6 @@ require 'pp' require 'active_support/dependencies' require 'active_support/core_ext/module/loading' require 'active_support/core_ext/kernel/reporting' -require 'active_support/core_ext/symbol/to_proc' module ModuleWithMissing mattr_accessor :missing_count diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 680936ded5..0e489c10e1 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -100,9 +100,14 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase def setup @chars = UNICODE_STRING.dup.mb_chars - # NEWLINE, SPACE, EM SPACE - @whitespace = "\n#{[32, 8195].pack('U*')}" - @whitespace.force_encoding(Encoding::UTF_8) if @whitespace.respond_to?(:force_encoding) + if RUBY_VERSION < '1.9' + # Multibyte support all kinds of whitespace (ie. NEWLINE, SPACE, EM SPACE) + @whitespace = "\n\t#{[32, 8195].pack('U*')}" + else + # Ruby 1.9 only supports basic whitespace + @whitespace = "\n\t ".force_encoding(Encoding::UTF_8) + end + @byte_order_mark = [65279].pack('U') end @@ -163,6 +168,7 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert chars('').strip.kind_of?(ActiveSupport::Multibyte.proxy_class) assert chars('').reverse.kind_of?(ActiveSupport::Multibyte.proxy_class) assert chars(' ').slice(0).kind_of?(ActiveSupport::Multibyte.proxy_class) + assert chars('').limit(0).kind_of?(ActiveSupport::Multibyte.proxy_class) assert chars('').upcase.kind_of?(ActiveSupport::Multibyte.proxy_class) assert chars('').downcase.kind_of?(ActiveSupport::Multibyte.proxy_class) assert chars('').capitalize.kind_of?(ActiveSupport::Multibyte.proxy_class) @@ -190,7 +196,9 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase def test_should_return_character_offset_for_regexp_matches assert_nil(@chars =~ /wrong/u) assert_equal 0, (@chars =~ /こ/u) + assert_equal 0, (@chars =~ /こに/u) assert_equal 1, (@chars =~ /に/u) + assert_equal 2, (@chars =~ /ち/u) assert_equal 3, (@chars =~ /わ/u) end @@ -220,10 +228,10 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert !@chars.include?('a') end - def test_include_raises_type_error_when_nil_is_passed - assert_raise(TypeError) do - @chars.include?(nil) - end + def test_include_raises_when_nil_is_passed + @chars.include?(nil) + flunk "Expected chars.include?(nil) to raise TypeError or NoMethodError" + rescue Exception => e end def test_index_should_return_character_offset @@ -378,6 +386,17 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase assert_equal 'わちにこ', @chars.reverse end + def test_reverse_should_work_with_normalized_strings + str = 'bös' + reversed_str = 'söb' + assert_equal chars(reversed_str).normalize(:kc), chars(str).normalize(:kc).reverse + assert_equal chars(reversed_str).normalize(:c), chars(str).normalize(:c).reverse + assert_equal chars(reversed_str).normalize(:d), chars(str).normalize(:d).reverse + assert_equal chars(reversed_str).normalize(:kd), chars(str).normalize(:kd).reverse + assert_equal chars(reversed_str).decompose, chars(str).decompose.reverse + assert_equal chars(reversed_str).compose, chars(str).compose.reverse + end + def test_slice_should_take_character_offsets assert_equal nil, ''.mb_chars.slice(0) assert_equal 'こ', @chars.slice(0) @@ -476,6 +495,43 @@ class MultibyteCharsExtrasTest < Test::Unit::TestCase end end + def test_limit_should_not_break_on_blank_strings + example = chars('') + assert_equal example, example.limit(0) + assert_equal example, example.limit(1) + end + + 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 + + assert_equal UNICODE_STRING, example.limit(bytesize) + assert_equal '', example.limit(0) + assert_equal '', example.limit(1) + assert_equal 'こ', example.limit(3) + assert_equal 'こに', example.limit(6) + assert_equal 'こに', example.limit(8) + assert_equal 'こにち', example.limit(9) + assert_equal 'こにちわ', example.limit(50) + end + + def test_limit_should_work_on_an_ascii_string + ascii = chars(ASCII_STRING) + assert_equal ASCII_STRING, ascii.limit(ASCII_STRING.length) + assert_equal '', ascii.limit(0) + assert_equal 'o', ascii.limit(1) + assert_equal 'oh', ascii.limit(2) + assert_equal 'ohay', ascii.limit(4) + assert_equal 'ohayo', ascii.limit(50) + end + + def test_limit_should_keep_under_the_specified_byte_limit + example = chars(UNICODE_STRING) + (1..UNICODE_STRING.length).each do |limit| + assert example.limit(limit).to_s.length <= limit + end + end + def test_composition_exclusion_is_set_up_properly # Normalization of DEVANAGARI LETTER QA breaks when composition exclusion isn't used correctly qa = [0x915, 0x93c].pack('U*') @@ -586,3 +642,21 @@ class MultibyteCharsExtrasTest < Test::Unit::TestCase end.pack('U*') end end + +class MultibyteInternalsTest < ActiveSupport::TestCase + include MultibyteTestHelpers + + test "Chars translates a character offset to a byte offset" do + example = chars("Puisque c'était son erreur, il m'a aidé") + [ + [0, 0], + [3, 3], + [12, 11], + [14, 13], + [41, 39] + ].each do |byte_offset, character_offset| + assert_equal character_offset, example.send(:translate_offset, byte_offset), + "Expected byte offset #{byte_offset} to translate to #{character_offset}" + end + end +end diff --git a/activesupport/test/multibyte_utils_test.rb b/activesupport/test/multibyte_utils_test.rb index 0a2f20d282..1dff944922 100644 --- a/activesupport/test/multibyte_utils_test.rb +++ b/activesupport/test/multibyte_utils_test.rb @@ -2,6 +2,7 @@ require 'abstract_unit' require 'multibyte_test_helpers' +require 'active_support/core_ext/kernel/reporting' class MultibyteUtilsTest < ActiveSupport::TestCase include MultibyteTestHelpers diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb index 15bd57181f..1521279437 100644 --- a/activesupport/test/ordered_hash_test.rb +++ b/activesupport/test/ordered_hash_test.rb @@ -191,4 +191,11 @@ class OrderedHashTest < Test::Unit::TestCase assert_equal "odd number of arguments for Hash", $!.message end end + + def test_replace_updates_keys + @other_ordered_hash = ActiveSupport::OrderedHash[:black, '000000', :white, '000000'] + original = @ordered_hash.replace(@other_ordered_hash) + assert_same original, @ordered_hash + assert_equal @other_ordered_hash.keys, @ordered_hash.keys + end end diff --git a/activesupport/test/ts_isolated.rb b/activesupport/test/ts_isolated.rb index 9378a13766..cbab61a523 100644 --- a/activesupport/test/ts_isolated.rb +++ b/activesupport/test/ts_isolated.rb @@ -8,8 +8,8 @@ class TestIsolated < Test::Unit::TestCase Dir["#{File.dirname(__FILE__)}/**/*_test.rb"].each do |file| define_method("test #{file}") do command = "#{ruby} -Ilib:test #{file}" - silence_stderr { `#{command}` } - assert_equal 0, $?.to_i, command + result = silence_stderr { `#{command}` } + assert_block("#{command}\n#{result}") { $?.to_i.zero? } end end end diff --git a/ci/ci_build.rb b/ci/ci_build.rb index b2f9f59bec..7ae660fb7d 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -1,12 +1,18 @@ #!/usr/bin/env ruby require 'fileutils' - include FileUtils -puts "[CruiseControl] Rails build" +def root_dir + @root_dir ||= File.expand_path('../..', __FILE__) +end + +def rake(*tasks) + tasks.each { |task| return false unless system("#{root_dir}/bin/rake", task) } + true +end +puts "[CruiseControl] Rails build" build_results = {} -root_dir = File.expand_path(File.dirname(__FILE__) + "/..") # Requires gem home and path to be writeable and/or overridden to be ~/.gem, # Will enable when RubyGems supports this properly (in a coming release) @@ -16,50 +22,48 @@ root_dir = File.expand_path(File.dirname(__FILE__) + "/..") # A security hole, but there is nothing valuable on rails CI box anyway. build_results[:geminstaller] = system "sudo geminstaller --config=#{root_dir}/ci/geminstaller.yml --exceptions" -rm_f "#{root_dir}/vendor" -system "rm -rf #{root_dir}/*/vendor" cd root_dir do puts puts "[CruiseControl] Bundling RubyGems" puts - build_results[:bundle] = system 'gem bundle' + build_results[:bundle] = system 'rm -rf vendor && env CI=1 gem bundle --update && chmod 755 bin vendor vendor/gems' end cd "#{root_dir}/activesupport" do puts puts "[CruiseControl] Building ActiveSupport" puts - build_results[:activesupport] = system 'rake' - build_results[:activesupport_isolated] = system 'rake test:isolated' + build_results[:activesupport] = rake 'test' + build_results[:activesupport_isolated] = rake 'test:isolated' end -rm_f "#{root_dir}/activerecord/debug.log" -cd "#{root_dir}/activerecord" do +cd "#{root_dir}/railties" do puts - puts "[CruiseControl] Building ActiveRecord with MySQL" + puts "[CruiseControl] Building RailTies" puts - build_results[:activerecord_mysql] = system 'rake mysql:rebuild_databases && rake test_mysql' + build_results[:railties] = rake 'test' end -cd "#{root_dir}/activerecord" do +cd "#{root_dir}/actionpack" do puts - puts "[CruiseControl] Building ActiveRecord with PostgreSQL" + puts "[CruiseControl] Building ActionPack" puts - build_results[:activerecord_postgresql8] = system 'rake postgresql:rebuild_databases && rake test_postgresql' + build_results[:actionpack] = rake 'test' + build_results[:actionpack_isolated] = rake 'test:isolated' end -cd "#{root_dir}/activerecord" do +cd "#{root_dir}/actionmailer" do puts - puts "[CruiseControl] Building ActiveRecord with SQLite 3" + puts "[CruiseControl] Building ActionMailer" puts - build_results[:activerecord_sqlite3] = system 'rake test_sqlite3' + build_results[:actionmailer] = rake 'test' end cd "#{root_dir}/activemodel" do puts puts "[CruiseControl] Building ActiveModel" puts - build_results[:activemodel] = system 'rake' + build_results[:activemodel] = rake 'test' end rm_f "#{root_dir}/activeresource/debug.log" @@ -67,29 +71,29 @@ cd "#{root_dir}/activeresource" do puts puts "[CruiseControl] Building ActiveResource" puts - build_results[:activeresource] = system 'rake' + build_results[:activeresource] = rake 'test' end -cd "#{root_dir}/actionpack" do +rm_f "#{root_dir}/activerecord/debug.log" +cd "#{root_dir}/activerecord" do puts - puts "[CruiseControl] Building ActionPack" + puts "[CruiseControl] Building ActiveRecord with MySQL" puts - build_results[:actionpack] = system 'rake' - build_results[:actionpack_isolated] = system 'rake test:isolated' + build_results[:activerecord_mysql] = rake 'mysql:rebuild_databases', 'test_mysql' end -cd "#{root_dir}/actionmailer" do +cd "#{root_dir}/activerecord" do puts - puts "[CruiseControl] Building ActionMailer" + puts "[CruiseControl] Building ActiveRecord with PostgreSQL" puts - build_results[:actionmailer] = system 'rake' + build_results[:activerecord_postgresql8] = rake 'postgresql:rebuild_databases', 'test_postgresql' end -cd "#{root_dir}/railties" do +cd "#{root_dir}/activerecord" do puts - puts "[CruiseControl] Building RailTies" + puts "[CruiseControl] Building ActiveRecord with SQLite 3" puts - build_results[:railties] = system 'rake' + build_results[:activerecord_sqlite3] = rake 'test_sqlite3' end @@ -102,6 +106,8 @@ puts "[CruiseControl] #{`mysql --version`}" puts "[CruiseControl] #{`pg_config --version`}" puts "[CruiseControl] SQLite3: #{`sqlite3 -version`}" `gem env`.each_line {|line| print "[CruiseControl] #{line}"} +puts "[CruiseControl] Bundled gems:" +`gem bundle --list`.each_line {|line| print "[CruiseControl] #{line}"} puts "[CruiseControl] Local gems:" `gem list`.each_line {|line| print "[CruiseControl] #{line}"} diff --git a/ci/geminstaller.yml b/ci/geminstaller.yml index 70729ea34a..776ae8d98d 100644 --- a/ci/geminstaller.yml +++ b/ci/geminstaller.yml @@ -1,29 +1,8 @@ --- gems: -- name: erubis - version: >= 2.6.5 - name: geminstaller version: >= 0.4.3 -- name: fcgi - version: >= 0.8.7 -- name: memcache-client - version: >= 1.5.0 -- name: mocha - version: >= 0.9.7 -- name: mysql - #version: >= 2.7 - version: = 2.7 -- name: nokogiri - version: >= 1.3.3 -- name: pg - version: >= 0.8.0 -- name: rack - version: '~> 1.0.0' -- name: rack-test - version: >= 0.5.0 -- name: rake - version: >= 0.8.1 -- name: sqlite3-ruby - version: >= 1.2.2 - name: rubygems-update - version: >= 1.3.3 + version: >= 1.3.5 +- name: bundler + version: >= 0.6.0 diff --git a/railties/Rakefile b/railties/Rakefile index 3a87a88ddc..e6f698fc74 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -6,12 +6,8 @@ require 'rake/gempackagetask' require 'date' require 'rbconfig' -begin - require File.expand_path('../../vendor/gems/environment', __FILE__) -rescue LoadError -end $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/lib" -require 'rails' +require 'rails/version' PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : '' PKG_NAME = ENV['PKG_NAME'] || 'rails' @@ -26,21 +22,23 @@ RUBY_FORGE_USER = "webster132" task :default => :test +task :test => 'test:isolated' ## This is required until the regular test task ## below passes. It's not ideal, but at least ## we can see the failures -task :test do - dir = ENV["TEST_DIR"] || "**" - Dir["test/#{dir}/*_test.rb"].all? do |file| - next true if file.include?("fixtures") - ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) - system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file) - end or raise "Failures" -end -task :isolated_test => :test - -Rake::TestTask.new("regular_test") do |t| +namespace :test do + task :isolated do + dir = ENV["TEST_DIR"] || "**" + Dir["test/#{dir}/*_test.rb"].all? do |file| + next true if file.include?("fixtures") + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file) + end or raise "Failures" + end +end + +Rake::TestTask.new('test:regular') do |t| t.libs << 'test' << "#{File.dirname(__FILE__)}/../activesupport/lib" t.pattern = 'test/**/*_test.rb' t.warning = true @@ -152,7 +150,7 @@ end # Publishing ------------------------------------------------------- desc "Publish the rails gem" -task :pgem => [:gem] do +task :pgem => [:gem] do require 'rake/contrib/sshpublisher' Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload `ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'` diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 26a55a73e1..b43dcb0041 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,6 +1,6 @@ module Rails class Application - extend Initializable + include Initializable class << self # Stub out App initialize @@ -8,6 +8,10 @@ module Rails new end + def new + @instance ||= super + end + def config @config ||= Configuration.new end @@ -27,23 +31,36 @@ module Rails config.root end - def routes - ActionController::Routing::Routes + def call(env) + new.call(env) end + end - def middleware - config.middleware - end + def initialize + run_initializers + end - def call(env) - @app ||= middleware.build(routes) - @app.call(env) - end + def config + self.class.config + end - def new - run_initializers - self - end + alias configuration config + + def plugin_loader + self.class.plugin_loader + end + + def middleware + config.middleware + end + + def routes + ActionController::Routing::Routes + end + + def call(env) + @app ||= middleware.build(routes) + @app.call(env) end initializer :initialize_rails do @@ -242,6 +259,7 @@ module Rails # If assigned value cannot be matched to a TimeZone, an exception will be raised. initializer :initialize_time_zone do if config.time_zone + require 'active_support/core_ext/time/zones' zone_default = Time.__send__(:get_zone, config.time_zone) unless zone_default @@ -411,17 +429,6 @@ module Rails end end - # Configure generators if they were already loaded - # === - # TODO: Does this need to be an initializer here? - initializer :initialize_generators do - if defined?(Rails::Generators) - Rails::Generators.no_color! unless config.generators.colorize_logging - Rails::Generators.aliases.deep_merge! config.generators.aliases - Rails::Generators.options.deep_merge! config.generators.options - end - end - # For each framework, search for instrument file with Notifications hooks. # initializer :load_notifications_hooks do diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb index 1270fdd033..f85c17bb94 100644 --- a/railties/lib/rails/commands/destroy.rb +++ b/railties/lib/rails/commands/destroy.rb @@ -1,4 +1,5 @@ -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'generators')) +require 'rails/generators' +Rails::Generators.configure! if ARGV.size == 0 Rails::Generators.help diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb index d91dcf9788..c5e3ae3529 100755 --- a/railties/lib/rails/commands/generate.rb +++ b/railties/lib/rails/commands/generate.rb @@ -1,4 +1,5 @@ -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'generators')) +require 'rails/generators' +Rails::Generators.configure! if ARGV.size == 0 Rails::Generators.help diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 0a545f23de..2b847ba711 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -278,12 +278,16 @@ module Rails end def method_missing(method, *args) - method = method.to_s.sub(/=$/, '').to_sym - namespace = args.first.is_a?(Symbol) ? args.shift : nil - configuration = args.first.is_a?(Hash) ? args.shift : nil + method = method.to_s.sub(/=$/, '').to_sym - @options[:rails][method] = namespace if namespace - namespace ||= method + if method == :rails + namespace, configuration = :rails, args.shift + elsif args.first.is_a?(Hash) + namespace, configuration = method, args.shift + else + namespace, configuration = args.shift, args.shift + @options[:rails][method] = namespace + end if configuration aliases = configuration.delete(:aliases) diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 49f32aa0db..19412c259e 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -9,7 +9,7 @@ require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/string/inflections' # TODO: Do not always push on vendored thor -$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.11.8/lib") +$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.12.0/lib") require 'rails/generators/base' require 'rails/generators/named_base' @@ -72,6 +72,12 @@ module Rails } } + def self.configure!(config = Rails.application.config.generators) #:nodoc: + no_color! unless config.colorize_logging + aliases.deep_merge! config.aliases + options.deep_merge! config.options + end + def self.aliases #:nodoc: @aliases ||= DEFAULT_ALIASES.dup end @@ -152,7 +158,18 @@ module Rails end load_paths # Cache load paths. Needed to avoid __FILE__ pointing to wrong paths. - # Receives a namespace and tries different combinations to find a generator. + # Rails finds namespaces exactly as thor, with three conveniences: + # + # 1) If your generator name ends with generator, as WebratGenerator, it sets + # its namespace to "webrat", so it can be invoked as "webrat" and not + # "webrat_generator"; + # + # 2) If your generator has a generators namespace, as Rails::Generators::WebratGenerator, + # the namespace is set to "rails:generators:webrat", but Rails allows it + # to be invoked simply as "rails:webrat". The "generators" is added + # automatically when doing the lookup; + # + # 3) Rails looks in load paths and loads the generator just before it's going to be used. # # ==== Examples # @@ -162,30 +179,29 @@ module Rails # # "rails:generators:webrat", "webrat:generators:integration", "webrat" # - # If the namespace has ":" included we consider that a absolute namespace - # was given and the lookup above does not happen. Just the name is searched. + # On the other hand, if "rails:webrat" is given, it will search for: # - # Finally, it deals with one kind of shortcut: + # "rails:generators:webrat", "rails:webrat" # - # find_by_namespace "test_unit:model" - # - # It will search for generators at: - # - # "test_unit:generators:model", "test_unit:model" + # Notice that the "generators" namespace is handled automatically by Rails, + # so you don't need to type it when you want to invoke a generator in specific. # def self.find_by_namespace(name, base=nil, context=nil) #:nodoc: - name, attempts = name.to_s, [] + name, attempts = name.to_s, [ ] case name.count(':') when 1 base, name = name.split(':') return find_by_namespace(name, base) when 0 - attempts << "#{base}:generators:#{name}" if base - attempts << "#{name}:generators:#{context}" if context + attempts += generator_names(base, name) if base + attempts += generator_names(name, context) if context end attempts << name + attempts += generator_names(name, name) unless name.include?(?:) + attempts.uniq! + unloaded = attempts - namespaces lookup(unloaded) @@ -231,7 +247,10 @@ module Rails until tail.empty? others += Dir[File.join(path, *tail)].collect do |file| - file.split('/')[-tail.size, 2].join(':').sub(/_generator\.rb$/, '') + name = file.split('/')[-tail.size, 2] + name.last.sub!(/_generator\.rb$/, '') + name.uniq! + name.join(':') end tail.shift end @@ -246,7 +265,7 @@ module Rails # Return all defined namespaces. # def self.namespaces #:nodoc: - Thor::Base.subclasses.map{ |klass| klass.namespace } + Thor::Base.subclasses.map { |klass| klass.namespace } end # Keep builtin generators in an Array[Array[group, name]]. @@ -257,6 +276,12 @@ module Rails end end + # By default, Rails strips the generator namespace to make invocations + # easier. This method generaters the both possibilities names. + def self.generator_names(first, second) + [ "#{first}:generators:#{second}", "#{first}:#{second}" ] + end + # Try callbacks for the given base. # def self.invoke_fallbacks_for(name, base) @@ -285,6 +310,9 @@ module Rails Dir[File.join(path, '**', attempts)].each do |file| begin require file + rescue NameError => e + raise unless e.message =~ /Rails::Generator/ + warn "[WARNING] Could not load generator at #{file.inspect} because it's a Rails 2.x generator, which is not supported anymore" rescue Exception => e warn "[WARNING] Could not load generator at #{file.inspect}. Error: #{e.message}" end diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 9254f8d918..8677bf283b 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -1,4 +1,5 @@ require 'open-uri' +require 'active_support/deprecation' module Rails module Generators @@ -45,19 +46,56 @@ module Rails # # gem "rspec", :env => :test # gem "technoweenie-restful-authentication", :lib => "restful-authentication", :source => "http://gems.github.com/" + # gem "rails", "3.0", :git => "git://github.com/rails/rails" # - def gem(name, options={}) - log :gem, name - env = options.delete(:env) + def gem(*args) + options = args.extract_options! + name, version = args - gems_code = "config.gem '#{name}'" + # Deal with deprecated options + { :env => :only, :lib => :require_as }.each do |old, new| + next unless options[old] + options[new] = options.delete(old) + ActiveSupport::Deprecation.warn "#{old.inspect} option in gem is deprecated, use #{new.inspect} instead" + end + + # Deal with deprecated source + if source = options.delete(:source) + ActiveSupport::Deprecation.warn ":source option in gem is deprecated, use add_source method instead" + add_source(source) + end + + # Set the message to be shown in logs. Uses the git repo if one is given, + # otherwise use name (version). + parts, message = [ name.inspect ], name + if version ||= options.delete(:version) + parts << version + message << " (#{version})" + end + message = options[:git] if options[:git] + + log :gemfile, message + + options.each do |option, value| + parts << ":#{option} => #{value.inspect}" + end - if options.any? - opts = options.inject([]) {|result, h| result << [":#{h[0]} => #{h[1].inspect.gsub('"',"'")}"] }.sort.join(", ") - gems_code << ", #{opts}" + in_root do + append_file "Gemfile", "gem #{parts.join(", ")}", :verbose => false end + end + + # Add the given source to Gemfile + # + # ==== Example + # + # source "http://gems.github.com/" + def add_source(source, options={}) + log :source, source - environment gems_code, :env => env + in_root do + prepend_file "Gemfile", "source #{source.inspect}", :verbose => false + end end # Adds a line inside the Initializer block for config/environment.rb. @@ -79,6 +117,7 @@ module Rails end end end + alias :application :environment # Run a command in git. # @@ -222,9 +261,8 @@ module Rails # # freeze! # - def freeze!(args = {}) - log :vendor, "rails" - in_root { run("#{extify(:rake)} rails:freeze:edge", :verbose => false) } + def freeze!(args={}) + ActiveSupport::Deprecation.warn "freeze! is deprecated since your rails app now comes bundled with Rails by default, please check your Gemfile" end # Make an entry in Rails routing file conifg/routes.rb @@ -251,6 +289,7 @@ module Rails if args.size == 1 say args.first.to_s else + args << (self.behavior == :invoke ? :green : :red) say_status *args end end diff --git a/railties/lib/rails/generators/active_record.rb b/railties/lib/rails/generators/active_record.rb index babad33db3..c62f75c384 100644 --- a/railties/lib/rails/generators/active_record.rb +++ b/railties/lib/rails/generators/active_record.rb @@ -1,6 +1,7 @@ require 'rails/generators/named_base' require 'rails/generators/migration' require 'rails/generators/active_model' +require 'active_record' module ActiveRecord module Generators diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 7af99797ea..226ae63963 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -12,11 +12,24 @@ module Rails add_runtime_options! + # Always move to rails source root. + # + def initialize(*args) #:nodoc: + if !invoked?(args) && defined?(Rails.root) && Rails.root + self.destination_root = Rails.root + FileUtils.cd(destination_root) + end + super + end + # Automatically sets the source root based on the class name. # def self.source_root - @_rails_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), - base_name, generator_name, 'templates')) + @_rails_source_root ||= begin + if base_name && generator_name + File.expand_path(File.join(File.dirname(__FILE__), base_name, generator_name, 'templates')) + end + end end # Tries to get the description from a USAGE file one folder above the source @@ -201,9 +214,12 @@ module Rails # def self.inherited(base) #:nodoc: super - base.source_root # Cache source root - if Rails.root && base.name !~ /Base$/ + # Cache source root, we need to do this, since __FILE__ is a relative value + # and can point to wrong directions when inside an specified directory. + base.source_root + + if base.name && base.name !~ /Base$/ && base.base_name && base.generator_name && defined?(Rails.root) && Rails.root path = File.expand_path(File.join(Rails.root, 'lib', 'templates')) if base.name.include?('::') base.source_paths << File.join(path, base.base_name, base.generator_name) @@ -247,6 +263,13 @@ module Rails end end + # Check if this generator was invoked from another one by inspecting + # parameters. + # + def invoked?(args) + args.last.is_a?(Hash) && args.last.key?(:invocations) + end + # Use Rails default banner. # def self.banner @@ -256,17 +279,24 @@ module Rails # Sets the base_name taking into account the current class namespace. # def self.base_name - @base_name ||= self.name.split('::').first.underscore + @base_name ||= begin + if base = name.to_s.split('::').first + base.underscore + end + end end # Removes the namespaces and get the generator name. For example, # Rails::Generators::MetalGenerator will return "metal" as generator name. # def self.generator_name - @generator_name ||= begin - klass_name = self.name.split('::').last - klass_name.sub!(/Generator$/, '') - klass_name.underscore + if name + @generator_name ||= begin + if klass_name = name.to_s.split('::').last + klass_name.sub!(/Generator$/, '') + klass_name.underscore + end + end end end @@ -274,35 +304,27 @@ module Rails # Rails::Generators.options. # def self.default_value_for_option(name, options) - config = Rails::Generators.options - generator, base = generator_name.to_sym, base_name.to_sym - - if config[generator] && config[generator].key?(name) - config[generator][name] - elsif config[base] && config[base].key?(name) - config[base][name] - elsif config[:rails].key?(name) - config[:rails][name] - else - options[:default] - end + default_for_option(Rails::Generators.options, name, options, options[:default]) end # Return default aliases for the option name given doing a lookup in # Rails::Generators.aliases. # def self.default_aliases_for_option(name, options) - config = Rails::Generators.aliases - generator, base = generator_name.to_sym, base_name.to_sym + default_for_option(Rails::Generators.aliases, name, options, options[:aliases]) + end - if config[generator] && config[generator].key?(name) - config[generator][name] - elsif config[base] && config[base].key?(name) - config[base][name] + # Return default for the option name given doing a lookup in config. + # + def self.default_for_option(config, name, options, default) + if generator_name and c = config[generator_name.to_sym] and c.key?(name) + c[name] + elsif base_name and c = config[base_name.to_sym] and c.key?(name) + c[name] elsif config[:rails].key?(name) config[:rails][name] else - options[:aliases] + default end end diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 0e5976f915..1d4f52286e 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -11,7 +11,10 @@ module Rails alias :file_name :singular_name - def initialize(*args) #:nodoc: + def initialize(args, *options) #:nodoc: + # Unfreeze name in case it's given as a frozen string + args[0] = args[0].dup if args[0].is_a?(String) && args[0].frozen? + super assign_names!(self.name) parse_attributes! if respond_to?(:attributes) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 93d9ac553d..2bcea4bc8f 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -12,9 +12,6 @@ module Rails::Generators class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" - class_option :freeze, :type => :boolean, :aliases => "-F", :default => false, - :desc => "Freeze Rails in vendor/rails from the gems" - class_option :template, :type => :string, :aliases => "-m", :desc => "Path to an application template (can be a filesystem path or URL)." @@ -126,8 +123,10 @@ module Rails::Generators end def create_script_files - directory "script" - chmod "script", 0755, :verbose => false + directory "script" do |file| + prepend_file file, "#{shebang}\n", :verbose => false + chmod file, 0755, :verbose => false + end end def create_test_files @@ -155,10 +154,6 @@ module Rails::Generators raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}" end - def freeze? - freeze! if options[:freeze] - end - protected attr_accessor :rails_template diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 3966c0f70d..8e851a64e7 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -1,20 +1,17 @@ -# Gemfile is where you list all of your application's dependencies -# -<%= "# " if options.freeze? %>gem "rails", "<%= Rails::VERSION::STRING %>" -# -# Bundling edge rails: -<%= "# " unless options.freeze? %>gem "rails", "<%= Rails::VERSION::STRING %>", :git => "git://github.com/rails/rails.git" +# Edit this Gemfile to bundle your application's dependencies. -# Specify gemcutter as a gem source -# source "http://gemcutter.org" +gem "rails", "<%= Rails::VERSION::STRING %>" -# Specify gems that this application depends on and have them installed with rake gems:install +## Bundle edge rails: +# gem "rails", :git => "git://github.com/rails/rails.git" + +## Bundle the gems you use: # gem "bj" # gem "hpricot", "0.6" # gem "sqlite3-ruby", :require_as => "sqlite3" # gem "aws-s3", :require_as => "aws/s3" -# Specify gems that should only be required in certain environments +## Bundle gems used only in certain environments: # gem "rspec", :only => :test # only :test do # gem "webrat" diff --git a/railties/lib/rails/generators/rails/app/templates/script/about.tt b/railties/lib/rails/generators/rails/app/templates/script/about index 7639d4040f..93fd007649 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/about.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/about @@ -1,4 +1,3 @@ -<%= shebang %> require File.expand_path('../../config/environment', __FILE__) $LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info" require 'rails/commands/about' diff --git a/railties/lib/rails/generators/rails/app/templates/script/console.tt b/railties/lib/rails/generators/rails/app/templates/script/console index 1cd2eb8b53..20aa799d2f 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/console.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/console @@ -1,3 +1,2 @@ -<%= shebang %> require File.expand_path('../../config/application', __FILE__) require 'rails/commands/console' diff --git a/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt b/railties/lib/rails/generators/rails/app/templates/script/dbconsole index 94beb13715..e6a1c59394 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/dbconsole @@ -1,3 +1,2 @@ -<%= shebang %> require File.expand_path('../../config/application', __FILE__) require 'rails/commands/dbconsole' diff --git a/railties/lib/rails/generators/rails/app/templates/script/destroy b/railties/lib/rails/generators/rails/app/templates/script/destroy new file mode 100755 index 0000000000..adfa8e8426 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/script/destroy @@ -0,0 +1,2 @@ +require File.expand_path('../../config/environment', __FILE__) +require 'rails/commands/destroy' diff --git a/railties/lib/rails/generators/rails/app/templates/script/destroy.tt b/railties/lib/rails/generators/rails/app/templates/script/destroy.tt deleted file mode 100755 index c97090cdee..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/script/destroy.tt +++ /dev/null @@ -1,3 +0,0 @@ -<%= shebang %> -require File.expand_path('../../config/application', __FILE__) -require 'rails/commands/destroy' diff --git a/railties/lib/rails/generators/rails/app/templates/script/generate.tt b/railties/lib/rails/generators/rails/app/templates/script/generate index 26f029c6a6..6fb8ad0395 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/generate.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/generate @@ -1,3 +1,2 @@ -<%= shebang %> require File.expand_path('../../config/environment', __FILE__) require 'rails/commands/generate' diff --git a/railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker.tt b/railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker index 9ebc4c92fc..9647d8f10a 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker @@ -1,3 +1,2 @@ -<%= shebang %> require File.expand_path('../../../config/environment', __FILE__) require 'rails/commands/performance/benchmarker' diff --git a/railties/lib/rails/generators/rails/app/templates/script/performance/profiler.tt b/railties/lib/rails/generators/rails/app/templates/script/performance/profiler index 5f4c763f9d..a5822042d2 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/performance/profiler.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/performance/profiler @@ -1,3 +1,2 @@ -<%= shebang %> require File.expand_path('../../../config/environment', __FILE__) require 'rails/commands/performance/profiler' diff --git a/railties/lib/rails/generators/rails/app/templates/script/plugin.tt b/railties/lib/rails/generators/rails/app/templates/script/plugin index 4a335ee33c..1f1af6c880 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/plugin.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/plugin @@ -1,3 +1,2 @@ -<%= shebang %> require File.expand_path('../../config/application', __FILE__) require 'rails/commands/plugin' diff --git a/railties/lib/rails/generators/rails/app/templates/script/runner.tt b/railties/lib/rails/generators/rails/app/templates/script/runner index 34ad7c18eb..7a70828e90 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/runner.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/runner @@ -1,3 +1,2 @@ -<%= shebang %> require File.expand_path('../../config/environment', __FILE__) require 'rails/commands/runner' diff --git a/railties/lib/rails/generators/rails/app/templates/script/server.tt b/railties/lib/rails/generators/rails/app/templates/script/server index 932e72ea58..a7aaee2953 100755 --- a/railties/lib/rails/generators/rails/app/templates/script/server.tt +++ b/railties/lib/rails/generators/rails/app/templates/script/server @@ -1,3 +1,2 @@ -<%= shebang %> require File.expand_path('../../config/application', __FILE__) require 'rails/commands/server' diff --git a/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb b/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb index 4b60558b43..a3dc38d9e4 100644 --- a/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb +++ b/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb @@ -1,5 +1,5 @@ require 'test_helper' -require 'performance_test_help' +require 'rails/performance_test_help' # Profiling results for each test method are written to tmp/performance. class BrowsingTest < ActionController::PerformanceTest diff --git a/railties/lib/rails/generators/resource_helpers.rb b/railties/lib/rails/generators/resource_helpers.rb index 0385581083..99954e2292 100644 --- a/railties/lib/rails/generators/resource_helpers.rb +++ b/railties/lib/rails/generators/resource_helpers.rb @@ -6,6 +6,8 @@ module Rails # ActiveModel. # module ResourceHelpers + mattr_accessor :skip_warn + def self.included(base) #:nodoc: base.send :attr_reader, :controller_name, :controller_class_name, :controller_file_name, :controller_class_path, :controller_file_path @@ -19,7 +21,11 @@ module Rails super if name == name.pluralize && !options[:force_plural] - say "Plural version of the model detected, using singularized version. Override with --force-plural." + unless ResourceHelpers.skip_warn + say "Plural version of the model detected, using singularized version. Override with --force-plural." + ResourceHelpers.skip_warn = true + end + name.replace name.singularize assign_names!(self.name) end diff --git a/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb b/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb index 27c91b0fca..362e3dc09f 100644 --- a/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb +++ b/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb @@ -1,5 +1,5 @@ require 'test_helper' -require 'performance_test_help' +require 'rails/performance_test_help' class <%= class_name %>Test < ActionController::PerformanceTest # Replace this with your real tests. diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb index c491d5e012..d78eab9a75 100644 --- a/railties/lib/rails/initializable.rb +++ b/railties/lib/rails/initializable.rb @@ -1,93 +1,116 @@ module Rails module Initializable - def self.included(klass) - klass.instance_eval do - extend Rails::Initializable - extend Rails::Initializable::ClassMethodsWhenIncluded - include Rails::Initializable::InstanceMethodsWhenIncluded - end + def self.included(base) + base.extend ClassMethods end - def self.extended(klass) - klass.extend Initializer - end + class Initializer + attr_reader :name, :before, :after, :global, :block - class Collection < Array - def initialize(klasses) - klasses.each do |klass| - (klass.added_initializers || []).each do |initializer| - index = if initializer.before - index_for(initializer.before) - elsif initializer.after - index_for(initializer.after) + 1 - else - length - end - - insert(index, initializer) - end - end + def initialize(name, context, options, &block) + @name, @context, @options, @block = name, context, options, block end - def index_for(name) - inst = find {|i| i.name == name } - inst && index(inst) + def before + @options[:before] end - end + def after + @options[:after] + end - attr_reader :added_initializers + def global + @options[:global] + end - # When you include Rails::Initializable, this method will be on instances - # of the class included into. When you extend it, it will be on the - # class or module itself. - # - # The #initializers method is set up to return the right list of - # initializers for the context in question. - def run_initializers - return if @_initialized + alias global? global - initializers.each {|initializer| instance_eval(&initializer.block) } + def run(*args) + @context.instance_exec(*args, &block) + end - @_initialized = true + def bind(context) + return self if @context + Initializer.new(@name, context, @options, &block) + end end - module Initializer - Initializer = Struct.new(:name, :before, :after, :block, :global) - - def all_initializers - klasses = ancestors.select {|klass| klass.is_a?(Initializable) }.reverse - initializers = Collection.new(klasses) + class Collection < Array + def initialize(initializers = []) + super() + initializers.each do |initializer| + if initializer.before + index = index_for(initializer.before) + elsif initializer.after + index = index_for(initializer.after) + 1 + else + index = length + end + insert(index || -1, initializer) + end end - alias initializers all_initializers + def +(other) + Collection.new(to_a + other.to_a) + end - def initializer(name, options = {}, &block) - @added_initializers ||= [] - @added_initializers << - Initializer.new(name, options[:before], options[:after], block, options[:global]) + def index_for(name) + initializer = find { |i| i.name == name } + initializer && index(initializer) end end - module ClassMethodsWhenIncluded - def initializers - all_initializers.select {|i| i.global == true } + def run_initializers(*args) + return if @ran + initializers.each do |initializer| + initializer.run(*args) end + @ran = true + end + def initializers + @initializers ||= begin + initializers = self.class.initializers_for(:instance) + Collection.new(initializers.map { |i| i.bind(self) }) + end end - module InstanceMethodsWhenIncluded + module ClassMethods def initializers - self.class.all_initializers.reject {|i| i.global == true } + @initializers ||= [] + end + + def initializers_for(scope = :global) + initializers = Collection.new + ancestors.reverse_each do |klass| + next unless klass.respond_to?(:initializers) + initializers = initializers + klass.initializers.select { |i| + (scope == :global) == !!i.global? + } + end + initializers + end + + def initializer(name, opts = {}, &blk) + @initializers ||= [] + @initializers << Initializer.new(name, nil, opts, &blk) + end + + def run_initializers(*args) + return if @ran + initializers_for(:global).each do |initializer| + instance_exec(*args, &initializer.block) + end + @ran = true end end end - extend Initializable + include Initializable # Check for valid Ruby version (1.8.2 or 1.8.4 or higher). This is done in an # external file, so we can use it from the `rails` program as well without duplication. - initializer :check_ruby_version do + initializer :check_ruby_version, :global => true do require 'rails/ruby_version_check' end @@ -97,7 +120,7 @@ module Rails # on ActionController::Base. # # For Ruby 1.9, UTF-8 is the default internal and external encoding. - initializer :initialize_encoding do + initializer :initialize_encoding, :global => true do if RUBY_VERSION < '1.9' $KCODE='u' else diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb index 1c0af6411a..090ec6e4cb 100644 --- a/railties/lib/rails/plugin.rb +++ b/railties/lib/rails/plugin.rb @@ -18,6 +18,7 @@ module Rails # plugin.about["url"] # => "http://interblah.net" class Plugin include Comparable + include Initializable attr_reader :directory, :name @@ -99,67 +100,69 @@ module Rails def locale_files Dir[ File.join(locale_path, '*.{rb,yml}') ] end - - private - def load_about_information - about_yml_path = File.join(@directory, "about.yml") - parsed_yml = File.exist?(about_yml_path) ? YAML.load(File.read(about_yml_path)) : {} - parsed_yml || {} - rescue Exception - {} - end + private + def load_about_information + about_yml_path = File.join(@directory, "about.yml") + parsed_yml = File.exist?(about_yml_path) ? YAML.load(File.read(about_yml_path)) : {} + parsed_yml || {} + rescue Exception + {} + end - def report_nonexistant_or_empty_plugin! - raise LoadError, "Can not find the plugin named: #{name}" - end + def report_nonexistant_or_empty_plugin! + raise LoadError, "Can not find the plugin named: #{name}" + end - - def app_paths - [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path, metal_path ] - end - - def lib_path - File.join(directory, 'lib') - end + def app_paths + [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path, metal_path ] + end - def classic_init_path - File.join(directory, 'init.rb') - end + def lib_path + File.join(directory, 'lib') + end - def gem_init_path - File.join(directory, 'rails', 'init.rb') - end + def classic_init_path + File.join(directory, 'init.rb') + end - def init_path - File.file?(gem_init_path) ? gem_init_path : classic_init_path - end + def gem_init_path + File.join(directory, 'rails', 'init.rb') + end + def init_path + File.file?(gem_init_path) ? gem_init_path : classic_init_path + end - def has_app_directory? - File.directory?(File.join(directory, 'app')) - end + def has_app_directory? + File.directory?(File.join(directory, 'app')) + end - def has_lib_directory? - File.directory?(lib_path) - end + def has_lib_directory? + File.directory?(lib_path) + end - def has_init_file? - File.file?(init_path) - end + def has_init_file? + File.file?(init_path) + end + def evaluate_init_rb(initializer) + if has_init_file? + require 'active_support/core_ext/kernel/reporting' + silence_warnings do + # Allow plugins to reference the current configuration object + config = initializer.configuration - def evaluate_init_rb(initializer) - if has_init_file? - require 'active_support/core_ext/kernel/reporting' - silence_warnings do - # Allow plugins to reference the current configuration object - config = initializer.configuration - - eval(IO.read(init_path), binding, init_path) - end + eval(IO.read(init_path), binding, init_path) end - end + end + end + + class Vendored < Plugin + initializer :init_rb do |application| + evaluate_init_rb(application) + end + end end # This Plugin subclass represents a Gem plugin. Although RubyGems has already diff --git a/railties/lib/rails/ruby_version_check.rb b/railties/lib/rails/ruby_version_check.rb index 68d3acc876..62d7804bf3 100644 --- a/railties/lib/rails/ruby_version_check.rb +++ b/railties/lib/rails/ruby_version_check.rb @@ -1,13 +1,6 @@ -min_release = "1.8.2 (2004-12-25)" +min_release = "1.8.7" ruby_release = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE})" -if ruby_release =~ /1\.8\.3/ - abort <<-end_message - - Rails does not work with Ruby version 1.8.3. - Please upgrade to version 1.8.4 or downgrade to 1.8.2. - - end_message -elsif ruby_release < min_release +if ruby_release < min_release abort <<-end_message Rails requires Ruby version #{min_release} or later. diff --git a/railties/lib/rails/vendor/thor-0.11.8/CHANGELOG.rdoc b/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc index dba25b7205..adedfeca9d 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/CHANGELOG.rdoc +++ b/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc @@ -2,7 +2,12 @@ * Improve spec coverage for Thor::Runner -== 0.11.x, released 2009-07-01 +== 0.12, released 2009-11-06 + +* [#7] Do not force white color on status +* [#8] Yield a block with the filename on directory + +== 0.11, released 2009-07-01 * Added a rake compatibility layer. It allows you to use spec and rdoc tasks on Thor classes. diff --git a/railties/lib/rails/vendor/thor-0.11.8/LICENSE b/railties/lib/rails/vendor/thor-0.12.0/LICENSE index 98722da459..98722da459 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/LICENSE +++ b/railties/lib/rails/vendor/thor-0.12.0/LICENSE diff --git a/railties/lib/rails/vendor/thor-0.11.8/README.rdoc b/railties/lib/rails/vendor/thor-0.12.0/README.rdoc index f1106f02b6..f1106f02b6 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/README.rdoc +++ b/railties/lib/rails/vendor/thor-0.12.0/README.rdoc diff --git a/railties/lib/rails/vendor/thor-0.11.8/Thorfile b/railties/lib/rails/vendor/thor-0.12.0/Thorfile index f71a1e57e2..f71a1e57e2 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/Thorfile +++ b/railties/lib/rails/vendor/thor-0.12.0/Thorfile diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb index 68944f140d..68944f140d 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb index d561ccb2aa..d561ccb2aa 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/create_file.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb index 8f6badee27..a3d9296823 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/create_file.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb @@ -60,6 +60,7 @@ class Thor FileUtils.mkdir_p(File.dirname(destination)) File.open(destination, 'w'){ |f| f.write render } end + given_destination end protected diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/directory.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb index 063ac57406..467e63732a 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/directory.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb @@ -40,15 +40,16 @@ class Thor # directory "doc" # directory "doc", "docs", :recursive => false # - def directory(source, destination=nil, config={}) - action Directory.new(self, source, destination || source, config) + def directory(source, destination=nil, config={}, &block) + action Directory.new(self, source, destination || source, config, &block) end class Directory < EmptyDirectory #:nodoc: attr_reader :source - def initialize(base, source, destination=nil, config={}) + def initialize(base, source, destination=nil, config={}, &block) @source = File.expand_path(base.find_in_source_paths(source.to_s)) + @block = block super(base, destination, { :recursive => true }.merge(config)) end @@ -70,6 +71,7 @@ class Thor Dir[lookup].each do |file_source| next if File.directory?(file_source) file_destination = File.join(given_destination, file_source.gsub(source, '.')) + file_destination.gsub!('/./', '/') case file_source when /\.empty_directory$/ @@ -77,9 +79,11 @@ class Thor next if dirname == given_destination base.empty_directory(dirname, config) when /\.tt$/ - base.template(file_source, file_destination[0..-4], config) + destination = base.template(file_source, file_destination[0..-4], config) + @block.call(destination) if @block else - base.copy_file(file_source, file_destination, config) + destination = base.copy_file(file_source, file_destination, config) + @block.call(destination) if @block end end end diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/empty_directory.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb index 03c1fe4af1..484cb820f8 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/empty_directory.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb @@ -55,6 +55,7 @@ class Thor def revoke! say_status :remove, :red ::FileUtils.rm_rf(destination) if !pretend? && exists? + given_destination end protected diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/file_manipulation.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb index d77d90d448..d77d90d448 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/file_manipulation.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/inject_into_file.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb index 0636ec6591..0636ec6591 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/inject_into_file.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/base.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb index 700d794123..700d794123 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/base.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/hash_with_indifferent_access.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb index 78bc5cf4bf..78bc5cf4bf 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/hash_with_indifferent_access.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/ordered_hash.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb index 27fea5bb35..27fea5bb35 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/ordered_hash.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/error.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb index f9b31a35d1..f9b31a35d1 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/error.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/group.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb index 1e59df2313..0964a9667a 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/group.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb @@ -74,7 +74,7 @@ class Thor::Group # def invoke(*names, &block) options = names.last.is_a?(Hash) ? names.pop : {} - verbose = options.fetch(:verbose, :white) + verbose = options.fetch(:verbose, true) names.each do |name| invocations[name] = false diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/invocation.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb index 32e6a72454..32e6a72454 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/invocation.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb index 57a3f6e1a5..57a3f6e1a5 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/argument.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb index aa8ace4719..aa8ace4719 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/argument.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/arguments.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb index fb5d965e06..fb5d965e06 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/arguments.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/option.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb index 9e40ec73fa..9e40ec73fa 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/option.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/options.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb index 75092308b5..75092308b5 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/options.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/rake_compat.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb index 0d0757fdda..0d0757fdda 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/rake_compat.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/runner.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb index 9dc70ea069..9dc70ea069 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/runner.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb index 1dc8f0e5b4..1dc8f0e5b4 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/basic.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb index ea9665380b..ea9665380b 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/basic.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/color.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/color.rb index 24704f7885..24704f7885 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/color.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/color.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/task.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/task.rb index 91c7564d3f..91c7564d3f 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/task.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/task.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/util.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb index ebae0a3193..ebae0a3193 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/util.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/version.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb index 885230fac4..885230fac4 100644 --- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/version.rb +++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index 445a867c85..ccbcd84176 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -23,7 +23,8 @@ module ApplicationTests Rails::Initializer.run do |c| c.generators.orm = :datamapper c.generators.test_framework = :rspec - expected = { :rails => { :orm => :datamapper, :test_framework => :rspec } } + c.generators.helper = false + expected = { :rails => { :orm => :datamapper, :test_framework => :rspec, :helper => false } } assert_equal(expected, c.generators.options) end end @@ -45,6 +46,7 @@ module ApplicationTests end # Initialize the application Rails.initialize! + Rails::Generators.configure! assert_equal :rspec, Rails::Generators.options[:rails][:test_framework] assert_equal "-w", Rails::Generators.aliases[:rails][:test_framework] @@ -57,6 +59,7 @@ module ApplicationTests end # Initialize the application Rails.initialize! + Rails::Generators.configure! assert_equal Thor::Base.shell, Thor::Shell::Basic end @@ -93,4 +96,4 @@ module ApplicationTests assert Rails::Generators.options.size >= 1 end end -end
\ No newline at end of file +end diff --git a/railties/test/backtrace_cleaner_test.rb b/railties/test/backtrace_cleaner_test.rb index 4e273852e0..6cff591b94 100644 --- a/railties/test/backtrace_cleaner_test.rb +++ b/railties/test/backtrace_cleaner_test.rb @@ -16,12 +16,12 @@ if defined? Test::Unit::Util::BacktraceFilter 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.filter_backtrace(@backtrace) + @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.filter_backtrace(@backtrace, '/opt/local/lib') + @test.send(:filter_backtrace, @backtrace, '/opt/local/lib') end end end diff --git a/railties/test/fixtures/lib/generators/foobar/foobar_generator.rb b/railties/test/fixtures/lib/generators/foobar/foobar_generator.rb new file mode 100644 index 0000000000..d1de8c56fa --- /dev/null +++ b/railties/test/fixtures/lib/generators/foobar/foobar_generator.rb @@ -0,0 +1,4 @@ +module Foobar + class FoobarGenerator < Rails::Generators::Base + end +end diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index 199b5fa8b4..7d03a37f2a 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -54,37 +54,37 @@ class ActionsTest < GeneratorsTestCase action :plugin, 'rest_auth', {} end - def test_gem_should_put_gem_dependency_in_enviroment + def test_add_source_adds_source_to_gemfile run_generator - action :gem, 'will-paginate' - assert_file 'config/application.rb', /config\.gem 'will\-paginate'/ + action :add_source, 'http://gems.github.com' + assert_file 'Gemfile', /source "http:\/\/gems\.github\.com"/ end - def test_gem_with_options_should_include_options_in_gem_dependency_in_environment + def test_gem_should_put_gem_dependency_in_gemfile run_generator - action :gem, 'mislav-will-paginate', :lib => 'will-paginate', :source => 'http://gems.github.com' - - regexp = /#{Regexp.escape("config.gem 'mislav-will-paginate', :lib => 'will-paginate', :source => 'http://gems.github.com'")}/ - assert_file 'config/application.rb', regexp + action :gem, 'will-paginate' + assert_file 'Gemfile', /gem "will\-paginate"/ end - def test_gem_with_env_string_should_put_gem_dependency_in_specified_environment + def test_gem_with_options_should_include_all_options_in_gemfile run_generator - action :gem, 'rspec', :env => 'test' - assert_file 'config/environments/test.rb', /config\.gem 'rspec'/ - end - def test_gem_with_env_array_should_put_gem_dependency_in_specified_environments - run_generator - action :gem, 'quietbacktrace', :env => %w[ development test ] - assert_file 'config/environments/development.rb', /config\.gem 'quietbacktrace'/ - assert_file 'config/environments/test.rb', /config\.gem 'quietbacktrace'/ + assert_deprecated do + action :gem, 'mislav-will-paginate', :lib => 'will-paginate', :source => 'http://gems.github.com' + end + + assert_file 'Gemfile', /gem "mislav\-will\-paginate", :require_as => "will\-paginate"/ + assert_file 'Gemfile', /source "http:\/\/gems\.github\.com"/ end - def test_gem_with_lib_option_set_to_false_should_put_gem_dependency_in_enviroment_correctly + def test_gem_with_env_should_include_all_dependencies_in_gemfile run_generator - action :gem, 'mislav-will-paginate', :lib => false - assert_file 'config/application.rb', /config\.gem 'mislav\-will\-paginate'\, :lib => false/ + + assert_deprecated do + action :gem, 'rspec', :env => %w(development test) + end + + assert_file 'Gemfile', /gem "rspec", :only => \["development", "test"\]/ end def test_environment_should_include_data_in_environment_initializer_block @@ -163,9 +163,10 @@ class ActionsTest < GeneratorsTestCase action :capify! end - def test_freeze_should_freeze_rails_edge - generator.expects(:run).once.with('rake rails:freeze:edge', :verbose => false) - action :freeze! + def test_freeze_is_deprecated + assert_deprecated do + action :freeze! + end end def test_route_should_add_data_to_the_routes_block_in_config_routes diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 20f2a24e6d..10d0bc6bc2 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -110,20 +110,6 @@ class AppGeneratorTest < GeneratorsTestCase ).each { |path| assert_file "script/#{path}", /#!\/usr\/bin\/env/ } end - def test_rails_is_frozen - generator(:freeze => true, :database => "sqlite3").expects(:run). - with("rake rails:freeze:edge", :verbose => false) - silence(:stdout){ generator.invoke } - - assert_file 'Gemfile' do |content| - flag = %(gem "rails", "#{Rails::VERSION::STRING}", :git => "git://github.com/rails/rails.git") - assert_match /^#{Regexp.escape(flag)}$/, content - - flag = %(# gem "rails", "#{Rails::VERSION::STRING}") - assert_match /^#{Regexp.escape(flag)}$/, content - end - end - def test_template_from_dir_pwd FileUtils.cd(Rails.root) assert_match /It works from file!/, run_generator(["-m", "lib/template.rb"]) diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index ccf08c347c..4ce48a453b 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -1,8 +1,14 @@ # TODO: Fix this RAILS_ENV stuff -RAILS_ENV = 'test' - +RAILS_ENV = 'test' unless defined?(RAILS_ENV) require 'abstract_unit' -Rails.application.config.root = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures')) + +module Rails + def self.root + @root ||= File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures')) + end +end +Rails.application.config.root = Rails.root + require 'rails/generators' require 'rubygems' require 'active_record' @@ -11,12 +17,11 @@ require 'action_dispatch' CURRENT_PATH = File.expand_path(Dir.pwd) Rails::Generators.no_color! -class GeneratorsTestCase < Test::Unit::TestCase +class GeneratorsTestCase < ActiveSupport::TestCase include FileUtils def destination_root - @destination_root ||= File.expand_path(File.join(File.dirname(__FILE__), - '..', 'fixtures', 'tmp')) + File.join(Rails.root, "tmp") end def setup diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb index dcae81c204..886af01b22 100644 --- a/railties/test/generators/resource_generator_test.rb +++ b/railties/test/generators/resource_generator_test.rb @@ -75,7 +75,7 @@ class ResourceGeneratorTest < GeneratorsTestCase end def test_plural_names_are_singularized - content = run_generator ["accounts"] + content = run_generator ["accounts".freeze] assert_file "app/models/account.rb", /class Account < ActiveRecord::Base/ assert_file "test/unit/account_test.rb", /class AccountTest/ assert_match /Plural version of the model detected, using singularized version. Override with --force-plural./, content diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb index 178b5ef6de..a8716d9992 100644 --- a/railties/test/generators_test.rb +++ b/railties/test/generators_test.rb @@ -1,4 +1,4 @@ -require File.join(File.dirname(__FILE__), 'generators', 'generators_test_helper') +require 'generators/generators_test_helper' require 'rails/generators/rails/model/model_generator' require 'rails/generators/test_unit/model/model_generator' require 'mocha' @@ -45,6 +45,12 @@ class GeneratorsTest < GeneratorsTestCase assert_equal "test_unit:generators:model", klass.namespace end + def test_find_by_namespace_with_duplicated_name + klass = Rails::Generators.find_by_namespace(:foobar) + assert klass + assert_equal "foobar:foobar", klass.namespace + end + def test_find_by_namespace_add_generators_to_raw_lookups klass = Rails::Generators.find_by_namespace("test_unit:model") assert klass @@ -101,14 +107,15 @@ class GeneratorsTest < GeneratorsTestCase def test_rails_generators_with_others_information output = capture(:stdout){ Rails::Generators.help }.split("\n").last - assert_equal "Others: active_record:fixjour, fixjour, mspec, rails:javascripts.", output + assert_equal "Others: active_record:fixjour, fixjour, foobar, mspec, rails:javascripts.", output end def test_warning_is_shown_if_generator_cant_be_loaded - Rails::Generators.load_paths << File.expand_path("../fixtures/vendor/gems/gems/wrong", __FILE__) + Rails::Generators.load_paths << File.join(Rails.root, "vendor", "gems", "gems", "wrong") output = capture(:stderr){ Rails::Generators.find_by_namespace(:wrong) } + assert_match /\[WARNING\] Could not load generator at/, output - assert_match /Error: uninitialized constant Rails::Generator/, output + assert_match /Rails 2\.x generator/, output end def test_no_color_sets_proper_shell @@ -159,10 +166,7 @@ class GeneratorsTest < GeneratorsTestCase Rails::Generators.options[:new_generator] = { :generate => false } klass = Class.new(Rails::Generators::Base) do - def self.name - "NewGenerator" - end - + def self.name() 'NewGenerator' end class_option :generate, :default => true end diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb index f7237e69cc..2920883132 100644 --- a/railties/test/initializable_test.rb +++ b/railties/test/initializable_test.rb @@ -4,59 +4,59 @@ require 'rails/initializable' module InitializableTests class Foo - extend Rails::Initializable + include Rails::Initializable class << self attr_accessor :foo, :bar end - initializer :omg do + initializer :omg, :global => true do @foo ||= 0 @foo += 1 end end class Bar < Foo - initializer :bar do + initializer :bar, :global => true do @bar ||= 0 @bar += 1 end end module Word - extend Rails::Initializable + include Rails::Initializable - initializer :word do + initializer :word, :global => true do $word = "bird" end end class Parent - extend Rails::Initializable + include Rails::Initializable - initializer :one do + initializer :one, :global => true do $arr << 1 end - initializer :two do + initializer :two, :global => true do $arr << 2 end end class Child < Parent - extend Rails::Initializable + include Rails::Initializable - initializer :three, :before => :one do + initializer :three, :before => :one, :global => true do $arr << 3 end - initializer :four, :after => :one do + initializer :four, :after => :one, :global => true do $arr << 4 end end class Parent - initializer :five, :before => :one do + initializer :five, :before => :one, :global => true do $arr << 5 end end @@ -81,6 +81,42 @@ module InitializableTests end end + class WithArgs + include Rails::Initializable + + initializer :foo do |arg| + $with_arg = arg + end + end + + class OverriddenInitializer + class MoreInitializers + include Rails::Initializable + + initializer :startup, :before => :last do + $arr << two + end + + def two + 2 + end + end + + include Rails::Initializable + + initializer :first do + $arr << 1 + end + + initializer :last do + $arr << 3 + end + + def self.initializers + super + MoreInitializers.new.initializers + end + end + class Basic < ActiveSupport::TestCase include ActiveSupport::Testing::Isolation @@ -140,4 +176,20 @@ module InitializableTests assert_equal [3, 4], $arr end end + + class WithArgsTest < ActiveSupport::TestCase + test "running initializers with args" do + $with_arg = nil + WithArgs.new.run_initializers('foo') + assert_equal 'foo', $with_arg + end + end + + class OverriddenInitializerTest < ActiveSupport::TestCase + test "merges in the initializers from the parent in the right order" do + $arr = [] + OverriddenInitializer.new.run_initializers + assert_equal [1, 2, 3], $arr + end + end end
\ No newline at end of file diff --git a/railties/test/initializer/check_ruby_version_test.rb b/railties/test/initializer/check_ruby_version_test.rb index cf956e68fb..97d884e1be 100644 --- a/railties/test/initializer/check_ruby_version_test.rb +++ b/railties/test/initializer/check_ruby_version_test.rb @@ -14,24 +14,32 @@ module InitializerTests assert_rails_does_not_boot "1.8.1" end - test "rails initializes with ruby version 1.8.2" do - assert_rails_boots "1.8.2" + test "rails does not initialize with ruby version 1.8.2" do + assert_rails_does_not_boot "1.8.2" end test "rails does not initialize with ruby version 1.8.3" do assert_rails_does_not_boot "1.8.3" end - test "rails initializes with ruby version 1.8.4" do - assert_rails_boots "1.8.4" + test "rails does not initialize with ruby version 1.8.4" do + assert_rails_does_not_boot "1.8.4" end - test "rails initializes with ruby version 1.8.5" do - assert_rails_boots "1.8.5" + test "rails does not initializes with ruby version 1.8.5" do + assert_rails_does_not_boot "1.8.5" end - test "rails initializes with ruby version 1.8.6" do - assert_rails_boots "1.8.6" + test "rails does not initialize with ruby version 1.8.6" do + assert_rails_does_not_boot "1.8.6" + end + + test "rails initializes with ruby version 1.8.7" do + assert_rails_boots "1.8.7" + end + + test "rails initializes with the current version of Ruby" do + assert_rails_boots end def set_ruby_version(version) @@ -39,8 +47,8 @@ module InitializerTests Object.const_set(:RUBY_VERSION, version.freeze) end - def assert_rails_boots(version) - set_ruby_version(version) + def assert_rails_boots(version = nil) + set_ruby_version(version) if version assert_nothing_raised "It appears that rails does not boot" do Rails::Initializer.run { |c| c.frameworks = [] } Rails.initialize! diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 462a4d8dea..0b479e944c 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -157,9 +157,13 @@ Module.new do FileUtils.mkdir(tmp_path) environment = File.expand_path('../../../../vendor/gems/environment', __FILE__) + if File.exist?(environment) + require_environment = "-r #{environment}" + end - `#{Gem.ruby} -r #{environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails #{tmp_path('app_template')}` + `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails #{tmp_path('app_template')}` File.open("#{tmp_path}/app_template/config/boot.rb", 'w') do |f| - f.puts "require '#{environment}' ; require 'rails'" + f.puts "require '#{environment}'" if require_environment + f.puts "require 'rails'" end end diff --git a/railties/test/metal_test.rb b/railties/test/metal_test.rb index 6864254e4c..2256b191e2 100644 --- a/railties/test/metal_test.rb +++ b/railties/test/metal_test.rb @@ -85,7 +85,7 @@ class MetalTest < Test::Unit::TestCase private def app - lambda{[402,{},["End of the Line"]]} + lambda{|env|[402,{},["End of the Line"]]} end def use_appdir(root) |