diff options
author | Xavier Noria <fxn@hashref.com> | 2010-03-31 07:47:58 -0700 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2010-03-31 07:47:58 -0700 |
commit | 824fa10f4d1306cc1e310a7d5de7e95cfb07d6f8 (patch) | |
tree | 1967c2a945d6e131d467fb4f0178a0f60e01ae8a | |
parent | 1ed1652bef981d9402797b6cb9f0920a40eea21a (diff) | |
parent | db28d407f76a790a31e27bf51560e23425dd6944 (diff) | |
download | rails-824fa10f4d1306cc1e310a7d5de7e95cfb07d6f8.tar.gz rails-824fa10f4d1306cc1e310a7d5de7e95cfb07d6f8.tar.bz2 rails-824fa10f4d1306cc1e310a7d5de7e95cfb07d6f8.zip |
Merge commit 'rails/master'
146 files changed, 1042 insertions, 436 deletions
diff --git a/.gitignore b/.gitignore index 9d68f4860f..16bffc157b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,6 @@ activesupport/test/fixtures/isolation_test railties/test/500.html railties/test/fixtures/tmp railties/test/initializer/root/log -railties/doc/guides/html/images -railties/doc/guides/html/stylesheets +railties/doc railties/guides/output railties/tmp @@ -11,6 +11,8 @@ group :mri do if RUBY_VERSION < '1.9' gem "system_timer" gem "ruby-debug", ">= 0.10.3" + elsif RUBY_VERSION < '1.9.2' + gem "ruby-debug19" end end @@ -72,8 +72,8 @@ Rake::RDocTask.new do |rdoc| rdoc.rdoc_files.include('railties/CHANGELOG') rdoc.rdoc_files.include('railties/MIT-LICENSE') rdoc.rdoc_files.include('railties/README') - rdoc.rdoc_files.include('railties/lib/{*.rb,commands/*.rb,rails/*.rb,generators/*.rb}') - rdoc.rdoc_files.exclude('railties/lib/vendor/*') + rdoc.rdoc_files.include('railties/lib/**/*.rb') + rdoc.rdoc_files.exclude('railties/lib/rails/generators/**/templates/*') rdoc.rdoc_files.include('activerecord/README') rdoc.rdoc_files.include('activerecord/CHANGELOG') @@ -88,6 +88,7 @@ Rake::RDocTask.new do |rdoc| rdoc.rdoc_files.include('actionpack/README') rdoc.rdoc_files.include('actionpack/CHANGELOG') rdoc.rdoc_files.include('actionpack/lib/action_controller/**/*.rb') + rdoc.rdoc_files.include('actionpack/lib/action_dispatch/**/*.rb') rdoc.rdoc_files.include('actionpack/lib/action_view/**/*.rb') rdoc.rdoc_files.exclude('actionpack/lib/action_controller/vendor/*') diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index a7a2599105..410df0e106 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -20,6 +20,6 @@ Gem::Specification.new do |s| s.has_rdoc = true s.add_dependency('actionpack', version) - s.add_dependency('mail', '~> 2.1.3') + s.add_dependency('mail', '~> 2.1.5.3') s.add_dependency('text-format', '~> 1.0.0') end diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 0519783d02..af7255ae4f 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -2,6 +2,7 @@ require 'mail' require 'action_mailer/tmail_compat' require 'action_mailer/collector' require 'active_support/core_ext/array/wrap' +require 'active_support/core_ext/object/blank' module ActionMailer #:nodoc: # Action Mailer allows you to send email from your application using a mailer model and views. @@ -290,7 +291,7 @@ module ActionMailer #:nodoc: :parts_order => [ "text/plain", "text/enriched", "text/html" ] }.freeze - ActionMailer.run_base_hooks(self) + ActiveSupport.run_load_hooks(:action_mailer, self) class << self diff --git a/actionmailer/lib/action_mailer/old_api.rb b/actionmailer/lib/action_mailer/old_api.rb index c7f341d46c..7c59a8ae50 100644 --- a/actionmailer/lib/action_mailer/old_api.rb +++ b/actionmailer/lib/action_mailer/old_api.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/object/try' +require 'active_support/core_ext/object/blank' module ActionMailer module OldApi #:nodoc: diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 2703367fdb..882e078d1b 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -6,18 +6,18 @@ module ActionMailer config.action_mailer = ActiveSupport::OrderedOptions.new initializer "action_mailer.url_for", :before => :load_environment_config do |app| - ActionMailer.base_hook { include app.routes.url_helpers } + ActiveSupport.on_load(:action_mailer) { include app.routes.url_helpers } end require "action_mailer/railties/log_subscriber" log_subscriber :action_mailer, ActionMailer::Railties::LogSubscriber.new initializer "action_mailer.logger" do - ActionMailer.base_hook { self.logger ||= Rails.logger } + ActiveSupport.on_load(:action_mailer) { self.logger ||= Rails.logger } end initializer "action_mailer.set_configs" do |app| - ActionMailer.base_hook do + ActiveSupport.on_load(:action_mailer) do app.config.action_mailer.each do |k,v| send "#{k}=", v end diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index 6f274c11df..baeee542be 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -39,8 +39,15 @@ class BaseTest < ActiveSupport::TestCase end def attachment_with_hash - attachments['invoice.jpg'] = { :data => "you smiling", :mime_type => "image/x-jpg", - :transfer_encoding => "base64" } + attachments['invoice.jpg'] = { :data => "\312\213\254\232)b", + :mime_type => "image/x-jpg", + :transfer_encoding => "base64" } + mail + end + + def attachment_with_hash_default_encoding + attachments['invoice.jpg'] = { :data => "\312\213\254\232)b", + :mime_type => "image/x-jpg" } mail end @@ -135,13 +142,13 @@ class BaseTest < ActiveSupport::TestCase :mime_version => '2.0', :reply_to => 'reply-to@test.lindsaar.net', :date => @time) - assert_equal(['bcc@test.lindsaar.net'], email.bcc) - assert_equal(['cc@test.lindsaar.net'], email.cc) - assert_equal('multipart/mixed', email.content_type) - assert_equal('iso-8559-1', email.charset) - assert_equal('2.0', email.mime_version) - assert_equal(['reply-to@test.lindsaar.net'], email.reply_to) - assert_equal(@time, email.date) + assert_equal(['bcc@test.lindsaar.net'], email.bcc) + assert_equal(['cc@test.lindsaar.net'], email.cc) + assert_equal('multipart/mixed; charset=iso-8559-1', email.content_type) + assert_equal('iso-8559-1', email.charset) + assert_equal('2.0', email.mime_version) + assert_equal(['reply-to@test.lindsaar.net'], email.reply_to) + assert_equal(@time, email.date) end test "mail() renders the template using the method being processed" do @@ -206,6 +213,15 @@ class BaseTest < ActiveSupport::TestCase assert_equal expected, email.attachments['invoice.jpg'].decoded end + test "attachment with hash using default mail encoding" do + email = BaseMailer.attachment_with_hash_default_encoding + assert_equal(1, email.attachments.length) + assert_equal('invoice.jpg', email.attachments[0].filename) + expected = "\312\213\254\232)b" + expected.force_encoding(Encoding::BINARY) if '1.9'.respond_to?(:force_encoding) + assert_equal expected, email.attachments['invoice.jpg'].decoded + end + test "sets mime type to multipart/mixed when attachment is included" do email = BaseMailer.attachment_with_content assert_equal(1, email.attachments.length) diff --git a/actionmailer/test/old_base/mail_service_test.rb b/actionmailer/test/old_base/mail_service_test.rb index e49307bfda..9eb067554f 100644 --- a/actionmailer/test/old_base/mail_service_test.rb +++ b/actionmailer/test/old_base/mail_service_test.rb @@ -784,7 +784,7 @@ EOF expected.date = Time.local 2004, 12, 12 created = TestMailer.utf8_body @recipient - assert_match(/åœö blah/, created.encoded) + assert_match(/åœö blah/, created.decoded) end def test_multiple_utf8_recipients @@ -1019,8 +1019,8 @@ EOF def test_empty_header_values_omitted result = TestMailer.unnamed_attachment(@recipient).encoded - assert_match %r{Content-Type: application/octet-stream;}, result - assert_match %r{Content-Disposition: attachment;}, result + assert_match %r{Content-Type: application/octet-stream}, result + assert_match %r{Content-Disposition: attachment}, result end def test_headers_with_nonalpha_chars diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 5797282b41..46a175d2fa 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -64,8 +64,7 @@ module ActionController filter end - ActionController.run_base_hooks(self) - + ActiveSupport.run_load_hooks(:action_controller, self) end end diff --git a/actionpack/lib/action_controller/deprecated/base.rb b/actionpack/lib/action_controller/deprecated/base.rb index bbde570ca9..2fd60aacc7 100644 --- a/actionpack/lib/action_controller/deprecated/base.rb +++ b/actionpack/lib/action_controller/deprecated/base.rb @@ -66,6 +66,18 @@ module ActionController Rails.application.config.action_dispatch.ip_spoofing_check end + def cookie_verifier_secret=(value) + ActiveSupport::Deprecation.warn "ActionController::Base.cookie_verifier_secret= is deprecated. " << + "Please configure it on your application with config.cookie_secret=", caller + ActionController::Base.config.secret = value + end + + def cookie_verifier_secret + ActiveSupport::Deprecation.warn "ActionController::Base.cookie_verifier_secret is deprecated. " << + "Please use ActionController::Base.config.secret instead.", caller + ActionController::Base.config.secret + end + def trusted_proxies=(value) ActiveSupport::Deprecation.warn "ActionController::Base.trusted_proxies= is deprecated. " << "Please configure it on your application with config.action_dispatch.trusted_proxies=", caller diff --git a/actionpack/lib/action_controller/metal/cookies.rb b/actionpack/lib/action_controller/metal/cookies.rb index 7aa687b52c..75e5d40a63 100644 --- a/actionpack/lib/action_controller/metal/cookies.rb +++ b/actionpack/lib/action_controller/metal/cookies.rb @@ -6,7 +6,6 @@ module ActionController #:nodoc: included do helper_method :cookies - cattr_accessor :cookie_verifier_secret end private diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 6ec788f302..424828f7e8 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -1,4 +1,5 @@ require 'active_support/base64' +require 'active_support/core_ext/object/blank' module ActionController module HttpAuthentication diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index d906e1fb5b..aebd71e867 100644 --- a/actionpack/lib/action_controller/metal/renderers.rb +++ b/actionpack/lib/action_controller/metal/renderers.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/object/blank' module ActionController def self.add_renderer(key, &block) diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 0ec89928af..29d8523ee1 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -41,7 +41,7 @@ module ActionController log_subscriber :action_controller, ActionController::Railties::LogSubscriber.new initializer "action_controller.logger" do - ActionController.base_hook { self.logger ||= Rails.logger } + ActiveSupport.on_load(:action_controller) { self.logger ||= Rails.logger } end initializer "action_controller.set_configs" do |app| @@ -53,23 +53,23 @@ module ActionController ac.stylesheets_dir = paths.public.stylesheets.to_a.first ac.secret = app.config.cookie_secret - ActionController.base_hook do + ActiveSupport.on_load(:action_controller) do self.config.merge!(ac) end end initializer "action_controller.initialize_framework_caches" do - ActionController.base_hook { self.cache_store ||= RAILS_CACHE } + ActiveSupport.on_load(:action_controller) { self.cache_store ||= RAILS_CACHE } end initializer "action_controller.set_helpers_path" do |app| - ActionController.base_hook do + ActiveSupport.on_load(:action_controller) do self.helpers_path = app.config.paths.app.helpers.to_a end end initializer "action_controller.url_helpers" do |app| - ActionController.base_hook do + ActiveSupport.on_load(:action_controller) do extend ::ActionController::Railties::UrlHelpers.with(app.routes) end diff --git a/actionpack/lib/action_controller/railties/log_subscriber.rb b/actionpack/lib/action_controller/railties/log_subscriber.rb index c2299d0b05..00ac3bdf67 100644 --- a/actionpack/lib/action_controller/railties/log_subscriber.rb +++ b/actionpack/lib/action_controller/railties/log_subscriber.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActionController module Railties class LogSubscriber < Rails::LogSubscriber diff --git a/actionpack/lib/action_controller/railties/url_helpers.rb b/actionpack/lib/action_controller/railties/url_helpers.rb index 5f95e1c621..9df5665542 100644 --- a/actionpack/lib/action_controller/railties/url_helpers.rb +++ b/actionpack/lib/action_controller/railties/url_helpers.rb @@ -1,14 +1,14 @@ module ActionController module Railties module UrlHelpers - def self.with(router) + def self.with(routes) Module.new do define_method(:inherited) do |klass| super(klass) - klass.send(:include, router.url_helpers) + klass.send(:include, routes.url_helpers) end end end end end -end
\ No newline at end of file +end diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb index 3f966b1b64..7fdaffe3eb 100644 --- a/actionpack/lib/action_controller/record_identifier.rb +++ b/actionpack/lib/action_controller/record_identifier.rb @@ -76,8 +76,8 @@ module ActionController # method that replaces all characters that are invalid inside DOM ids, with valid ones. You need to # make sure yourself that your dom ids are valid, in case you overwrite this method. def record_key_for_dom_id(record) - return record.id unless record.respond_to?(:to_model) - key = record.to_model.to_key + record = record.to_model if record.respond_to?(:to_model) + key = record.to_key key ? sanitize_dom_id(key.join('_')) : key end diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 120f34460e..2d4cf2fafb 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -1,4 +1,5 @@ require 'rack/session/abstract/id' +require 'active_support/core_ext/object/blank' module ActionController module TemplateAssertions @@ -117,9 +118,9 @@ module ActionController end end - def assign_parameters(router, controller_path, action, parameters = {}) + def assign_parameters(routes, controller_path, action, parameters = {}) parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action) - extra_keys = router.extra_keys(parameters) + extra_keys = routes.extra_keys(parameters) non_path_parameters = get? ? query_parameters : request_parameters parameters.each do |key, value| if value.is_a? Fixnum @@ -321,7 +322,7 @@ module ActionController def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET') # Sanity check for required instance variables so we can give an # understandable error message. - %w(@router @controller @request @response).each do |iv_name| + %w(@routes @controller @request @response).each do |iv_name| if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil? raise "#{iv_name} is nil: make sure you set it in your test's setup method." end @@ -337,7 +338,7 @@ module ActionController @request.env['REQUEST_METHOD'] = http_method parameters ||= {} - @request.assign_parameters(@router, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters) + @request.assign_parameters(@routes, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters) @request.session = ActionController::TestSession.new(session) unless session.nil? @request.session["flash"] = @request.flash.update(flash || {}) @@ -446,7 +447,7 @@ module ActionController :relative_url_root => nil, :_path_segments => @request.symbolized_path_parameters) - url, query_string = @router.url_for(options).split("?", 2) + url, query_string = @routes.url_for(options).split("?", 2) @request.env["SCRIPT_NAME"] = @controller.config.relative_url_root @request.env["PATH_INFO"] = url diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index d2404e63c5..9b9e81440b 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActionDispatch module Http module Cache diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index e42b4d09b0..152aaa2e67 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/hash/keys' +require 'active_support/core_ext/object/duplicable' module ActionDispatch module Http diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index fec250e928..be89924015 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -5,7 +5,7 @@ module ActionDispatch # # For backward compatibility, the post \format is extracted from the # X-Post-Data-Format HTTP header if present. - def content_type + def content_mime_type @env["action_dispatch.request.content_type"] ||= begin if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/ Mime::Type.lookup($1.strip.downcase) @@ -15,13 +15,17 @@ module ActionDispatch end end + def content_type + content_mime_type && content_mime_type.to_s + end + # Returns the accepted MIME type for the request. def accepts @env["action_dispatch.request.accepts"] ||= begin header = @env['HTTP_ACCEPT'].to_s.strip if header.empty? - [content_type] + [content_mime_type] else Mime::Type.parse(header) end diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 3f1a77295d..d6a805bf3b 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -1,5 +1,6 @@ require 'set' require 'active_support/core_ext/class/attribute_accessors' +require 'active_support/core_ext/object/blank' module Mime class Mimes < Array diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index ea9f0f99c2..8b8426b5aa 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -96,11 +96,11 @@ module ActionDispatch end def forgery_whitelisted? - method == :get || xhr? || content_type.nil? || !content_type.verify_request? + method == :get || xhr? || content_mime_type.nil? || !content_mime_type.verify_request? end def media_type - content_type.to_s + content_mime_type.to_s end # Returns the content length of the request as an integer. @@ -157,7 +157,7 @@ module ActionDispatch end def form_data? - FORM_DATA_MEDIA_TYPES.include?(content_type.to_s) + FORM_DATA_MEDIA_TYPES.include?(content_mime_type.to_s) end def body_stream #:nodoc: diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 9cfe5a5ea9..362e5ec970 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -1,5 +1,6 @@ require 'digest/md5' require 'active_support/core_ext/module/delegation' +require 'active_support/core_ext/object/blank' module ActionDispatch # :nodoc: # Represents an HTTP response generated by a controller action. One can use diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index dc6121b911..81d2517304 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActionDispatch module Http module UploadedFile diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index ab7130ab08..cb0d12cab1 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -168,12 +168,12 @@ module ActionDispatch class SignedCookieJar < CookieJar #:nodoc: def initialize(parent_jar) - unless ActionController::Base.cookie_verifier_secret - raise "You must set ActionController::Base.cookie_verifier_secret to use signed cookies" + unless ActionController::Base.config.secret + raise "You must set ActionController::Base.config.secret" end @parent_jar = parent_jar - @verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.cookie_verifier_secret) + @verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.config.secret) end def [](name) diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index f4c4324fb0..18a3688bb0 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -25,7 +25,9 @@ module ActionDispatch return false if request.content_length.zero? - mime_type = content_type_from_legacy_post_data_format_header(env) || request.content_type + mime_type = content_type_from_legacy_post_data_format_header(env) || + request.content_mime_type + strategy = @parsers[mime_type] return false unless strategy @@ -53,7 +55,7 @@ module ActionDispatch raise { "body" => request.raw_post, - "content_type" => request.content_type, + "content_type" => request.content_mime_type, "content_length" => request.content_length, "exception" => "#{e.message} (#{e.class})", "backtrace" => e.backtrace } diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 311880cabc..dddedc832f 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -1,5 +1,6 @@ require 'rack/utils' require 'rack/request' +require 'active_support/core_ext/object/blank' module ActionDispatch module Session diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 22da82479e..3331b7c25e 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/hash/keys' +require 'active_support/core_ext/object/blank' module ActionDispatch module Session diff --git a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb index 58beaf4824..e8c2e74314 100644 --- a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb +++ b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActionDispatch module Routing class RouteSet diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 39260f7ff9..74d0297898 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/hash/except' +require 'active_support/core_ext/object/blank' module ActionDispatch module Routing @@ -258,6 +259,7 @@ module ActionDispatch def scope(*args) options = args.extract_options! + options = options.dup case args.first when String @@ -423,8 +425,13 @@ module ActionDispatch singular end + # Checks for uncountable plurals, and appends "_index" if they're. def collection_name - plural + uncountable? ? "#{plural}_index" : plural + end + + def uncountable? + singular == plural end def name_for_action(action) @@ -439,6 +446,32 @@ module ActionDispatch def id_segment ":#{singular}_id" end + + def constraints + options[:constraints] || {} + end + + def id_constraint? + options[:id] && options[:id].is_a?(Regexp) || constraints[:id] && constraints[:id].is_a?(Regexp) + end + + def id_constraint + options[:id] || constraints[:id] + end + + def collection_options + (options || {}).dup.tap do |options| + options.delete(:id) + options[:constraints] = options[:constraints].dup if options[:constraints] + options[:constraints].delete(:id) if options[:constraints].is_a?(Hash) + end + end + + def nested_options + options = { :name_prefix => member_name } + options["#{singular}_id".to_sym] = id_constraint if id_constraint? + options + end end class SingletonResource < Resource #:nodoc: @@ -483,12 +516,14 @@ module ActionDispatch yield if block_given? end - get :show if resource.actions.include?(:show) - post :create if resource.actions.include?(:create) - put :update if resource.actions.include?(:update) - delete :destroy if resource.actions.include?(:destroy) - get :new, :as => resource.name if resource.actions.include?(:new) - get :edit, :as => resource.name if resource.actions.include?(:edit) + scope(resource.options) do + get :show if resource.actions.include?(:show) + post :create if resource.actions.include?(:create) + put :update if resource.actions.include?(:update) + delete :destroy if resource.actions.include?(:destroy) + get :new, :as => resource.name if resource.actions.include?(:new) + get :edit, :as => resource.name if resource.actions.include?(:edit) + end end end @@ -509,17 +544,21 @@ module ActionDispatch yield if block_given? with_scope_level(:collection) do - get :index if resource.actions.include?(:index) - post :create if resource.actions.include?(:create) - get :new, :as => resource.singular if resource.actions.include?(:new) + scope(resource.collection_options) do + get :index if resource.actions.include?(:index) + post :create if resource.actions.include?(:create) + get :new, :as => resource.singular if resource.actions.include?(:new) + end end with_scope_level(:member) do scope(':id') do - get :show if resource.actions.include?(:show) - put :update if resource.actions.include?(:update) - delete :destroy if resource.actions.include?(:destroy) - get :edit, :as => resource.singular if resource.actions.include?(:edit) + scope(resource.options) do + get :show if resource.actions.include?(:show) + put :update if resource.actions.include?(:update) + delete :destroy if resource.actions.include?(:destroy) + get :edit, :as => resource.singular if resource.actions.include?(:edit) + end end end end @@ -558,7 +597,7 @@ module ActionDispatch end with_scope_level(:nested) do - scope(parent_resource.id_segment, :name_prefix => parent_resource.member_name) do + scope(parent_resource.id_segment, parent_resource.nested_options) do yield end end diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 1bb81ede3b..b7e9b0c95a 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -80,7 +80,7 @@ module ActionDispatch expected_path = "/#{expected_path}" unless expected_path[0] == ?/ # Load routes.rb if it hasn't been loaded. - generated_path, extra_keys = @router.generate_extras(options, defaults) + generated_path, extra_keys = @routes.generate_extras(options, defaults) found_extras = options.reject {|k, v| ! extra_keys.include? k} msg = build_message(message, "found extras <?>, not <?>", found_extras, extras) @@ -125,7 +125,7 @@ module ActionDispatch end # A helper to make it easier to test different route configurations. - # This method temporarily replaces @router + # This method temporarily replaces @routes # with a new RouteSet instance. # # The new instance is yielded to the passed block. Typically the block @@ -142,9 +142,9 @@ module ActionDispatch # end # def with_routing - old_routes, @router = @router, ActionDispatch::Routing::RouteSet.new + old_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new old_controller, @controller = @controller, @controller.clone if @controller - _router = @router + _routes = @routes # Unfortunately, there is currently an abstraction leak between AC::Base # and AV::Base which requires having the URL helpers in both AC and AV. @@ -153,14 +153,14 @@ module ActionDispatch # # TODO: Make this unnecessary if @controller - @controller.singleton_class.send(:include, _router.url_helpers) + @controller.singleton_class.send(:include, _routes.url_helpers) @controller.view_context_class = Class.new(@controller.view_context_class) do - include _router.url_helpers + include _routes.url_helpers end end - yield @router + yield @routes ensure - @router = old_routes + @routes = old_routes if @controller @controller = old_controller end @@ -168,7 +168,7 @@ module ActionDispatch # ROUTES TODO: These assertions should really work in an integration context def method_missing(selector, *args, &block) - if @controller && @router.named_routes.helpers.include?(selector) + if @controller && @routes && @routes.named_routes.helpers.include?(selector) @controller.send(selector, *args, &block) else super @@ -185,7 +185,7 @@ module ActionDispatch request.env["REQUEST_METHOD"] = request_method.to_s.upcase if request_method request.path = path - params = @router.recognize_path(path, { :method => request.method }) + params = @routes.recognize_path(path, { :method => request.method }) request.path_parameters = params.with_indifferent_access request diff --git a/actionpack/lib/action_dispatch/testing/performance_test.rb b/actionpack/lib/action_dispatch/testing/performance_test.rb index 1b9a6c18b7..33a5c68b9d 100644 --- a/actionpack/lib/action_dispatch/testing/performance_test.rb +++ b/actionpack/lib/action_dispatch/testing/performance_test.rb @@ -1,7 +1,7 @@ require 'active_support/testing/performance' require 'active_support/testing/default' -if defined?(ActiveSupport::Testing::Performance) +begin module ActionDispatch # An integration test that runs a code profiler on your test methods. # Profiling output for combinations of each test method, measurement, and @@ -14,4 +14,6 @@ if defined?(ActiveSupport::Testing::Performance) include ActiveSupport::Testing::Default end end +rescue NameError + $stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks." end
\ No newline at end of file diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb index 20288aa7a5..090e03cf44 100644 --- a/actionpack/lib/action_dispatch/testing/test_request.rb +++ b/actionpack/lib/action_dispatch/testing/test_request.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActionDispatch class TestRequest < Request DEFAULT_ENV = Rack::MockRequest.env_for('/') diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 919b1e3470..a9b0715b2e 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -173,7 +173,7 @@ module ActionView #:nodoc: delegate :logger, :to => 'ActionController::Base', :allow_nil => true end - ActionView.run_base_hooks(self) + ActiveSupport.run_load_hooks(:action_view, self) attr_accessor :base_path, :assigns, :template_extension, :lookup_context attr_internal :captures, :request, :controller, :template, :config diff --git a/actionpack/lib/action_view/helpers/active_model_helper.rb b/actionpack/lib/action_view/helpers/active_model_helper.rb index 80b3d3a664..44e193f18e 100644 --- a/actionpack/lib/action_view/helpers/active_model_helper.rb +++ b/actionpack/lib/action_view/helpers/active_model_helper.rb @@ -6,7 +6,7 @@ require 'active_support/core_ext/kernel/reporting' require 'active_support/core_ext/object/blank' module ActionView - ActionView.base_hook do + ActiveSupport.on_load(:action_view) do class ActionView::Base @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe } cattr_accessor :field_error_proc @@ -97,10 +97,10 @@ module ActionView end # Returns a string containing the error message attached to the +method+ on the +object+ if one exists. - # This error message is wrapped in a <tt>DIV</tt> tag, which can be extended to include a <tt>:prepend_text</tt> - # and/or <tt>:append_text</tt> (to properly explain the error), and a <tt>:css_class</tt> to style it - # accordingly. +object+ should either be the name of an instance variable or the actual object. The method can be - # passed in either as a string or a symbol. + # This error message is wrapped in a <tt>DIV</tt> tag by default or with <tt>:html_tag</tt> if specified, + # which can be extended to include a <tt>:prepend_text</tt> and/or <tt>:append_text</tt> (to properly explain + # the error), and a <tt>:css_class</tt> to style it accordingly. +object+ should either be the name of an + # instance variable or the actual object. The method can be passed in either as a string or a symbol. # As an example, let's say you have a model <tt>@post</tt> that has an error message on the +title+ attribute: # # <%= error_message_on "post", "title" %> @@ -112,25 +112,28 @@ module ActionView # <%= error_message_on "post", "title", # :prepend_text => "Title simply ", # :append_text => " (or it won't work).", + # :html_tag => "span", # :css_class => "inputError" %> + # # => <span class="inputError">Title simply can't be empty (or it won't work).</span> def error_message_on(object, method, *args) options = args.extract_options! unless args.empty? ActiveSupport::Deprecation.warn('error_message_on takes an option hash instead of separate ' + - 'prepend_text, append_text, and css_class arguments', caller) + 'prepend_text, append_text, html_tag, and css_class arguments', caller) options[:prepend_text] = args[0] || '' options[:append_text] = args[1] || '' - options[:css_class] = args[2] || 'formError' + options[:html_tag] = args[2] || 'div' + options[:css_class] = args[3] || 'formError' end - options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError') + options.reverse_merge!(:prepend_text => '', :append_text => '', :html_tag => 'div', :css_class => 'formError') object = convert_to_model(object) if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) && (errors = obj.errors[method]).presence - content_tag("div", - "#{options[:prepend_text]}#{ERB::Util.h(errors.first)}#{options[:append_text]}".html_safe, + content_tag(options[:html_tag], + (options[:prepend_text].html_safe << errors.first).safe_concat(options[:append_text]), :class => options[:css_class] ) else diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 02ad41719b..e4ec17467e 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -108,7 +108,7 @@ module ActionView # "http://asset%d.example.com", "https://asset1.example.com" # ) # - # === Using asset timestamps + # === Customizing the asset path # # By default, Rails appends asset's timestamps to all asset paths. This allows # you to set a cache-expiration date for the asset far into the future, but @@ -133,6 +133,65 @@ module ActionView # will request the same assets over and over again even thought they didn't # change. You can use something like Live HTTP Headers for Firefox to verify # that the cache is indeed working. + # + # This strategy works well enough for most server setups and requires the + # least configuration, but if you deploy several application servers at + # different times - say to handle a temporary spike in load - then the + # asset time stamps will be out of sync. In a setup like this you may want + # to set the way that asset paths are generated yourself. + # + # Altering the asset paths that Rails generates can be done in two ways. + # The easiest is to define the RAILS_ASSET_ID environment variable. The + # contents of this variable will always be used in preference to + # calculated timestamps. A more complex but flexible way is to set + # <tt>ActionController::Base.config.asset_path</tt> to a proc + # that takes the unmodified asset path and returns the path needed for + # your asset caching to work. Typically you'd do something like this in + # <tt>config/environments/production.rb</tt>: + # + # # Normally you'd calculate RELEASE_NUMBER at startup. + # RELEASE_NUMBER = 12345 + # config.action_controller.asset_path_template = proc { |asset_path| + # "/release-#{RELEASE_NUMBER}#{asset_path}" + # } + # + # This example would cause the following behaviour on all servers no + # matter when they were deployed: + # + # image_tag("rails.png") + # # => <img alt="Rails" src="/release-12345/images/rails.png" /> + # stylesheet_link_tag("application") + # # => <link href="/release-12345/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" /> + # + # Changing the asset_path does require that your web servers have + # knowledge of the asset template paths that you rewrite to so it's not + # suitable for out-of-the-box use. To use the example given above you + # could use something like this in your Apache VirtualHost configuration: + # + # <LocationMatch "^/release-\d+/(images|javascripts|stylesheets)/.*$"> + # # Some browsers still send conditional-GET requests if there's a + # # Last-Modified header or an ETag header even if they haven't + # # reached the expiry date sent in the Expires header. + # Header unset Last-Modified + # Header unset ETag + # FileETag None + # + # # Assets requested using a cache-busting filename should be served + # # only once and then cached for a really long time. The HTTP/1.1 + # # spec frowns on hugely-long expiration times though and suggests + # # that assets which never expire be served with an expiration date + # # 1 year from access. + # ExpiresActive On + # ExpiresDefault "access plus 1 year" + # </LocationMatch> + # + # # We use cached-busting location names with the far-future expires + # # headers to ensure that if a file does change it can force a new + # # request. The actual asset filenames are still the same though so we + # # need to rewrite the location from the cache-busting location to the + # # real asset location so that we can serve it. + # RewriteEngine On + # RewriteRule ^/release-\d+/(images|javascripts|stylesheets)/(.*)$ /$1/$2 [L] module AssetTagHelper JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls', 'rails'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES) @@ -646,7 +705,7 @@ module ActionView source += ".#{ext}" if rewrite_extension?(source, dir, ext) source = "/#{dir}/#{source}" unless source[0] == ?/ - source = rewrite_asset_path(source) + source = rewrite_asset_path(source, config.asset_path) has_request = controller.respond_to?(:request) if has_request && include_host && source !~ %r{^#{controller.config.relative_url_root}/} @@ -710,7 +769,13 @@ module ActionView # Break out the asset path rewrite in case plugins wish to put the asset id # someplace other than the query string. - def rewrite_asset_path(source) + def rewrite_asset_path(source, path = nil) + if path && path.respond_to?(:call) + return path.call(source) + elsif path && path.is_a?(String) + return path % [source] + end + asset_id = rails_asset_id(source) if asset_id.blank? source diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index f0be814700..20598237e9 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActionView module Helpers # CaptureHelper exposes methods to let you extract generated markup which diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 2ba5339b7d..89560d0b49 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -4,6 +4,7 @@ require 'action_view/helpers/tag_helper' require 'action_view/helpers/form_tag_helper' require 'active_support/core_ext/class/inheritable_attributes' require 'active_support/core_ext/hash/slice' +require 'active_support/core_ext/object/blank' module ActionView module Helpers @@ -1220,7 +1221,7 @@ module ActionView end end - ActionView.base_hook do + ActiveSupport.on_load(:action_view) do class ActionView::Base cattr_accessor :default_form_builder @@default_form_builder = ::ActionView::Helpers::FormBuilder diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 4c523d4b20..11c6351bd3 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -1,6 +1,7 @@ require 'cgi' require 'erb' require 'action_view/helpers/form_helper' +require 'active_support/core_ext/object/blank' module ActionView module Helpers diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 07694f5ebb..ca100e102e 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -1,6 +1,7 @@ require 'cgi' require 'action_view/helpers/tag_helper' require 'active_support/core_ext/object/returning' +require 'active_support/core_ext/object/blank' module ActionView module Helpers diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 719b64b940..605e5d5873 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/big_decimal/conversions' require 'active_support/core_ext/float/rounding' +require 'active_support/core_ext/object/blank' module ActionView module Helpers #:nodoc: diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index ccdc8181db..ebe0b4e876 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -1,6 +1,7 @@ require 'set' require 'active_support/json' require 'active_support/core_ext/object/returning' +require 'active_support/core_ext/object/blank' module ActionView module Helpers diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb index 9b4cacd4d7..c09d01eeee 100644 --- a/actionpack/lib/action_view/helpers/tag_helper.rb +++ b/actionpack/lib/action_view/helpers/tag_helper.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/object/blank' require 'set' module ActionView diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb index 27be1690dd..0e1bc139ff 100644 --- a/actionpack/lib/action_view/helpers/text_helper.rb +++ b/actionpack/lib/action_view/helpers/text_helper.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/object/blank' require 'action_view/helpers/tag_helper' module ActionView diff --git a/actionpack/lib/action_view/railtie.rb b/actionpack/lib/action_view/railtie.rb index 9cf007cd2b..c606a71e18 100644 --- a/actionpack/lib/action_view/railtie.rb +++ b/actionpack/lib/action_view/railtie.rb @@ -10,14 +10,14 @@ module ActionView initializer "action_view.cache_asset_timestamps" do |app| unless app.config.cache_classes - ActionView.base_hook do + ActiveSupport.on_load(:action_view) do ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false end end end initializer "action_view.set_configs" do |app| - ActionView.base_hook do + ActiveSupport.on_load(:action_view) do app.config.action_view.each do |k,v| send "#{k}=", v end diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index 17d16556b9..f04a89c1ac 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActionView # There's also a convenience method for rendering sub templates within the current controller that depends on a # single object (we call this kind of sub templates for partials). It relies on the fact that partials should diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 8e8afaa43f..a223b3a55f 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -35,12 +35,7 @@ module ActionView def cached(key, prefix, name, partial) return yield unless key && caching? - scope = @cached[key][prefix][name] - if scope.key?(partial) - scope[partial] - else - scope[partial] = yield - end + @cached[key][prefix][name][partial] ||= yield end end diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb index b0ababe344..23b0c6e121 100644 --- a/actionpack/lib/action_view/test_case.rb +++ b/actionpack/lib/action_view/test_case.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/object/blank' require 'action_controller/test_case' require 'action_view' diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 5b2ff3e871..143491a640 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -95,7 +95,7 @@ module ActiveSupport map.connect ':controller/:action/:id' end - ActionController::IntegrationTest.app.router.draw do |map| + ActionController::IntegrationTest.app.routes.draw do |map| # FIXME: match ':controller(/:action(/:id))' map.connect ':controller/:action/:id' end @@ -104,12 +104,11 @@ module ActiveSupport end class RoutedRackApp - attr_reader :router - alias routes router + attr_reader :routes - def initialize(router, &blk) - @router = router - @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@router) + def initialize(routes, &blk) + @routes = routes + @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes) end def call(env) @@ -234,7 +233,7 @@ module ActionView # Must repeat the setup because AV::TestCase is a duplication # of AC::TestCase setup do - @router = SharedTestRoutes + @routes = SharedTestRoutes end end end @@ -250,7 +249,7 @@ module ActionController include ActionDispatch::TestProcess setup do - @router = SharedTestRoutes + @routes = SharedTestRoutes end end end diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index 5643ad5ad6..9f5e8ec657 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -40,12 +40,12 @@ class PolymorphicRoutesTest < ActionController::TestCase end def test_with_record - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}", polymorphic_url(@project) end end - + def test_with_class with_test_routes do assert_equal "http://example.com/projects", polymorphic_url(@project.class) @@ -53,67 +53,67 @@ class PolymorphicRoutesTest < ActionController::TestCase end def test_with_new_record - with_test_routes do + with_test_routes do assert_equal "http://example.com/projects", polymorphic_url(@project) end end def test_with_destroyed_record - with_test_routes do + with_test_routes do @project.destroy assert_equal "http://example.com/projects", polymorphic_url(@project) end end def test_with_record_and_action - with_test_routes do + with_test_routes do assert_equal "http://example.com/projects/new", polymorphic_url(@project, :action => 'new') end end def test_url_helper_prefixed_with_new - with_test_routes do + with_test_routes do assert_equal "http://example.com/projects/new", new_polymorphic_url(@project) end end def test_url_helper_prefixed_with_edit - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}/edit", edit_polymorphic_url(@project) end end - + def test_url_helper_prefixed_with_edit_with_url_options - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}/edit?param1=10", edit_polymorphic_url(@project, :param1 => '10') end end - + def test_url_helper_with_url_options - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}?param1=10", polymorphic_url(@project, :param1 => '10') end end def test_format_option - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}.pdf", polymorphic_url(@project, :format => :pdf) end end - + def test_format_option_with_url_options - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}.pdf?param1=10", polymorphic_url(@project, :format => :pdf, :param1 => '10') end end - + def test_id_and_format_option - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}.pdf", polymorphic_url(:id => @project, :format => :pdf) end @@ -126,14 +126,14 @@ class PolymorphicRoutesTest < ActionController::TestCase assert_equal "http://example.com/projects/#{@project.id}/tasks/#{@task.id}", polymorphic_url([@project, @task]) end end - + def test_with_nested_unsaved with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}/tasks", polymorphic_url([@project, @task]) end end - + def test_with_nested_destroyed with_test_routes do @project.save @@ -141,63 +141,63 @@ class PolymorphicRoutesTest < ActionController::TestCase assert_equal "http://example.com/projects/#{@project.id}/tasks", polymorphic_url([@project, @task]) end end - + def test_with_nested_class with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}/tasks", polymorphic_url([@project, @task.class]) end end - + def test_class_with_array_and_namespace - with_admin_test_routes do + with_admin_test_routes do assert_equal "http://example.com/admin/projects", polymorphic_url([:admin, @project.class]) end end - + def test_new_with_array_and_namespace - with_admin_test_routes do + with_admin_test_routes do assert_equal "http://example.com/admin/projects/new", polymorphic_url([:admin, @project], :action => 'new') end end - + def test_unsaved_with_array_and_namespace - with_admin_test_routes do + with_admin_test_routes do assert_equal "http://example.com/admin/projects", polymorphic_url([:admin, @project]) end end - + def test_nested_unsaved_with_array_and_namespace - with_admin_test_routes do + with_admin_test_routes do @project.save assert_equal "http://example.com/admin/projects/#{@project.id}/tasks", polymorphic_url([:admin, @project, @task]) end end - + def test_nested_with_array_and_namespace - with_admin_test_routes do + with_admin_test_routes do @project.save @task.save assert_equal "http://example.com/admin/projects/#{@project.id}/tasks/#{@task.id}", polymorphic_url([:admin, @project, @task]) end end - + def test_ordering_of_nesting_and_namespace - with_admin_and_site_test_routes do + with_admin_and_site_test_routes do @project.save @task.save @step.save assert_equal "http://example.com/admin/projects/#{@project.id}/site/tasks/#{@task.id}/steps/#{@step.id}", polymorphic_url([:admin, @project, :site, @task, @step]) end end - + def test_nesting_with_array_ending_in_singleton_resource with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}/bid", polymorphic_url([@project, :bid]) end end - + def test_nesting_with_array_containing_singleton_resource with_test_routes do @project.save @@ -205,7 +205,7 @@ class PolymorphicRoutesTest < ActionController::TestCase assert_equal "http://example.com/projects/#{@project.id}/bid/tasks/#{@task.id}", polymorphic_url([@project, :bid, @task]) end end - + def test_nesting_with_array_containing_singleton_resource_and_format with_test_routes do @project.save @@ -213,7 +213,7 @@ class PolymorphicRoutesTest < ActionController::TestCase assert_equal "http://example.com/projects/#{@project.id}/bid/tasks/#{@task.id}.pdf", polymorphic_url([@project, :bid, @task], :format => :pdf) end end - + def test_nesting_with_array_containing_namespace_and_singleton_resource with_admin_test_routes do @project.save @@ -221,47 +221,47 @@ class PolymorphicRoutesTest < ActionController::TestCase assert_equal "http://example.com/admin/projects/#{@project.id}/bid/tasks/#{@task.id}", polymorphic_url([:admin, @project, :bid, @task]) end end - + def test_nesting_with_array_containing_nil with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}/bid", polymorphic_url([@project, nil, :bid]) end end - + def test_with_array_containing_single_object - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}", polymorphic_url([nil, @project]) end end - + def test_with_array_containing_single_name - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects", polymorphic_url([:projects]) end end - + def test_with_array_containing_symbols with_test_routes do assert_equal "http://example.com/series/new", polymorphic_url([:new, :series]) end end - + def test_with_hash - with_test_routes do + with_test_routes do @project.save assert_equal "http://example.com/projects/#{@project.id}", polymorphic_url(:id => @project) end end - + def test_polymorphic_path_accepts_options - with_test_routes do + with_test_routes do assert_equal "/projects/new", polymorphic_path(@project, :action => 'new') end end - + def test_polymorphic_path_does_not_modify_arguments with_admin_test_routes do @project.save @@ -275,108 +275,108 @@ class PolymorphicRoutesTest < ActionController::TestCase assert_equal original_args, [object_array, options] end end - + # Tests for names where .plural.singular doesn't round-trip def test_with_irregular_plural_record - with_test_routes do + with_test_routes do @tax.save assert_equal "http://example.com/taxes/#{@tax.id}", polymorphic_url(@tax) end end - + def test_with_irregular_plural_class - with_test_routes do + with_test_routes do assert_equal "http://example.com/taxes", polymorphic_url(@tax.class) end end - + def test_with_irregular_plural_new_record - with_test_routes do + with_test_routes do assert_equal "http://example.com/taxes", polymorphic_url(@tax) end end def test_with_irregular_plural_destroyed_record with_test_routes do - @tax.destroy + @tax.destroy assert_equal "http://example.com/taxes", polymorphic_url(@tax) end end - + def test_with_irregular_plural_record_and_action - with_test_routes do + with_test_routes do assert_equal "http://example.com/taxes/new", polymorphic_url(@tax, :action => 'new') end end - + def test_irregular_plural_url_helper_prefixed_with_new - with_test_routes do + with_test_routes do assert_equal "http://example.com/taxes/new", new_polymorphic_url(@tax) end end - + def test_irregular_plural_url_helper_prefixed_with_edit - with_test_routes do + with_test_routes do @tax.save assert_equal "http://example.com/taxes/#{@tax.id}/edit", edit_polymorphic_url(@tax) end end - + def test_with_nested_irregular_plurals - with_test_routes do + with_test_routes do @tax.save @fax.save assert_equal "http://example.com/taxes/#{@tax.id}/faxes/#{@fax.id}", polymorphic_url([@tax, @fax]) end end - + def test_with_nested_unsaved_irregular_plurals - with_test_routes do + with_test_routes do @tax.save assert_equal "http://example.com/taxes/#{@tax.id}/faxes", polymorphic_url([@tax, @fax]) end end - + def test_new_with_irregular_plural_array_and_namespace - with_admin_test_routes do + with_admin_test_routes do assert_equal "http://example.com/admin/taxes/new", polymorphic_url([:admin, @tax], :action => 'new') end end - + def test_class_with_irregular_plural_array_and_namespace - with_admin_test_routes do + with_admin_test_routes do assert_equal "http://example.com/admin/taxes", polymorphic_url([:admin, @tax.class]) end end - + def test_unsaved_with_irregular_plural_array_and_namespace - with_admin_test_routes do + with_admin_test_routes do assert_equal "http://example.com/admin/taxes", polymorphic_url([:admin, @tax]) end end - + def test_nesting_with_irregular_plurals_and_array_ending_in_singleton_resource - with_test_routes do + with_test_routes do @tax.save assert_equal "http://example.com/taxes/#{@tax.id}/bid", polymorphic_url([@tax, :bid]) end end - + def test_with_array_containing_single_irregular_plural_object - with_test_routes do + with_test_routes do @tax.save assert_equal "http://example.com/taxes/#{@tax.id}", polymorphic_url([nil, @tax]) end end - + def test_with_array_containing_single_name_irregular_plural - with_test_routes do + with_test_routes do @tax.save assert_equal "http://example.com/taxes", polymorphic_url([:taxes]) end end - - # Tests for uncountable names + + # Tests for uncountable names def test_uncountable_resource with_test_routes do @series.save @@ -400,11 +400,11 @@ class PolymorphicRoutesTest < ActionController::TestCase map.resources :series end - self.class.send(:include, @router.url_helpers) + self.class.send(:include, @routes.url_helpers) yield end end - + def with_admin_test_routes(options = {}) with_routing do |set| set.draw do |map| @@ -422,11 +422,11 @@ class PolymorphicRoutesTest < ActionController::TestCase end end - self.class.send(:include, @router.url_helpers) + self.class.send(:include, @routes.url_helpers) yield end end - + def with_admin_and_site_test_routes(options = {}) with_routing do |set| set.draw do |map| @@ -441,7 +441,7 @@ class PolymorphicRoutesTest < ActionController::TestCase end end - self.class.send(:include, @router.url_helpers) + self.class.send(:include, @routes.url_helpers) yield end end diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index f0ad652d50..217260fdcd 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -81,9 +81,9 @@ class PageCachingTest < ActionController::TestCase match '/', :to => 'posts#index', :as => :main end @params[:format] = 'rss' - assert_equal '/posts.rss', @router.url_for(@params) + assert_equal '/posts.rss', @routes.url_for(@params) @params[:format] = nil - assert_equal '/', @router.url_for(@params) + assert_equal '/', @routes.url_for(@params) end end @@ -518,7 +518,7 @@ class ActionCacheTest < ActionController::TestCase @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new @controller = ActionCachingTestController.new - @controller.singleton_class.send(:include, @router.url_helpers) + @controller.singleton_class.send(:include, @routes.url_helpers) @request.host = 'hostname.com' end diff --git a/actionpack/test/controller/cookie_test.rb b/actionpack/test/controller/cookie_test.rb index 36498d13a9..278cae1415 100644 --- a/actionpack/test/controller/cookie_test.rb +++ b/actionpack/test/controller/cookie_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' -ActionController::Base.cookie_verifier_secret = "thisISverySECRET123" +ActionController::Base.config.secret = "thisISverySECRET123" class CookieTest < ActionController::TestCase class TestController < ActionController::Base diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index c9782856bd..1e2ee06adc 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -430,3 +430,50 @@ class MetalIntegrationTest < ActionController::IntegrationTest assert_equal 'http://www.example.com/foo', url_for(:controller => "foo") end end + +class ApplicationIntegrationTest < ActionController::IntegrationTest + class TestController < ActionController::Base + def index + render :text => "index" + end + end + + def self.call(env) + routes.call(env) + end + + def self.routes + @routes ||= ActionDispatch::Routing::RouteSet.new + end + + routes.draw do + match 'foo', :to => 'application_integration_test/test#index', :as => :foo + match 'bar', :to => 'application_integration_test/test#index', :as => :bar + end + + def app + self.class + end + + test "includes route helpers" do + assert_equal '/foo', foo_path + assert_equal '/bar', bar_path + end + + test "route helpers after controller access" do + get '/foo' + assert_equal '/foo', foo_path + + get '/bar' + assert_equal '/bar', bar_path + end + + test "missing route helper before controller access" do + assert_raise(NameError) { missing_path } + end + + test "missing route helper after controller access" do + get '/foo' + assert_raise(NameError) { missing_path } + end +end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 17c645c04c..a9d1c55c05 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -126,7 +126,7 @@ class ResourcesTest < ActionController::TestCase def test_with_custom_conditions with_restful_routing :messages, :conditions => { :subdomain => 'app' } do - assert @router.recognize_path("/messages", :method => :get, :subdomain => 'app') + assert @routes.recognize_path("/messages", :method => :get, :subdomain => 'app') end end @@ -395,7 +395,7 @@ class ResourcesTest < ActionController::TestCase assert_restful_routes_for :messages do |options| assert_recognizes(options.merge(:action => "new"), :path => "/messages/new", :method => :get) assert_raise(ActionController::RoutingError) do - @router.recognize_path("/messages/new", :method => :post) + @routes.recognize_path("/messages/new", :method => :post) end end end @@ -505,7 +505,7 @@ class ResourcesTest < ActionController::TestCase def test_restful_routes_dont_generate_duplicates with_restful_routing :messages do - routes = @router.routes + routes = @routes.routes routes.each do |route| routes.each do |r| next if route === r # skip the comparison instance @@ -1169,8 +1169,8 @@ class ResourcesTest < ActionController::TestCase options[:shallow_options] = options[:options] end - new_action = @router.resources_path_names[:new] || "new" - edit_action = @router.resources_path_names[:edit] || "edit" + new_action = @routes.resources_path_names[:new] || "new" + edit_action = @routes.resources_path_names[:edit] || "edit" if options[:path_names] new_action = options[:path_names][:new] if options[:path_names][:new] @@ -1237,7 +1237,7 @@ class ResourcesTest < ActionController::TestCase end @controller = "#{options[:options][:controller].camelize}Controller".constantize.new - @controller.singleton_class.send(:include, @router.url_helpers) + @controller.singleton_class.send(:include, @routes.url_helpers) @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new get :index, options[:options] @@ -1307,7 +1307,7 @@ class ResourcesTest < ActionController::TestCase def assert_singleton_named_routes_for(singleton_name, options = {}) (options[:options] ||= {})[:controller] ||= singleton_name.to_s.pluralize @controller = "#{options[:options][:controller].camelize}Controller".constantize.new - @controller.singleton_class.send(:include, @router.url_helpers) + @controller.singleton_class.send(:include, @routes.url_helpers) @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new get :show, options[:options] diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb index f6ba275849..8910454b8b 100644 --- a/actionpack/test/controller/test_test.rb +++ b/actionpack/test/controller/test_test.rb @@ -478,8 +478,8 @@ XML end def test_with_routing_places_routes_back - assert @router - routes_id = @router.object_id + assert @routes + routes_id = @routes.object_id begin with_routing { raise 'fail' } @@ -487,8 +487,8 @@ XML rescue RuntimeError end - assert @router - assert_equal routes_id, @router.object_id + assert @routes + assert_equal routes_id, @routes.object_id end def test_remote_addr diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index 7b46a48a1d..a8d7b75372 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -10,8 +10,8 @@ class UrlRewriterTests < ActionController::TestCase } end - def rewrite(router, options) - router.url_for(@options.merge(options)) + def rewrite(routes, options) + routes.url_for(@options.merge(options)) end end @@ -23,63 +23,63 @@ class UrlRewriterTests < ActionController::TestCase def test_port assert_equal('http://test.host:1271/c/a/i', - @rewriter.rewrite(@router, :controller => 'c', :action => 'a', :id => 'i', :port => 1271) + @rewriter.rewrite(@routes, :controller => 'c', :action => 'a', :id => 'i', :port => 1271) ) end def test_protocol_with_and_without_separator assert_equal('https://test.host/c/a/i', - @rewriter.rewrite(@router, :protocol => 'https', :controller => 'c', :action => 'a', :id => 'i') + @rewriter.rewrite(@routes, :protocol => 'https', :controller => 'c', :action => 'a', :id => 'i') ) assert_equal('https://test.host/c/a/i', - @rewriter.rewrite(@router, :protocol => 'https://', :controller => 'c', :action => 'a', :id => 'i') + @rewriter.rewrite(@routes, :protocol => 'https://', :controller => 'c', :action => 'a', :id => 'i') ) end def test_user_name_and_password assert_equal( 'http://david:secret@test.host/c/a/i', - @rewriter.rewrite(@router, :user => "david", :password => "secret", :controller => 'c', :action => 'a', :id => 'i') + @rewriter.rewrite(@routes, :user => "david", :password => "secret", :controller => 'c', :action => 'a', :id => 'i') ) end def test_user_name_and_password_with_escape_codes assert_equal( 'http://openid.aol.com%2Fnextangler:one+two%3F@test.host/c/a/i', - @rewriter.rewrite(@router, :user => "openid.aol.com/nextangler", :password => "one two?", :controller => 'c', :action => 'a', :id => 'i') + @rewriter.rewrite(@routes, :user => "openid.aol.com/nextangler", :password => "one two?", :controller => 'c', :action => 'a', :id => 'i') ) end def test_anchor assert_equal( 'http://test.host/c/a/i#anchor', - @rewriter.rewrite(@router, :controller => 'c', :action => 'a', :id => 'i', :anchor => 'anchor') + @rewriter.rewrite(@routes, :controller => 'c', :action => 'a', :id => 'i', :anchor => 'anchor') ) end def test_anchor_should_call_to_param assert_equal( 'http://test.host/c/a/i#anchor', - @rewriter.rewrite(@router, :controller => 'c', :action => 'a', :id => 'i', :anchor => Struct.new(:to_param).new('anchor')) + @rewriter.rewrite(@routes, :controller => 'c', :action => 'a', :id => 'i', :anchor => Struct.new(:to_param).new('anchor')) ) end def test_anchor_should_be_cgi_escaped assert_equal( 'http://test.host/c/a/i#anc%2Fhor', - @rewriter.rewrite(@router, :controller => 'c', :action => 'a', :id => 'i', :anchor => Struct.new(:to_param).new('anc/hor')) + @rewriter.rewrite(@routes, :controller => 'c', :action => 'a', :id => 'i', :anchor => Struct.new(:to_param).new('anc/hor')) ) end def test_trailing_slash options = {:controller => 'foo', :action => 'bar', :id => '3', :only_path => true} - assert_equal '/foo/bar/3', @rewriter.rewrite(@router, options) - assert_equal '/foo/bar/3?query=string', @rewriter.rewrite(@router, options.merge({:query => 'string'})) + assert_equal '/foo/bar/3', @rewriter.rewrite(@routes, options) + assert_equal '/foo/bar/3?query=string', @rewriter.rewrite(@routes, options.merge({:query => 'string'})) options.update({:trailing_slash => true}) - assert_equal '/foo/bar/3/', @rewriter.rewrite(@router, options) + assert_equal '/foo/bar/3/', @rewriter.rewrite(@routes, options) options.update({:query => 'string'}) - assert_equal '/foo/bar/3/?query=string', @rewriter.rewrite(@router, options) + assert_equal '/foo/bar/3/?query=string', @rewriter.rewrite(@routes, options) end end diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb index 05545395fb..5942950b15 100644 --- a/actionpack/test/controller/webservice_test.rb +++ b/actionpack/test/controller/webservice_test.rb @@ -245,7 +245,7 @@ class WebServiceTest < ActionController::IntegrationTest private def with_params_parsers(parsers = {}) old_session = @integration_session - @app = ActionDispatch::ParamsParser.new(app.router, parsers) + @app = ActionDispatch::ParamsParser.new(app.routes, parsers) reset! yield ensure diff --git a/actionpack/test/dispatch/rack_test.rb b/actionpack/test/dispatch/rack_test.rb index 94eba2a24f..504bebbb86 100644 --- a/actionpack/test/dispatch/rack_test.rb +++ b/actionpack/test/dispatch/rack_test.rb @@ -122,7 +122,7 @@ class RackRequestTest < BaseRackTest test "cgi environment variables" do assert_equal "Basic", @request.auth_type assert_equal 0, @request.content_length - assert_equal nil, @request.content_type + assert_equal nil, @request.content_mime_type assert_equal "CGI/1.1", @request.gateway_interface assert_equal "*/*", @request.accept assert_equal "UTF-8", @request.accept_charset @@ -177,12 +177,12 @@ end class RackRequestContentTypeTest < BaseRackTest test "html content type verification" do @request.env['CONTENT_TYPE'] = Mime::HTML.to_s - assert @request.content_type.verify_request? + assert @request.content_mime_type.verify_request? end test "xml content type verification" do @request.env['CONTENT_TYPE'] = Mime::XML.to_s - assert !@request.content_type.verify_request? + assert !@request.content_mime_type.verify_request? end end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index badef4e92e..9093e1ed65 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -295,7 +295,7 @@ class RequestTest < ActiveSupport::TestCase test "content type" do request = stub_request 'CONTENT_TYPE' => 'text/html' - assert_equal Mime::HTML, request.content_type + assert_equal Mime::HTML, request.content_mime_type end test "can override format with parameter" do @@ -310,17 +310,17 @@ class RequestTest < ActiveSupport::TestCase test "no content type" do request = stub_request - assert_equal nil, request.content_type + assert_equal nil, request.content_mime_type end test "content type is XML" do request = stub_request 'CONTENT_TYPE' => 'application/xml' - assert_equal Mime::XML, request.content_type + assert_equal Mime::XML, request.content_mime_type end test "content type with charset" do request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8' - assert_equal Mime::XML, request.content_type + assert_equal Mime::XML, request.content_mime_type end test "user agent" do diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index c4e71a8689..e58653cb8c 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -114,6 +114,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resources :comments, :except => :destroy end + resources :sheep + match 'sprockets.js' => ::TestRoutingMapper::SprocketsApp match 'people/:id/update', :to => 'people#update', :as => :update_person @@ -171,6 +173,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resources :descriptions root :to => 'projects#index' end + + resources :products, :constraints => { :id => /\d{4}/ } do + resources :images + end + + resource :dashboard, :constraints => { :ip => /192\.168\.1\.\d{1,3}/ } end end @@ -525,6 +533,23 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_resource_with_slugs_in_ids + with_test_routes do + get '/posts/rails-rocks' + assert_equal 'posts#show', @response.body + assert_equal '/posts/rails-rocks', post_path(:id => 'rails-rocks') + end + end + + def test_resources_for_uncountable_names + with_test_routes do + assert_equal '/sheep', sheep_index_path + assert_equal '/sheep/1', sheep_path(1) + assert_equal '/sheep/new', new_sheep_path + assert_equal '/sheep/1/edit', edit_sheep_path(1) + end + end + def test_path_names with_test_routes do get '/es/projeto' @@ -794,6 +819,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_resource_constraints + with_test_routes do + assert_raise(ActionController::RoutingError) { get '/products/1' } + get '/products' + assert_equal 'products#index', @response.body + get '/products/0001' + assert_equal 'products#show', @response.body + + assert_raise(ActionController::RoutingError) { get '/products/1/images' } + get '/products/0001/images' + assert_equal 'images#index', @response.body + get '/products/0001/images/1' + assert_equal 'images#show', @response.body + + assert_raise(ActionController::RoutingError) { get '/dashboard', {}, {'REMOTE_ADDR' => '10.0.0.100'} } + get '/dashboard', {}, {'REMOTE_ADDR' => '192.168.1.100'} + assert_equal 'dashboards#show', @response.body + end + end + private def with_test_routes yield diff --git a/actionpack/test/template/active_model_helper_test.rb b/actionpack/test/template/active_model_helper_test.rb index 7a665b00bc..1a5316a689 100644 --- a/actionpack/test/template/active_model_helper_test.rb +++ b/actionpack/test/template/active_model_helper_test.rb @@ -266,6 +266,10 @@ class ActiveModelHelperTest < ActionView::TestCase assert_dom_equal "<div class=\"differentError\">beforecan't be emptyafter</div>", error_message_on(:post, :author_name, :css_class => 'differentError', :prepend_text => 'before', :append_text => 'after') end + def test_error_message_on_with_tag_option_in_options_hash + assert_dom_equal "<span class=\"differentError\">beforecan't be emptyafter</span>", error_message_on(:post, :author_name, :html_tag => "span", :css_class => 'differentError', :prepend_text => 'before', :append_text => 'after') + end + def test_error_message_on_handles_empty_errors assert_equal "", error_message_on(@post, :tag) end diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index c471df861d..fbd504ae7d 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -373,6 +373,22 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal %(<img alt="Rails" src="/images/rails.png?#{expected_time}" />), image_tag("rails.png") end + def test_string_asset_id + @controller.config.asset_path = "/assets.v12345%s" + + expected_path = "/assets.v12345/images/rails.png" + assert_equal %(<img alt="Rails" src="#{expected_path}" />), image_tag("rails.png") + end + + def test_proc_asset_id + @controller.config.asset_path = Proc.new do |asset_path| + "/assets.v12345#{asset_path}" + end + + expected_path = "/assets.v12345/images/rails.png" + assert_equal %(<img alt="Rails" src="#{expected_path}" />), image_tag("rails.png") + end + def test_timebased_asset_id_with_relative_url_root @controller.config.relative_url_root = "/collaboration/hieraki" expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).mtime.to_i.to_s diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index 195a6ea3ae..c1a38a25de 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -114,7 +114,7 @@ module ActionView end test "is able to use routes" do - controller.request.assign_parameters(@router, 'foo', 'index') + controller.request.assign_parameters(@routes, 'foo', 'index') assert_equal '/foo', url_for assert_equal '/bar', url_for(:controller => 'bar') end diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index cb67ef7270..2d5acdfced 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -1,4 +1,7 @@ +require 'active_model/attribute_methods' +require 'active_support/concern' require 'active_support/hash_with_indifferent_access' +require 'active_support/core_ext/object/duplicable' module ActiveModel # <tt>ActiveModel::Dirty</tt> provides a way to track changes in your diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index a9a54a90e0..8d28040c32 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/string/inflections' +require 'active_support/core_ext/object/blank' require 'active_support/ordered_hash' module ActiveModel diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 0c1334fe1b..c1838bb93e 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -4,7 +4,7 @@ module ActiveModel def check_validity! raise ArgumentError, "An object with the method include? is required must be supplied as the " << ":in option of the configuration hash" unless options[:in].respond_to?(:include?) - end + end def validate_each(record, attribute, value) return if options[:in].include?(value) diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index b7c52be3f0..906d239bcc 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/array/wrap' require "active_support/core_ext/module/anonymous" +require 'active_support/core_ext/object/blank' module ActiveModel #:nodoc: # A simple base class that can be used along with diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 214ec8c1d8..e379f4f967 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,9 +1,11 @@ -*Edge* +*Rails 3.0.0 [Beta 2] (pending)* + +* To prefix the table names of all models in a module, define self.table_name_prefix on the module. #4032 [Andrew White] * Silenced "SHOW FIELDS" and "SET SQL_AUTO_IS_NULL=0" statements from the MySQL driver to improve log signal to noise ration in development [DHH] -*Rails 3.0 [Beta] (February 4th, 2010)* +*Rails 3.0.0 [Beta 1] (February 4th, 2010)* * PostgreSQLAdapter: set time_zone to UTC when Base.default_timezone == :utc so that Postgres doesn't incorrectly offset-adjust values inserted into TIMESTAMP WITH TIME ZONE columns. #3777 [Jack Christensen] diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 5942640c85..8a1aa50e24 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -111,10 +111,10 @@ module ActiveRecord autoload :TestCase autoload :TestFixtures, 'active_record/fixtures' +end - base_hook do - Arel::Table.engine = Arel::Sql::Engine.new(self) - end +ActiveSupport.on_load(:active_record) do + Arel::Table.engine = Arel::Sql::Engine.new(self) end I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
\ No newline at end of file diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb index 6725d4e88b..95bbaf00cf 100644 --- a/activerecord/lib/active_record/association_preload.rb +++ b/activerecord/lib/active_record/association_preload.rb @@ -159,6 +159,11 @@ module ActiveRecord association_proxy.__send__(:set_inverse_instance, associated_record, mapped_record) end end + + id_to_record_map.each do |id, records| + next if seen_keys.include?(id.to_s) + records.each {|record| record.send("set_#{reflection_name}_target", nil) } + end end # Given a collection of ActiveRecord objects, constructs a Hash which maps @@ -324,7 +329,7 @@ module ActiveRecord klass = klass_name.constantize table_name = klass.quoted_table_name - primary_key = klass.primary_key + primary_key = reflection.options[:primary_key] || klass.primary_key column_type = klass.columns.detect{|c| c.name == primary_key}.type ids = id_map.keys.map do |id| diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index d623ddb915..7406daf837 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/enumerable' +require 'active_support/core_ext/object/blank' module ActiveRecord class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc: @@ -85,6 +86,15 @@ module ActiveRecord end end + # This error is raised when trying to destroy a parent instance in a N:1, 1:1 assosications + # (has_many, has_one) when there is at least 1 child assosociated instance. + # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project + class DeleteRestrictionError < ActiveRecordError #:nodoc: + def initialize(reflection) + super("Cannot delete record because of dependent #{reflection.name}") + end + end + # See ActiveRecord::Associations::ClassMethods for documentation. module Associations # :nodoc: extend ActiveSupport::Concern @@ -830,6 +840,8 @@ module ActiveRecord # objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated # objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. *Warning:* This option is ignored when also using # the <tt>:through</tt> option. + # the <tt>:through</tt> option. If set to <tt>:restrict</tt> + # this object cannot be deleted if it has any associated object. # [:finder_sql] # Specify a complete SQL statement to fetch the association. This is a good way to go for complex # associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added. @@ -1468,9 +1480,15 @@ module ActiveRecord # Creates before_destroy callback methods that nullify, delete or destroy # has_many associated objects, according to the defined :dependent rule. + # If the association is marked as :dependent => :restrict, create a callback + # that prevents deleting entirely. # # See HasManyAssociation#delete_records. Dependent associations # delete children, otherwise foreign key is set to NULL. + # See HasManyAssociation#delete_records. Dependent associations + # delete children if the option is set to :destroy or :delete_all, set the + # foreign key to NULL if the option is set to :nullify, and do not touch the + # child records if the option is set to :restrict. # # The +extra_conditions+ parameter, which is not used within the main # Active Record codebase, is meant to allow plugins to define extra @@ -1530,14 +1548,24 @@ module ActiveRecord %@#{dependent_conditions}@) end CALLBACK + when :restrict + method_name = "has_many_dependent_restrict_for_#{reflection.name}".to_sym + define_method(method_name) do + unless send(reflection.name).empty? + raise DeleteRestrictionError.new(reflection) + end + end + before_destroy method_name else - raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, or :nullify (#{reflection.options[:dependent].inspect})" + raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, :nullify or :restrict (#{reflection.options[:dependent].inspect})" end end end # Creates before_destroy callback methods that nullify, delete or destroy # has_one associated objects, according to the defined :dependent rule. + # If the association is marked as :dependent => :restrict, create a callback + # that prevents deleting entirely. def configure_dependency_for_has_one(reflection) if reflection.options.include?(:dependent) name = reflection.options[:dependent] @@ -1558,8 +1586,16 @@ module ActiveRecord association.update_attribute(#{reflection.primary_key_name.inspect}, nil) if association end eoruby + when :restrict + method_name = "has_one_dependent_restrict_for_#{reflection.name}".to_sym + define_method(method_name) do + unless send(reflection.name).nil? + raise DeleteRestrictionError.new(reflection) + end + end + before_destroy method_name else - raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})" + raise ArgumentError, "The :dependent option expects either :destroy, :delete, :nullify or :restrict (#{reflection.options[:dependent].inspect})" end before_destroy method_name @@ -1995,7 +2031,7 @@ module ActiveRecord [aliased_table[foreign_key].eq(parent_table[reflection.options[:primary_key] || parent.primary_key])] end when :belongs_to - [aliased_table[reflection.klass.primary_key].eq(parent_table[options[:foreign_key] || reflection.primary_key_name])] + [aliased_table[options[:primary_key] || reflection.klass.primary_key].eq(parent_table[options[:foreign_key] || reflection.primary_key_name])] end unless klass.descends_from_active_record? diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index bd2acd4340..5338bb099d 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -1,4 +1,5 @@ require "active_record/associations/through_association_scope" +require 'active_support/core_ext/object/blank' module ActiveRecord module Associations diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index a8698a2f5a..435aea9b09 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord module AttributeMethods module Dirty diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index 095814b635..411330dda2 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -3,6 +3,12 @@ module ActiveRecord module PrimaryKey extend ActiveSupport::Concern + # Returns this record's primary key value wrapped in an Array + # or nil if the record is a new_record? + def to_key + new_record? ? nil : [ send(self.class.primary_key) ] + end + module ClassMethods # Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the # primary_key_prefix_type setting, though. @@ -39,22 +45,6 @@ module ActiveRecord end alias :primary_key= :set_primary_key end - - module InstanceMethods - - # Returns this record's primary key value wrapped in an Array - # or nil if the record is a new_record? - # This is done to comply with the AMo interface that expects - # every AMo compliant object to respond_to?(:to_key) and return - # an Enumerable object from that call, or nil if new_record? - # This method also takes custom primary keys specified via - # the +set_primary_key+ into account. - def to_key - new_record? ? nil : [ self.primary_key ] - end - - end - end end end diff --git a/activerecord/lib/active_record/attribute_methods/query.rb b/activerecord/lib/active_record/attribute_methods/query.rb index a949d80120..948809c65a 100644 --- a/activerecord/lib/active_record/attribute_methods/query.rb +++ b/activerecord/lib/active_record/attribute_methods/query.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord module AttributeMethods module Query diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 1c93346a52..37b379af9e 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -13,6 +13,8 @@ require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/string/behavior' require 'active_support/core_ext/object/singleton_class' require 'active_support/core_ext/module/delegation' +require 'active_support/core_ext/object/duplicable' +require 'active_support/core_ext/object/blank' require 'arel' require 'active_record/errors' @@ -336,6 +338,9 @@ module ActiveRecord #:nodoc: # Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace # for tables in a shared database. By default, the prefix is the empty string. + # + # If you are organising your models within modules you can add a prefix to the models within a namespace by defining + # a singleton method in the parent module called table_name_prefix which returns your chosen prefix. cattr_accessor :table_name_prefix, :instance_writer => false @@table_name_prefix = "" @@ -763,7 +768,7 @@ module ActiveRecord #:nodoc: contained = contained.singularize if parent.pluralize_table_names contained << '_' end - name = "#{table_name_prefix}#{contained}#{undecorated_table_name(base.name)}#{table_name_suffix}" + name = "#{full_table_name_prefix}#{contained}#{undecorated_table_name(base.name)}#{table_name_suffix}" end @quoted_table_name = nil @@ -771,6 +776,10 @@ module ActiveRecord #:nodoc: name end + def full_table_name_prefix #:nodoc: + (parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix + end + # Defines the column name for use with single table inheritance # -- can be set in subclasses like so: self.inheritance_column = "type_id" def inheritance_column @@ -1288,7 +1297,7 @@ module ActiveRecord #:nodoc: # <tt>options</tt> argument is the same as in find. # # class Person < ActiveRecord::Base - # default_scope :order => 'last_name, first_name' + # default_scope order('last_name, first_name') # end def default_scope(options = {}) self.default_scoping << construct_finder_arel(options) @@ -2214,6 +2223,7 @@ module ActiveRecord #:nodoc: extend QueryCache::ClassMethods extend ActiveSupport::Benchmarkable + include ActiveModel::Conversion include Validations include Locking::Optimistic, Locking::Pessimistic include AttributeMethods @@ -2223,12 +2233,10 @@ module ActiveRecord #:nodoc: include AttributeMethods::Dirty include Callbacks, ActiveModel::Observing, Timestamp include Associations, AssociationPreload, NamedScope - include ActiveModel::Conversion # AutosaveAssociation needs to be included before Transactions, because we want # #save_with_autosave_associations to be wrapped inside a transaction. include AutosaveAssociation, NestedAttributes - include Aggregations, Transactions, Reflection, Serialization NilClass.add_whiner(self) if NilClass.respond_to?(:add_whiner) @@ -2237,4 +2245,4 @@ end # TODO: Remove this and make it work with LAZY flag require 'active_record/connection_adapters/abstract_adapter' -ActiveRecord.run_base_hooks(ActiveRecord::Base) +ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb index 020acbbe5a..1e095110f2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/duplicable' + module ActiveRecord module ConnectionAdapters # :nodoc: module QueryCache diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 64faaef4a0..046825d43f 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/object/blank' require 'date' require 'set' require 'bigdecimal' diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 521bd810d0..55d9d20bb5 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -1,5 +1,6 @@ require 'active_record/connection_adapters/abstract_adapter' require 'active_support/core_ext/kernel/requires' +require 'active_support/core_ext/object/blank' require 'set' module MysqlCompat #:nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 31d5266da8..a6042e1382 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -1,5 +1,6 @@ require 'active_record/connection_adapters/abstract_adapter' require 'active_support/core_ext/kernel/requires' +require 'active_support/core_ext/object/blank' begin require_library_or_gem 'pg' @@ -299,7 +300,7 @@ module ActiveRecord # QUOTING ================================================== # Escapes binary strings for bytea input to the database. - def escape_bytea(value) + def escape_bytea(original_value) if @connection.respond_to?(:escape_bytea) self.class.instance_eval do define_method(:escape_bytea) do |value| @@ -323,13 +324,13 @@ module ActiveRecord end end end - escape_bytea(value) + escape_bytea(original_value) end # Unescapes bytea output from a database to the binary string it represents. # NOTE: This is NOT an inverse of escape_bytea! This is only to be used # on escaped binary output from database drive. - def unescape_bytea(value) + def unescape_bytea(original_value) # In each case, check if the value actually is escaped PostgreSQL bytea output # or an unescaped Active Record attribute that was just written. if PGconn.respond_to?(:unescape_bytea) @@ -369,7 +370,7 @@ module ActiveRecord end end end - unescape_bytea(value) + unescape_bytea(original_value) end # Quotes PostgreSQL-specific data types for SQL input. @@ -394,7 +395,7 @@ module ActiveRecord end # Quotes strings for use in SQL input in the postgres driver for better performance. - def quote_string(s) #:nodoc: + def quote_string(original_value) #:nodoc: if @connection.respond_to?(:escape) self.class.instance_eval do define_method(:quote_string) do |s| @@ -414,7 +415,7 @@ module ActiveRecord remove_method(:quote_string) end end - quote_string(s) + quote_string(original_value) end # Checks the following cases: diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 79f70f07cd..22f0e60083 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -4,6 +4,7 @@ require 'csv' require 'zlib' require 'active_support/dependencies' require 'active_support/core_ext/logger' +require 'active_support/core_ext/object/blank' if RUBY_VERSION < '1.9' module YAML #:nodoc: diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb index 394e1587e1..9abf979cd0 100644 --- a/activerecord/lib/active_record/named_scope.rb +++ b/activerecord/lib/active_record/named_scope.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/array' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/object/singleton_class' +require 'active_support/core_ext/object/blank' module ActiveRecord module NamedScope @@ -101,7 +102,8 @@ module ActiveRecord name = name.to_sym if !scopes[name] && respond_to?(name, true) - raise ArgumentError, "Cannot define scope :#{name} because #{self.name}.#{name} method already exists." + logger.warn "Creating scope :#{name}. " \ + "Overwriting existing method #{self.name}.#{name}." end scopes[name] = lambda do |parent_scope, *args| @@ -165,7 +167,14 @@ module ActiveRecord end def ==(other) - other.respond_to?(:to_ary) ? to_a == other.to_a : false + case other + when Scope + to_sql == other.to_sql + when Relation + other == self + when Array + to_a == other.to_a + end end private diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 76ec7eb681..ee2d420194 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/hash/except' require 'active_support/core_ext/object/try' +require 'active_support/core_ext/object/blank' module ActiveRecord module NestedAttributes #:nodoc: diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb index eb92bc2545..093c6c1e55 100644 --- a/activerecord/lib/active_record/query_cache.rb +++ b/activerecord/lib/active_record/query_cache.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord class QueryCache module ClassMethods diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index de47461c73..04c4a9c153 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -23,18 +23,18 @@ module ActiveRecord log_subscriber :active_record, ActiveRecord::Railties::LogSubscriber.new initializer "active_record.initialize_timezone" do - ActiveRecord.base_hook do + ActiveSupport.on_load(:active_record) do self.time_zone_aware_attributes = true self.default_timezone = :utc end end initializer "active_record.logger" do - ActiveRecord.base_hook { self.logger ||= ::Rails.logger } + ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger } end initializer "active_record.set_configs" do |app| - ActiveRecord.base_hook do + ActiveSupport.on_load(:active_record) do app.config.active_record.each do |k,v| send "#{k}=", v end @@ -44,7 +44,7 @@ module ActiveRecord # This sets the database configuration from Configuration#database_configuration # and then establishes the connection. initializer "active_record.initialize_database" do |app| - ActiveRecord.base_hook do + ActiveSupport.on_load(:active_record) do self.configurations = app.config.database_configuration establish_connection end @@ -53,7 +53,7 @@ module ActiveRecord # Expose database runtime to controller for logging. initializer "active_record.log_runtime" do |app| require "active_record/railties/controller_runtime" - ActionController.base_hook do + ActiveSupport.on_load(:action_controller) do include ActiveRecord::Railties::ControllerRuntime end end @@ -71,9 +71,9 @@ module ActiveRecord end initializer "active_record.load_observers" do - ActiveRecord.base_hook { instantiate_observers } + ActiveSupport.on_load(:active_record) { instantiate_observers } - ActiveRecord.base_hook do + ActiveSupport.on_load(:active_record) do ActionDispatch::Callbacks.to_prepare(:activerecord_instantiate_observers) do ActiveRecord::Base.instantiate_observers end @@ -81,7 +81,7 @@ module ActiveRecord end initializer "active_record.set_dispatch_hooks", :before => :set_clear_dependencies_hook do |app| - ActiveRecord.base_hook do + ActiveSupport.on_load(:active_record) do unless app.config.cache_classes ActionDispatch::Callbacks.after do ActiveRecord::Base.reset_subclasses diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index a20c152eeb..8577ec58f7 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord class Relation JoinOperation = Struct.new(:relation, :join_class, :on) diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb index 4a260d4caa..1c61e7d450 100644 --- a/activerecord/lib/active_record/relation/batches.rb +++ b/activerecord/lib/active_record/relation/batches.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord module Batches # :nodoc: # Yields each record that was found by the find +options+. The find is @@ -48,6 +50,10 @@ module ActiveRecord def find_in_batches(options = {}) relation = self + if orders.present? || taken.present? + ActiveRecord::Base.logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size") + end + if (finder_options = options.except(:start, :batch_size)).present? raise "You can't specify an order, it's forced to be #{batch_order}" if options[:order].present? raise "You can't specify a limit, it's forced to be the batch_size" if options[:limit].present? @@ -75,4 +81,4 @@ module ActiveRecord "#{@klass.table_name}.#{@klass.primary_key} ASC" end end -end
\ No newline at end of file +end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index e77424a64b..a5ea6e7e3a 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord module Calculations # Count operates using three different approaches. diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index c1cce679b6..37aaac0894 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord module FinderMethods # Find operates with four different retrieval approaches: diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 7e83eccbb5..711df16bf1 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -27,12 +27,7 @@ module ActiveRecord values = value.to_a attribute.in(values) when Range - # TODO : Arel should handle ranges with excluded end. - if value.exclude_end? - [attribute.gteq(value.begin), attribute.lt(value.end)] - else - attribute.in(value) - end + attribute.in(value) else attribute.eq(value) end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 0250e739b8..e224781016 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord module QueryMethods extend ActiveSupport::Concern diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 2841ff1239..a17de1bdbb 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord module SpawnMethods def merge(r) diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index a996a0ebac..a833356d15 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveRecord # Allows programmers to programmatically define a schema in a portable # DSL. This means you can define tables, indexes, etc. without using SQL diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index e28808df98..4806fa0ecc 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -67,13 +67,11 @@ module ActiveRecord if value.nil? || (options[:case_sensitive] || !column.text?) sql = "#{sql_attribute} #{operator}" - params = [value] else - sql = "LOWER(#{sql_attribute}) #{operator}" - params = [value.mb_chars.downcase] + sql = "LOWER(#{sql_attribute}) = LOWER(?)" end - [sql, params] + [sql, [value]] end end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 41a23d7f61..62121b93cb 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -32,6 +32,17 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal companies(:first_firm).name, client.firm_with_primary_key.name end + def test_belongs_to_with_primary_key_joins_on_correct_column + sql = Client.joins(:firm_with_primary_key).to_sql + if current_adapter?(:MysqlAdapter) + assert_no_match /`firm_with_primary_keys_companies`\.`id`/, sql + assert_match /`firm_with_primary_keys_companies`\.`name`/, sql + else + assert_no_match /"firm_with_primary_keys_companies"\."id"/, sql + assert_match /"firm_with_primary_keys_companies"\."name"/, sql + end + end + def test_proxy_assignment account = Account.find(1) assert_nothing_raised { account.firm = account.firm } @@ -61,6 +72,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal apple.name, citibank.firm_name end + def test_eager_loading_with_primary_key + apple = Firm.create("name" => "Apple") + citibank = Client.create("name" => "Citibank", :firm_name => "Apple") + citibank_result = Client.find(:first, :conditions => {:name => "Citibank"}, :include => :firm_with_primary_key) + assert_not_nil citibank_result.instance_variable_get("@firm_with_primary_key") + end + def test_no_unexpected_aliasing first_firm = companies(:first_firm) another_firm = companies(:another_firm) @@ -439,9 +457,15 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids end - def test_invalid_belongs_to_dependent_option_raises_exception + def test_invalid_belongs_to_dependent_option_nullify_raises_exception assert_raise ArgumentError do Author.belongs_to :special_author_address, :dependent => :nullify end end + + def test_invalid_belongs_to_dependent_option_restrict_raises_exception + assert_raise ArgumentError do + Author.belongs_to :special_author_address, :dependent => :restrict + end + end end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 42a891bc3b..79e5ecf4ce 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -833,4 +833,10 @@ class EagerAssociationTest < ActiveRecord::TestCase end end + def test_preloading_empty_polymorphic_parent + t = Tagging.create!(:taggable_type => 'Post', :taggable_id => Post.maximum(:id) + 1, :tag => tags(:general)) + + assert_queries(2) { @tagging = Tagging.preload(:taggable).find(t.id) } + assert_no_queries { assert ! @tagging.taggable } + end end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 54624e79ce..c1e539d573 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -836,6 +836,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal num_accounts, Account.count end + def test_restrict + firm = RestrictedFirm.new(:name => 'restrict') + firm.save! + child_firm = firm.companies.create(:name => 'child') + assert !firm.companies.empty? + assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy } + end + def test_included_in_collection assert companies(:first_firm).clients.include?(Client.find(2)) end diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 7372f2da1b..8f5540950e 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -177,7 +177,15 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert_nothing_raised { firm.destroy } end - def test_succesful_build_association + def test_dependence_with_restrict + firm = RestrictedFirm.new(:name => 'restrict') + firm.save! + account = firm.create_account(:credit_limit => 10) + assert !firm.account.nil? + assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy } + end + + def test_successful_build_association firm = Firm.new("name" => "GlobalMegaCorp") firm.save diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb index e417d8a803..83deabb5b7 100644 --- a/activerecord/test/cases/batches_test.rb +++ b/activerecord/test/cases/batches_test.rb @@ -8,7 +8,7 @@ class EachTest < ActiveRecord::TestCase @posts = Post.order("id asc") @total = Post.count end - + def test_each_should_excecute_one_query_per_batch assert_queries(Post.count + 1) do Post.find_each(:batch_size => 1) do |post| @@ -28,7 +28,17 @@ class EachTest < ActiveRecord::TestCase Post.find_each(:limit => 1) { |post| post } end end - + + def test_warn_if_limit_scope_is_set + ActiveRecord::Base.logger.expects(:warn) + Post.limit(1).find_each { |post| post } + end + + def test_warn_if_order_scope_is_set + ActiveRecord::Base.logger.expects(:warn) + Post.order("title").find_each { |post| post } + end + def test_find_in_batches_should_return_batches assert_queries(Post.count + 1) do Post.find_in_batches(:batch_size => 1) do |batch| @@ -58,4 +68,4 @@ class EachTest < ActiveRecord::TestCase Post.find_in_batches(:batch_size => post_count + 1) {|batch| assert_kind_of Array, batch } end end -end
\ No newline at end of file +end diff --git a/activerecord/test/cases/modules_test.rb b/activerecord/test/cases/modules_test.rb index d781a229f4..7209966bf8 100644 --- a/activerecord/test/cases/modules_test.rb +++ b/activerecord/test/cases/modules_test.rb @@ -82,4 +82,32 @@ class ModulesTest < ActiveRecord::TestCase end end end + + def test_module_table_name_prefix + assert_equal 'prefixed_companies', MyApplication::Business::Prefixed::Company.table_name, 'inferred table_name for ActiveRecord model in module with table_name_prefix' + assert_equal 'prefixed_companies', MyApplication::Business::Prefixed::Nested::Company.table_name, 'table_name for ActiveRecord model in nested module with a parent table_name_prefix' + assert_equal 'companies', MyApplication::Business::Prefixed::Firm.table_name, 'explicit table_name for ActiveRecord model in module with table_name_prefix should not be prefixed' + end + + def test_module_table_name_prefix_with_global_prefix + classes = [ MyApplication::Business::Company, + MyApplication::Business::Firm, + MyApplication::Business::Client, + MyApplication::Business::Client::Contact, + MyApplication::Business::Developer, + MyApplication::Business::Project, + MyApplication::Business::Prefixed::Company, + MyApplication::Business::Prefixed::Nested::Company, + MyApplication::Billing::Account ] + + ActiveRecord::Base.table_name_prefix = 'global_' + classes.each(&:reset_table_name) + assert_equal 'global_companies', MyApplication::Business::Company.table_name, 'inferred table_name for ActiveRecord model in module without table_name_prefix' + assert_equal 'prefixed_companies', MyApplication::Business::Prefixed::Company.table_name, 'inferred table_name for ActiveRecord model in module with table_name_prefix' + assert_equal 'prefixed_companies', MyApplication::Business::Prefixed::Nested::Company.table_name, 'table_name for ActiveRecord model in nested module with a parent table_name_prefix' + assert_equal 'companies', MyApplication::Business::Prefixed::Firm.table_name, 'explicit table_name for ActiveRecord model in module with table_name_prefix should not be prefixed' + ensure + ActiveRecord::Base.table_name_prefix = '' + classes.each(&:reset_table_name) + end end diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 6c2b4fa3a7..2396ca10b0 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -371,8 +371,21 @@ class NamedScopeTest < ActiveRecord::TestCase end def test_named_scopes_with_reserved_names - [:where, :with_scope].each do |protected_method| - assert_raises(ArgumentError) { Topic.scope protected_method } + class << Topic + def public_method; end + public :public_method + + def protected_method; end + protected :protected_method + + def private_method; end + private :private_method + end + + [:public_method, :protected_method, :private_method].each do |reserved_method| + assert Topic.respond_to?(reserved_method, true) + ActiveRecord::Base.logger.expects(:warn) + Topic.scope(reserved_method) end end @@ -394,6 +407,12 @@ class NamedScopeTest < ActiveRecord::TestCase assert_equal topics(:second), approved[0] assert approved.loaded? end + + def test_nested_named_scopes_queries_size + assert_queries(1) do + Topic.approved.by_lifo.replied.written_before(Time.now).all + end + end end class DynamicScopeMatchTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/pk_test.rb b/activerecord/test/cases/pk_test.rb index 5bba1d5625..33ad5992de 100644 --- a/activerecord/test/cases/pk_test.rb +++ b/activerecord/test/cases/pk_test.rb @@ -23,6 +23,12 @@ class PrimaryKeysTest < ActiveRecord::TestCase assert_equal keyboard.to_key, [keyboard.id] end + def test_to_key_with_primary_key_after_destroy + topic = Topic.find(1) + topic.destroy + assert_equal topic.to_key, [1] + end + def test_integer_key topic = Topic.find(1) assert_equal(topics(:first).author_name, topic.author_name) diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index f31d5f87e5..be6dd71e3b 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -95,6 +95,11 @@ class DependentFirm < Company has_many :companies, :foreign_key => 'client_of', :dependent => :nullify end +class RestrictedFirm < Company + has_one :account, :foreign_key => "firm_id", :dependent => :restrict, :order => "id" + has_many :companies, :foreign_key => 'client_of', :order => "id", :dependent => :restrict +end + class Client < Company belongs_to :firm, :foreign_key => "client_of" belongs_to :firm_with_basic_id, :class_name => "Firm", :foreign_key => "firm_id" diff --git a/activerecord/test/models/company_in_module.rb b/activerecord/test/models/company_in_module.rb index cdda7a44d4..83d71b6909 100644 --- a/activerecord/test/models/company_in_module.rb +++ b/activerecord/test/models/company_in_module.rb @@ -32,6 +32,23 @@ module MyApplication has_and_belongs_to_many :developers end + module Prefixed + def self.table_name_prefix + 'prefixed_' + end + + class Company < ActiveRecord::Base + end + + class Firm < Company + self.table_name = 'companies' + end + + module Nested + class Company < ActiveRecord::Base + end + end + end end module Billing diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index 67296a171a..5cfe4f7c7d 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -9,6 +9,7 @@ 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 'active_support/core_ext/object/duplicable' require 'set' require 'uri' diff --git a/activeresource/lib/active_resource/custom_methods.rb b/activeresource/lib/active_resource/custom_methods.rb index ff14b49b07..dd3e35dfc7 100644 --- a/activeresource/lib/active_resource/custom_methods.rb +++ b/activeresource/lib/active_resource/custom_methods.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/blank' + module ActiveResource # A module to support custom REST methods and sub-resources, allowing you to break out # of the "default" REST methods with your own custom resource requests. For example, diff --git a/activeresource/lib/active_resource/validations.rb b/activeresource/lib/active_resource/validations.rb index 4774c6dd22..a19e0d0ac9 100644 --- a/activeresource/lib/active_resource/validations.rb +++ b/activeresource/lib/active_resource/validations.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/array/wrap' +require 'active_support/core_ext/object/blank' module ActiveResource class ResourceInvalid < ClientError #:nodoc: diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 56c81cf63b..3822abcab6 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0 (pending)* +* New assertions assert_blank and assert_present. #4299 [Juanjo Bazan] + * Use Object#singleton_class instead of #metaclass. Prefer Ruby's choice. [Jeremy Kemper] * JSON backend for YAJL. Preferred if available. #2666 [Brian Lopez] diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb index d584c9e254..d84a62ca2d 100644 --- a/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -91,7 +91,7 @@ module ActiveSupport def delete(key, options = nil) # :nodoc: super do - response = @data.delete(key, expires_in(options)) + response = @data.delete(key) response == Response::DELETED end rescue MemCache::MemCacheError => e diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb index e4d429fc2b..045a6944fa 100644 --- a/activesupport/lib/active_support/core_ext/hash/keys.rb +++ b/activesupport/lib/active_support/core_ext/hash/keys.rb @@ -22,7 +22,7 @@ class Hash # to +to_sym+. def symbolize_keys! keys.each do |key| - self[(key.to_sym rescue key)] = delete(key) if key.respond_to?(:to_sym) && !key.is_a?(Fixnum) + self[(key.to_sym rescue key) || key] = delete(key) end self end diff --git a/activesupport/lib/active_support/core_ext/time/marshal.rb b/activesupport/lib/active_support/core_ext/time/marshal.rb new file mode 100644 index 0000000000..1a4d918ce7 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/time/marshal.rb @@ -0,0 +1,56 @@ +# Pre-1.9 versions of Ruby have a bug with marshaling Time instances, where utc instances are +# unmarshalled in the local zone, instead of utc. We're layering behavior on the _dump and _load +# methods so that utc instances can be flagged on dump, and coerced back to utc on load. +if !Marshal.load(Marshal.dump(Time.now.utc)).utc? + class Time + class << self + alias_method :_load_without_utc_flag, :_load + def _load(marshaled_time) + time = _load_without_utc_flag(marshaled_time) + time.instance_eval do + if defined?(@marshal_with_utc_coercion) + val = remove_instance_variable("@marshal_with_utc_coercion") + end + val ? utc : self + end + end + end + + alias_method :_dump_without_utc_flag, :_dump + def _dump(*args) + obj = dup + obj.instance_variable_set('@marshal_with_utc_coercion', utc?) + obj._dump_without_utc_flag(*args) + end + end +end + +# Ruby 1.9.2 adds utc_offset and zone to Time, but marshaling only +# preserves utc_offset. Preserve zone also, even though it may not +# work in some edge cases. +if Time.local(2010).zone != Marshal.load(Marshal.dump(Time.local(2010))).zone + class Time + class << self + alias_method :_load_without_zone, :_load + def _load(marshaled_time) + time = _load_without_zone(marshaled_time) + time.instance_eval do + if zone = defined?(@_zone) && remove_instance_variable('@_zone') + ary = to_a + ary[-1] = zone + utc? ? Time.utc(*ary) : Time.local(*ary) + else + self + end + end + end + end + + alias_method :_dump_without_zone, :_dump + def _dump(*args) + obj = dup + obj.instance_variable_set('@_zone', zone) + obj._dump_without_zone(*args) + end + end +end diff --git a/activesupport/lib/active_support/core_ext/time/marshal_with_utc_flag.rb b/activesupport/lib/active_support/core_ext/time/marshal_with_utc_flag.rb deleted file mode 100644 index 8d46d80251..0000000000 --- a/activesupport/lib/active_support/core_ext/time/marshal_with_utc_flag.rb +++ /dev/null @@ -1,26 +0,0 @@ -# Pre-1.9 versions of Ruby have a bug with marshaling Time instances, where utc instances are -# unmarshalled in the local zone, instead of utc. We're layering behavior on the _dump and _load -# methods so that utc instances can be flagged on dump, and coerced back to utc on load. -if RUBY_VERSION < '1.9' - class Time - class << self - alias_method :_original_load, :_load - def _load(marshaled_time) - time = _original_load(marshaled_time) - time.instance_eval do - if defined?(@marshal_with_utc_coercion) - val = remove_instance_variable("@marshal_with_utc_coercion") - end - val ? utc : self - end - end - end - - alias_method :_original_dump, :_dump - def _dump(*args) - obj = dup - obj.instance_variable_set('@marshal_with_utc_coercion', utc?) - obj._original_dump(*args) - end - end -end diff --git a/activesupport/lib/active_support/dependencies/autoload.rb b/activesupport/lib/active_support/dependencies/autoload.rb index f669f4a77e..4c771da096 100644 --- a/activesupport/lib/active_support/dependencies/autoload.rb +++ b/activesupport/lib/active_support/dependencies/autoload.rb @@ -3,10 +3,6 @@ require "active_support/lazy_load_hooks" module ActiveSupport module Autoload - def self.extended(base) - base.extend(LazyLoadHooks) - end - @@autoloads = {} @@under_path = nil @@at_path = nil diff --git a/activesupport/lib/active_support/i18n.rb b/activesupport/lib/active_support/i18n.rb index 034d7d8ddc..11af48d67e 100644 --- a/activesupport/lib/active_support/i18n.rb +++ b/activesupport/lib/active_support/i18n.rb @@ -1,3 +1,3 @@ require 'i18n' I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml" -ActiveSupport.run_base_hooks(:i18n)
\ No newline at end of file +ActiveSupport.run_load_hooks(:i18n)
\ No newline at end of file diff --git a/activesupport/lib/active_support/lazy_load_hooks.rb b/activesupport/lib/active_support/lazy_load_hooks.rb index 36acfda524..642a4c105c 100644 --- a/activesupport/lib/active_support/lazy_load_hooks.rb +++ b/activesupport/lib/active_support/lazy_load_hooks.rb @@ -1,25 +1,17 @@ module ActiveSupport - module LazyLoadHooks - def _setup_base_hooks - @base_hooks ||= Hash.new {|h,k| h[k] = [] } - @base ||= {} - end - - def base_hook(name = nil, &block) - _setup_base_hooks + @load_hooks = Hash.new {|h,k| h[k] = [] } + @loaded = {} - if base = @base[name] - base.instance_eval(&block) - else - @base_hooks[name] << block - end + def self.on_load(name, &block) + if base = @loaded[name] + base.instance_eval(&block) + else + @load_hooks[name] << block end + end - def run_base_hooks(base, name = nil) - _setup_base_hooks - - @base_hooks[name].each { |hook| base.instance_eval(&hook) } if @base_hooks - @base[name] = base - end + def self.run_load_hooks(name, base = Object) + @load_hooks[name].each { |hook| base.instance_eval(&hook) } + @loaded[name] = base end end
\ No newline at end of file diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb index e45d16ee96..b8d54ff839 100644 --- a/activesupport/lib/active_support/railtie.rb +++ b/activesupport/lib/active_support/railtie.rb @@ -35,7 +35,7 @@ module I18n config.i18n.load_path = [] initializer "i18n.initialize" do - ActiveSupport.base_hook(:i18n) do + ActiveSupport.on_load(:i18n) do I18n.reload! ActionDispatch::Callbacks.to_prepare do diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb index c529b92240..33793f0688 100644 --- a/activesupport/lib/active_support/testing/assertions.rb +++ b/activesupport/lib/active_support/testing/assertions.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/array/wrap' +require 'active_support/core_ext/object/blank' module ActiveSupport module Testing @@ -62,6 +63,20 @@ module ActiveSupport def assert_no_difference(expression, message = nil, &block) assert_difference expression, 0, message, &block end + + # Test if an expression is blank. Passes if object.blank? is true. + # + # assert_blank [] # => true + def assert_blank(object) + assert object.blank?, "#{object.inspect} is not blank" + end + + # Test if an expression is not blank. Passes if object.present? is true. + # + # assert_present {:data => 'x' } # => true + def assert_present(object) + assert object.present?, "#{object.inspect} is blank" + end end end end diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb index 0f421421d0..784c7173a9 100644 --- a/activesupport/lib/active_support/time.rb +++ b/activesupport/lib/active_support/time.rb @@ -14,7 +14,7 @@ require 'date' require 'time' require 'active_support/core_ext/time/publicize_conversion_methods' -require 'active_support/core_ext/time/marshal_with_utc_flag' +require 'active_support/core_ext/time/marshal' require 'active_support/core_ext/time/acts_like' require 'active_support/core_ext/time/calculations' 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 3cb4d89e02..945cdd5278 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -198,10 +198,12 @@ module ActiveSupport @name = name @utc_offset = utc_offset @tzinfo = tzinfo + @current_period = nil end def utc_offset - @utc_offset ||= tzinfo.current_period.utc_offset + @current_period ||= tzinfo.current_period + @current_period.utc_offset end # Returns the offset of this time zone as a formatted string, of the @@ -362,13 +364,14 @@ module ActiveSupport "Wellington" ], [ 46_800, "Nuku'alofa" ]]. each do |offset, *places| - places.sort.each do |place| + places.each do |place| place.freeze zone = new(place, offset) ZONES << zone ZONES_MAP[place] = zone end end + ZONES.sort! ZONES.freeze ZONES_MAP.freeze diff --git a/activesupport/lib/active_support/xml_mini/libxmlsax.rb b/activesupport/lib/active_support/xml_mini/libxmlsax.rb index d7b2f4c5be..fe2c1b9349 100644 --- a/activesupport/lib/active_support/xml_mini/libxmlsax.rb +++ b/activesupport/lib/active_support/xml_mini/libxmlsax.rb @@ -1,4 +1,5 @@ require 'libxml' +require 'active_support/core_ext/object/blank' # = XmlMini LibXML implementation using a SAX-based parser module ActiveSupport diff --git a/activesupport/lib/active_support/xml_mini/nokogirisax.rb b/activesupport/lib/active_support/xml_mini/nokogirisax.rb index d538a9110f..8af7b5e565 100644 --- a/activesupport/lib/active_support/xml_mini/nokogirisax.rb +++ b/activesupport/lib/active_support/xml_mini/nokogirisax.rb @@ -1,4 +1,5 @@ require 'nokogiri' +require 'active_support/core_ext/object/blank' # = XmlMini Nokogiri implementation using a SAX-based parser module ActiveSupport diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb index 3db48ce5a3..863d66a91d 100644 --- a/activesupport/lib/active_support/xml_mini/rexml.rb +++ b/activesupport/lib/active_support/xml_mini/rexml.rb @@ -27,7 +27,13 @@ module ActiveSupport data.ungetc(char) silence_warnings { require 'rexml/document' } unless defined?(REXML::Document) doc = REXML::Document.new(data) - merge_element!({}, doc.root) + + if doc.root + merge_element!({}, doc.root) + else + raise REXML::ParseException, + "The document #{doc.to_s.inspect} does not have a valid root" + end end end diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index 67f652325e..ea6ebca3ce 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -10,6 +10,7 @@ $:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) require 'test/unit' require 'active_support/core_ext/kernel/reporting' +require 'empty_bool' silence_warnings { require 'mocha' } diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 00e05f76fe..d96f8e1de5 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -333,6 +333,12 @@ uses_memcached 'memcached backed store' do assert_equal 'bat', @cache.read('baz') assert_equal nil, @cache.read('foo') end + + def test_delete_should_only_pass_key_to_data + key = 'foo' + @data.expects(:delete).with(key) + @cache.delete(key) + end end class CompressedMemCacheStore < ActiveSupport::TestCase diff --git a/activesupport/test/core_ext/blank_test.rb b/activesupport/test/core_ext/blank_test.rb index ed6c625a0a..97c6b213ba 100644 --- a/activesupport/test/core_ext/blank_test.rb +++ b/activesupport/test/core_ext/blank_test.rb @@ -1,14 +1,6 @@ require 'abstract_unit' require 'active_support/core_ext/object/blank' -class EmptyTrue - def empty?() true; end -end - -class EmptyFalse - def empty?() false; end -end - class BlankTest < Test::Unit::TestCase BLANK = [ EmptyTrue.new, nil, false, '', ' ', " \n\t \r ", [], {} ] NOT = [ EmptyFalse.new, Object.new, true, 0, 1, 'a', [nil], { nil => 0 } ] diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 159b7d8366..c24c8619c6 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -758,33 +758,29 @@ end class TimeExtMarshalingTest < Test::Unit::TestCase def test_marshaling_with_utc_instance t = Time.utc(2000) - marshaled = Marshal.dump t - unmarshaled = Marshal.load marshaled - assert_equal t, unmarshaled + unmarshaled = Marshal.load(Marshal.dump(t)) assert_equal "UTC", unmarshaled.zone + assert_equal t, unmarshaled end def test_marshaling_with_local_instance t = Time.local(2000) - marshaled = Marshal.dump t - unmarshaled = Marshal.load marshaled - assert_equal t, unmarshaled + unmarshaled = Marshal.load(Marshal.dump(t)) assert_equal t.zone, unmarshaled.zone + assert_equal t, unmarshaled end def test_marshaling_with_frozen_utc_instance t = Time.utc(2000).freeze - marshaled = Marshal.dump t - unmarshaled = Marshal.load marshaled - assert_equal t, unmarshaled + unmarshaled = Marshal.load(Marshal.dump(t)) assert_equal "UTC", unmarshaled.zone + assert_equal t, unmarshaled end def test_marshaling_with_frozen_local_instance t = Time.local(2000).freeze - marshaled = Marshal.dump t - unmarshaled = Marshal.load marshaled - assert_equal t, unmarshaled + unmarshaled = Marshal.load(Marshal.dump(t)) assert_equal t.zone, unmarshaled.zone + assert_equal t, unmarshaled end end diff --git a/activesupport/test/empty_bool.rb b/activesupport/test/empty_bool.rb new file mode 100644 index 0000000000..005b3523ef --- /dev/null +++ b/activesupport/test/empty_bool.rb @@ -0,0 +1,7 @@ +class EmptyTrue + def empty?() true; end +end + +class EmptyFalse + def empty?() false; end +end diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb index 5c2b44f188..2fba62bdd6 100644 --- a/activesupport/test/message_encryptor_test.rb +++ b/activesupport/test/message_encryptor_test.rb @@ -4,7 +4,7 @@ require 'active_support/time' class MessageEncryptorTest < Test::Unit::TestCase def setup @encryptor = ActiveSupport::MessageEncryptor.new(ActiveSupport::SecureRandom.hex(64)) - @data = {:some=>"data", :now=>Time.now} + @data = { :some => "data", :now => Time.local(2010) } end def test_simple_round_tripping diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index 714a3b3a39..4821311244 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -12,7 +12,7 @@ require 'active_support/time' class MessageVerifierTest < Test::Unit::TestCase def setup @verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!") - @data = {:some=>"data", :now=>Time.now} + @data = { :some => "data", :now => Time.local(2010) } end def test_simple_round_tripping diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb index 1928da51ca..3092fe01ae 100644 --- a/activesupport/test/test_test.rb +++ b/activesupport/test/test_test.rb @@ -86,6 +86,46 @@ class AssertDifferenceTest < ActiveSupport::TestCase end end +class AssertBlankTest < ActiveSupport::TestCase + BLANK = [ EmptyTrue.new, nil, false, '', ' ', " \n\t \r ", [], {} ] + NOT_BLANK = [ EmptyFalse.new, Object.new, true, 0, 1, 'x', [nil], { nil => 0 } ] + + def test_assert_blank_true + BLANK.each { |v| assert_blank v } + end + + def test_assert_blank_false + NOT_BLANK.each { |v| + begin + assert_blank v + fail 'should not get to here' + rescue Exception => e + assert_match(/is not blank/, e.message) + end + } + end +end + +class AssertPresentTest < ActiveSupport::TestCase + BLANK = [ EmptyTrue.new, nil, false, '', ' ', " \n\t \r ", [], {} ] + NOT_BLANK = [ EmptyFalse.new, Object.new, true, 0, 1, 'x', [nil], { nil => 0 } ] + + def test_assert_blank_true + NOT_BLANK.each { |v| assert_present v } + end + + def test_assert_blank_false + BLANK.each { |v| + begin + assert_present v + fail 'should not get to here' + rescue Exception => e + assert_match(/is blank/, e.message) + end + } + end +end + # These should always pass if ActiveSupport::Testing.const_defined?(:Default) class NotTestingThingsTest < Test::Unit::TestCase diff --git a/ci/ci_build.rb b/ci/ci_build.rb index 1602c5106d..cd62381d9c 100755 --- a/ci/ci_build.rb +++ b/ci/ci_build.rb @@ -19,7 +19,7 @@ puts "[CruiseControl] Rails build" build_results = {} # Install required version of bundler. -bundler_install_cmd = "sudo gem install bundler -v 0.9.10 --no-ri --no-rdoc" +bundler_install_cmd = "sudo gem install bundler --no-ri --no-rdoc" puts "Running command: #{bundler_install_cmd}" build_results[:install_bundler] = system bundler_install_cmd diff --git a/railties/Rakefile b/railties/Rakefile index 6368456366..d88036f829 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -1,5 +1,3 @@ -require File.expand_path('../../load_paths', __FILE__) - require 'rake' require 'rake/testtask' require 'rake/rdoctask' @@ -60,10 +58,8 @@ Rake::RDocTask.new { |rdoc| rdoc.options << '--charset' << 'utf-8' rdoc.template = ENV['template'] ? "#{ENV['template']}.rb" : '../doc/template/horo' rdoc.rdoc_files.include('README', 'CHANGELOG') - rdoc.rdoc_files.include('lib/*.rb') - rdoc.rdoc_files.include('lib/rails/*.rb') - rdoc.rdoc_files.include('lib/rails/generators/*.rb') - rdoc.rdoc_files.include('lib/rails/commands/**/*.rb') + rdoc.rdoc_files.include('lib/**/*.rb') + rdoc.rdoc_files.exclude('lib/rails/generators/**/templates/*') } # Generate GEM ---------------------------------------------------------------------------- diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index 5418ad7dd4..55077bcd24 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -9,24 +9,24 @@ endprologue. h3. Locations for Initialization Code -Rails offers (at least) five good spots to place initialization code: +Rails offers (at least) four good spots to place initialization code: -* Preinitializers -* environment.rb +* application.rb * Environment-specific Configuration Files * Initializers (load_application_initializers) * After-Initializers -h3. Using a Preinitializer +h3. Running Code Before Rails -Rails allows you to use a preinitializer to run code before the framework itself is loaded. If you save code in +RAILS_ROOT/config/preinitializer.rb+, that code will be the first thing loaded, before any of the framework components (Active Record, Action Pack, and so on.) If you want to change the behavior of one of the classes that is used in the initialization process, you can do so in this file. +To run some code before Rails itself is loaded, simply put it above the call to ++require 'rails/all'+ in your +application.rb+. h3. Configuring Rails Components -In general, the work of configuring Rails means configuring the components of Rails, as well as configuring Rails itself. The +environment.rb+ and environment-specific configuration files (such as +config/environments/production.rb+) allow you to specify the various settings that you want to pass down to all of the components. For example, the default Rails 2.3 +environment.rb+ file includes one setting: +In general, the work of configuring Rails means configuring the components of Rails, as well as configuring Rails itself. The +application.rb+ and environment-specific configuration files (such as +config/environments/production.rb+) allow you to specify the various settings that you want to pass down to all of the components. For example, the default Rails 2.3 +application.rb+ file includes one setting: <ruby> -config.time_zone = 'UTC' +config.filter_parameters << :password </ruby> This is a setting for Rails itself. If you want to pass settings to individual Rails components, you can do so via the same +config+ object: @@ -53,8 +53,6 @@ h4. Rails General Configuration * +config.eager_load_paths+ accepts an array of paths from which Rails will eager load on boot if cache classes is enabled. All elements of this array must also be in +load_paths+. -* +config.frameworks+ accepts an array of rails framework components that should be loaded. (Defaults to +:active_record+, +:action_controller+, +:action_view+, +:action_mailer+, and +:active_resource+). - * +config.load_once_paths+ accepts an array of paths from which Rails will automatically load from only once. All elements of this array must also be in +load_paths+. * +config.load_paths+ accepts an array of additional paths to prepend to the load path. By default, all app, lib, vendor and mock paths are included in this list. @@ -133,6 +131,8 @@ h4. Configuring Action Controller * +config.action_controller.asset_host+ provides a string that is prepended to all of the URL-generating helpers in +AssetHelper+. This is designed to allow moving all javascript, CSS, and image files to a separate asset host. +* +config.action_controller.asset_path+ allows you to override the default asset path generation by providing your own instructions. + * +config.action_controller.consider_all_requests_local+ is generally set to +true+ during development and +false+ during production; if it is set to +true+, then any error will cause detailed debugging information to be dumped in the HTTP response. For finer-grained control, set this to +false+ and implement +local_request?+ to specify which requests should provide debugging information on errors. * +config.action_controller.allow_concurrency+ should be set to +true+ to allow concurrent (threadsafe) action processing. Set to +false+ by default. You probably don't want to call this one directly, though, because a series of other adjustments need to be made for threadsafe mode to work properly. Instead, you should simply call +config.threadsafe!+ inside your +production.rb+ file, which makes all the necessary adjustments. diff --git a/railties/lib/rails/application/routes_reloader.rb b/railties/lib/rails/application/routes_reloader.rb index a5154f4bba..a2b3622df8 100644 --- a/railties/lib/rails/application/routes_reloader.rb +++ b/railties/lib/rails/application/routes_reloader.rb @@ -27,7 +27,7 @@ module Rails routes.clear! paths.each { |path| load(path) } - ActionController.base_hook { routes.finalize! } + ActiveSupport.on_load(:action_controller) { routes.finalize! } nil ensure diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index c57660c0d1..3f74cd49fc 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -54,6 +54,11 @@ module Rails trap(:INT) { exit } puts "=> Ctrl-C to shutdown server" unless options[:daemonize] + #Create required tmp directories if not found + %w(cache pids sessions sockets).each do |dir_to_make| + FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make)) + end + super ensure # The '-h' option calls exit before @options is set. diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 85cae75bce..e9013348b5 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -180,8 +180,13 @@ module Rails initializer :add_view_paths do views = paths.app.views.to_a - ActionController.base_hook { prepend_view_path(views) } if defined?(ActionController) - ActionMailer.base_hook { prepend_view_path(views) } if defined?(ActionMailer) + ActiveSupport.on_load(:action_controller) do + prepend_view_path(views) + end + + ActiveSupport.on_load(:action_mailer) do + prepend_view_path(views) + end end initializer :add_metals do |app| 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 a3dc38d9e4..867fc8c985 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 @@ -2,7 +2,7 @@ require 'test_helper' require 'rails/performance_test_help' # Profiling results for each test method are written to tmp/performance. -class BrowsingTest < ActionController::PerformanceTest +class BrowsingTest < ActionDispatch::PerformanceTest def test_homepage get '/' end diff --git a/railties/lib/rails/generators/rails/model_subclass/model_subclass_generator.rb b/railties/lib/rails/generators/rails/model_subclass/model_subclass_generator.rb deleted file mode 100644 index 99fd2f45bc..0000000000 --- a/railties/lib/rails/generators/rails/model_subclass/model_subclass_generator.rb +++ /dev/null @@ -1,12 +0,0 @@ -module Rails - module Generators - # TODO Deprecate me in a release > Rails 3.0 - class ModelSubclassGenerator < Base - desc "model_subclass is deprecated. Invoke model with --parent option instead." - - def say_deprecation_warn - say self.class.desc - end - end - end -end diff --git a/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt b/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt index e94c0bfc77..733e321c94 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt @@ -1,10 +1,23 @@ +require 'rake' require 'rake/testtask' +require 'rake/rdoctask' desc 'Default: run unit tests.' task :default => :test desc 'Test the <%= file_name %> plugin.' Rake::TestTask.new(:test) do |t| + t.libs << 'lib' t.libs << 'test' t.pattern = 'test/**/*_test.rb' + t.verbose = true end + +desc 'Generate documentation for the <%= file_name %> plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = '<%= class_name %>' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end
\ No newline at end of file diff --git a/railties/lib/rails/generators/rails/resource/resource_generator.rb b/railties/lib/rails/generators/rails/resource/resource_generator.rb index 1e78945a7e..8a46708009 100644 --- a/railties/lib/rails/generators/rails/resource/resource_generator.rb +++ b/railties/lib/rails/generators/rails/resource/resource_generator.rb @@ -1,5 +1,6 @@ require 'rails/generators/resource_helpers' require 'rails/generators/rails/model/model_generator' +require 'active_support/core_ext/object/blank' module Rails module Generators diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake index f2fee45594..957c375f6a 100644 --- a/railties/lib/rails/tasks/documentation.rake +++ b/railties/lib/rails/tasks/documentation.rake @@ -1,4 +1,9 @@ namespace :doc do + def gem_path(gem_name) + path = $LOAD_PATH.grep(/#{gem_name}[\w.-]*\/lib$/).first + yield File.dirname(path) if path + end + desc "Generate documentation for the application. Set custom template with TEMPLATE=/path/to/rdoc/template.rb or title with TITLE=\"Custom Title\"" Rake::RDocTask.new("app") { |rdoc| rdoc.rdoc_dir = 'doc/app' @@ -11,54 +16,56 @@ namespace :doc do rdoc.rdoc_files.include('lib/**/*.rb') } - desc 'Generate documentation for the Rails framework. Specify path with RAILS_PATH="/path/to/rails"' - path = ENV['RAILS_PATH'] - unless path && File.directory?(path) - task :rails do - if path - $stderr.puts "Skipping doc:rails, missing Rails directory at #{path}" - else - $stderr.puts "Skipping doc:rails, RAILS_PATH environment variable is not set" + desc 'Generate documentation for the Rails framework.' + Rake::RDocTask.new("rails") { |rdoc| + rdoc.rdoc_dir = 'doc/api' + rdoc.template = "#{ENV['template']}.rb" if ENV['template'] + rdoc.title = "Rails Framework Documentation" + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + + gem_path('actionmailer') do |actionmailer| + %w(README CHANGELOG MIT-LICENSE lib/action_mailer/base.rb).each do |file| + rdoc.rdoc_files.include("#{actionmailer}/#{file}") end end - else - Rake::RDocTask.new("rails") { |rdoc| - version = "-#{Rails::VERSION::STRING}" unless ENV['RAILS_PATH'] - rdoc.rdoc_dir = 'doc/api' - rdoc.template = "#{ENV['template']}.rb" if ENV['template'] - rdoc.title = "Rails Framework Documentation" - rdoc.options << '--line-numbers' << '--inline-source' - rdoc.rdoc_files.include('README') - - %w(README CHANGELOG lib/action_mailer/base.rb).each do |file| - rdoc.rdoc_files.include("#{path}/actionmailer#{version}/#{file}") - end - %w(README CHANGELOG lib/action_controller/**/*.rb lib/action_view/**/*.rb).each do |file| - rdoc.rdoc_files.include("#{path}/actionpack#{version}/#{file}") + gem_path('actionpack') do |actionpack| + %w(README CHANGELOG MIT-LICENSE lib/action_controller/**/*.rb lib/action_view/**/*.rb).each do |file| + rdoc.rdoc_files.include("#{actionpack}/#{file}") end + end - %w(README CHANGELOG lib/active_model/**/*.rb).each do |file| - rdoc.rdoc_files.include("#{path}/activemodel#{version}/#{file}") + gem_path('activemodel') do |activemodel| + %w(README CHANGELOG MIT-LICENSE lib/active_model/**/*.rb).each do |file| + rdoc.rdoc_files.include("#{activemodel}/#{file}") end + end + gem_path('activerecord') do |activerecord| %w(README CHANGELOG lib/active_record/**/*.rb).each do |file| - rdoc.rdoc_files.include("#{path}/activerecord#{version}/#{file}") + rdoc.rdoc_files.include("#{activerecord}/#{file}") end + end + gem_path('activeresource') do |activeresource| %w(README CHANGELOG lib/active_resource.rb lib/active_resource/*).each do |file| - rdoc.rdoc_files.include("#{path}/activeresource#{version}/#{file}") + rdoc.rdoc_files.include("#{activeresource}/#{file}") end + end + gem_path('activesupport') do |activesupport| %w(README CHANGELOG lib/active_support/**/*.rb).each do |file| - rdoc.rdoc_files.include("#{path}/activesupport#{version}/#{file}") + rdoc.rdoc_files.include("#{activesupport}/#{file}") end + end - %w(README CHANGELOG MIT-LICENSE lib/{*.rb,commands/*.rb,generators/*.rb}).each do |file| - rdoc.rdoc_files.include("#{path}/railties#{version}/#{file}") + gem_path('railties') do |railties| + %w(README CHANGELOG lib/{*.rb,commands/*.rb,generators/*.rb}).each do |file| + rdoc.rdoc_files.include("#{railties}/#{file}") end - } - end + end + } plugins = FileList['vendor/plugins/**'].collect { |plugin| File.basename(plugin) } diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 6522c94ad6..3ce4e2c780 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -30,7 +30,7 @@ end class ActionController::TestCase setup do - @router = Rails.application.routes + @routes = Rails.application.routes end end diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb index 05ec359f61..aa76979c27 100644 --- a/railties/test/rails_info_controller_test.rb +++ b/railties/test/rails_info_controller_test.rb @@ -15,9 +15,9 @@ class InfoControllerTest < ActionController::TestCase match '/rails/info/properties' => "rails/info#properties" end @controller.stubs(:consider_all_requests_local? => false, :local_request? => true) - @router = Rails.application.routes + @routes = Rails.application.routes - Rails::InfoController.send(:include, @router.url_helpers) + Rails::InfoController.send(:include, @routes.url_helpers) end test "info controller does not allow remote requests" do diff --git a/tools/console b/tools/console new file mode 100755 index 0000000000..ea995a1a54 --- /dev/null +++ b/tools/console @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby +require File.expand_path('../../load_paths', __FILE__) +require 'rails/all' +require 'active_support/all' +require 'irb' +require 'irb/completion' +IRB.start |