diff options
71 files changed, 333 insertions, 761 deletions
diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile index 45c238d302..d1134ba2b5 100644 --- a/actionmailer/Rakefile +++ b/actionmailer/Rakefile @@ -1,5 +1,4 @@ require 'rake/testtask' -require 'rake/packagetask' require 'rubygems/package_task' desc "Default Task" diff --git a/actionpack/Rakefile b/actionpack/Rakefile index ba7956c3ab..56fc92963a 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -1,5 +1,4 @@ require 'rake/testtask' -require 'rake/packagetask' require 'rubygems/package_task' desc "Default Task" @@ -22,11 +21,15 @@ Rake::TestTask.new(:test_action_pack) do |t| end namespace :test do - Rake::TestTask.new(:isolated) do |t| - t.libs << 'test' - t.pattern = 'test/ts_isolated.rb' + task :isolated do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + Dir.glob("test/{abstract,controller,dispatch,template}/**/*_test.rb").all? do |file| + sh(ruby, '-Ilib:test', file) + end or raise "Failures" end +end +namespace :test do Rake::TestTask.new(:template) do |t| t.libs << 'test' t.pattern = 'test/template/**/*.rb' diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 9cacb3862b..9fdad63b45 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -46,10 +46,6 @@ module ActionController autoload :TestCase, 'action_controller/test_case' autoload :TemplateAssertions, 'action_controller/test_case' - eager_autoload do - autoload :RecordIdentifier - end - def self.eager_load! super ActionController::Caching.eager_load! diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 971c4189c8..d7b09b67c0 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -223,7 +223,6 @@ module ActionController ForceSSL, Streaming, DataStreaming, - RecordIdentifier, HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods, HttpAuthentication::Token::ControllerMethods, diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb deleted file mode 100644 index d598bac467..0000000000 --- a/actionpack/lib/action_controller/record_identifier.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'action_view/record_identifier' - -module ActionController - module RecordIdentifier - MODULE_MESSAGE = 'Calling ActionController::RecordIdentifier.%s is deprecated and ' \ - 'will be removed in Rails 4.1, please call using ActionView::RecordIdentifier instead.' - INSTANCE_MESSAGE = '%s method will no longer be included by default in controllers ' \ - 'since Rails 4.1. If you would like to use it in controllers, please include ' \ - 'ActionView::RecordIdentifier module.' - - def dom_id(record, prefix = nil) - ActiveSupport::Deprecation.warn(INSTANCE_MESSAGE % 'dom_id') - ActionView::RecordIdentifier.dom_id(record, prefix) - end - - def dom_class(record, prefix = nil) - ActiveSupport::Deprecation.warn(INSTANCE_MESSAGE % 'dom_class') - ActionView::RecordIdentifier.dom_class(record, prefix) - end - - def self.dom_id(record, prefix = nil) - ActiveSupport::Deprecation.warn(MODULE_MESSAGE % 'dom_id') - ActionView::RecordIdentifier.dom_id(record, prefix) - end - - def self.dom_class(record, prefix = nil) - ActiveSupport::Deprecation.warn(MODULE_MESSAGE % 'dom_class') - ActionView::RecordIdentifier.dom_class(record, prefix) - end - end -end diff --git a/actionpack/lib/action_controller/vendor/html-scanner.rb b/actionpack/lib/action_controller/vendor/html-scanner.rb deleted file mode 100644 index 896208bc05..0000000000 --- a/actionpack/lib/action_controller/vendor/html-scanner.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'action_view/vendor/html-scanner' -require 'active_support/deprecation' - -ActiveSupport::Deprecation.warn 'Vendored html-scanner was moved to action_view, please require "action_view/vendor/html-scanner" instead. ' + - 'This file will be removed in Rails 4.1' diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index f29ad359ac..61dbf2b96c 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -53,10 +53,6 @@ module Mime @@html_types = Set.new [:html, :all] cattr_reader :html_types - # These are the content types which browsers can generate without using ajax, flash, etc - # i.e. following a link, getting an image or posting a form. CSRF protection - # only needs to protect against these types. - @@browser_generated_types = Set.new [:html, :url_encoded_form, :multipart_form, :text] attr_reader :symbol @register_callbacks = [] @@ -272,18 +268,6 @@ module Mime end end - # Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See - # ActionController::RequestForgeryProtection. - def verify_request? - ActiveSupport::Deprecation.warn "Mime::Type#verify_request? is deprecated and will be removed in Rails 4.1" - @@browser_generated_types.include?(to_sym) - end - - def self.browser_generated_types - ActiveSupport::Deprecation.warn "Mime::Type.browser_generated_types is deprecated and will be removed in Rails 4.1" - @@browser_generated_types - end - def html? @@html_types.include?(to_sym) || @string =~ /html/ end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index ebd87c40b5..4ca1d35489 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -22,6 +22,7 @@ module ActionDispatch include ActionDispatch::Http::URL autoload :Session, 'action_dispatch/request/session' + autoload :Utils, 'action_dispatch/request/utils' LOCALHOST = Regexp.union [/^127\.0\.0\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/] @@ -299,26 +300,10 @@ module ActionDispatch LOCALHOST =~ remote_addr && LOCALHOST =~ remote_ip end - # Remove nils from the params hash - def deep_munge(hash) - hash.each do |k, v| - case v - when Array - v.grep(Hash) { |x| deep_munge(x) } - v.compact! - hash[k] = nil if v.empty? - when Hash - deep_munge(v) - end - end - - hash - end - protected def parse_query(qs) - deep_munge(super) + Utils.deep_munge(super) end private diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 60a2cccdc5..5697282791 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -31,10 +31,17 @@ module ActionDispatch # :nodoc: # end # end class Response - attr_accessor :request, :header + # The request that the response is responding to. + attr_accessor :request + + # The HTTP status code. attr_reader :status + attr_writer :sending_file + # Get and set headers for this response. + attr_accessor :header + alias_method :headers=, :header= alias_method :headers, :header @@ -49,9 +56,12 @@ module ActionDispatch # :nodoc: # If a character set has been defined for this response (see charset=) then # the character set information will also be included in the content type # information. - attr_accessor :charset attr_reader :content_type + # The charset of the response. HTML wants to know the encoding of the + # content you're giving them, so we need to send that along. + attr_accessor :charset + CONTENT_TYPE = "Content-Type".freeze SET_COOKIE = "Set-Cookie".freeze LOCATION = "Location".freeze @@ -93,6 +103,7 @@ module ActionDispatch # :nodoc: end end + # The underlying body, as a streamable object. attr_reader :stream def initialize(status = 200, header = {}, body = []) @@ -142,6 +153,7 @@ module ActionDispatch # :nodoc: @status = Rack::Utils.status_code(status) end + # Sets the HTTP content type. def content_type=(content_type) @content_type = content_type.to_s end @@ -216,11 +228,13 @@ module ActionDispatch # :nodoc: ::Rack::Utils.delete_cookie_header!(header, key, value) end + # The location header we'll be responding with. def location headers[LOCATION] end alias_method :redirect_url, :location + # Sets the location header we'll be responding with. def location=(url) headers[LOCATION] = url end @@ -229,11 +243,13 @@ module ActionDispatch # :nodoc: stream.close if stream.respond_to?(:close) end + # Turns the Response into a Rack-compatible array of the status, headers, + # and body. def to_a rack_response @status, @header.to_hash end alias prepare! to_a - alias to_ary to_a # For implicit splat on 1.9.2 + alias to_ary to_a # Returns the response cookies, converted to a Hash of (name => value) pairs # diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb index 0fa1e9b859..fb70b60ef6 100644 --- a/actionpack/lib/action_dispatch/middleware/params_parser.rb +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -43,7 +43,7 @@ module ActionDispatch when :json data = ActiveSupport::JSON.decode(request.body) data = {:_json => data} unless data.is_a?(Hash) - request.deep_munge(data).with_indifferent_access + Request::Utils.deep_munge(data).with_indifferent_access else false end diff --git a/actionpack/lib/action_dispatch/request/utils.rb b/actionpack/lib/action_dispatch/request/utils.rb new file mode 100644 index 0000000000..8b43cdada8 --- /dev/null +++ b/actionpack/lib/action_dispatch/request/utils.rb @@ -0,0 +1,24 @@ +module ActionDispatch + class Request < Rack::Request + class Utils # :nodoc: + class << self + # Remove nils from the params hash + def deep_munge(hash) + hash.each do |k, v| + case v + when Array + v.grep(Hash) { |x| deep_munge(x) } + v.compact! + hash[k] = nil if v.empty? + when Hash + deep_munge(v) + end + end + + hash + end + end + end + end +end + diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb index d251de33df..cffb814e1e 100644 --- a/actionpack/lib/action_dispatch/routing/inspector.rb +++ b/actionpack/lib/action_dispatch/routing/inspector.rb @@ -69,7 +69,7 @@ module ActionDispatch end def internal? - controller =~ %r{\Arails/(info|welcome)} || path =~ %r{\A#{Rails.application.config.assets.prefix}} + controller.to_s =~ %r{\Arails/(info|welcome)} || path =~ %r{\A#{Rails.application.config.assets.prefix}} end def engine? diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 3a6f449eb8..2b3a3c6a29 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -127,11 +127,7 @@ module ActionView # # => <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed" /> def auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {}) if !(type == :rss || type == :atom) && tag_options[:type].blank? - message = "You have passed type other than :rss or :atom to auto_discovery_link_tag and haven't supplied " + - "the :type option key. This behavior is deprecated and will be remove in Rails 4.1. You should pass " + - ":type option explicitly if you want to use other types, for example: " + - "auto_discovery_link_tag(:xml, '/feed.xml', :type => 'application/xml')" - ActiveSupport::Deprecation.warn message + raise ArgumentError.new("You should pass :type tag_option key explicitly, because you have passed #{type} type other than :rss or :atom.") end tag( diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index c10566a87d..3fa7696b83 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -426,22 +426,6 @@ module ActionView def submit_tag(value = "Save changes", options = {}) options = options.stringify_keys - if disable_with = options.delete("disable_with") - message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { disable_with: \'Text\' }' instead." - ActiveSupport::Deprecation.warn message - - options["data-disable-with"] = disable_with - end - - if confirm = options.delete("confirm") - message = ":confirm option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { confirm: \'Text\' }' instead'." - ActiveSupport::Deprecation.warn message - - options["data-confirm"] = confirm - end - tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options) end @@ -488,22 +472,6 @@ module ActionView options ||= {} options = options.stringify_keys - if disable_with = options.delete("disable_with") - message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { disable_with: \'Text\' }' instead." - ActiveSupport::Deprecation.warn message - - options["data-disable-with"] = disable_with - end - - if confirm = options.delete("confirm") - message = ":confirm option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { confirm: \'Text\' }' instead'." - ActiveSupport::Deprecation.warn message - - options["data-confirm"] = confirm - end - options.reverse_merge! 'name' => 'button', 'type' => 'submit' content_tag :button, content_or_options || 'Button', options, &block @@ -541,15 +509,6 @@ module ActionView # # => <input alt="Save" src="/images/save.png" data-confirm="Are you sure?" type="image" /> def image_submit_tag(source, options = {}) options = options.stringify_keys - - if confirm = options.delete("confirm") - message = ":confirm option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { confirm: \'Text\' }' instead'." - ActiveSupport::Deprecation.warn message - - options["data-confirm"] = confirm - end - tag :input, { "alt" => image_alt(source), "type" => "image", "src" => path_to_image(source) }.update(options) end diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index edff98ddaa..e475d5b018 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -70,48 +70,6 @@ module ActionView def javascript_cdata_section(content) #:nodoc: "\n//#{cdata_section("\n#{content}\n//")}\n".html_safe end - - # Returns a button whose +onclick+ handler triggers the passed JavaScript. - # - # The helper receives a name, JavaScript code, and an optional hash of HTML options. The - # name is used as button label and the JavaScript code goes into its +onclick+ attribute. - # If +html_options+ has an <tt>:onclick</tt>, that one is put before +function+. - # - # button_to_function "Greeting", "alert('Hello world!')", class: "ok" - # # => <input class="ok" onclick="alert('Hello world!');" type="button" value="Greeting" /> - # - def button_to_function(name, function=nil, html_options={}) - message = "button_to_function is deprecated and will be removed from Rails 4.1. We recommend using Unobtrusive JavaScript instead. " + - "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript" - ActiveSupport::Deprecation.warn message - - onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};" - - tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick)) - end - - # Returns a link whose +onclick+ handler triggers the passed JavaScript. - # - # The helper receives a name, JavaScript code, and an optional hash of HTML options. The - # name is used as the link text and the JavaScript code goes into the +onclick+ attribute. - # If +html_options+ has an <tt>:onclick</tt>, that one is put before +function+. Once all - # the JavaScript is set, the helper appends "; return false;". - # - # The +href+ attribute of the tag is set to "#" unless +html_options+ has one. - # - # link_to_function "Greeting", "alert('Hello world!')", class: "nav_link" - # # => <a class="nav_link" href="#" onclick="alert('Hello world!'); return false;">Greeting</a> - # - def link_to_function(name, function, html_options={}) - message = "link_to_function is deprecated and will be removed from Rails 4.1. We recommend using Unobtrusive JavaScript instead. " + - "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript" - ActiveSupport::Deprecation.warn message - - onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;" - href = html_options[:href] || '#' - - content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick)) - end end end end diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 22059a0170..8a83f6f356 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -548,28 +548,10 @@ module ActionView html_options = html_options.stringify_keys html_options['data-remote'] = 'true' if link_to_remote_options?(options) || link_to_remote_options?(html_options) - disable_with = html_options.delete("disable_with") - confirm = html_options.delete('confirm') method = html_options.delete('method') - if confirm - message = ":confirm option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { confirm: \'Text\' }' instead." - ActiveSupport::Deprecation.warn message - - html_options["data-confirm"] = confirm - end - add_method_to_attributes!(html_options, method) if method - if disable_with - message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \ - "Use 'data: { disable_with: \'Text\' }' instead." - ActiveSupport::Deprecation.warn message - - html_options["data-disable-with"] = disable_with - end - html_options else link_to_remote_options?(options) ? {'data-remote' => 'true'} : {} diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index ebbc1c79d6..c25b1efc2b 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -146,12 +146,6 @@ module ActionView handle_render_error(view, e) end - def mime_type - message = 'Template#mime_type is deprecated and will be removed in Rails 4.1. Please use type method instead.' - ActiveSupport::Deprecation.warn message - @mime_type ||= Mime::Type.lookup_by_extension(@formats.first.to_s) if @formats.first - end - def type @type ||= Types[@formats.first] if @formats.first end diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index d4f18d55a6..b2bfdae174 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -61,10 +61,7 @@ class UrlOptionsController < ActionController::Base end end -class RecordIdentifierController < ActionController::Base -end - -class RecordIdentifierWithoutDeprecationController < ActionController::Base +class RecordIdentifierIncludedController < ActionController::Base include ActionView::RecordIdentifier end @@ -88,43 +85,20 @@ class ControllerClassTests < ActiveSupport::TestCase assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name end - def test_record_identifier - assert_respond_to RecordIdentifierController.new, :dom_id - assert_respond_to RecordIdentifierController.new, :dom_class - end - - def test_record_identifier_is_deprecated - record = Comment.new - record.save - - dom_id = nil - assert_deprecated 'dom_id method will no longer' do - dom_id = RecordIdentifierController.new.dom_id(record) - end - - assert_equal 'comment_1', dom_id - - dom_class = nil - assert_deprecated 'dom_class method will no longer' do - dom_class = RecordIdentifierController.new.dom_class(record) - end - assert_equal 'comment', dom_class - end - def test_no_deprecation_when_action_view_record_identifier_is_included record = Comment.new record.save dom_id = nil assert_not_deprecated do - dom_id = RecordIdentifierWithoutDeprecationController.new.dom_id(record) + dom_id = RecordIdentifierIncludedController.new.dom_id(record) end assert_equal 'comment_1', dom_id dom_class = nil assert_not_deprecated do - dom_class = RecordIdentifierWithoutDeprecationController.new.dom_class(record) + dom_class = RecordIdentifierIncludedController.new.dom_class(record) end assert_equal 'comment', dom_class end diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/controller/record_identifier_test.rb deleted file mode 100644 index ff5d7fd3bd..0000000000 --- a/actionpack/test/controller/record_identifier_test.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'abstract_unit' -require 'controller/fake_models' - -class ControllerRecordIdentifierTest < ActiveSupport::TestCase - include ActionController::RecordIdentifier - - def setup - @record = Comment.new - end - - def test_dom_id_deprecation - assert_deprecated(/dom_id method will no longer be included by default in controllers/) do - dom_id(@record) - end - end - - def test_dom_class_deprecation - assert_deprecated(/dom_class method will no longer be included by default in controllers/) do - dom_class(@record) - end - end - - def test_dom_id_from_module_deprecation - assert_deprecated(/Calling ActionController::RecordIdentifier.dom_id is deprecated/) do - ActionController::RecordIdentifier.dom_id(@record) - end - end - - def test_dom_class_from_module_deprecation - assert_deprecated(/Calling ActionController::RecordIdentifier.dom_class is deprecated/) do - ActionController::RecordIdentifier.dom_class(@record) - end - end -end diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 6a2eb7da9f..8a19129695 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -185,11 +185,6 @@ class MimeTypeTest < ActiveSupport::TestCase all_types.uniq! # Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE all_types.delete_if { |type| !Mime.const_defined?(type.upcase) } - assert_deprecated do - verified, unverified = all_types.partition { |type| Mime::Type.browser_generated_types.include? type } - assert verified.each { |type| assert Mime.const_get(type.upcase).verify_request?, "Verifiable Mime Type is not verified: #{type.inspect}" } - assert unverified.each { |type| assert !Mime.const_get(type.upcase).verify_request?, "Nonverifiable Mime Type is verified: #{type.inspect}" } - end end test "references gives preference to symbols before strings" do diff --git a/actionpack/test/dispatch/rack_test.rb b/actionpack/test/dispatch/rack_test.rb index 6d239d0a0c..42067854ee 100644 --- a/actionpack/test/dispatch/rack_test.rb +++ b/actionpack/test/dispatch/rack_test.rb @@ -174,22 +174,6 @@ class RackRequestParamsParsingTest < BaseRackTest end end -class RackRequestContentTypeTest < BaseRackTest - test "html content type verification" do - assert_deprecated do - @request.env['CONTENT_TYPE'] = Mime::HTML.to_s - assert @request.content_mime_type.verify_request? - end - end - - test "xml content type verification" do - assert_deprecated do - @request.env['CONTENT_TYPE'] = Mime::XML.to_s - assert !@request.content_mime_type.verify_request? - end - end -end - class RackRequestNeedsRewoundTest < BaseRackTest test "body should be rewound" do data = 'foo' diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb index 234ae5764f..4f97d28d2b 100644 --- a/actionpack/test/dispatch/routing/inspector_test.rb +++ b/actionpack/test/dispatch/routing/inspector_test.rb @@ -234,6 +234,15 @@ module ActionDispatch " PUT /posts/:id(.:format) posts#update", " DELETE /posts/:id(.:format) posts#destroy"], output end + + def test_regression_route_with_controller_regexp + output = draw do + get ':controller(/:action)', controller: /api\/[^\/]+/, format: false + end + + assert_equal ["Prefix Verb URI Pattern Controller#Action", + " GET /:controller(/:action) (?-mix:api\\/[^\\/]+)#:action"], output + end end end end diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index 67f593c22f..8d0ab7fd81 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -298,13 +298,15 @@ class AssetTagHelperTest < ActionView::TestCase %(font_path("font.ttf?123")) => %(/fonts/font.ttf?123) } - def test_autodiscovery_link_tag_deprecated_types - result = nil - assert_deprecated do - result = auto_discovery_link_tag(:xml) + def test_autodiscovery_link_tag_with_unknown_type_but_not_pass_type_option_key + assert_raise(ArgumentError) do + auto_discovery_link_tag(:xml) end + end - expected = %(<link href="http://www.example.com" rel="alternate" title="XML" type="application/xml" />) + def test_autodiscovery_link_tag_with_unknown_type + result = auto_discovery_link_tag(:xml, '/feed.xml', :type => 'application/xml') + expected = %(<link href="/feed.xml" rel="alternate" title="XML" type="application/xml" />) assert_equal expected, result end diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 6c6a142397..70fc6a588b 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -410,15 +410,6 @@ class FormTagHelperTest < ActionView::TestCase ) end - def test_submit_tag_with_deprecated_confirmation - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %(<input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />), - submit_tag("Save", :confirm => "Are you sure?") - ) - end - end - def test_button_tag assert_dom_equal( %(<button name="button" type="submit">Button</button>), @@ -477,15 +468,6 @@ class FormTagHelperTest < ActionView::TestCase ) end - def test_button_tag_with_deprecated_confirmation - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %(<button name="button" type="submit" data-confirm="Are you sure?">Save</button>), - button_tag("Save", :type => "submit", :confirm => "Are you sure?") - ) - end - end - def test_image_submit_tag_with_confirmation assert_dom_equal( %(<input alt="Save" type="image" src="/images/save.gif" data-confirm="Are you sure?" />), @@ -493,16 +475,6 @@ class FormTagHelperTest < ActionView::TestCase ) end - def test_image_submit_tag_with_deprecated_confirmation - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %(<input alt="Save" type="image" src="/images/save.gif" data-confirm="Are you sure?" />), - image_submit_tag("save.gif", :confirm => "Are you sure?") - ) - end - end - - def test_color_field_tag expected = %{<input id="car" name="car" type="color" />} assert_dom_equal(expected, color_field_tag("car")) diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index 1eed8adb62..de6a6eaab3 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -42,48 +42,6 @@ class JavaScriptHelperTest < ActionView::TestCase assert_instance_of ActiveSupport::SafeBuffer, escape_javascript(ActiveSupport::SafeBuffer.new(given)) end - def test_button_to_function - assert_deprecated do - assert_dom_equal %(<input type="button" onclick="alert('Hello world!');" value="Greeting" />), - button_to_function("Greeting", "alert('Hello world!')") - end - end - - def test_button_to_function_with_onclick - assert_deprecated do - assert_dom_equal "<input onclick=\"alert('Goodbye World :('); alert('Hello world!');\" type=\"button\" value=\"Greeting\" />", - button_to_function("Greeting", "alert('Hello world!')", :onclick => "alert('Goodbye World :(')") - end - end - - def test_button_to_function_without_function - assert_deprecated do - assert_dom_equal "<input onclick=\";\" type=\"button\" value=\"Greeting\" />", - button_to_function("Greeting") - end - end - - def test_link_to_function - assert_deprecated do - assert_dom_equal %(<a href="#" onclick="alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')") - end - end - - def test_link_to_function_with_existing_onclick - assert_deprecated do - assert_dom_equal %(<a href="#" onclick="confirm('Sanity!'); alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')", :onclick => "confirm('Sanity!')") - end - end - - def test_function_with_href - assert_deprecated do - assert_dom_equal %(<a href="http://example.com/" onclick="alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/') - end - end - def test_javascript_tag self.output_buffer = 'foo' diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 8d32205fb8..c94508d678 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -64,13 +64,6 @@ class TestERBTemplate < ActiveSupport::TestCase @context = Context.new end - def test_mime_type_is_deprecated - template = new_template - assert_deprecated 'Template#mime_type is deprecated and will be removed' do - template.mime_type - end - end - def test_basic_template @template = new_template assert_equal "Hello", render diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index 9b4c419807..f63f235a5c 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -93,15 +93,6 @@ class UrlHelperTest < ActiveSupport::TestCase ) end - def test_button_to_with_deprecated_confirm - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %{<form method="post" action="http://www.example.com" class="button_to"><div><input data-confirm="Are you sure?" type="submit" value="Hello" /></div></form>}, - button_to("Hello", "http://www.example.com", confirm: "Are you sure?") - ) - end - end - def test_button_to_with_javascript_disable_with assert_dom_equal( %{<form method="post" action="http://www.example.com" class="button_to"><div><input data-disable-with="Greeting..." type="submit" value="Hello" /></div></form>}, @@ -109,15 +100,6 @@ class UrlHelperTest < ActiveSupport::TestCase ) end - def test_button_to_with_javascript_deprecated_disable_with - assert_deprecated ":disable_with option is deprecated and will be removed from Rails 4.1. Use 'data: { disable_with: \'Text\' }' instead" do - assert_dom_equal( - %{<form method="post" action="http://www.example.com" class="button_to"><div><input data-disable-with="Greeting..." type="submit" value="Hello" /></div></form>}, - button_to("Hello", "http://www.example.com", disable_with: "Greeting...") - ) - end - end - def test_button_to_with_remote_and_form_options assert_dom_equal( %{<form method="post" action="http://www.example.com" class="custom-class" data-remote="true" data-type="json"><div><input type="submit" value="Hello" /></div></form>}, @@ -132,15 +114,6 @@ class UrlHelperTest < ActiveSupport::TestCase ) end - def test_button_to_with_remote_and_javascript_with_deprecated_confirm - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %{<form method="post" action="http://www.example.com" class="button_to" data-remote="true"><div><input data-confirm="Are you sure?" type="submit" value="Hello" /></div></form>}, - button_to("Hello", "http://www.example.com", remote: true, confirm: "Are you sure?") - ) - end - end - def test_button_to_with_remote_and_javascript_disable_with assert_dom_equal( %{<form method="post" action="http://www.example.com" class="button_to" data-remote="true"><div><input data-disable-with="Greeting..." type="submit" value="Hello" /></div></form>}, @@ -148,15 +121,6 @@ class UrlHelperTest < ActiveSupport::TestCase ) end - def test_button_to_with_remote_and_javascript_deprecated_disable_with - assert_deprecated ":disable_with option is deprecated and will be removed from Rails 4.1. Use 'data: { disable_with: \'Text\' }' instead" do - assert_dom_equal( - %{<form method="post" action="http://www.example.com" class="button_to" data-remote="true"><div><input data-disable-with="Greeting..." type="submit" value="Hello" /></div></form>}, - button_to("Hello", "http://www.example.com", remote: true, disable_with: "Greeting...") - ) - end - end - def test_button_to_with_remote_false assert_dom_equal( %{<form method="post" action="http://www.example.com" class="button_to"><div><input type="submit" value="Hello" /></div></form>}, @@ -265,27 +229,6 @@ class UrlHelperTest < ActiveSupport::TestCase ) end - def test_link_tag_with_deprecated_confirm - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %{<a href="http://www.example.com" data-confirm="Are you sure?">Hello</a>}, - link_to("Hello", "http://www.example.com", confirm: "Are you sure?") - ) - end - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %{<a href="http://www.example.com" data-confirm="You cant possibly be sure, can you?">Hello</a>}, - link_to("Hello", "http://www.example.com", confirm: "You cant possibly be sure, can you?") - ) - end - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %{<a href="http://www.example.com" data-confirm="You cant possibly be sure,\n can you?">Hello</a>}, - link_to("Hello", "http://www.example.com", confirm: "You cant possibly be sure,\n can you?") - ) - end - end - def test_link_to_with_remote assert_dom_equal( %{<a href="http://www.example.com" data-remote="true">Hello</a>}, @@ -349,15 +292,6 @@ class UrlHelperTest < ActiveSupport::TestCase ) end - def test_link_tag_using_post_javascript_and_with_deprecated_confirm - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %{<a href="http://www.example.com" data-method="post" rel="nofollow" data-confirm="Are you serious?">Hello</a>}, - link_to("Hello", "http://www.example.com", method: :post, confirm: "Are you serious?") - ) - end - end - def test_link_tag_using_delete_javascript_and_href_and_confirm assert_dom_equal( %{<a href="\#" rel="nofollow" data-confirm="Are you serious?" data-method="delete">Destroy</a>}, @@ -365,15 +299,6 @@ class UrlHelperTest < ActiveSupport::TestCase ) end - def test_link_tag_using_delete_javascript_and_href_and_with_deprecated_confirm - assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do - assert_dom_equal( - %{<a href="\#" rel="nofollow" data-confirm="Are you serious?" data-method="delete">Destroy</a>}, - link_to("Destroy", "http://www.example.com", method: :delete, href: '#', confirm: "Are you serious?") - ) - end - end - def test_link_tag_with_block assert_dom_equal %{<a href="/"><span>Example site</span></a>}, link_to('/') { content_tag(:span, 'Example site') } diff --git a/actionpack/test/ts_isolated.rb b/actionpack/test/ts_isolated.rb deleted file mode 100644 index 55620abe84..0000000000 --- a/actionpack/test/ts_isolated.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'active_support/testing/autorun' -require 'rbconfig' -require 'abstract_unit' - -class TestIsolated < ActiveSupport::TestCase - ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) - - Dir["#{File.dirname(__FILE__)}/{abstract,controller,dispatch,template}/**/*_test.rb"].each do |file| - define_method("test #{file}") do - command = "#{ruby} -Ilib:test #{file}" - result = silence_stderr { `#{command}` } - assert $?.to_i.zero?, "#{command}\n#{result}" - end - end -end diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 8c7af2d078..6fc34ecd60 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,8 @@ +* Fix regression in has_secure_password. When a password is set, but a + confirmation is an empty string, it would incorrectly save. + + *Steve Klabnik* and *Phillip Calvin* + * Deprecate `Validator#setup`. This should be done manually now in the validator's constructor. *Nick Sutterer* diff --git a/activemodel/Rakefile b/activemodel/Rakefile index fc5aaf9f8f..45d1587ed6 100644 --- a/activemodel/Rakefile +++ b/activemodel/Rakefile @@ -20,7 +20,6 @@ namespace :test do end end -require 'rake/packagetask' require 'rubygems/package_task' spec = eval(File.read("#{dir}/activemodel.gemspec")) diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 750fd723a0..e553590671 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -56,8 +56,9 @@ module ActiveModel include InstanceMethodsOnActivation if options.fetch(:validations, true) - validates_confirmation_of :password + validates_confirmation_of :password, if: lambda { |m| m.password.present? } validates_presence_of :password, on: :create + validates_presence_of :password_confirmation, if: lambda { |m| m.password.present? } before_create { raise "Password digest missing on new record" if password_digest.blank? } end @@ -106,9 +107,7 @@ module ActiveModel end def password_confirmation=(unencrypted_password) - unless unencrypted_password.blank? - @password_confirmation = unencrypted_password - end + @password_confirmation = unencrypted_password end end end diff --git a/activemodel/test/cases/secure_password_test.rb b/activemodel/test/cases/secure_password_test.rb index 02cd3b8a93..0b900d934d 100644 --- a/activemodel/test/cases/secure_password_test.rb +++ b/activemodel/test/cases/secure_password_test.rb @@ -94,4 +94,13 @@ class SecurePasswordTest < ActiveModel::TestCase @user.password_confirmation = "" assert @user.valid?(:update), "user should be valid" end + + test "will not save if confirmation is blank but password is not" do + @user.password = "password" + @user.password_confirmation = "" + assert_not @user.valid?(:create) + + @user.password_confirmation = "password" + assert @user.valid?(:create) + end end diff --git a/activerecord/Rakefile b/activerecord/Rakefile index cd73489cbe..136bb1dfbc 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -1,5 +1,4 @@ require 'rake/testtask' -require 'rake/packagetask' require 'rubygems/package_task' require File.expand_path(File.dirname(__FILE__)) + "/test/config" diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 7f1ebab4cd..d326ef7c22 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -50,13 +50,6 @@ module ActiveRecord end end - # *DEPRECATED*: Use ActiveRecord::AttributeMethods::Serialization::ClassMethods#serialized_attributes class level method instead. - def serialized_attributes - message = "Instance level serialized_attributes method is deprecated, please use class level method." - ActiveSupport::Deprecation.warn message - defined?(@serialized_attributes) ? @serialized_attributes : self.class.serialized_attributes - end - class Type # :nodoc: def initialize(column) @column = column diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 87d4daa6d9..a8a1847554 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -301,7 +301,7 @@ module ActiveRecord def association_valid?(reflection, record) return true if record.destroyed? || record.marked_for_destruction? - unless valid = record.valid?(validation_context) + unless valid = record.valid? if reflection.options[:autosave] record.errors.each do |attribute, message| attribute = "#{reflection.name}.#{attribute}" diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 8ffe150de6..2a4eda3622 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -606,7 +606,7 @@ module ActiveRecord index_options = options.delete(:index) add_column(table_name, "#{ref_name}_id", :integer, options) add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic - add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : nil) if index_options + add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options end alias :add_belongs_to :add_reference @@ -775,37 +775,23 @@ module ActiveRecord column_names = Array(column_name) index_name = index_name(table_name, column: column_names) - if Hash === options # legacy support, since this param was a string - options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type) + options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type) - index_type = options[:unique] ? "UNIQUE" : "" - index_type = options[:type].to_s if options.key?(:type) - index_name = options[:name].to_s if options.key?(:name) - max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length + index_type = options[:unique] ? "UNIQUE" : "" + index_type = options[:type].to_s if options.key?(:type) + index_name = options[:name].to_s if options.key?(:name) + max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length - if options.key?(:algorithm) - algorithm = index_algorithms.fetch(options[:algorithm]) { - raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}") - } - end - - using = "USING #{options[:using]}" if options[:using].present? - - if supports_partial_index? - index_options = options[:where] ? " WHERE #{options[:where]}" : "" - end - else - if options - message = "Passing a string as third argument of `add_index` is deprecated and will" + - " be removed in Rails 4.1." + - " Use add_index(#{table_name.inspect}, #{column_name.inspect}, unique: true) instead" + if options.key?(:algorithm) + algorithm = index_algorithms.fetch(options[:algorithm]) { + raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}") + } + end - ActiveSupport::Deprecation.warn message - end + using = "USING #{options[:using]}" if options[:using].present? - index_type = options - max_index_length = allowed_index_name_length - algorithm = using = nil + if supports_partial_index? + index_options = options[:where] ? " WHERE #{options[:where]}" : "" end if index_name.length > max_index_length diff --git a/activerecord/lib/active_record/locking/pessimistic.rb b/activerecord/lib/active_record/locking/pessimistic.rb index 8e4ddcac82..ddf2afca0c 100644 --- a/activerecord/lib/active_record/locking/pessimistic.rb +++ b/activerecord/lib/active_record/locking/pessimistic.rb @@ -64,7 +64,7 @@ module ActiveRecord end # Wraps the passed block in a transaction, locking the object - # before yielding. You pass can the SQL locking clause + # before yielding. You can pass the SQL locking clause # as argument (see <tt>lock!</tt>). def with_lock(lock = true) transaction do diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index a8905ed739..582006ea7d 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -333,10 +333,44 @@ module ActiveRecord toggle(attribute).update_attribute(attribute, self[attribute]) end - # Reloads the attributes of this object from the database. - # The optional options argument is passed to find when reloading so you - # may do e.g. record.reload(lock: true) to reload the same record with - # an exclusive row lock. + # Reloads the record from the database. + # + # This method modifies the receiver in-place. Attributes are updated, and + # caches busted, in particular the associations cache. + # + # If the record no longer exists in the database <tt>ActiveRecord::RecordNotFound</tt> + # is raised. Otherwise, in addition to the in-place modification the method + # returns +self+ for convenience. + # + # The optional <tt>:lock</tt> flag option allows you to lock the reloaded record: + # + # reload(lock: true) # reload with pessimistic locking + # + # Reloading is commonly used in test suites to test something is actually + # written to the database, or when some action modifies the corresponding + # row in the database but not the object in memory: + # + # assert account.deposit!(25) + # assert_equal 25, account.credit # check it is updated in memory + # assert_equal 25, account.reload.credit # check it is also persisted + # + # Another commom use case is optimistic locking handling: + # + # def with_optimistic_retry + # begin + # yield + # rescue ActiveRecord::StaleObjectError + # begin + # # Reload lock_version in particular. + # reload + # rescue ActiveRecord::RecordNotFound + # # If the record is gone there is nothing to do. + # else + # retry + # end + # end + # end + # def reload(options = nil) clear_aggregation_cache clear_association_cache diff --git a/activerecord/lib/active_record/readonly_attributes.rb b/activerecord/lib/active_record/readonly_attributes.rb index 8499bb16e7..b3ddfd63d4 100644 --- a/activerecord/lib/active_record/readonly_attributes.rb +++ b/activerecord/lib/active_record/readonly_attributes.rb @@ -20,11 +20,5 @@ module ActiveRecord self._attr_readonly end end - - def _attr_readonly - message = "Instance level _attr_readonly method is deprecated, please use class level method." - ActiveSupport::Deprecation.warn message - defined?(@_attr_readonly) ? @_attr_readonly : self.class._attr_readonly - end end end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 9857ab0f8f..d54479edbb 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -154,34 +154,58 @@ module ActiveRecord first || new(attributes, &block) end - # Finds the first record with the given attributes, or creates a record with the attributes - # if one is not found. + # Finds the first record with the given attributes, or creates a record + # with the attributes if one is not found: # - # ==== Examples - # # Find the first user named Penélope or create a new one. + # # Find the first user named "Penélope" or create a new one. # User.find_or_create_by(first_name: 'Penélope') - # # => <User id: 1, first_name: 'Penélope', last_name: nil> + # # => #<User id: 1, first_name: "Penélope", last_name: nil> # - # # Find the first user named Penélope or create a new one. + # # Find the first user named "Penélope" or create a new one. # # We already have one so the existing record will be returned. # User.find_or_create_by(first_name: 'Penélope') - # # => <User id: 1, first_name: 'Penélope', last_name: nil> + # # => #<User id: 1, first_name: "Penélope", last_name: nil> # - # # Find the first user named Scarlett or create a new one with a particular last name. + # # Find the first user named "Scarlett" or create a new one with + # # a particular last name. # User.create_with(last_name: 'Johansson').find_or_create_by(first_name: 'Scarlett') - # # => <User id: 2, first_name: 'Scarlett', last_name: 'Johansson'> + # # => #<User id: 2, first_name: "Scarlett", last_name: "Johansson"> # - # # Find the first user named Scarlett or create a new one with a different last name. - # # We already have one so the existing record will be returned. + # This method accepts a block, which is passed down to +create+. The last example + # above can be alternatively written this way: + # + # # Find the first user named "Scarlett" or create a new one with a + # # different last name. # User.find_or_create_by(first_name: 'Scarlett') do |user| - # user.last_name = "O'Hara" + # user.last_name = 'Johansson' # end - # # => <User id: 2, first_name: 'Scarlett', last_name: 'Johansson'> + # # => #<User id: 2, first_name: "Scarlett", last_name: "Johansson"> + # + # This method always returns a record, but if creation was attempted and + # failed due to validation errors it won't be persisted, you get what + # +create+ returns in such situation. + # + # Please note *this method is not atomic*, it runs first a SELECT, and if + # there are no results an INSERT is attempted. If there are other threads + # or processes there is a race condition between both calls and it could + # be the case that you end up with two similar records. + # + # Whether that is a problem or not depends on the logic of the + # application, but in the particular case in which rows have a UNIQUE + # constraint an exception may be raised, just retry: + # + # begin + # CreditAccount.find_or_create_by(user_id: user.id) + # rescue ActiveRecord::RecordNotUnique + # retry + # end + # def find_or_create_by(attributes, &block) find_by(attributes) || create(attributes, &block) end - # Like <tt>find_or_create_by</tt>, but calls <tt>create!</tt> so an exception is raised if the created record is invalid. + # Like <tt>find_or_create_by</tt>, but calls <tt>create!</tt> so an exception + # is raised if the created record is invalid. def find_or_create_by!(attributes, &block) find_by(attributes) || create!(attributes, &block) end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 7239270c4d..e234e02032 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -56,15 +56,7 @@ module ActiveRecord # # Person.sum(:age) # => 4562 def sum(*args) - if block_given? - ActiveSupport::Deprecation.warn( - "Calling #sum with a block is deprecated and will be removed in Rails 4.1. " \ - "If you want to perform sum calculation over the array of elements, use `to_a.sum(&block)`." - ) - self.to_a.sum(*args) {|*block_args| yield(*block_args)} - else - calculate(:sum, *args) - end + calculate(:sum, *args) end # This calculates aggregate values in the given column. Methods for count, sum, average, diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index fe8fec4dfa..ca1de2d4dc 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1010,7 +1010,7 @@ module ActiveRecord end def validate_order_args(args) - args.select { |a| Hash === a }.each do |h| + args.grep(Hash) do |h| unless (h.values - [:asc, :desc]).empty? raise ArgumentError, 'Direction should be :asc or :desc' end diff --git a/activerecord/lib/active_record/schema_migration.rb b/activerecord/lib/active_record/schema_migration.rb index 6077144265..fee19b1096 100644 --- a/activerecord/lib/active_record/schema_migration.rb +++ b/activerecord/lib/active_record/schema_migration.rb @@ -4,31 +4,37 @@ require 'active_record/base' module ActiveRecord class SchemaMigration < ActiveRecord::Base + class << self - def self.table_name - "#{Base.table_name_prefix}schema_migrations#{Base.table_name_suffix}" - end + def table_name + "#{table_name_prefix}schema_migrations#{table_name_suffix}" + end - def self.index_name - "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}" - end + def index_name + "#{table_name_prefix}unique_schema_migrations#{table_name_suffix}" + end - def self.create_table(limit=nil) - unless connection.table_exists?(table_name) - version_options = {null: false} - version_options[:limit] = limit if limit + def table_exists? + connection.table_exists?(table_name) + end + + def create_table(limit=nil) + unless table_exists? + version_options = {null: false} + version_options[:limit] = limit if limit - connection.create_table(table_name, id: false) do |t| - t.column :version, :string, version_options + connection.create_table(table_name, id: false) do |t| + t.column :version, :string, version_options + end + connection.add_index table_name, :version, unique: true, name: index_name end - connection.add_index table_name, :version, unique: true, name: index_name end - end - def self.drop_table - if connection.table_exists?(table_name) - connection.remove_index table_name, name: index_name - connection.drop_table(table_name) + def drop_table + if table_exists? + connection.remove_index table_name, name: index_name + connection.drop_table(table_name) + end end end diff --git a/activerecord/lib/active_record/validations/associated.rb b/activerecord/lib/active_record/validations/associated.rb index 744780d069..b4785d3ba4 100644 --- a/activerecord/lib/active_record/validations/associated.rb +++ b/activerecord/lib/active_record/validations/associated.rb @@ -2,7 +2,7 @@ module ActiveRecord module Validations class AssociatedValidator < ActiveModel::EachValidator #:nodoc: def validate_each(record, attribute, value) - if Array.wrap(value).reject {|r| r.marked_for_destruction? || r.valid?(record.validation_context) }.any? + if Array.wrap(value).reject {|r| r.marked_for_destruction? || r.valid?}.any? record.errors.add(attribute, :invalid, options.merge(:value => value)) end end diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index b5d7ea603e..36d7294bc8 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -246,7 +246,7 @@ _SQL assert_equal 2...10, @second_range.int4_range assert_equal 2...Float::INFINITY, @third_range.int4_range assert_equal(-Float::INFINITY...Float::INFINITY, @fourth_range.int4_range) - assert_equal nil, @empty_range.int4_range + assert_nil @empty_range.int4_range end def test_int8range_values @@ -255,7 +255,7 @@ _SQL assert_equal 11...100, @second_range.int8_range assert_equal 11...Float::INFINITY, @third_range.int8_range assert_equal(-Float::INFINITY...Float::INFINITY, @fourth_range.int8_range) - assert_equal nil, @empty_range.int8_range + assert_nil @empty_range.int8_range end def test_daterange_values @@ -264,7 +264,7 @@ _SQL assert_equal Date.new(2012, 1, 3)...Date.new(2012, 1, 4), @second_range.date_range assert_equal Date.new(2012, 1, 3)...Float::INFINITY, @third_range.date_range assert_equal(-Float::INFINITY...Float::INFINITY, @fourth_range.date_range) - assert_equal nil, @empty_range.date_range + assert_nil @empty_range.date_range end def test_numrange_values @@ -273,7 +273,7 @@ _SQL assert_equal BigDecimal.new('0.1')...BigDecimal.new('0.2'), @second_range.num_range assert_equal BigDecimal.new('0.1')...BigDecimal.new('Infinity'), @third_range.num_range assert_equal BigDecimal.new('-Infinity')...BigDecimal.new('Infinity'), @fourth_range.num_range - assert_equal nil, @empty_range.num_range + assert_nil @empty_range.num_range end def test_tsrange_values @@ -282,7 +282,7 @@ _SQL assert_equal Time.send(tz, 2010, 1, 1, 14, 30, 0)..Time.send(tz, 2011, 1, 1, 14, 30, 0), @first_range.ts_range assert_equal Time.send(tz, 2010, 1, 1, 14, 30, 0)...Time.send(tz, 2011, 1, 1, 14, 30, 0), @second_range.ts_range assert_equal(-Float::INFINITY...Float::INFINITY, @fourth_range.ts_range) - assert_equal nil, @empty_range.ts_range + assert_nil @empty_range.ts_range end def test_tstzrange_values @@ -290,7 +290,7 @@ _SQL assert_equal Time.parse('2010-01-01 09:30:00 UTC')..Time.parse('2011-01-01 17:30:00 UTC'), @first_range.tstz_range assert_equal Time.parse('2010-01-01 09:30:00 UTC')...Time.parse('2011-01-01 17:30:00 UTC'), @second_range.tstz_range assert_equal(-Float::INFINITY...Float::INFINITY, @fourth_range.tstz_range) - assert_equal nil, @empty_range.tstz_range + assert_nil @empty_range.tstz_range end def test_money_values @@ -314,11 +314,11 @@ _SQL assert @first_range.tstz_range = new_tstzrange assert @first_range.save assert @first_range.reload - assert_equal @first_range.tstz_range, new_tstzrange + assert_equal new_tstzrange, @first_range.tstz_range assert @first_range.tstz_range = Time.parse('2010-01-01 14:30:00 +0100')...Time.parse('2010-01-01 13:30:00 +0000') assert @first_range.save assert @first_range.reload - assert_equal @first_range.tstz_range, nil + assert_nil @first_range.tstz_range end def test_create_tsrange @@ -338,11 +338,11 @@ _SQL assert @first_range.ts_range = new_tsrange assert @first_range.save assert @first_range.reload - assert_equal @first_range.ts_range, new_tsrange + assert_equal new_tsrange, @first_range.ts_range assert @first_range.ts_range = Time.send(tz, 2010, 1, 1, 14, 30, 0)...Time.send(tz, 2010, 1, 1, 14, 30, 0) assert @first_range.save assert @first_range.reload - assert_equal @first_range.ts_range, nil + assert_nil @first_range.ts_range end def test_create_numrange @@ -360,11 +360,11 @@ _SQL assert @first_range.num_range = new_numrange assert @first_range.save assert @first_range.reload - assert_equal @first_range.num_range, new_numrange + assert_equal new_numrange, @first_range.num_range assert @first_range.num_range = BigDecimal.new('0.5')...BigDecimal.new('0.5') assert @first_range.save assert @first_range.reload - assert_equal @first_range.num_range, nil + assert_nil @first_range.num_range end def test_create_daterange @@ -382,11 +382,11 @@ _SQL assert @first_range.date_range = new_daterange assert @first_range.save assert @first_range.reload - assert_equal @first_range.date_range, new_daterange + assert_equal new_daterange, @first_range.date_range assert @first_range.date_range = Date.new(2012, 2, 3)...Date.new(2012, 2, 3) assert @first_range.save assert @first_range.reload - assert_equal @first_range.date_range, nil + assert_nil @first_range.date_range end def test_create_int4range @@ -404,11 +404,11 @@ _SQL assert @first_range.int4_range = new_int4range assert @first_range.save assert @first_range.reload - assert_equal @first_range.int4_range, new_int4range + assert_equal new_int4range, @first_range.int4_range assert @first_range.int4_range = 3...3 assert @first_range.save assert @first_range.reload - assert_equal @first_range.int4_range, nil + assert_nil @first_range.int4_range end def test_create_int8range @@ -426,11 +426,11 @@ _SQL assert @first_range.int8_range = new_int8range assert @first_range.save assert @first_range.reload - assert_equal @first_range.int8_range, new_int8range + assert_equal new_int8range, @first_range.int8_range assert @first_range.int8_range = 39999...39999 assert @first_range.save assert @first_range.reload - assert_equal @first_range.int8_range, nil + assert_nil @first_range.int8_range end def test_update_tsvector @@ -441,7 +441,7 @@ _SQL assert @first_tsvector.text_vector = new_text_vector assert @first_tsvector.save assert @first_tsvector.reload - assert_equal @first_tsvector.text_vector, new_text_vector + assert_equal new_text_vector, @first_tsvector.text_vector end def test_number_values @@ -482,11 +482,11 @@ _SQL assert @first_array.commission_by_quarter = new_value assert @first_array.save assert @first_array.reload - assert_equal @first_array.commission_by_quarter, new_value + assert_equal new_value, @first_array.commission_by_quarter assert @first_array.commission_by_quarter = new_value assert @first_array.save assert @first_array.reload - assert_equal @first_array.commission_by_quarter, new_value + assert_equal new_value, @first_array.commission_by_quarter end def test_update_text_array @@ -494,11 +494,11 @@ _SQL assert @first_array.nicknames = new_value assert @first_array.save assert @first_array.reload - assert_equal @first_array.nicknames, new_value + assert_equal new_value, @first_array.nicknames assert @first_array.nicknames = new_value assert @first_array.save assert @first_array.reload - assert_equal @first_array.nicknames, new_value + assert_equal new_value, @first_array.nicknames end def test_update_money @@ -516,15 +516,15 @@ _SQL assert @first_number.double = new_double assert @first_number.save assert @first_number.reload - assert_equal @first_number.single, new_single - assert_equal @first_number.double, new_double + assert_equal new_single, @first_number.single + assert_equal new_double, @first_number.double end def test_update_time assert @first_time.time_interval = '2 years 3 minutes' assert @first_time.save assert @first_time.reload - assert_equal @first_time.time_interval, '2 years 00:03:00' + assert_equal '2 years 00:03:00', @first_time.time_interval end def test_update_network_address @@ -548,10 +548,10 @@ _SQL assert @first_bit_string.bit_string_varying = new_bit_string_varying assert @first_bit_string.save assert @first_bit_string.reload - assert_equal @first_bit_string.bit_string, new_bit_string + assert_equal new_bit_string, @first_bit_string.bit_string assert_equal @first_bit_string.bit_string, @first_bit_string.bit_string_varying end - + def test_invalid_hex_string new_bit_string = 'FF' @first_bit_string.bit_string = new_bit_string @@ -563,7 +563,7 @@ _SQL assert @first_oid.obj_id = new_value assert @first_oid.save assert @first_oid.reload - assert_equal @first_oid.obj_id, new_value + assert_equal new_value, @first_oid.obj_id end def test_timestamp_with_zone_values_with_rails_time_zone_support diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 87af24cbe6..95896971a8 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -338,7 +338,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase topic.replies.create!(:title => "re: 37s", :content => "rails") assert_equal 1, Topic.find(topic.id)[:replies_count] - topic.update_columns(content: "rails is wonderfull") + topic.update_columns(content: "rails is wonderful") assert_equal 1, Topic.find(topic.id)[:replies_count] end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 058c812dca..9f64ecd845 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1747,12 +1747,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_deprecated { klass.has_many :foo, :counter_sql => 'lol' } end - test "sum calculation with block for array compatibility is deprecated" do - assert_deprecated do - posts(:welcome).comments.sum { |c| c.id } - end - end - test "has many associations on new records use null relations" do post = Post.new diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 56b417562b..395f28f280 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -581,12 +581,6 @@ class BasicsTest < ActiveRecord::TestCase assert_equal "changed", post.body end - def test_attr_readonly_is_class_level_setting - post = ReadonlyTitlePost.new - assert_raise(NoMethodError) { post._attr_readonly = [:title] } - assert_deprecated { post._attr_readonly } - end - def test_non_valid_identifier_column_name weird = Weird.create('a$b' => 'value') weird.reload @@ -1228,38 +1222,6 @@ class BasicsTest < ActiveRecord::TestCase assert_no_queries { assert true } end - def test_silence_sets_log_level_to_error_in_block - original_logger = ActiveRecord::Base.logger - - assert_deprecated do - log = StringIO.new - ActiveRecord::Base.logger = ActiveSupport::Logger.new(log) - ActiveRecord::Base.logger.level = Logger::DEBUG - ActiveRecord::Base.silence do - ActiveRecord::Base.logger.warn "warn" - ActiveRecord::Base.logger.error "error" - end - assert_equal "error\n", log.string - end - ensure - ActiveRecord::Base.logger = original_logger - end - - def test_silence_sets_log_level_back_to_level_before_yield - original_logger = ActiveRecord::Base.logger - - assert_deprecated do - log = StringIO.new - ActiveRecord::Base.logger = ActiveSupport::Logger.new(log) - ActiveRecord::Base.logger.level = Logger::WARN - ActiveRecord::Base.silence do - end - assert_equal Logger::WARN, ActiveRecord::Base.logger.level - end - ensure - ActiveRecord::Base.logger = original_logger - end - def test_benchmark_with_log_level original_logger = ActiveRecord::Base.logger log = StringIO.new diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index f49bef2346..095b78c6c8 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -410,12 +410,6 @@ class CalculationsTest < ActiveRecord::TestCase Account.where("credit_limit > 50").from('accounts').sum(:credit_limit) end - def test_sum_array_compatibility_deprecation - assert_deprecated do - assert_equal Account.sum(:credit_limit), Account.sum(&:credit_limit) - end - end - def test_average_with_from_option assert_equal Account.average(:credit_limit), Account.from('accounts').average(:credit_limit) assert_equal Account.where("credit_limit > 50").average(:credit_limit), diff --git a/activerecord/test/cases/migration/index_test.rb b/activerecord/test/cases/migration/index_test.rb index 0e375af6e8..04521a5f5a 100644 --- a/activerecord/test/cases/migration/index_test.rb +++ b/activerecord/test/cases/migration/index_test.rb @@ -109,16 +109,6 @@ module ActiveRecord end end - def test_deprecated_type_argument - message = "Passing a string as third argument of `add_index` is deprecated and will" + - " be removed in Rails 4.1." + - " Use add_index(:testings, [:foo, :bar], unique: true) instead" - - assert_deprecated message do - connection.add_index :testings, [:foo, :bar], "UNIQUE" - end - end - def test_unique_index_exists connection.add_index :testings, :foo, :unique => true diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 03c7009568..55fd068d37 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -186,7 +186,7 @@ module ActiveRecord post = Post.select(:title).first assert_equal false, post.respond_to?(:body), "post should not respond_to?(:body) since invoking it raises exception" - post = Post.select("'title' as post_title").first + silence_warnings { post = Post.select("'title' as post_title").first } assert_equal false, post.respond_to?(:title), "post should not respond_to?(:body) since invoking it raises exception" end diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index 765e92ccca..b49c27bc78 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -19,12 +19,6 @@ class SerializedAttributeTest < ActiveRecord::TestCase assert_equal %w(content), Topic.serialized_attributes.keys end - def test_serialized_attributes_are_class_level_settings - topic = Topic.new - assert_raise(NoMethodError) { topic.serialized_attributes = [] } - assert_deprecated { topic.serialized_attributes } - end - def test_serialized_attribute Topic.serialize("content", MyObject) diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb index 3e32d866ee..c2c56abacd 100644 --- a/activerecord/test/cases/store_test.rb +++ b/activerecord/test/cases/store_test.rb @@ -150,9 +150,4 @@ class StoreTest < ActiveRecord::TestCase test "all stored attributes are returned" do assert_equal [:color, :homepage, :favorite_food], Admin::User.stored_attributes[:settings] end - - test "stores_attributes are class level settings" do - assert_raise(NoMethodError) { @john.stored_attributes = Hash.new } - assert_raise(NoMethodError) { @john.stored_attributes } - end end diff --git a/activerecord/test/cases/validations/association_validation_test.rb b/activerecord/test/cases/validations/association_validation_test.rb index 7ac34bc71e..7e92a2b127 100644 --- a/activerecord/test/cases/validations/association_validation_test.rb +++ b/activerecord/test/cases/validations/association_validation_test.rb @@ -118,21 +118,4 @@ class AssociationValidationTest < ActiveRecord::TestCase end end - def test_validates_associated_models_in_the_same_context - Topic.validates_presence_of :title, :on => :custom_context - Topic.validates_associated :replies - Reply.validates_presence_of :title, :on => :custom_context - - t = Topic.new('title' => '') - r = t.replies.new('title' => '') - - assert t.valid? - assert !t.valid?(:custom_context) - - t.title = "Longer" - assert !t.valid?(:custom_context), "Should NOT be valid if the associated object is not valid in the same context." - - r.title = "Longer" - assert t.valid?(:custom_context), "Should be valid if the associated object is not valid in the same context." - end end diff --git a/activesupport/Rakefile b/activesupport/Rakefile index e3788ed54f..f50225a9f0 100644 --- a/activesupport/Rakefile +++ b/activesupport/Rakefile @@ -9,13 +9,16 @@ Rake::TestTask.new do |t| t.verbose = true end + namespace :test do - Rake::TestTask.new(:isolated) do |t| - t.pattern = 'test/ts_isolated.rb' + task :isolated do + ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) + Dir.glob("test/**/*_test.rb").all? do |file| + sh(ruby, '-Ilib:test', file) + end or raise "Failures" end end - spec = eval(File.read('activesupport.gemspec')) Gem::PackageTask.new(spec) do |p| diff --git a/activesupport/lib/active_support/benchmarkable.rb b/activesupport/lib/active_support/benchmarkable.rb index 6413502b53..805b7a714f 100644 --- a/activesupport/lib/active_support/benchmarkable.rb +++ b/activesupport/lib/active_support/benchmarkable.rb @@ -45,15 +45,5 @@ module ActiveSupport yield end end - - # Silence the logger during the execution of the block. - def silence - message = "ActiveSupport::Benchmarkable#silence is deprecated. It will be removed from Rails 4.1." - ActiveSupport::Deprecation.warn message - old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger - yield - ensure - logger.level = old_logger_level if logger - end end end diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index 106a65610c..06e4847e82 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -119,4 +119,15 @@ class Date options.fetch(:day, day) ) end + + # Allow Date to be compared with Time by converting to DateTime and relying on the <=> from there. + def compare_with_coercion(other) + if other.is_a?(Time) + self.to_datetime <=> other + else + compare_without_coercion(other) + end + end + alias_method :compare_without_coercion, :<=> + alias_method :<=>, :compare_with_coercion end diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index 7f8b41d218..77b5d8d227 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -2,7 +2,6 @@ require 'active_support/core_ext/object/to_json' require 'active_support/core_ext/module/delegation' -require 'active_support/json/variable' require 'bigdecimal' require 'active_support/core_ext/big_decimal/conversions' # for #to_s diff --git a/activesupport/lib/active_support/json/variable.rb b/activesupport/lib/active_support/json/variable.rb deleted file mode 100644 index d69dab6408..0000000000 --- a/activesupport/lib/active_support/json/variable.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'active_support/deprecation' - -module ActiveSupport - module JSON - # Deprecated: A string that returns itself as its JSON-encoded form. - class Variable < String - def initialize(*args) - message = 'ActiveSupport::JSON::Variable is deprecated and will be removed in Rails 4.1. ' \ - 'For your own custom JSON literals, define #as_json and #encode_json yourself.' - ActiveSupport::Deprecation.warn message - super - end - - def as_json(options = nil) self end #:nodoc: - def encode_json(encoder) self end #:nodoc: - end - end -end diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index b124ae184d..2f27aff2bd 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -4,7 +4,6 @@ require 'active_support/testing/tagged_logging' require 'active_support/testing/setup_and_teardown' require 'active_support/testing/assertions' require 'active_support/testing/deprecation' -require 'active_support/testing/pending' require 'active_support/testing/declarative' require 'active_support/testing/isolation' require 'active_support/testing/constant_lookup' @@ -54,7 +53,6 @@ module ActiveSupport include ActiveSupport::Testing::SetupAndTeardown include ActiveSupport::Testing::Assertions include ActiveSupport::Testing::Deprecation - include ActiveSupport::Testing::Pending extend ActiveSupport::Testing::Declarative # test/unit backwards compatibility methods diff --git a/activesupport/lib/active_support/testing/pending.rb b/activesupport/lib/active_support/testing/pending.rb deleted file mode 100644 index b04bbbbaea..0000000000 --- a/activesupport/lib/active_support/testing/pending.rb +++ /dev/null @@ -1,14 +0,0 @@ -require 'active_support/deprecation' - -module ActiveSupport - module Testing - module Pending # :nodoc: - unless defined?(Spec) - def pending(description = "", &block) - ActiveSupport::Deprecation.warn("#pending is deprecated and will be removed in Rails 4.1, please use #skip instead.") - skip(description.blank? ? nil : description) - end - end - end - end -end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index b1adf6d396..aa5e4461fd 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -48,6 +48,10 @@ class DateExtCalculationsTest < ActiveSupport::TestCase end end + def test_compare_to_time + assert Date.yesterday < Time.now + end + def test_to_datetime assert_equal DateTime.civil(2005, 2, 21), Date.new(2005, 2, 21).to_datetime assert_equal 0, Date.new(2005, 2, 21).to_datetime.offset # use UTC offset diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb index 14f4366f7b..ed1326705c 100644 --- a/activesupport/test/json/encoding_test.rb +++ b/activesupport/test/json/encoding_test.rb @@ -96,13 +96,6 @@ class TestJSONEncoding < ActiveSupport::TestCase end end - def test_json_variable - assert_deprecated do - assert_equal ActiveSupport::JSON::Variable.new('foo'), 'foo' - assert_equal ActiveSupport::JSON::Variable.new('alert("foo")'), 'alert("foo")' - end - end - def test_hash_encoding assert_equal %({\"a\":\"b\"}), ActiveSupport::JSON.encode(:a => :b) assert_equal %({\"a\":1}), ActiveSupport::JSON.encode('a' => 1) diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb deleted file mode 100644 index 08df67827e..0000000000 --- a/activesupport/test/test_case_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'abstract_unit' - -module ActiveSupport - class TestCaseTest < ActiveSupport::TestCase - def test_pending_deprecation - assert_deprecated do - pending "should use #skip instead" - end - end - end -end diff --git a/activesupport/test/ts_isolated.rb b/activesupport/test/ts_isolated.rb deleted file mode 100644 index 294d6595f7..0000000000 --- a/activesupport/test/ts_isolated.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'active_support/testing/autorun' -require 'active_support/test_case' -require 'rbconfig' -require 'active_support/core_ext/kernel/reporting' - -class TestIsolated < ActiveSupport::TestCase - ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) - - Dir["#{File.dirname(__FILE__)}/**/*_test.rb"].each do |file| - define_method("test #{file}") do - command = "#{ruby} -Ilib:test #{file}" - result = silence_stderr { `#{command}` } - assert $?.to_i.zero?, "#{command}\n#{result}" - end - end -end diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index 6c3e763f53..5a1594102a 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -24,22 +24,63 @@ TIP: Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails. Ruby Enterp ### HTTP PATCH -Rails 4 now uses `PATCH` as the primary HTTP verb for updates. When a resource -is declared in `config/routes.rb`: +Rails 4 now uses `PATCH` as the primary HTTP verb for updates when a RESTful +resource is declared in `config/routes.rb`. The `update` action is still used, +and `PUT` requests will continue to be routed to the `update` action as well. +So, if you're using only the standard RESTful routes, no changes need to be made: ```ruby resources :users ``` -the action in `UsersController` to update a user is still `update`. +```erb +<%= form_for @user do |f| %> +``` + +```ruby +class UsersController < ApplicationController + def update + # No change needed; PATCH will be preferred, and PUT will still work. + end +end +``` + +However, you will need to make a change if you are using `form_for` to update +a resource in conjunction with a custom route using the `PUT` HTTP method: + +```ruby +resources :users, do + put :update_name, on: :member +end +``` + +```erb +<%= form_for [ :update_name, @user ] do |f| %> +``` + +```ruby +class UsersController < ApplicationController + def update_name + # Change needed; form_for will try to use a non-existant PATCH route. + end +end +``` -`PUT` requests to `/users/:id` in Rails 4 get routed to `update` as they are -today. So, if you have an API that gets real PUT requests it is going to work. -The router also routes `PATCH` requests to `/users/:id` to the `update` action. +If the action is not being used in a public API and you are free to change the +HTTP method, you can update your route to use `patch` instead of `put`: -So, in Rails 4 both `PUT` and `PATCH` are routed to update. We recommend -switching to `PATCH` as part of your upgrade process if possible, as it's more -likely what you want. +```ruby +resources :users do + patch :update_name, on: :member +end +``` + +If the action is being used in a public API and you can't change to HTTP method +being used, you can update your form to use the `PUT` method instead: + +```erb +<%= form_for [ :update_name, @user ], method: :put do |f| %> +``` For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/) on the Rails blog. diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index e3119ecf22..87d6505ed5 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -63,6 +63,9 @@ module Rails puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}" puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}" puts "=> Run `rails server -h` for more startup options" + if options[:Host].to_s.match(/0\.0\.0\.0/) + puts "=> Notice: server is listening on all interfaces (#{options[:Host]}). Consider using 127.0.0.1 (--binding option)" + end trap(:INT) { exit } puts "=> Ctrl-C to shutdown server" unless options[:daemonize] diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt index 6899dfe9c9..8b91313e51 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt @@ -7,7 +7,8 @@ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // -// stub path allows dependency to be excluded from the asset bundle. +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. // <% unless options[:skip_javascript] -%> //= require <%= options[:javascript] %> diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js b/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js index f84de00fd3..5bc2e1c8b5 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js +++ b/railties/lib/rails/generators/rails/plugin_new/templates/rails/javascripts.js @@ -7,6 +7,7 @@ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // -// stub path allows dependency to be excluded from the asset bundle. +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. // //= require_tree . diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb index ab1ebe1f8c..75180ff978 100644 --- a/railties/lib/rails/test_unit/railtie.rb +++ b/railties/lib/rails/test_unit/railtie.rb @@ -1,4 +1,4 @@ -if defined?(Rake) && Rake.application.top_level_tasks.grep(/^(default$|test(:|$))/).any? +if defined?(Rake.application) && Rake.application.top_level_tasks.grep(/^(default$|test(:|$))/).any? ENV['RAILS_ENV'] ||= 'test' end diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 6703f8df51..cfa5cc1322 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -151,6 +151,19 @@ module ApplicationTests assert_equal "Prefix Verb URI Pattern Controller#Action\ncart GET /cart(.:format) cart#show\n", output end + def test_rake_routes_with_controller_environment + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + get '/cart', to: 'cart#show' + get '/basketball', to: 'basketball#index' + end + RUBY + + ENV['CONTROLLER'] = 'cart' + output = Dir.chdir(app_path){ `rake routes` } + assert_equal "Prefix Verb URI Pattern Controller#Action\ncart GET /cart(.:format) cart#show\n", output + end + def test_rake_routes_displays_message_when_no_routes_are_defined app_file "config/routes.rb", <<-RUBY AppTemplate::Application.routes.draw do |