From b50e88ebdf375cf81ad63586ce4599979262f975 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sat, 28 Nov 2015 16:32:24 +0900 Subject: Make `assert_recognizes` to traverse mounted engines Before this commit paths of mounted engines are not traversed when `assert_recognizes` is called, causing strange test results. This commit enable to traverse mounted paths. --- actionpack/CHANGELOG.md | 4 ++ actionpack/lib/action_dispatch/routing/endpoint.rb | 10 +-- .../lib/action_dispatch/routing/inspector.rb | 4 +- .../lib/action_dispatch/routing/route_set.rb | 7 +++ .../test/dispatch/routing_assertions_test.rb | 71 ++++++++++++++++++++++ 5 files changed, 90 insertions(+), 6 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 370e3a1958..7eb56e596e 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,7 @@ +* Make `assert_recognizes` to traverse mounted engines + + *Yuichiro Kaneko* + * Add extension synonyms `yml` and `yaml` for MIME type `application/x-yaml`. *bogdanvlviv* diff --git a/actionpack/lib/action_dispatch/routing/endpoint.rb b/actionpack/lib/action_dispatch/routing/endpoint.rb index 88aa13c3e8..819305615e 100644 --- a/actionpack/lib/action_dispatch/routing/endpoint.rb +++ b/actionpack/lib/action_dispatch/routing/endpoint.rb @@ -1,10 +1,12 @@ module ActionDispatch module Routing class Endpoint # :nodoc: - def dispatcher?; false; end - def redirect?; false; end - def matches?(req); true; end - def app; self; end + def dispatcher?; false; end + def redirect?; false; end + def engine?; rack_app.respond_to?(:routes); end + def matches?(req); true; end + def app; self; end + def rack_app; app; end end end end diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb index 5d30a545a2..4e859fbac3 100644 --- a/actionpack/lib/action_dispatch/routing/inspector.rb +++ b/actionpack/lib/action_dispatch/routing/inspector.rb @@ -13,7 +13,7 @@ module ActionDispatch end def rack_app - app.app + app.rack_app end def path @@ -45,7 +45,7 @@ module ActionDispatch end def engine? - rack_app.respond_to?(:routes) + app.engine? end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 16237bd564..d8df247068 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -751,6 +751,10 @@ module ActionDispatch end req = make_request(env) + recognize_path_with_request(req, path, extras) + end + + def recognize_path_with_request(req, path, extras) @router.recognize(req) do |route, params| params.merge!(extras) params.each do |key, value| @@ -770,6 +774,9 @@ module ActionDispatch end return req.path_parameters + elsif app.matches?(req) && app.engine? + path_parameters = app.rack_app.routes.recognize_path_with_request(req, path, extras) + return path_parameters end end diff --git a/actionpack/test/dispatch/routing_assertions_test.rb b/actionpack/test/dispatch/routing_assertions_test.rb index 56ea644f22..111d5d637f 100644 --- a/actionpack/test/dispatch/routing_assertions_test.rb +++ b/actionpack/test/dispatch/routing_assertions_test.rb @@ -1,13 +1,39 @@ require 'abstract_unit' +require 'rails/engine' require 'controller/fake_controllers' class SecureArticlesController < ArticlesController; end class BlockArticlesController < ArticlesController; end class QueryArticlesController < ArticlesController; end +class SecureBooksController < BooksController; end +class BlockBooksController < BooksController; end +class QueryBooksController < BooksController; end + class RoutingAssertionsTest < ActionController::TestCase def setup + engine = Class.new(Rails::Engine) do + def self.name + "blog_engine" + end + end + engine.routes.draw do + resources :books + + scope 'secure', :constraints => { :protocol => 'https://' } do + resources :books, :controller => 'secure_books' + end + + scope 'block', :constraints => lambda { |r| r.ssl? } do + resources :books, :controller => 'block_books' + end + + scope 'query', :constraints => lambda { |r| r.params[:use_query] == 'true' } do + resources :books, :controller => 'query_books' + end + end + @routes = ActionDispatch::Routing::RouteSet.new @routes.draw do resources :articles @@ -23,6 +49,8 @@ class RoutingAssertionsTest < ActionController::TestCase scope 'query', :constraints => lambda { |r| r.params[:use_query] == 'true' } do resources :articles, :controller => 'query_articles' end + + mount engine => "/shelf" end end @@ -82,6 +110,49 @@ class RoutingAssertionsTest < ActionController::TestCase assert_match err.message, "This is a really bad msg" end + def test_assert_recognizes_with_engine + assert_recognizes({ :controller => 'books', :action => 'index' }, '/shelf/books') + assert_recognizes({ :controller => 'books', :action => 'show', :id => '1' }, '/shelf/books/1') + end + + def test_assert_recognizes_with_engine_and_extras + assert_recognizes({ :controller => 'books', :action => 'index', :page => '1' }, '/shelf/books', { :page => '1' }) + end + + def test_assert_recognizes_with_engine_and_method + assert_recognizes({ :controller => 'books', :action => 'create' }, { :path => '/shelf/books', :method => :post }) + assert_recognizes({ :controller => 'books', :action => 'update', :id => '1' }, { :path => '/shelf/books/1', :method => :put }) + end + + def test_assert_recognizes_with_engine_and_hash_constraint + assert_raise(Assertion) do + assert_recognizes({ :controller => 'secure_books', :action => 'index' }, 'http://test.host/shelf/secure/books') + end + assert_recognizes({ :controller => 'secure_books', :action => 'index', :protocol => 'https://' }, 'https://test.host/shelf/secure/books') + end + + def test_assert_recognizes_with_engine_and_block_constraint + assert_raise(Assertion) do + assert_recognizes({ :controller => 'block_books', :action => 'index' }, 'http://test.host/shelf/block/books') + end + assert_recognizes({ :controller => 'block_books', :action => 'index' }, 'https://test.host/shelf/block/books') + end + + def test_assert_recognizes_with_engine_and_query_constraint + assert_raise(Assertion) do + assert_recognizes({ :controller => 'query_books', :action => 'index', :use_query => 'false' }, '/shelf/query/books', { :use_query => 'false' }) + end + assert_recognizes({ :controller => 'query_books', :action => 'index', :use_query => 'true' }, '/shelf/query/books', { :use_query => 'true' }) + end + + def test_assert_recognizes_raises_message_with_engine + err = assert_raise(Assertion) do + assert_recognizes({ :controller => 'secure_books', :action => 'index' }, 'http://test.host/shelf/secure/books', {}, "This is a really bad msg") + end + + assert_match err.message, "This is a really bad msg" + end + def test_assert_routing assert_routing('/articles', :controller => 'articles', :action => 'index') end -- cgit v1.2.3 From 61ac2167eff741bffb44aec231f4ea13d004134e Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Sat, 16 Sep 2017 17:33:53 +0300 Subject: Allows pass argument for `Time#prev_day` and `Time#next_day` --- activesupport/CHANGELOG.md | 27 ++++++++++++++++++++++ .../core_ext/date_and_time/calculations.rb | 12 +++++----- .../test/core_ext/date_and_time_behavior.rb | 10 ++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 8e8e9b9440..435c863025 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,30 @@ +* Add same method signature for `Time#prev_day` and `Time#next_day` + in accordance with `Date#prev_day`, `Date#next_day`. + + Allows pass argument for `Time#prev_day` and `Time#next_day`. + + Before: + ``` + Time.new(2017, 9, 16, 17, 0).prev_day # => 2017-09-15 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).prev_day(1) + # => ArgumentError: wrong number of arguments (given 1, expected 0) + + Time.new(2017, 9, 16, 17, 0).next_day # => 2017-09-17 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).next_day(1) + # => ArgumentError: wrong number of arguments (given 1, expected 0) + ``` + + After: + ``` + Time.new(2017, 9, 16, 17, 0).prev_day # => 2017-09-15 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).prev_day(1) # => 2017-09-15 17:00:00 +0300 + + Time.new(2017, 9, 16, 17, 0).next_day # => 2017-09-17 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).next_day(1) # => 2017-09-17 17:00:00 +0300 + ``` + + *bogdanvlviv* + * `IO#to_json` now returns the `to_s` representation, rather than attempting to convert to an array. This fixes a bug where `IO#to_json` would raise an `IOError` when called on an unreadable object. diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb index 265c6949e1..9b5477b199 100644 --- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb @@ -20,9 +20,9 @@ module DateAndTime advance(days: -1) end - # Returns a new date/time representing the previous day. - def prev_day - advance(days: -1) + # Returns a new date/time the specified number of days ago. + def prev_day(days = 1) + advance(days: -days) end # Returns a new date/time representing tomorrow. @@ -30,9 +30,9 @@ module DateAndTime advance(days: 1) end - # Returns a new date/time representing the next day. - def next_day - advance(days: 1) + # Returns a new date/time the specified number of days in the future. + def next_day(days = 1) + advance(days: days) end # Returns true if the date/time is today. diff --git a/activesupport/test/core_ext/date_and_time_behavior.rb b/activesupport/test/core_ext/date_and_time_behavior.rb index 256353c309..438eb8b755 100644 --- a/activesupport/test/core_ext/date_and_time_behavior.rb +++ b/activesupport/test/core_ext/date_and_time_behavior.rb @@ -9,6 +9,11 @@ module DateAndTimeBehavior end def test_prev_day + assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-2) + assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(0) + assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(1) + assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day(2) assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_day assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2005, 3, 2, 10, 10, 10).prev_day.prev_day end @@ -19,6 +24,11 @@ module DateAndTimeBehavior end def test_next_day + assert_equal date_time_init(2005, 2, 20, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-2) + assert_equal date_time_init(2005, 2, 21, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(0) + assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(1) + assert_equal date_time_init(2005, 2, 24, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day(2) assert_equal date_time_init(2005, 2, 23, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_day assert_equal date_time_init(2005, 3, 2, 10, 10, 10), date_time_init(2005, 2, 28, 10, 10, 10).next_day.next_day end -- cgit v1.2.3 From f2c1e3a793570584d9708aaee387214bc3543530 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Sat, 16 Sep 2017 18:36:49 +0300 Subject: Allows pass argument for `Time#prev_month` and `Time#next_month` --- activesupport/CHANGELOG.md | 27 ++++++++++++++++++++++ .../core_ext/date_and_time/calculations.rb | 14 +++++++---- .../test/core_ext/date_and_time_behavior.rb | 24 +++++++++++++++++++ activesupport/test/core_ext/date_ext_test.rb | 4 ---- activesupport/test/core_ext/date_time_ext_test.rb | 4 ---- activesupport/test/core_ext/time_ext_test.rb | 4 ---- guides/source/active_support_core_extensions.md | 12 ++++++---- 7 files changed, 67 insertions(+), 22 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 435c863025..14435649cd 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,30 @@ +* Add same method signature for `Time#prev_month` and `Time#next_month` + in accordance with `Date#prev_month`, `Date#next_month`. + + Allows pass argument for `Time#prev_month` and `Time#next_month`. + + Before: + ``` + Time.new(2017, 9, 16, 17, 0).prev_month # => 2017-08-16 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).prev_month(1) + # => ArgumentError: wrong number of arguments (given 1, expected 0) + + Time.new(2017, 9, 16, 17, 0).next_month # => 2017-10-16 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).next_month(1) + # => ArgumentError: wrong number of arguments (given 1, expected 0) + ``` + + After: + ``` + Time.new(2017, 9, 16, 17, 0).prev_month # => 2017-08-16 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).prev_month(1) # => 2017-08-16 17:00:00 +0300 + + Time.new(2017, 9, 16, 17, 0).next_month # => 2017-10-16 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).next_month(1) # => 2017-10-16 17:00:00 +0300 + ``` + + *bogdanvlviv* + * Add same method signature for `Time#prev_day` and `Time#next_day` in accordance with `Date#prev_day`, `Date#next_day`. diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb index 9b5477b199..59c87b9c06 100644 --- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb @@ -188,9 +188,9 @@ module DateAndTime end end - # Short-hand for months_since(1). - def next_month - months_since(1) + # Returns a new date/time the specified number of months in the future. + def next_month(months = 1) + advance(months: months) end # Short-hand for months_since(3) @@ -223,11 +223,15 @@ module DateAndTime end alias_method :last_weekday, :prev_weekday + # Returns a new date/time the specified number of months ago. + def prev_month(months = 1) + advance(months: -months) + end + # Short-hand for months_ago(1). - def prev_month + def last_month months_ago(1) end - alias_method :last_month, :prev_month # Short-hand for months_ago(3). def prev_quarter diff --git a/activesupport/test/core_ext/date_and_time_behavior.rb b/activesupport/test/core_ext/date_and_time_behavior.rb index 438eb8b755..091d5611d0 100644 --- a/activesupport/test/core_ext/date_and_time_behavior.rb +++ b/activesupport/test/core_ext/date_and_time_behavior.rb @@ -161,6 +161,16 @@ module DateAndTimeBehavior assert_equal date_time_init(2015, 1, 5, 15, 15, 10), date_time_init(2015, 1, 3, 15, 15, 10).next_weekday end + def test_next_month + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-2) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(0) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(1) + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month(2) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).next_month.next_month + end + def test_next_month_on_31st assert_equal date_time_init(2005, 9, 30, 15, 15, 10), date_time_init(2005, 8, 31, 15, 15, 10).next_month end @@ -213,6 +223,16 @@ module DateAndTimeBehavior assert_equal date_time_init(2015, 1, 2, 15, 15, 10), date_time_init(2015, 1, 4, 15, 15, 10).prev_weekday end + def test_prev_month + assert_equal date_time_init(2005, 4, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-2) + assert_equal date_time_init(2005, 3, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(-1) + assert_equal date_time_init(2005, 2, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(0) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(1) + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month(2) + assert_equal date_time_init(2005, 1, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month + assert_equal date_time_init(2004, 12, 22, 10, 10, 10), date_time_init(2005, 2, 22, 10, 10, 10).prev_month.prev_month + end + def test_prev_month_on_31st assert_equal date_time_init(2004, 2, 29, 10, 10, 10), date_time_init(2004, 3, 31, 10, 10, 10).prev_month end @@ -225,6 +245,10 @@ module DateAndTimeBehavior assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year end + def test_last_month_on_31st + assert_equal date_time_init(2004, 2, 29, 0, 0, 0), date_time_init(2004, 3, 31, 0, 0, 0).last_month + end + def test_days_to_week_start assert_equal 0, date_time_init(2011, 11, 01, 0, 0, 0).days_to_week_start(:tuesday) assert_equal 1, date_time_init(2011, 11, 02, 0, 0, 0).days_to_week_start(:tuesday) diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index b8672eac4b..1d05ac6157 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -185,10 +185,6 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(1582, 10, 18), Date.new(1582, 10, 4).next_week end - def test_last_month_on_31st - assert_equal Date.new(2004, 2, 29), Date.new(2004, 3, 31).last_month - end - def test_last_quarter_on_31st assert_equal Date.new(2004, 2, 29), Date.new(2004, 5, 31).last_quarter end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index a3c2018a31..a795ed0102 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -248,10 +248,6 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2016, 2, 29), DateTime.civil(2016, 3, 7).last_week end - def test_last_month_on_31st - assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 3, 31).last_month - end - def test_last_quarter_on_31st assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 5, 31).last_quarter end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index dc2f4c5ac7..b720e32022 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -664,10 +664,6 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end end - def test_last_month_on_31st - assert_equal Time.local(2004, 2, 29), Time.local(2004, 3, 31).last_month - end - def test_xmlschema_is_available assert_nothing_raised { Time.now.xmlschema } end diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index 54d3dec1c2..ae64ad93d6 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -3019,11 +3019,9 @@ Date.new(2000, 5, 31).next_month # => Fri, 30 Jun 2000 Date.new(2000, 1, 31).next_month # => Tue, 29 Feb 2000 ``` -`prev_month` is aliased to `last_month`. - ##### `prev_quarter`, `next_quarter` -Same as `prev_month` and `next_month`. It returns the date with the same day in the previous or next quarter: +`prev_quarter` and `next_quarter` return the date with the same day in the previous or next quarter: ```ruby t = Time.local(2010, 5, 8) # => Sat, 08 May 2010 @@ -3175,6 +3173,8 @@ Date.new(2010, 4, 30).months_ago(2) # => Sun, 28 Feb 2010 Date.new(2009, 12, 31).months_since(2) # => Sun, 28 Feb 2010 ``` +`last_month` is short-hand for `#months_ago(1)`. + ##### `weeks_ago` The method `weeks_ago` works analogously for weeks: @@ -3353,8 +3353,9 @@ months_ago months_since beginning_of_month (at_beginning_of_month) end_of_month (at_end_of_month) -prev_month (last_month) +prev_month next_month +last_month beginning_of_quarter (at_beginning_of_quarter) end_of_quarter (at_end_of_quarter) beginning_of_year (at_beginning_of_year) @@ -3541,8 +3542,9 @@ months_ago months_since beginning_of_month (at_beginning_of_month) end_of_month (at_end_of_month) -prev_month (last_month) +prev_month next_month +last_month beginning_of_quarter (at_beginning_of_quarter) end_of_quarter (at_end_of_quarter) beginning_of_year (at_beginning_of_year) -- cgit v1.2.3 From ee9d81837b5eba9d5ec869ae7601d7ffce763e3e Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Sat, 16 Sep 2017 19:06:45 +0300 Subject: Allows pass argument for `Time#prev_year` and `Time#next_year`. --- activesupport/CHANGELOG.md | 27 ++++++++++++++++++++++ .../core_ext/date_and_time/calculations.rb | 14 +++++++---- .../test/core_ext/date_and_time_behavior.rb | 16 +++++++++++++ activesupport/test/core_ext/date_ext_test.rb | 4 ---- activesupport/test/core_ext/date_time_ext_test.rb | 4 ---- activesupport/test/core_ext/time_ext_test.rb | 4 ---- guides/source/active_support_core_extensions.md | 10 ++++---- 7 files changed, 58 insertions(+), 21 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 14435649cd..d664bc2027 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,30 @@ +* Add same method signature for `Time#prev_year` and `Time#next_year` + in accordance with `Date#prev_year`, `Date#next_year`. + + Allows pass argument for `Time#prev_year` and `Time#next_year`. + + Before: + ``` + Time.new(2017, 9, 16, 17, 0).prev_year # => 2016-09-16 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).prev_year(1) + # => ArgumentError: wrong number of arguments (given 1, expected 0) + + Time.new(2017, 9, 16, 17, 0).next_year # => 2018-09-16 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).next_year(1) + # => ArgumentError: wrong number of arguments (given 1, expected 0) + ``` + + After: + ``` + Time.new(2017, 9, 16, 17, 0).prev_year # => 2016-09-16 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).prev_year(1) # => 2016-09-16 17:00:00 +0300 + + Time.new(2017, 9, 16, 17, 0).next_year # => 2018-09-16 17:00:00 +0300 + Time.new(2017, 9, 16, 17, 0).next_year(1) # => 2018-09-16 17:00:00 +0300 + ``` + + *bogdanvlviv* + * Add same method signature for `Time#prev_month` and `Time#next_month` in accordance with `Date#prev_month`, `Date#next_month`. diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb index 59c87b9c06..061b79e098 100644 --- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb @@ -198,9 +198,9 @@ module DateAndTime months_since(3) end - # Short-hand for years_since(1). - def next_year - years_since(1) + # Returns a new date/time the specified number of years in the future. + def next_year(years = 1) + advance(years: years) end # Returns a new date/time representing the given day in the previous week. @@ -239,11 +239,15 @@ module DateAndTime end alias_method :last_quarter, :prev_quarter + # Returns a new date/time the specified number of years ago. + def prev_year(years = 1) + advance(years: -years) + end + # Short-hand for years_ago(1). - def prev_year + def last_year years_ago(1) end - alias_method :last_year, :prev_year # Returns the number of days to the start of the week on the given day. # Week is assumed to start on +start_day+, default is diff --git a/activesupport/test/core_ext/date_and_time_behavior.rb b/activesupport/test/core_ext/date_and_time_behavior.rb index 091d5611d0..42da6f6cd0 100644 --- a/activesupport/test/core_ext/date_and_time_behavior.rb +++ b/activesupport/test/core_ext/date_and_time_behavior.rb @@ -180,7 +180,13 @@ module DateAndTimeBehavior end def test_next_year + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-2) + assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(-1) + assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(0) + assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(1) + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year(2) assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).next_year.next_year end def test_prev_week @@ -242,13 +248,23 @@ module DateAndTimeBehavior end def test_prev_year + assert_equal date_time_init(2007, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(-2) + assert_equal date_time_init(2006, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(-1) + assert_equal date_time_init(2005, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(0) + assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(1) + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year(2) assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year + assert_equal date_time_init(2003, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).prev_year.prev_year end def test_last_month_on_31st assert_equal date_time_init(2004, 2, 29, 0, 0, 0), date_time_init(2004, 3, 31, 0, 0, 0).last_month end + def test_last_year + assert_equal date_time_init(2004, 6, 5, 10, 0, 0), date_time_init(2005, 6, 5, 10, 0, 0).last_year + end + def test_days_to_week_start assert_equal 0, date_time_init(2011, 11, 01, 0, 0, 0).days_to_week_start(:tuesday) assert_equal 1, date_time_init(2011, 11, 02, 0, 0, 0).days_to_week_start(:tuesday) diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index 1d05ac6157..0c6f3f595a 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -120,10 +120,6 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(1582, 10, 4), Date.new(1583, 10, 14).prev_year end - def test_last_year - assert_equal Date.new(2004, 6, 5), Date.new(2005, 6, 5).last_year - end - def test_last_year_in_leap_years assert_equal Date.new(1999, 2, 28), Date.new(2000, 2, 29).last_year end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index a795ed0102..d942cddb2a 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -162,10 +162,6 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2005, 4, 30, 23, 59, Rational(59999999999, 1000000000)), DateTime.civil(2005, 4, 20, 10, 10, 10).end_of_month end - def test_last_year - assert_equal DateTime.civil(2004, 6, 5, 10), DateTime.civil(2005, 6, 5, 10, 0, 0).last_year - end - def test_ago assert_equal DateTime.civil(2005, 2, 22, 10, 10, 9), DateTime.civil(2005, 2, 22, 10, 10, 10).ago(1) assert_equal DateTime.civil(2005, 2, 22, 9, 10, 10), DateTime.civil(2005, 2, 22, 10, 10, 10).ago(3600) diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index b720e32022..8cb17df01b 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -178,10 +178,6 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2005, 2, 4, 19, 30, 59, Rational(999999999, 1000)), Time.local(2005, 2, 4, 19, 30, 10).end_of_minute end - def test_last_year - assert_equal Time.local(2004, 6, 5, 10), Time.local(2005, 6, 5, 10, 0, 0).last_year - end - def test_ago assert_equal Time.local(2005, 2, 22, 10, 10, 9), Time.local(2005, 2, 22, 10, 10, 10).ago(1) assert_equal Time.local(2005, 2, 22, 9, 10, 10), Time.local(2005, 2, 22, 10, 10, 10).ago(3600) diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index ae64ad93d6..a80fd5dcc1 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -2998,8 +2998,6 @@ d.prev_year # => Sun, 28 Feb 1999 d.next_year # => Wed, 28 Feb 2001 ``` -`prev_year` is aliased to `last_year`. - ##### `prev_month`, `next_month` In Ruby 1.9 `prev_month` and `next_month` return the date with the same day in the last or next month: @@ -3157,6 +3155,8 @@ Date.new(2012, 2, 29).years_ago(3) # => Sat, 28 Feb 2009 Date.new(2012, 2, 29).years_since(3) # => Sat, 28 Feb 2015 ``` +`last_year` is short-hand for `#years_ago(1)`. + ##### `months_ago`, `months_since` The methods `months_ago` and `months_since` work analogously for months: @@ -3362,7 +3362,8 @@ beginning_of_year (at_beginning_of_year) end_of_year (at_end_of_year) years_ago years_since -prev_year (last_year) +prev_year +last_year next_year on_weekday? on_weekend? @@ -3551,7 +3552,8 @@ beginning_of_year (at_beginning_of_year) end_of_year (at_end_of_year) years_ago years_since -prev_year (last_year) +prev_year +last_year next_year on_weekday? on_weekend? -- cgit v1.2.3 From 97ee3dc788b0f596e182313dd32cb876e01fc2e9 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Sat, 16 Sep 2017 21:24:53 +0300 Subject: Update "Active Support Core Extensions" guide --- guides/source/active_support_core_extensions.md | 188 ++++++++++++------------ 1 file changed, 97 insertions(+), 91 deletions(-) diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index a80fd5dcc1..66d2fbd939 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -2970,6 +2970,32 @@ Extensions to `Date` NOTE: All the following methods are defined in `active_support/core_ext/date/calculations.rb`. +```ruby +yesterday +tomorrow +beginning_of_week (at_beginning_of_week) +end_of_week (at_end_of_week) +monday +sunday +weeks_ago +prev_week (last_week) +next_week +months_ago +months_since +beginning_of_month (at_beginning_of_month) +end_of_month (at_end_of_month) +last_month +beginning_of_quarter (at_beginning_of_quarter) +end_of_quarter (at_end_of_quarter) +beginning_of_year (at_beginning_of_year) +end_of_year (at_end_of_year) +years_ago +years_since +last_year +on_weekday? +on_weekend? +``` + INFO: The following calculation methods have edge cases in October 1582, since days 5..14 just do not exist. This guide does not document their behavior around those days for brevity, but it is enough to say that they do what you would expect. That is, `Date.new(1582, 10, 4).tomorrow` returns `Date.new(1582, 10, 15)` and so on. Please check `test/core_ext/date_ext_test.rb` in the Active Support test suite for expected behavior. #### `Date.current` @@ -2980,64 +3006,6 @@ When making Date comparisons using methods which honor the user time zone, make #### Named dates -##### `prev_year`, `next_year` - -In Ruby 1.9 `prev_year` and `next_year` return a date with the same day/month in the last or next year: - -```ruby -d = Date.new(2010, 5, 8) # => Sat, 08 May 2010 -d.prev_year # => Fri, 08 May 2009 -d.next_year # => Sun, 08 May 2011 -``` - -If date is the 29th of February of a leap year, you obtain the 28th: - -```ruby -d = Date.new(2000, 2, 29) # => Tue, 29 Feb 2000 -d.prev_year # => Sun, 28 Feb 1999 -d.next_year # => Wed, 28 Feb 2001 -``` - -##### `prev_month`, `next_month` - -In Ruby 1.9 `prev_month` and `next_month` return the date with the same day in the last or next month: - -```ruby -d = Date.new(2010, 5, 8) # => Sat, 08 May 2010 -d.prev_month # => Thu, 08 Apr 2010 -d.next_month # => Tue, 08 Jun 2010 -``` - -If such a day does not exist, the last day of the corresponding month is returned: - -```ruby -Date.new(2000, 5, 31).prev_month # => Sun, 30 Apr 2000 -Date.new(2000, 3, 31).prev_month # => Tue, 29 Feb 2000 -Date.new(2000, 5, 31).next_month # => Fri, 30 Jun 2000 -Date.new(2000, 1, 31).next_month # => Tue, 29 Feb 2000 -``` - -##### `prev_quarter`, `next_quarter` - -`prev_quarter` and `next_quarter` return the date with the same day in the previous or next quarter: - -```ruby -t = Time.local(2010, 5, 8) # => Sat, 08 May 2010 -t.prev_quarter # => Mon, 08 Feb 2010 -t.next_quarter # => Sun, 08 Aug 2010 -``` - -If such a day does not exist, the last day of the corresponding month is returned: - -```ruby -Time.local(2000, 7, 31).prev_quarter # => Sun, 30 Apr 2000 -Time.local(2000, 5, 31).prev_quarter # => Tue, 29 Feb 2000 -Time.local(2000, 10, 31).prev_quarter # => Mon, 30 Oct 2000 -Time.local(2000, 11, 31).next_quarter # => Wed, 28 Feb 2001 -``` - -`prev_quarter` is aliased to `last_quarter`. - ##### `beginning_of_week`, `end_of_week` The methods `beginning_of_week` and `end_of_week` return the dates for the @@ -3337,37 +3305,7 @@ WARNING: `DateTime` is not aware of DST rules and so some of these methods have NOTE: All the following methods are defined in `active_support/core_ext/date_time/calculations.rb`. -The class `DateTime` is a subclass of `Date` so by loading `active_support/core_ext/date/calculations.rb` you inherit these methods and their aliases, except that they will always return datetimes: - -```ruby -yesterday -tomorrow -beginning_of_week (at_beginning_of_week) -end_of_week (at_end_of_week) -monday -sunday -weeks_ago -prev_week (last_week) -next_week -months_ago -months_since -beginning_of_month (at_beginning_of_month) -end_of_month (at_end_of_month) -prev_month -next_month -last_month -beginning_of_quarter (at_beginning_of_quarter) -end_of_quarter (at_end_of_quarter) -beginning_of_year (at_beginning_of_year) -end_of_year (at_end_of_year) -years_ago -years_since -prev_year -last_year -next_year -on_weekday? -on_weekend? -``` +The class `DateTime` is a subclass of `Date` so by loading `active_support/core_ext/date/calculations.rb` you inherit these methods and their aliases, except that they will always return datetimes. The following methods are reimplemented so you do **not** need to load `active_support/core_ext/date/calculations.rb` for these ones: @@ -3515,8 +3453,6 @@ Extensions to `Time` NOTE: All the following methods are defined in `active_support/core_ext/time/calculations.rb`. -Active Support adds to `Time` many of the methods available for `DateTime`: - ```ruby past? today? @@ -3528,6 +3464,8 @@ change advance ago since (in) +prev_day +next_day beginning_of_day (midnight, at_midnight, at_beginning_of_day) end_of_day beginning_of_hour (at_beginning_of_hour) @@ -3611,6 +3549,74 @@ now.all_year # => Fri, 01 Jan 2010 00:00:00 UTC +00:00..Fri, 31 Dec 2010 23:59:59 UTC +00:00 ``` +#### `prev_day`, `next_day` + +In Ruby 1.9 `prev_day` and `next_day` return the date in the last or next day: + +```ruby +d = Date.new(2010, 5, 8) # => Sat, 08 May 2010 +d.prev_day # => Fri, 07 May 2010 +d.next_day # => Sun, 09 May 2010 +``` + +#### `prev_month`, `next_month` + +In Ruby 1.9 `prev_month` and `next_month` return the date with the same day in the last or next month: + +```ruby +d = Date.new(2010, 5, 8) # => Sat, 08 May 2010 +d.prev_month # => Thu, 08 Apr 2010 +d.next_month # => Tue, 08 Jun 2010 +``` + +If such a day does not exist, the last day of the corresponding month is returned: + +```ruby +Date.new(2000, 5, 31).prev_month # => Sun, 30 Apr 2000 +Date.new(2000, 3, 31).prev_month # => Tue, 29 Feb 2000 +Date.new(2000, 5, 31).next_month # => Fri, 30 Jun 2000 +Date.new(2000, 1, 31).next_month # => Tue, 29 Feb 2000 +``` + +#### `prev_year`, `next_year` + +In Ruby 1.9 `prev_year` and `next_year` return a date with the same day/month in the last or next year: + +```ruby +d = Date.new(2010, 5, 8) # => Sat, 08 May 2010 +d.prev_year # => Fri, 08 May 2009 +d.next_year # => Sun, 08 May 2011 +``` + +If date is the 29th of February of a leap year, you obtain the 28th: + +```ruby +d = Date.new(2000, 2, 29) # => Tue, 29 Feb 2000 +d.prev_year # => Sun, 28 Feb 1999 +d.next_year # => Wed, 28 Feb 2001 +``` + +#### `prev_quarter`, `next_quarter` + +`prev_quarter` and `next_quarter` return the date with the same day in the previous or next quarter: + +```ruby +t = Time.local(2010, 5, 8) # => 2010-05-08 00:00:00 +0300 +t.prev_quarter # => 2010-02-08 00:00:00 +0200 +t.next_quarter # => 2010-08-08 00:00:00 +0300 +``` + +If such a day does not exist, the last day of the corresponding month is returned: + +```ruby +Time.local(2000, 7, 31).prev_quarter # => 2000-04-30 00:00:00 +0300 +Time.local(2000, 5, 31).prev_quarter # => 2000-02-29 00:00:00 +0200 +Time.local(2000, 10, 31).prev_quarter # => 2000-07-31 00:00:00 +0300 +Time.local(2000, 11, 31).next_quarter # => 2001-03-01 00:00:00 +0200 +``` + +`prev_quarter` is aliased to `last_quarter`. + ### Time Constructors Active Support defines `Time.current` to be `Time.zone.now` if there's a user time zone defined, with fallback to `Time.now`: -- cgit v1.2.3 From f5f0b49b9b233f85664d7a464c18afb2f3f10692 Mon Sep 17 00:00:00 2001 From: Dillon Welch Date: Thu, 26 Oct 2017 18:17:38 -0700 Subject: Prevent extra string allocations when no 'rel' arg passed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do a check if the 'rel' argument is passed in, and simply set it to 'nofollow' if 'rel' was not passed in. This prevents three string allocations for each call to `link_to` in that scenario. In the scenario where the 'rel' argument is passed in, performance is around the same as before as the `key?` check is very fast. ```ruby begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end gemfile(true) do source "https://rubygems.org" gem "benchmark-ips" gem "rails" end def allocate_count GC.disable before = ObjectSpace.count_objects yield after = ObjectSpace.count_objects after.each { |k,v| after[k] = v - before[k] } after[:T_HASH] -= 1 # probe effect - we created the before hash. GC.enable result = after.reject { |k,v| v == 0 } GC.start result end @hash = {} def master_version "#{@hash['rel'.freeze]} nofollow".lstrip end def fast_version if @hash.key?('rel'.freeze) "#{@hash["rel"]} nofollow".lstrip else "nofollow".freeze end end puts 'no rel key' puts "master_version" puts allocate_count { 1000.times { master_version } } puts "fast_version" puts allocate_count { 1000.times { fast_version } } Benchmark.ips do |x| x.report("master_version") { master_version } x.report("fast_version") { fast_version } x.compare! end puts 'rel key' @hash['rel'] = 'hi'.freeze puts "master_version" puts allocate_count { 1000.times { master_version } } puts "fast_version" puts allocate_count { 1000.times { fast_version } } Benchmark.ips do |x| x.report("master_version") { master_version } x.report("fast_version") { fast_version } x.compare! end ``` ``` no rel key master_version {:FREE=>-2791, :T_STRING=>3052} fast_version {:FREE=>-1} Warming up -------------------------------------- master_version 80.324k i/100ms fast_version 200.262k i/100ms Calculating ------------------------------------- master_version 2.049M (±11.9%) i/s - 10.121M in 5.025613s fast_version 6.645M (±21.3%) i/s - 29.439M in 5.007488s Comparison: fast_version: 6644506.3 i/s master_version: 2048833.0 i/s - 3.24x slower rel key master_version {:FREE=>-2001, :T_STRING=>2000} fast_version {:FREE=>-2001, :T_STRING=>2000} Warming up -------------------------------------- master_version 155.673k i/100ms fast_version 106.515k i/100ms Calculating ------------------------------------- master_version 2.652M (±20.4%) i/s - 12.610M in 5.036494s fast_version 2.237M (±16.8%) i/s - 10.865M in 5.035366s Comparison: master_version: 2651702.2 i/s fast_version: 2237470.6 i/s - same-ish: difference falls within error ``` --- actionview/lib/action_view/helpers/url_helper.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb index efda549c0d..4e436433c4 100644 --- a/actionview/lib/action_view/helpers/url_helper.rb +++ b/actionview/lib/action_view/helpers/url_helper.rb @@ -589,10 +589,14 @@ module ActionView end def add_method_to_attributes!(html_options, method) - if method && method.to_s.downcase != "get".freeze && html_options["rel".freeze] !~ /nofollow/ - html_options["rel".freeze] = "#{html_options["rel".freeze]} nofollow".lstrip + if method && method.to_s.downcase != "get" && html_options["rel"] !~ /nofollow/ + if html_options.key?("rel") + html_options["rel"] = "#{html_options["rel"]} nofollow".lstrip + else + html_options["rel"] = "nofollow" + end end - html_options["data-method".freeze] = method + html_options["data-method"] = method end def token_tag(token = nil, form_options: {}) -- cgit v1.2.3 From 23d5d5830690a8d22f0fe3762a8399a1f8a6d069 Mon Sep 17 00:00:00 2001 From: Aditya Kapoor Date: Wed, 1 Nov 2017 12:00:17 +0530 Subject: [ci skip] show the correct example to demonstrate inflections. --- activesupport/lib/active_support/inflector/transliterate.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb index 9801f1d118..e689f0718e 100644 --- a/activesupport/lib/active_support/inflector/transliterate.rb +++ b/activesupport/lib/active_support/inflector/transliterate.rb @@ -76,13 +76,19 @@ module ActiveSupport # To use a custom separator, override the `separator` argument. # # parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth" - # parameterize("^trés|Jolie-- ", separator: '_') # => "tres_jolie" + # parameterize("^trés|Jolie__ ", separator: '_') # => "tres_jolie" # # To preserve the case of the characters in a string, use the `preserve_case` argument. # # parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth" # parameterize("^trés|Jolie-- ", preserve_case: true) # => "tres-Jolie" # + # It preserves dashes and underscores unless they are used as separators: + # + # parameterize("^trés|Jolie__ ") # => "tres-jolie__" + # parameterize("^trés|Jolie-- ", separator: "_") # => "tres_jolie--" + # parameterize("^trés_Jolie-- ", separator: ".") # => "tres_jolie--" + # def parameterize(string, separator: "-", preserve_case: false) # Replace accented chars with their ASCII equivalents. parameterized_string = transliterate(string) -- cgit v1.2.3 From d404e2cbe9e078d286c7acb13fd18fb3c04a3f4f Mon Sep 17 00:00:00 2001 From: Dillon Welch Date: Thu, 2 Nov 2017 14:50:38 -0700 Subject: Use blank? check instead of key? check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to prevent an extra string allocation when there is a rel argument and performs better/within error of the key check for other scenarios such as passing in rel: nil ```ruby begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end gemfile(true) do source "https://rubygems.org" gem "benchmark-ips" gem "rails" end def allocate_count GC.disable before = ObjectSpace.count_objects yield after = ObjectSpace.count_objects after.each { |k,v| after[k] = v - before[k] } after[:T_HASH] -= 1 # probe effect - we created the before hash. GC.enable result = after.reject { |k,v| v == 0 } GC.start result end @hash = {} def master_version "#{@hash["rel"]} nofollow".lstrip end def key_version if @hash.key?("rel") "#{@hash["rel"]} nofollow".lstrip else "nofollow" end end def present_version if @hash["rel"].present? "#{@hash["rel"]} nofollow" else "nofollow".freeze end end def nil_version if @hash["rel"].nil? "nofollow".freeze else "#{@hash["rel"]} nofollow" end end def blank_version if @hash["rel"].blank? "nofollow".freeze else "#{@hash["rel"]} nofollow" end end def test puts "master_version" puts allocate_count { 1000.times { master_version } } puts "key_version" puts allocate_count { 1000.times { key_version } } puts "present_version" puts allocate_count { 1000.times { present_version } } puts "nil_version" puts allocate_count { 1000.times { nil_version } } puts "blank_version" puts allocate_count { 1000.times { blank_version } } Benchmark.ips do |x| x.report("master_version") { master_version } x.report("key_version") { key_version } x.report("present_version") { present_version } x.report("nil_version") { nil_version } x.report("blank_version") { blank_version } x.compare! end end puts 'no rel key' test puts 'rel key with real stuff' @hash['rel'] = 'hi'.freeze test puts 'rel key with nil' @hash['rel'] = nil test puts 'rel key with ""' @hash['rel'] = "" test ``` ``` no rel key master_version {:FREE=>-2818, :T_STRING=>3052} key_version {:FREE=>-1} present_version {:FREE=>-1} nil_version {:FREE=>-1} blank_version {:FREE=>-1} Warming up -------------------------------------- master_version 124.677k i/100ms key_version 227.992k i/100ms present_version 208.068k i/100ms nil_version 235.272k i/100ms blank_version 176.274k i/100ms Calculating ------------------------------------- master_version 1.968M (±10.8%) i/s - 9.725M in 5.010763s key_version 7.734M (±11.2%) i/s - 38.075M in 5.001613s present_version 5.688M (±11.4%) i/s - 28.089M in 5.019560s nil_version 6.965M (±10.2%) i/s - 34.585M in 5.024806s blank_version 6.139M (±18.7%) i/s - 29.085M in 5.010919s Comparison: key_version: 7734058.3 i/s nil_version: 6965050.2 i/s - same-ish: difference falls within error blank_version: 6138744.3 i/s - same-ish: difference falls within error present_version: 5688248.4 i/s - 1.36x slower master_version: 1967932.3 i/s - 3.93x slower rel key with real stuff master_version {:FREE=>-2001, :T_STRING=>2000} key_version {:FREE=>-2001, :T_STRING=>2000} present_version {:FREE=>-1001, :T_STRING=>1000} nil_version {:FREE=>-1002, :T_STRING=>1000, :T_IMEMO=>1} blank_version {:FREE=>-1001, :T_STRING=>1000} Warming up -------------------------------------- master_version 93.351k i/100ms key_version 89.747k i/100ms present_version 91.963k i/100ms nil_version 103.370k i/100ms blank_version 74.845k i/100ms Calculating ------------------------------------- master_version 2.179M (±21.4%) i/s - 10.362M in 5.044668s key_version 2.345M (± 9.8%) i/s - 11.667M in 5.030982s present_version 1.738M (±14.8%) i/s - 8.553M in 5.056406s nil_version 2.485M (±19.1%) i/s - 11.888M in 5.015940s blank_version 1.951M (±12.3%) i/s - 9.580M in 5.011932s Comparison: nil_version: 2484704.1 i/s key_version: 2344664.8 i/s - same-ish: difference falls within error master_version: 2178975.8 i/s - same-ish: difference falls within error blank_version: 1950532.0 i/s - same-ish: difference falls within error present_version: 1737866.7 i/s - 1.43x slower rel key with nil master_version {:FREE=>-3001, :T_STRING=>3000} key_version {:FREE=>-3001, :T_STRING=>3000} present_version {:FREE=>-1} nil_version {:FREE=>-1} blank_version {:FREE=>-1} Warming up -------------------------------------- master_version 112.655k i/100ms key_version 105.048k i/100ms present_version 136.219k i/100ms nil_version 192.026k i/100ms blank_version 184.846k i/100ms Calculating ------------------------------------- master_version 1.893M (±12.6%) i/s - 9.238M in 5.002621s key_version 1.672M (±13.5%) i/s - 8.194M in 5.021197s present_version 4.484M (±20.5%) i/s - 21.114M in 5.002982s nil_version 5.294M (±18.1%) i/s - 25.155M in 5.020721s blank_version 5.588M (± 6.7%) i/s - 27.912M in 5.019305s Comparison: blank_version: 5588489.6 i/s nil_version: 5293929.9 i/s - same-ish: difference falls within error present_version: 4484493.7 i/s - same-ish: difference falls within error master_version: 1892919.0 i/s - 2.95x slower key_version: 1672343.9 i/s - 3.34x slower rel key with "" master_version {:FREE=>-2001, :T_STRING=>2000} key_version {:FREE=>-2001, :T_STRING=>2000} present_version {:FREE=>-1} nil_version {:FREE=>-1001, :T_STRING=>1000} blank_version {:FREE=>-1} Warming up -------------------------------------- master_version 140.499k i/100ms key_version 124.738k i/100ms present_version 186.659k i/100ms nil_version 148.063k i/100ms blank_version 178.707k i/100ms Calculating ------------------------------------- master_version 1.826M (±24.2%) i/s - 8.289M in 5.026603s key_version 1.561M (±15.3%) i/s - 7.609M in 5.005662s present_version 3.622M (±19.9%) i/s - 17.173M in 5.042217s nil_version 2.438M (±11.5%) i/s - 12.141M in 5.053335s blank_version 4.911M (±15.5%) i/s - 23.768M in 5.009106s Comparison: blank_version: 4910741.1 i/s present_version: 3622183.5 i/s - same-ish: difference falls within error nil_version: 2437606.2 i/s - 2.01x slower master_version: 1825652.2 i/s - 2.69x slower key_version: 1560530.5 i/s - 3.15x slower ``` --- actionview/lib/action_view/helpers/url_helper.rb | 6 +- test.rb | 110 +++++++++++++++++++++++ 2 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 test.rb diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb index 4e436433c4..71fed39351 100644 --- a/actionview/lib/action_view/helpers/url_helper.rb +++ b/actionview/lib/action_view/helpers/url_helper.rb @@ -590,10 +590,10 @@ module ActionView def add_method_to_attributes!(html_options, method) if method && method.to_s.downcase != "get" && html_options["rel"] !~ /nofollow/ - if html_options.key?("rel") - html_options["rel"] = "#{html_options["rel"]} nofollow".lstrip - else + if html_options.("rel").blank? html_options["rel"] = "nofollow" + else + html_options["rel"] = "#{html_options["rel"]} nofollow" end end html_options["data-method"] = method diff --git a/test.rb b/test.rb new file mode 100644 index 0000000000..3d5e508fa7 --- /dev/null +++ b/test.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true +begin + require "bundler/inline" +rescue LoadError => e + $stderr.puts "Bundler version 1.10 or later is required. Please update + your Bundler" + raise e +end + +gemfile(true) do + source "https://rubygems.org" + + gem "benchmark-ips" + gem "rails" +end + +def allocate_count + GC.disable + before = ObjectSpace.count_objects + yield + after = ObjectSpace.count_objects + after.each { |k,v| after[k] = v - before[k] } + after[:T_HASH] -= 1 # probe effect - we created the before hash. + GC.enable + result = after.reject { |k,v| v == 0 } + GC.start + result +end + +@hash = {} + +def master_version + "#{@hash["rel"]} nofollow".lstrip +end + +def key_version + if @hash.key?("rel") + "#{@hash["rel"]} nofollow".lstrip + else + "nofollow" + end +end + +def present_version + if @hash["rel"].present? + "#{@hash["rel"]} nofollow" + else + "nofollow".freeze + end +end + +def nil_version + if @hash["rel"].nil? + "nofollow".freeze + else + "#{@hash["rel"]} nofollow" + end +end + +def blank_version + if @hash["rel"].blank? + "nofollow".freeze + else + "#{@hash["rel"]} nofollow" + end +end + +def test + puts "master_version" + puts allocate_count { 1000.times { master_version } } + puts "key_version" + puts allocate_count { 1000.times { key_version } } + puts "present_version" + puts allocate_count { 1000.times { present_version } } + puts "nil_version" + puts allocate_count { 1000.times { nil_version } } + puts "blank_version" + puts allocate_count { 1000.times { blank_version } } + + Benchmark.ips do |x| + x.report("master_version") { master_version } + x.report("key_version") { key_version } + x.report("present_version") { present_version } + x.report("nil_version") { nil_version } + x.report("blank_version") { blank_version } + x.compare! + end +end + +puts 'no rel key' + +test + +puts 'rel key with real stuff' + +@hash['rel'] = 'hi'.freeze + +test + +puts 'rel key with nil' + +@hash['rel'] = nil + +test + +puts 'rel key with ""' + +@hash['rel'] = "" + +test -- cgit v1.2.3 From 019c8ae814d0e89af3da543a956f22a4db92c5a3 Mon Sep 17 00:00:00 2001 From: Dillon Welch Date: Thu, 2 Nov 2017 14:55:51 -0700 Subject: Remove test file --- test.rb | 110 ---------------------------------------------------------------- 1 file changed, 110 deletions(-) delete mode 100644 test.rb diff --git a/test.rb b/test.rb deleted file mode 100644 index 3d5e508fa7..0000000000 --- a/test.rb +++ /dev/null @@ -1,110 +0,0 @@ -# frozen_string_literal: true -begin - require "bundler/inline" -rescue LoadError => e - $stderr.puts "Bundler version 1.10 or later is required. Please update - your Bundler" - raise e -end - -gemfile(true) do - source "https://rubygems.org" - - gem "benchmark-ips" - gem "rails" -end - -def allocate_count - GC.disable - before = ObjectSpace.count_objects - yield - after = ObjectSpace.count_objects - after.each { |k,v| after[k] = v - before[k] } - after[:T_HASH] -= 1 # probe effect - we created the before hash. - GC.enable - result = after.reject { |k,v| v == 0 } - GC.start - result -end - -@hash = {} - -def master_version - "#{@hash["rel"]} nofollow".lstrip -end - -def key_version - if @hash.key?("rel") - "#{@hash["rel"]} nofollow".lstrip - else - "nofollow" - end -end - -def present_version - if @hash["rel"].present? - "#{@hash["rel"]} nofollow" - else - "nofollow".freeze - end -end - -def nil_version - if @hash["rel"].nil? - "nofollow".freeze - else - "#{@hash["rel"]} nofollow" - end -end - -def blank_version - if @hash["rel"].blank? - "nofollow".freeze - else - "#{@hash["rel"]} nofollow" - end -end - -def test - puts "master_version" - puts allocate_count { 1000.times { master_version } } - puts "key_version" - puts allocate_count { 1000.times { key_version } } - puts "present_version" - puts allocate_count { 1000.times { present_version } } - puts "nil_version" - puts allocate_count { 1000.times { nil_version } } - puts "blank_version" - puts allocate_count { 1000.times { blank_version } } - - Benchmark.ips do |x| - x.report("master_version") { master_version } - x.report("key_version") { key_version } - x.report("present_version") { present_version } - x.report("nil_version") { nil_version } - x.report("blank_version") { blank_version } - x.compare! - end -end - -puts 'no rel key' - -test - -puts 'rel key with real stuff' - -@hash['rel'] = 'hi'.freeze - -test - -puts 'rel key with nil' - -@hash['rel'] = nil - -test - -puts 'rel key with ""' - -@hash['rel'] = "" - -test -- cgit v1.2.3 From ec13ef75260f6d143e947b0e5176e35e4c1229c2 Mon Sep 17 00:00:00 2001 From: Dillon Welch Date: Thu, 2 Nov 2017 17:54:54 -0700 Subject: Fix typo --- actionview/lib/action_view/helpers/url_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb index 71fed39351..9900e0cd03 100644 --- a/actionview/lib/action_view/helpers/url_helper.rb +++ b/actionview/lib/action_view/helpers/url_helper.rb @@ -590,7 +590,7 @@ module ActionView def add_method_to_attributes!(html_options, method) if method && method.to_s.downcase != "get" && html_options["rel"] !~ /nofollow/ - if html_options.("rel").blank? + if html_options["rel"].blank? html_options["rel"] = "nofollow" else html_options["rel"] = "#{html_options["rel"]} nofollow" -- cgit v1.2.3 From 0d7ab973e15b476ed42471395027e329f95c8951 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Fri, 3 Nov 2017 10:09:43 +0900 Subject: Remove unused classes * `HasManyThroughCantDissociateNewRecords` and `HasManyThroughCantAssociateNewRecords` are no longer used since f6b12c1. * `ReadOnlyAssociation` is no longer used since 0da426b. --- activerecord/lib/active_record/associations.rb | 30 -------------------------- 1 file changed, 30 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index bc7e288500..661605d3e5 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -140,26 +140,6 @@ module ActiveRecord class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc: end - class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc: - def initialize(owner = nil, reflection = nil) - if owner && reflection - super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.") - else - super("Cannot associate new records.") - end - end - end - - class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc: - def initialize(owner = nil, reflection = nil) - if owner && reflection - super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.") - else - super("Cannot dissociate new records.") - end - end - end - class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc: def initialize(owner = nil, reflection = nil) if owner && reflection @@ -189,16 +169,6 @@ module ActiveRecord end end - class ReadOnlyAssociation < ActiveRecordError #:nodoc: - def initialize(reflection = nil) - if reflection - super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.") - else - super("Read-only reflection error.") - end - end - end - # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations # (has_many, has_one) when there is at least 1 child associated instance. # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project -- cgit v1.2.3 From b106242f52272c4a5ced7a0e9d1dcb1b50542501 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Fri, 3 Nov 2017 15:24:45 +0900 Subject: Specify bundler version in template files We have already specified to install `bundler` 1.15.4 in `.travis.yml`. https://github.com/rails/rails/blob/master/.travis.yml#L31..L32 However, `bundler` 1.16.0 may be used in the test. https://travis-ci.org/rails/rails/jobs/296582467#L2208 The test failed due to this influence. In order to avoid this, specifying `bundler` version in bug report templates. --- guides/bug_report_templates/action_controller_master.rb | 2 ++ guides/bug_report_templates/active_job_master.rb | 2 ++ guides/bug_report_templates/active_record_master.rb | 2 ++ guides/bug_report_templates/active_record_migrations_master.rb | 2 ++ guides/bug_report_templates/benchmark.rb | 2 ++ guides/bug_report_templates/generic_master.rb | 2 ++ 6 files changed, 12 insertions(+) diff --git a/guides/bug_report_templates/action_controller_master.rb b/guides/bug_report_templates/action_controller_master.rb index cf76de80d2..932d329943 100644 --- a/guides/bug_report_templates/action_controller_master.rb +++ b/guides/bug_report_templates/action_controller_master.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +gem "bundler", "< 1.16" + begin require "bundler/inline" rescue LoadError => e diff --git a/guides/bug_report_templates/active_job_master.rb b/guides/bug_report_templates/active_job_master.rb index ce480cbb52..36d9137b71 100644 --- a/guides/bug_report_templates/active_job_master.rb +++ b/guides/bug_report_templates/active_job_master.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +gem "bundler", "< 1.16" + begin require "bundler/inline" rescue LoadError => e diff --git a/guides/bug_report_templates/active_record_master.rb b/guides/bug_report_templates/active_record_master.rb index 78411e2d57..b66deb36f3 100644 --- a/guides/bug_report_templates/active_record_master.rb +++ b/guides/bug_report_templates/active_record_master.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +gem "bundler", "< 1.16" + begin require "bundler/inline" rescue LoadError => e diff --git a/guides/bug_report_templates/active_record_migrations_master.rb b/guides/bug_report_templates/active_record_migrations_master.rb index fce8d1d848..737ce66d7b 100644 --- a/guides/bug_report_templates/active_record_migrations_master.rb +++ b/guides/bug_report_templates/active_record_migrations_master.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +gem "bundler", "< 1.16" + begin require "bundler/inline" rescue LoadError => e diff --git a/guides/bug_report_templates/benchmark.rb b/guides/bug_report_templates/benchmark.rb index fb51273e3e..f5c88086a9 100644 --- a/guides/bug_report_templates/benchmark.rb +++ b/guides/bug_report_templates/benchmark.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +gem "bundler", "< 1.16" + begin require "bundler/inline" rescue LoadError => e diff --git a/guides/bug_report_templates/generic_master.rb b/guides/bug_report_templates/generic_master.rb index 384c8b1833..240571ba9a 100644 --- a/guides/bug_report_templates/generic_master.rb +++ b/guides/bug_report_templates/generic_master.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +gem "bundler", "< 1.16" + begin require "bundler/inline" rescue LoadError => e -- cgit v1.2.3 From 288fbc7ff47b6aae0d5bab978ae16858a425f643 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 3 Nov 2017 23:41:35 +0900 Subject: Revert "Merge pull request #31025 from y-yagi/follow_up_31023_part2" This reverts commit 6f481e05bb24fe3589ef0f65e97a9b1fa66ae0f7, reversing changes made to 592f790b7693c0a32cd06d5e8201639923a734c5. In favor of #31039. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ffb2e33282..e357a0ca3e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,6 @@ bundler_args: --without test --jobs 3 --retry 3 before_install: - "rm ${BUNDLE_GEMFILE}.lock" - "travis_retry gem update --system" - - "rvm @global do gem uninstall bundler --all --ignore-dependencies --executables || true" - "travis_retry gem install bundler -v 1.15.4" - "[ -f /tmp/beanstalkd-1.10/Makefile ] || (curl -L https://github.com/kr/beanstalkd/archive/v1.10.tar.gz | tar xz -C /tmp)" - "pushd /tmp/beanstalkd-1.10 && make && (./beanstalkd &); popd" -- cgit v1.2.3 From 9ec67362054e874ed905310a79b670941fa397af Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Fri, 3 Nov 2017 11:29:21 -0400 Subject: Permit configuring Active Storage's job queue --- activestorage/app/jobs/active_storage/analyze_job.rb | 2 +- activestorage/app/jobs/active_storage/base_job.rb | 5 +++++ activestorage/app/jobs/active_storage/purge_job.rb | 2 +- activestorage/lib/active_storage.rb | 1 + activestorage/lib/active_storage/engine.rb | 19 +++++-------------- 5 files changed, 13 insertions(+), 16 deletions(-) create mode 100644 activestorage/app/jobs/active_storage/base_job.rb diff --git a/activestorage/app/jobs/active_storage/analyze_job.rb b/activestorage/app/jobs/active_storage/analyze_job.rb index a11a73d030..2a952f9f74 100644 --- a/activestorage/app/jobs/active_storage/analyze_job.rb +++ b/activestorage/app/jobs/active_storage/analyze_job.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Provides asynchronous analysis of ActiveStorage::Blob records via ActiveStorage::Blob#analyze_later. -class ActiveStorage::AnalyzeJob < ActiveJob::Base +class ActiveStorage::AnalyzeJob < ActiveStorage::BaseJob def perform(blob) blob.analyze end diff --git a/activestorage/app/jobs/active_storage/base_job.rb b/activestorage/app/jobs/active_storage/base_job.rb new file mode 100644 index 0000000000..6caab42a2d --- /dev/null +++ b/activestorage/app/jobs/active_storage/base_job.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class ActiveStorage::BaseJob < ActiveJob::Base + queue_as { ActiveStorage.queue } +end diff --git a/activestorage/app/jobs/active_storage/purge_job.rb b/activestorage/app/jobs/active_storage/purge_job.rb index 188840f702..98874d2250 100644 --- a/activestorage/app/jobs/active_storage/purge_job.rb +++ b/activestorage/app/jobs/active_storage/purge_job.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Provides asynchronous purging of ActiveStorage::Blob records via ActiveStorage::Blob#purge_later. -class ActiveStorage::PurgeJob < ActiveJob::Base +class ActiveStorage::PurgeJob < ActiveStorage::BaseJob # FIXME: Limit this to a custom ActiveStorage error retry_on StandardError diff --git a/activestorage/lib/active_storage.rb b/activestorage/lib/active_storage.rb index cfdb2a8acd..d1ff6b7032 100644 --- a/activestorage/lib/active_storage.rb +++ b/activestorage/lib/active_storage.rb @@ -38,6 +38,7 @@ module ActiveStorage mattr_accessor :logger mattr_accessor :verifier + mattr_accessor :queue mattr_accessor :previewers, default: [] mattr_accessor :analyzers, default: [] end diff --git a/activestorage/lib/active_storage/engine.rb b/activestorage/lib/active_storage/engine.rb index a01a14cd83..6cf6635c4f 100644 --- a/activestorage/lib/active_storage/engine.rb +++ b/activestorage/lib/active_storage/engine.rb @@ -19,9 +19,12 @@ module ActiveStorage config.eager_load_namespaces << ActiveStorage - initializer "active_storage.logger" do + initializer "active_storage.configs" do config.after_initialize do |app| - ActiveStorage.logger = app.config.active_storage.logger || Rails.logger + ActiveStorage.logger = app.config.active_storage.logger || Rails.logger + ActiveStorage.queue = app.config.active_storage.queue + ActiveStorage.previewers = app.config.active_storage.previewers || [] + ActiveStorage.analyzers = app.config.active_storage.analyzers || [] end end @@ -65,17 +68,5 @@ module ActiveStorage end end end - - initializer "active_storage.previewers" do - config.after_initialize do |app| - ActiveStorage.previewers = app.config.active_storage.previewers || [] - end - end - - initializer "active_storage.analyzers" do - config.after_initialize do |app| - ActiveStorage.analyzers = app.config.active_storage.analyzers || [] - end - end end end -- cgit v1.2.3 From 3812353845fa91bb500691aced10533730c07801 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Sat, 4 Nov 2017 00:38:44 +0400 Subject: Fix Capybara::Webkit::Driver#resize_window deprecation warning >[DEPRECATION] Capybara::Webkit::Driver#resize_window is deprecated. Please use Capybara::Window#resize_to instead. --- actionpack/lib/action_dispatch/system_testing/driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/system_testing/driver.rb b/actionpack/lib/action_dispatch/system_testing/driver.rb index 770fbde74e..7577d3e68a 100644 --- a/actionpack/lib/action_dispatch/system_testing/driver.rb +++ b/actionpack/lib/action_dispatch/system_testing/driver.rb @@ -59,7 +59,7 @@ module ActionDispatch def register_webkit(app) Capybara::Webkit::Driver.new(app, Capybara::Webkit::Configuration.to_hash.merge(@options)).tap do |driver| - driver.resize_window(*@screen_size) + driver.resize_window_to(*@screen_size) end end -- cgit v1.2.3 From 11f3f0377ba392c15a7fa6130be16db6318a2575 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Fri, 3 Nov 2017 23:33:55 +0000 Subject: Improve docs of ActionDispatch::Routing::Mapper --- actionpack/lib/action_dispatch/routing/mapper.rb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index dea8387c3d..ded42adee9 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -475,6 +475,16 @@ module ActionDispatch # # resources :users, param: :name # + # The +users+ resource here will have the following routes generated for it: + # + # GET /users(.:format) + # POST /users(.:format) + # GET /users/new(.:format) + # GET /users/:name/edit(.:format) + # GET /users/:name(.:format) + # PATCH/PUT /users/:name(.:format) + # DELETE /users/:name(.:format) + # # You can override ActiveRecord::Base#to_param of a related # model to construct a URL: # @@ -484,8 +494,8 @@ module ActionDispatch # end # end # - # user = User.find_by(name: 'Phusion') - # user_path(user) # => "/users/Phusion" + # user = User.find_by(name: 'Phusion') + # user_path(user) # => "/users/Phusion" # # [:path] # The path prefix for the routes. @@ -1265,7 +1275,7 @@ module ActionDispatch # POST /profile # # === Options - # Takes same options as +resources+. + # Takes same options as resources[rdoc-ref:#resources] def resource(*resources, &block) options = resources.extract_options!.dup @@ -1330,7 +1340,7 @@ module ActionDispatch # DELETE /photos/:photo_id/comments/:id # # === Options - # Takes same options as Base#match as well as: + # Takes same options as match[rdoc-ref:Base#match] as well as: # # [:path_names] # Allows you to change the segment component of the +edit+ and +new+ actions. -- cgit v1.2.3 From e20b049873ed6cdc53d99fe80bb0e292e17f30f5 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Fri, 3 Nov 2017 16:35:15 +0900 Subject: Remove unused `calculate_rounded_number` and `digit_count` These methods unused since 5533696. --- .../active_support/number_helper/number_to_rounded_converter.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb b/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb index b7ad76bb62..eb528a0583 100644 --- a/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb @@ -37,14 +37,6 @@ module ActiveSupport private - def calculate_rounded_number(multiplier) - (number / BigDecimal.new(multiplier.to_f.to_s)).round * multiplier - end - - def digit_count(number) - number.zero? ? 1 : (Math.log10(absolute_number(number)) + 1).floor - end - def strip_insignificant_zeros options[:strip_insignificant_zeros] end -- cgit v1.2.3 From 85cda0f6f349744b6f1452d5f1f6cf74ef694393 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sat, 4 Nov 2017 20:11:36 +0900 Subject: s/an/a/ --- railties/test/application/middleware/exceptions_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/application/middleware/exceptions_test.rb b/railties/test/application/middleware/exceptions_test.rb index 75afeec905..2d659ade8d 100644 --- a/railties/test/application/middleware/exceptions_test.rb +++ b/railties/test/application/middleware/exceptions_test.rb @@ -102,7 +102,7 @@ module ApplicationTests end end - test "routing to an nonexistent controller when action_dispatch.show_exceptions and consider_all_requests_local are set shows diagnostics" do + test "routing to a nonexistent controller when action_dispatch.show_exceptions and consider_all_requests_local are set shows diagnostics" do app_file "config/routes.rb", <<-RUBY Rails.application.routes.draw do resources :articles -- cgit v1.2.3 From 4dcb630c6eaf7e4d8e450b3e9f19e38ebbf41d8b Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Sun, 5 Nov 2017 13:37:21 +0900 Subject: Generate the correct path in nested scaffold generator Currently, namespaced scaffold generator will generate an incorrect path and the generated file will not work properly. ``` $ ./bin/rails g scaffold admin/user $ ./bin/rails db:migrate $ ./bin/rails t test/controllers # Running: E Error: Admin::UsersControllerTest#test_should_create_admin_user: NameError: undefined local variable or method `admin_admin_users_url' for # Did you mean? admin_users test/controllers/admin/users_controller_test.rb:20:in `block (2 levels) in ' test/controllers/admin/users_controller_test.rb:19:in `block in ' bin/rails test test/controllers/admin/users_controller_test.rb:18 ``` This is because combine `controller_class_path` and `singular_table_name` to generate route. https://github.com/rails/rails/blob/360698aa245b45349d1d1b12e1afb34759515e69/railties/lib/rails/generators/named_base.rb#L172 Normally, if using namspaced generator, table name already contains namespace. Therefore, adding `controller_class_path` adds extra namespace. Since it is special only when explicitly specifying `model-name`, it is modified to change the value only when `model-name`is specified. Follow up of #30729 --- railties/lib/rails/generators/named_base.rb | 18 +++++++++--------- railties/test/generators/named_base_test.rb | 22 ++++++++++++++++++++++ .../test/generators/scaffold_generator_test.rb | 9 ++++++++- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 44f5ab45d3..e0285835a8 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -158,26 +158,26 @@ module Rails def model_resource_name(prefix: "") # :doc: resource_name = "#{prefix}#{singular_table_name}" - if controller_class_path.empty? - resource_name - else + if options[:model_name] "[#{controller_class_path.map { |name| ":" + name }.join(", ")}, #{resource_name}]" + else + resource_name end end def singular_route_name # :doc: - if controller_class_path.empty? - singular_table_name - else + if options[:model_name] "#{controller_class_path.join('_')}_#{singular_table_name}" + else + singular_table_name end end def plural_route_name # :doc: - if controller_class_path.empty? - plural_table_name - else + if options[:model_name] "#{controller_class_path.join('_')}_#{plural_table_name}" + else + plural_table_name end end diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb index 967754c813..4e61b660d7 100644 --- a/railties/test/generators/named_base_test.rb +++ b/railties/test/generators/named_base_test.rb @@ -33,6 +33,17 @@ class NamedBaseTest < Rails::Generators::TestCase assert_name g, "foos", :plural_name assert_name g, "admin.foo", :i18n_scope assert_name g, "admin_foos", :table_name + assert_name g, "admin/foos", :controller_name + assert_name g, %w(admin), :controller_class_path + assert_name g, "Admin::Foos", :controller_class_name + assert_name g, "admin/foos", :controller_file_path + assert_name g, "foos", :controller_file_name + assert_name g, "admin.foos", :controller_i18n_scope + assert_name g, "admin_foo", :singular_route_name + assert_name g, "admin_foos", :plural_route_name + assert_name g, "@admin_foo", :redirect_resource_name + assert_name g, "admin_foo", :model_resource_name + assert_name g, "admin_foos", :index_helper end def test_named_generator_attributes_as_ruby @@ -47,6 +58,17 @@ class NamedBaseTest < Rails::Generators::TestCase assert_name g, "foos", :plural_name assert_name g, "admin.foo", :i18n_scope assert_name g, "admin_foos", :table_name + assert_name g, "Admin::Foos", :controller_name + assert_name g, %w(admin), :controller_class_path + assert_name g, "Admin::Foos", :controller_class_name + assert_name g, "admin/foos", :controller_file_path + assert_name g, "foos", :controller_file_name + assert_name g, "admin.foos", :controller_i18n_scope + assert_name g, "admin_foo", :singular_route_name + assert_name g, "admin_foos", :plural_route_name + assert_name g, "@admin_foo", :redirect_resource_name + assert_name g, "admin_foo", :model_resource_name + assert_name g, "admin_foos", :index_helper end def test_named_generator_attributes_without_pluralized diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index 03322c1c59..b6294c3b94 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -282,7 +282,14 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase /class Admin::RolesTest < ApplicationSystemTestCase/ # Views - %w(index edit new show _form).each do |view| + assert_file "app/views/admin/roles/index.html.erb" do |content| + assert_match("'Show', admin_role", content) + assert_match("'Edit', edit_admin_role_path(admin_role)", content) + assert_match("'Destroy', admin_role", content) + assert_match("'New Admin Role', new_admin_role_path", content) + end + + %w(edit new show _form).each do |view| assert_file "app/views/admin/roles/#{view}.html.erb" end assert_no_file "app/views/layouts/admin/roles.html.erb" -- cgit v1.2.3 From ab293293c33792621c90c02c5516a99e78460663 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Sun, 5 Nov 2017 21:23:05 +0900 Subject: Show `RequestForgeryProtection` methods in api doc [ci skip] Several methods of `RequestForgeryProtection` are not showed in the api doc even though `:doc:` is specified. (e.g. `form_authenticity_param`) http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html These methods are listed in the doc of v4.1. http://api.rubyonrails.org/v4.1/classes/ActionController/RequestForgeryProtection.html This is due to the influence of `:nodoc:` added in #18102, methods after `CROSS_ORIGIN_JAVASCRIPT_WARNING` not showed from the doc. Therefore, in order to show the method like originally, added `startdoc` after `CROSS_ORIGIN_JAVASCRIPT_WARNING`. --- actionpack/lib/action_controller/metal/request_forgery_protection.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index d6cd5fd9e0..bd133f24a1 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -248,6 +248,7 @@ module ActionController #:nodoc: "If you know what you're doing, go ahead and disable forgery " \ "protection on this action to permit cross-origin JavaScript embedding." private_constant :CROSS_ORIGIN_JAVASCRIPT_WARNING + # :startdoc: # If `verify_authenticity_token` was run (indicating that we have # forgery protection enabled for this request) then also verify that -- cgit v1.2.3 From e3a295664681ea0480a9c95f6bfc776a113ff926 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 1 Nov 2017 10:36:47 +0900 Subject: Ensure `apply_join_dependency` for `collection_cache_key` if eager-loading is needed Fixes #30315. --- activerecord/lib/active_record/collection_cache_key.rb | 3 +++ activerecord/lib/active_record/relation/calculations.rb | 4 ++-- activerecord/lib/active_record/relation/finder_methods.rb | 2 +- activerecord/test/cases/collection_cache_key_test.rb | 10 ++++++++++ activerecord/test/schema/schema.rb | 1 + 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/collection_cache_key.rb b/activerecord/lib/active_record/collection_cache_key.rb index f3e6516414..88b398ad45 100644 --- a/activerecord/lib/active_record/collection_cache_key.rb +++ b/activerecord/lib/active_record/collection_cache_key.rb @@ -12,6 +12,9 @@ module ActiveRecord timestamp = collection.max_by(×tamp_column)._read_attribute(timestamp_column) end else + if collection.eager_loading? + collection = collection.send(:apply_join_dependency) + end column_type = type_for_attribute(timestamp_column.to_s) column = connection.column_name_from_arel_node(collection.arel_attribute(timestamp_column)) select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp" diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 116bddce85..11256ab3d9 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -130,7 +130,7 @@ module ActiveRecord # end def calculate(operation, column_name) if has_include?(column_name) - relation = apply_join_dependency(construct_join_dependency) + relation = apply_join_dependency relation.distinct! if operation.to_s.downcase == "count" relation.calculate(operation, column_name) @@ -180,7 +180,7 @@ module ActiveRecord end if has_include?(column_names.first) - relation = apply_join_dependency(construct_join_dependency) + relation = apply_join_dependency relation.pluck(*column_names) else relation = spawn diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 707245bab2..18566b5662 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -394,7 +394,7 @@ module ActiveRecord ) end - def apply_join_dependency(join_dependency) + def apply_join_dependency(join_dependency = construct_join_dependency) relation = except(:includes, :eager_load, :preload).joins!(join_dependency) if using_limitable_reflections?(join_dependency.reflections) diff --git a/activerecord/test/cases/collection_cache_key_test.rb b/activerecord/test/cases/collection_cache_key_test.rb index c137693211..19d6464a22 100644 --- a/activerecord/test/cases/collection_cache_key_test.rb +++ b/activerecord/test/cases/collection_cache_key_test.rb @@ -73,6 +73,16 @@ module ActiveRecord assert_equal last_developer_timestamp.to_s(ActiveRecord::Base.cache_timestamp_format), $3 end + test "cache_key for relation with includes" do + comments = Comment.includes(:post).where("posts.type": "Post") + assert_match(/\Acomments\/query-(\h+)-(\d+)-(\d+)\z/, comments.cache_key) + end + + test "cache_key for loaded relation with includes" do + comments = Comment.includes(:post).where("posts.type": "Post").load + assert_match(/\Acomments\/query-(\h+)-(\d+)-(\d+)\z/, comments.cache_key) + end + test "it triggers at most one query" do developers = Developer.where(name: "David") diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 8f872c38ba..a4505a4892 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -191,6 +191,7 @@ ActiveRecord::Schema.define do t.string :resource_id t.string :resource_type t.integer :developer_id + t.datetime :updated_at t.datetime :deleted_at t.integer :comments end -- cgit v1.2.3 From 8a2ee3d8c6921ce34e597658e3f2b43b41423d1d Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 16 Oct 2017 01:33:40 +0900 Subject: Ensure `apply_join_dependency` for `update_all` and `delete_all` if eager-loading is needed If a relation has eager-loading values, `count` and `exists?` works properly, but `update_all` and `delete_all` doesn't work due to missing `apply_join_dependency`. It should be applied to work consistently. Fixes #28863. --- activerecord/lib/active_record/relation.rb | 10 ++++++ activerecord/test/cases/persistence_test.rb | 49 ++++++++++++++++++----------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 997cfe4b5e..7615fb6ee9 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -359,6 +359,11 @@ module ActiveRecord def update_all(updates) raise ArgumentError, "Empty list of attributes to change" if updates.blank? + if eager_loading? + relation = apply_join_dependency + return relation.update_all(updates) + end + stmt = Arel::UpdateManager.new stmt.set Arel.sql(@klass.send(:sanitize_sql_for_assignment, updates)) @@ -423,6 +428,11 @@ module ActiveRecord raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}") end + if eager_loading? + relation = apply_join_dependency + return relation.delete_all + end + stmt = Arel::DeleteManager.new stmt.from(table) diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 6cbe18cc8c..f088c064f5 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -94,27 +94,31 @@ class PersistenceTest < ActiveRecord::TestCase end def test_delete_all_with_joins_and_where_part_is_hash - where_args = { toys: { name: "Bone" } } - count = Pet.joins(:toys).where(where_args).count + pets = Pet.joins(:toys).where(toys: { name: "Bone" }) - assert_equal count, 1 - assert_equal count, Pet.joins(:toys).where(where_args).delete_all + assert_equal true, pets.exists? + assert_equal pets.count, pets.delete_all + end + + def test_delete_all_with_joins_and_where_part_is_not_hash + pets = Pet.joins(:toys).where("toys.name = ?", "Bone") + + assert_equal true, pets.exists? + assert_equal pets.count, pets.delete_all end def test_delete_all_with_left_joins - where_args = { toys: { name: "Bone" } } - count = Pet.left_joins(:toys).where(where_args).count + pets = Pet.left_joins(:toys).where(toys: { name: "Bone" }) - assert_equal count, 1 - assert_equal count, Pet.left_joins(:toys).where(where_args).delete_all + assert_equal true, pets.exists? + assert_equal pets.count, pets.delete_all end - def test_delete_all_with_joins_and_where_part_is_not_hash - where_args = ["toys.name = ?", "Bone"] - count = Pet.joins(:toys).where(where_args).count + def test_delete_all_with_includes + pets = Pet.includes(:toys).where(toys: { name: "Bone" }) - assert_equal count, 1 - assert_equal count, Pet.joins(:toys).where(where_args).delete_all + assert_equal true, pets.exists? + assert_equal pets.count, pets.delete_all end def test_increment_attribute @@ -496,17 +500,24 @@ class PersistenceTest < ActiveRecord::TestCase end def test_update_all_with_joins - where_args = { toys: { name: "Bone" } } - count = Pet.left_joins(:toys).where(where_args).count + pets = Pet.joins(:toys).where(toys: { name: "Bone" }) - assert_equal count, Pet.joins(:toys).where(where_args).update_all(name: "Bob") + assert_equal true, pets.exists? + assert_equal pets.count, pets.update_all(name: "Bob") end def test_update_all_with_left_joins - where_args = { toys: { name: "Bone" } } - count = Pet.left_joins(:toys).where(where_args).count + pets = Pet.left_joins(:toys).where(toys: { name: "Bone" }) + + assert_equal true, pets.exists? + assert_equal pets.count, pets.update_all(name: "Bob") + end + + def test_update_all_with_includes + pets = Pet.includes(:toys).where(toys: { name: "Bone" }) - assert_equal count, Pet.left_joins(:toys).where(where_args).update_all(name: "Bob") + assert_equal true, pets.exists? + assert_equal pets.count, pets.update_all(name: "Bob") end def test_update_all_with_non_standard_table_name -- cgit v1.2.3 From 7308991630af3fb8a2a7e2cde9fd322316153ec2 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Sun, 5 Nov 2017 19:19:41 +0000 Subject: Execute `ConfirmationValidator` validation when `_confirmation`'s value is `false` --- activemodel/CHANGELOG.md | 4 ++++ activemodel/lib/active_model/validations/confirmation.rb | 2 +- .../test/cases/validations/confirmation_validation_test.rb | 13 +++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 82e3a7f4dd..794744c646 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,7 @@ +* Execute `ConfirmationValidator` validation when `_confirmation`'s value is `false`. + + *bogdanvlviv* + * Allow passing a Proc or Symbol to length validator options. *Matt Rohrer* diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index 0abec56b68..1b5d5b09ab 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -9,7 +9,7 @@ module ActiveModel end def validate_each(record, attribute, value) - if (confirmed = record.send("#{attribute}_confirmation")) + unless (confirmed = record.send("#{attribute}_confirmation")).nil? unless confirmation_value_equal?(record, attribute, value, confirmed) human_attribute_name = record.class.human_attribute_name(attribute) record.errors.add(:"#{attribute}_confirmation", :confirmation, options.except(:case_sensitive).merge!(attribute: human_attribute_name)) diff --git a/activemodel/test/cases/validations/confirmation_validation_test.rb b/activemodel/test/cases/validations/confirmation_validation_test.rb index e84415a868..8b2c65289b 100644 --- a/activemodel/test/cases/validations/confirmation_validation_test.rb +++ b/activemodel/test/cases/validations/confirmation_validation_test.rb @@ -37,6 +37,19 @@ class ConfirmationValidationTest < ActiveModel::TestCase assert t.valid? end + def test_validates_confirmation_of_with_boolean_attribute + Topic.validates_confirmation_of(:approved) + + t = Topic.new(approved: true, approved_confirmation: nil) + assert t.valid? + + t.approved_confirmation = false + assert t.invalid? + + t.approved_confirmation = true + assert t.valid? + end + def test_validates_confirmation_of_for_ruby_class Person.validates_confirmation_of :karma -- cgit v1.2.3 From e617fb57f5a388d5f0a47fd5e576588dd10066b0 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 30 Oct 2017 23:55:48 +0900 Subject: Fix preloading polymorphic association when through association has already loaded If through association has already loaded, `source_type` is ignored to loaded through records. The loaded records should be filtered by `source_type` in that case. Fixes #30904. --- .../associations/preloader/through_association.rb | 20 ++++++++++++++++---- .../associations/nested_through_associations_test.rb | 11 +++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index fa32cc5553..5bd49b041a 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -13,18 +13,30 @@ module ActiveRecord end def associated_records_by_owner(preloader) + already_loaded = owners.first.association(through_reflection.name).loaded? through_scope = through_scope() - preloader.preload(owners, - through_reflection.name, - through_scope) + unless already_loaded + preloader.preload(owners, through_reflection.name, through_scope) + end through_records = owners.map do |owner| center = owner.association(through_reflection.name).target [owner, Array(center)] end - reset_association(owners, through_reflection.name, through_scope) + if already_loaded + if source_type = reflection.options[:source_type] + through_records.map! do |owner, center| + center = center.select do |record| + record[reflection.foreign_type] == source_type + end + [owner, center] + end + end + else + reset_association(owners, through_reflection.name, through_scope) + end middle_records = through_records.flat_map(&:last) diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index 4cf5a9ffc4..11ee45917f 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -579,6 +579,17 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase assert !c.post_taggings.empty? end + def test_polymorphic_has_many_through_when_through_association_has_already_loaded + cake_designer = CakeDesigner.create!(chef: Chef.new) + drink_designer = DrinkDesigner.create!(chef: Chef.new) + department = Department.create!(chefs: [cake_designer.chef, drink_designer.chef]) + Hotel.create!(departments: [department]) + hotel = Hotel.includes(:chefs, :cake_designers, :drink_designers).take + + assert_equal [cake_designer], hotel.cake_designers + assert_equal [drink_designer], hotel.drink_designers + end + def test_polymorphic_has_many_through_joined_different_table_twice cake_designer = CakeDesigner.create!(chef: Chef.new) drink_designer = DrinkDesigner.create!(chef: Chef.new) -- cgit v1.2.3 From e0bef22665f93e88f6b2f3ac6bd55543ed0d6343 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 6 Nov 2017 06:40:36 +0900 Subject: Fix preloading polymorphic multi-level through association This is partially fixed by e617fb57 when through association has already loaded. Otherwise, second level through association should respect `preload_scope`. Fixes #30242. Closes #30076. [Ryuta Kamizono & CicholGricenchos] --- .../associations/preloader/through_association.rb | 8 +++++++- .../cases/associations/nested_through_associations_test.rb | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index 5bd49b041a..b16fca7dc9 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -40,7 +40,11 @@ module ActiveRecord middle_records = through_records.flat_map(&:last) - reflection_scope = reflection_scope() if reflection.scope + if preload_scope + reflection_scope = reflection_scope().merge(preload_scope) + elsif reflection.scope + reflection_scope = reflection_scope() + end preloaders = preloader.preload(middle_records, source_reflection.name, @@ -70,6 +74,8 @@ module ActiveRecord rhs_records end end + end.tap do + reset_association(middle_records, source_reflection.name, preload_scope) end end diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index 11ee45917f..65d30d011b 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -579,6 +579,17 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase assert !c.post_taggings.empty? end + def test_polymorphic_has_many_through_when_through_association_has_not_loaded + cake_designer = CakeDesigner.create!(chef: Chef.new) + drink_designer = DrinkDesigner.create!(chef: Chef.new) + department = Department.create!(chefs: [cake_designer.chef, drink_designer.chef]) + Hotel.create!(departments: [department]) + hotel = Hotel.includes(:cake_designers, :drink_designers).take + + assert_equal [cake_designer], hotel.cake_designers + assert_equal [drink_designer], hotel.drink_designers + end + def test_polymorphic_has_many_through_when_through_association_has_already_loaded cake_designer = CakeDesigner.create!(chef: Chef.new) drink_designer = DrinkDesigner.create!(chef: Chef.new) -- cgit v1.2.3 From ffc1ed9bd54f3cf746f7ddf798e000fc025edef6 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Mon, 6 Nov 2017 08:29:40 +0900 Subject: `scoping` should respect current class and STI constraint (#29199) A relation includes `klass`, so it can not be used as it is if current class is different from `current_scope.klass`. It should be created new relation by current class to respect the klass and STI constraint. Fixes #17603. Fixes #23576. --- activerecord/lib/active_record/scoping/named.rb | 8 +++++++- activerecord/test/cases/scoping/relation_scoping_test.rb | 14 ++++++++++++++ activerecord/test/models/comment.rb | 4 ++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index 6fa096c1fe..310af72c41 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -24,8 +24,14 @@ module ActiveRecord # You can define a scope that applies to all finders using # {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope]. def all + current_scope = self.current_scope + if current_scope - current_scope.clone + if self == current_scope.klass + current_scope.clone + else + relation.merge!(current_scope) + end else default_scoped end diff --git a/activerecord/test/cases/scoping/relation_scoping_test.rb b/activerecord/test/cases/scoping/relation_scoping_test.rb index f3b84d88c2..116f8e83aa 100644 --- a/activerecord/test/cases/scoping/relation_scoping_test.rb +++ b/activerecord/test/cases/scoping/relation_scoping_test.rb @@ -240,6 +240,20 @@ class RelationScopingTest < ActiveRecord::TestCase assert_nil SpecialComment.current_scope end + def test_scoping_respects_current_class + Comment.unscoped do + assert_equal "a comment...", Comment.all.what_are_you + assert_equal "a special comment...", SpecialComment.all.what_are_you + end + end + + def test_scoping_respects_sti_constraint + Comment.unscoped do + assert_equal comments(:greetings), Comment.find(1) + assert_raises(ActiveRecord::RecordNotFound) { SpecialComment.find(1) } + end + end + def test_circular_joins_with_scoping_does_not_crash posts = Post.joins(comments: :post).scoping do Post.first(10) diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb index 740aa593ac..5ab433f2d9 100644 --- a/activerecord/test/models/comment.rb +++ b/activerecord/test/models/comment.rb @@ -60,6 +60,10 @@ end class SpecialComment < Comment default_scope { where(deleted_at: nil) } + + def self.what_are_you + "a special comment..." + end end class SubSpecialComment < SpecialComment -- cgit v1.2.3 From 8847e608b9a0f7a3f8d65832e1815b4ab1f021f3 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Mon, 6 Nov 2017 13:11:04 +0900 Subject: Explicitly pass window handle to `resize_window_to` Unlike `resize_window`, `resize_window_to` has three arguments. https://github.com/thoughtbot/capybara-webkit/blob/d63c3c8e3ae844f0c59359532a6dcb50f4a64d0a/lib/capybara/webkit/driver.rb#L135-L143 Therefore, if pass only width and height just like `resize_window`, `ArgumentError`will be raised. To prevent this, explicitly pass window handler. Follow up of #31046 --- actionpack/lib/action_dispatch/system_testing/driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/lib/action_dispatch/system_testing/driver.rb b/actionpack/lib/action_dispatch/system_testing/driver.rb index 7577d3e68a..2687772b4b 100644 --- a/actionpack/lib/action_dispatch/system_testing/driver.rb +++ b/actionpack/lib/action_dispatch/system_testing/driver.rb @@ -59,7 +59,7 @@ module ActionDispatch def register_webkit(app) Capybara::Webkit::Driver.new(app, Capybara::Webkit::Configuration.to_hash.merge(@options)).tap do |driver| - driver.resize_window_to(*@screen_size) + driver.resize_window_to(driver.current_window_handle, *@screen_size) end end -- cgit v1.2.3 From bb6d369f891963f8ed6ec3eeaaba3066c438aaee Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Mon, 6 Nov 2017 16:47:46 +0900 Subject: Remove unused require Since f182831, this file does not use methods added by `module/introspection`. --- railties/lib/rails/generators/named_base.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index e0285835a8..60625283ac 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "active_support/core_ext/module/introspection" require "rails/generators/base" require "rails/generators/generated_attribute" -- cgit v1.2.3 From afc188fd7600b62bb9b43cd41eb9b9ea4d77a2e2 Mon Sep 17 00:00:00 2001 From: Skander Date: Mon, 6 Nov 2017 04:54:25 -0500 Subject: Fix french spelling mistake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trés -> Très https://fr.wiktionary.org/wiki/tr%C3%A8s --- activesupport/lib/active_support/inflector/transliterate.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb index e689f0718e..9fb3a2e0af 100644 --- a/activesupport/lib/active_support/inflector/transliterate.rb +++ b/activesupport/lib/active_support/inflector/transliterate.rb @@ -71,23 +71,23 @@ module ActiveSupport # a 'pretty' URL. # # parameterize("Donald E. Knuth") # => "donald-e-knuth" - # parameterize("^trés|Jolie-- ") # => "tres-jolie" + # parameterize("^très|Jolie-- ") # => "tres-jolie" # # To use a custom separator, override the `separator` argument. # # parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth" - # parameterize("^trés|Jolie__ ", separator: '_') # => "tres_jolie" + # parameterize("^très|Jolie__ ", separator: '_') # => "tres_jolie" # # To preserve the case of the characters in a string, use the `preserve_case` argument. # # parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth" - # parameterize("^trés|Jolie-- ", preserve_case: true) # => "tres-Jolie" + # parameterize("^très|Jolie-- ", preserve_case: true) # => "tres-Jolie" # # It preserves dashes and underscores unless they are used as separators: # - # parameterize("^trés|Jolie__ ") # => "tres-jolie__" - # parameterize("^trés|Jolie-- ", separator: "_") # => "tres_jolie--" - # parameterize("^trés_Jolie-- ", separator: ".") # => "tres_jolie--" + # parameterize("^très|Jolie__ ") # => "tres-jolie__" + # parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--" + # parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--" # def parameterize(string, separator: "-", preserve_case: false) # Replace accented chars with their ASCII equivalents. -- cgit v1.2.3 From 0ddde0a8fca6a0ca3158e3329713959acd65605d Mon Sep 17 00:00:00 2001 From: Andrew White Date: Mon, 6 Nov 2017 14:46:42 +0000 Subject: Fix acronym support in `humanize` Acronym inflections are stored with lowercase keys in the hash but the match wasn't being lowercased before being looked up in the hash. This shouldn't have any performance impact because before it would fail to find the acronym and perform the `downcase` operation anyway. Fixes #31052. --- activesupport/CHANGELOG.md | 11 +++++++++++ activesupport/lib/active_support/inflector/methods.rb | 2 +- activesupport/test/inflector_test.rb | 13 +++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index d664bc2027..9c27c68919 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,14 @@ +* Fix acronym support in `humanize` + + Acronym inflections are stored with lowercase keys in the hash but + the match wasn't being lowercased before being looked up in the hash. + This shouldn't have any performance impact because before it would + fail to find the acronym and perform the `downcase` operation anyway. + + Fixes #31052. + + *Andrew White* + * Add same method signature for `Time#prev_year` and `Time#next_year` in accordance with `Date#prev_year`, `Date#next_year`. diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 72de42b1c3..3357b5eb32 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -138,7 +138,7 @@ module ActiveSupport result.tr!("_".freeze, " ".freeze) result.gsub!(/([a-z\d]*)/i) do |match| - "#{inflections.acronyms[match] || match.downcase}" + "#{inflections.acronyms[match.downcase] || match.downcase}" end if capitalize diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index eeec0ab1a5..6cc1039d8e 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -356,6 +356,19 @@ class InflectorTest < ActiveSupport::TestCase assert_equal("Col rpted bugs", ActiveSupport::Inflector.humanize("COL_rpted_bugs")) end + def test_humanize_with_acronyms + ActiveSupport::Inflector.inflections do |inflect| + inflect.acronym "LAX" + inflect.acronym "SFO" + end + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("LAX ROUNDTRIP TO SFO")) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("LAX ROUNDTRIP TO SFO", capitalize: false)) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("lax roundtrip to sfo")) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("lax roundtrip to sfo", capitalize: false)) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("Lax Roundtrip To Sfo")) + assert_equal("LAX roundtrip to SFO", ActiveSupport::Inflector.humanize("Lax Roundtrip To Sfo", capitalize: false)) + end + def test_constantize run_constantize_tests_on do |string| ActiveSupport::Inflector.constantize(string) -- cgit v1.2.3 From edcc0a714d911468caf7db0879fc7a3d1185ee3c Mon Sep 17 00:00:00 2001 From: Bogdan Gusiev Date: Mon, 6 Nov 2017 17:32:54 +0200 Subject: Refactor Preloader Code --- .../associations/preloader/association.rb | 4 +- .../associations/preloader/has_many_through.rb | 10 -- .../associations/preloader/through_association.rb | 107 ++++++++------------- 3 files changed, 40 insertions(+), 81 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 607d376a08..b0c41c7d5f 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -17,7 +17,7 @@ module ActiveRecord end def run(preloader) - associated_records_by_owner(preloader).each do |owner, records| + associated_records_by_owner(preloader) do |owner, records| associate_records_to_owner(owner, records) end end @@ -41,7 +41,7 @@ module ActiveRecord end owners.each_with_object({}) do |owner, result| - result[owner] = records[convert_key(owner[owner_key_name])] || [] + yield(owner, records[convert_key(owner[owner_key_name])] || []) end end diff --git a/activerecord/lib/active_record/associations/preloader/has_many_through.rb b/activerecord/lib/active_record/associations/preloader/has_many_through.rb index 0639fdca44..3e17d07a33 100644 --- a/activerecord/lib/active_record/associations/preloader/has_many_through.rb +++ b/activerecord/lib/active_record/associations/preloader/has_many_through.rb @@ -5,16 +5,6 @@ module ActiveRecord class Preloader class HasManyThrough < CollectionAssociation #:nodoc: include ThroughAssociation - - def associated_records_by_owner(preloader) - records_by_owner = super - - if reflection_scope.distinct_value - records_by_owner.each_value(&:uniq!) - end - - records_by_owner - end end end end diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index b16fca7dc9..1bb7e98231 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -13,86 +13,45 @@ module ActiveRecord end def associated_records_by_owner(preloader) - already_loaded = owners.first.association(through_reflection.name).loaded? - through_scope = through_scope() - - unless already_loaded - preloader.preload(owners, through_reflection.name, through_scope) - end - - through_records = owners.map do |owner| - center = owner.association(through_reflection.name).target - [owner, Array(center)] - end + already_loaded = owners.first.association(through_reflection.name).loaded? + through_scope = through_scope() + reflection_scope = target_reflection_scope + through_preloaders = preloader.preload(owners, through_reflection.name, through_scope) + middle_records = through_preloaders.flat_map(&:preloaded_records) + preloaders = preloader.preload(middle_records, source_reflection.name, reflection_scope) + @preloaded_records = preloaders.flat_map(&:preloaded_records) - if already_loaded - if source_type = reflection.options[:source_type] - through_records.map! do |owner, center| - center = center.select do |record| + owners.each do |owner| + through_records = Array(owner.association(through_reflection.name).target) + if already_loaded + if source_type = reflection.options[:source_type] + through_records = through_records.select do |record| record[reflection.foreign_type] == source_type end - [owner, center] end + else + owner.association(through_reflection.name).reset if through_scope end - else - reset_association(owners, through_reflection.name, through_scope) - end - - middle_records = through_records.flat_map(&:last) - - if preload_scope - reflection_scope = reflection_scope().merge(preload_scope) - elsif reflection.scope - reflection_scope = reflection_scope() - end - - preloaders = preloader.preload(middle_records, - source_reflection.name, - reflection_scope) - - @preloaded_records = preloaders.flat_map(&:preloaded_records) - - middle_to_pl = preloaders.each_with_object({}) do |pl, h| - pl.owners.each { |middle| - h[middle] = pl - } - end - - through_records.each_with_object({}) do |(lhs, center), records_by_owner| - pl_to_middle = center.group_by { |record| middle_to_pl[record] } - - records_by_owner[lhs] = pl_to_middle.flat_map do |pl, middles| - rhs_records = middles.flat_map { |r| - r.association(source_reflection.name).target - }.compact - - # Respect the order on `reflection_scope` if it exists, else use the natural order. - if reflection_scope && !reflection_scope.order_values.empty? - @id_map ||= id_to_index_map @preloaded_records - rhs_records.sort_by { |rhs| @id_map[rhs] } - else - rhs_records - end + result = through_records.flat_map do |record| + association = record.association(source_reflection.name) + target = association.target + association.reset if preload_scope + target end - end.tap do - reset_association(middle_records, source_reflection.name, preload_scope) + result.compact! + if reflection_scope + result.sort_by! { |rhs| preload_index[rhs] } if reflection_scope.order_values.any? + result.uniq! if reflection_scope.distinct_value + end + yield(owner, result) end end private - def id_to_index_map(ids) - id_map = {} - ids.each_with_index { |id, index| id_map[id] = index } - id_map - end - - def reset_association(owners, association_name, should_reset) - # Don't cache the association - we would only be caching a subset - if should_reset - owners.each { |owner| - owner.association(association_name).reset - } + def preload_index + @preload_index ||= @preloaded_records.each_with_object({}).with_index do |(id, result), index| + result[id] = index end end @@ -133,6 +92,16 @@ module ActiveRecord scope unless scope.empty_scope? end + + def target_reflection_scope + if preload_scope + reflection_scope.merge(preload_scope) + elsif reflection.scope + reflection_scope + else + nil + end + end end end end -- cgit v1.2.3 From 1fe7168df0a23b69539b60327943495a3dded9e5 Mon Sep 17 00:00:00 2001 From: Dan Ott Date: Mon, 6 Nov 2017 10:56:24 -0500 Subject: Resolve Minitest 6 deprecation in assert_no_changes These changes resolve a deprecation warning in `assert_no_changes` when asserting that an expression evaluates to `nil` before and after the passed block is evaluated. The smallest demonstration of this edge case: ```ruby assert_no_changes "nil" do true # noop end ``` Under the covers, this is evaluating ```ruby assert_equal nil, nil ``` Minitest 5 issues a deprecation warning, and Minitest will fail completely. For additional context, the motivations and implications of this change to Minitest have been discussed at length in [seattlerb/minitest#666][]. [seattlerb/minitest#666]: https://github.com/seattlerb/minitest/issues/666 --- activesupport/lib/active_support/testing/assertions.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb index e2bc51ff7a..46eed73d24 100644 --- a/activesupport/lib/active_support/testing/assertions.rb +++ b/activesupport/lib/active_support/testing/assertions.rb @@ -190,7 +190,12 @@ module ActiveSupport error = "#{expression.inspect} did change to #{after}" error = "#{message}.\n#{error}" if message - assert_equal before, after, error + + if before.nil? + assert_nil after, error + else + assert_equal before, after, error + end retval end -- cgit v1.2.3 From 01c703248396528d9f3398d0f9d0143831e9d0dc Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Thu, 9 Mar 2017 11:48:44 -0500 Subject: Properly check transaction in persistence ``` [NoMethodError]: undefined method `state' for nil:NilClass Method:[rescue in block in refresh] ``` In `within_new_transaction`, there is the possibility that `begin_transaction` returns a `nil`. (i.e.: so `transaction = nil`) So this method is checking `transaction` for nil in 2 spots. Unfortunately, there is one line that is not checking `transaction` for `nil` That line, `commit_transaction`, throws an exception for us in AR 5.0.0.1 The problem with the method is finally realized in the error checking itself. it calls `transaction.state` (i.e.: nil.state) and that is the final exception raised. The actual underlying (user) issue is hidden by this line. Solution is test transaction for nil. --- .../lib/active_record/connection_adapters/abstract/transaction.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 147e16e9fa..d9ac8db6a8 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -240,7 +240,7 @@ module ActiveRecord rollback_transaction if transaction else begin - commit_transaction + commit_transaction if transaction rescue Exception rollback_transaction(transaction) unless transaction.state.completed? raise -- cgit v1.2.3 From 4a835aa3236eedb135ccf8b59ed3c03e040b8b01 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Sun, 6 Aug 2017 20:41:31 +0000 Subject: Add --skip-active-storage and do so automatically when --skip-active-record is used Closes #30102 Revert part 787fe90dc0a7c5b91bb5af51f2858ea8c4676268 --skip-active-storage pass throughs `rails plugin new` Add changelog entry about default initialization of Active Storage --- railties/CHANGELOG.md | 6 + railties/lib/rails/all.rb | 2 +- railties/lib/rails/app_updater.rb | 11 +- railties/lib/rails/generators/app_base.rb | 123 +++++++++++++-------- .../rails/generators/rails/app/app_generator.rb | 8 +- .../rails/generators/rails/app/templates/Gemfile | 3 +- .../app/assets/javascripts/application.js.tt | 2 + .../rails/app/templates/config/application.rb | 2 +- .../config/environments/development.rb.tt | 2 + .../templates/config/environments/production.rb.tt | 2 + .../app/templates/config/environments/test.rb.tt | 3 + .../rails/generators/rails/app/templates/gitignore | 2 + .../generators/rails/plugin/plugin_generator.rb | 2 +- .../generators/rails/plugin/templates/gitignore | 3 + .../rails/plugin/templates/rails/application.rb | 2 +- .../rails/plugin/templates/rails/javascripts.js | 3 + railties/test/generators/app_generator_test.rb | 61 ++++++++++ railties/test/generators/plugin_generator_test.rb | 5 +- .../test/generators/plugin_test_runner_test.rb | 2 +- railties/test/generators/shared_generator_tests.rb | 91 +++++++++++++++ 20 files changed, 270 insertions(+), 65 deletions(-) diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 20603dedaf..e69a1231b1 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,9 @@ +* `rails new` and `rails plugin new` get `Active Storage` by default. + Add ability to skip `Active Storage` with `--skip-active-storage` + and do so automatically when `--skip-active-record` is used. + + *bogdanvlviv* + * Gemfile for new apps: upgrade redis-rb from ~> 3.0 to 4.0. *Jeremy Daer* diff --git a/railties/lib/rails/all.rb b/railties/lib/rails/all.rb index e55b2e2433..f5dccd2381 100644 --- a/railties/lib/rails/all.rb +++ b/railties/lib/rails/all.rb @@ -4,12 +4,12 @@ require "rails" %w( active_record/railtie + active_storage/engine action_controller/railtie action_view/railtie action_mailer/railtie active_job/railtie action_cable/engine - active_storage/engine rails/test_unit/railtie sprockets/railtie ).each do |railtie| diff --git a/railties/lib/rails/app_updater.rb b/railties/lib/rails/app_updater.rb index c2436a69f9..a076d082d5 100644 --- a/railties/lib/rails/app_updater.rb +++ b/railties/lib/rails/app_updater.rb @@ -21,11 +21,12 @@ module Rails private def generator_options options = { api: !!Rails.application.config.api_only, update: true } - options[:skip_active_record] = !defined?(ActiveRecord::Railtie) - options[:skip_action_mailer] = !defined?(ActionMailer::Railtie) - options[:skip_action_cable] = !defined?(ActionCable::Engine) - options[:skip_sprockets] = !defined?(Sprockets::Railtie) - options[:skip_puma] = !defined?(Puma) + options[:skip_active_record] = !defined?(ActiveRecord::Railtie) + options[:skip_active_storage] = !defined?(ActiveStorage::Engine) || !defined?(ActiveRecord::Railtie) + options[:skip_action_mailer] = !defined?(ActionMailer::Railtie) + options[:skip_action_cable] = !defined?(ActionCable::Engine) + options[:skip_sprockets] = !defined?(Sprockets::Railtie) + options[:skip_puma] = !defined?(Puma) options end end diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index bc00adabae..2809c433f6 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -26,75 +26,78 @@ module Rails end def self.add_shared_options_for(name) - class_option :template, type: :string, aliases: "-m", - desc: "Path to some #{name} template (can be a filesystem path or URL)" + class_option :template, type: :string, aliases: "-m", + desc: "Path to some #{name} template (can be a filesystem path or URL)" - class_option :database, type: :string, aliases: "-d", default: "sqlite3", - desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})" + class_option :database, type: :string, aliases: "-d", default: "sqlite3", + desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})" - class_option :skip_yarn, type: :boolean, default: false, - desc: "Don't use Yarn for managing JavaScript dependencies" + class_option :skip_yarn, type: :boolean, default: false, + desc: "Don't use Yarn for managing JavaScript dependencies" - class_option :skip_gemfile, type: :boolean, default: false, - desc: "Don't create a Gemfile" + class_option :skip_gemfile, type: :boolean, default: false, + desc: "Don't create a Gemfile" - class_option :skip_git, type: :boolean, aliases: "-G", default: false, - desc: "Skip .gitignore file" + class_option :skip_git, type: :boolean, aliases: "-G", default: false, + desc: "Skip .gitignore file" - class_option :skip_keeps, type: :boolean, default: false, - desc: "Skip source control .keep files" + class_option :skip_keeps, type: :boolean, default: false, + desc: "Skip source control .keep files" - class_option :skip_action_mailer, type: :boolean, aliases: "-M", - default: false, - desc: "Skip Action Mailer files" + class_option :skip_action_mailer, type: :boolean, aliases: "-M", + default: false, + desc: "Skip Action Mailer files" - class_option :skip_active_record, type: :boolean, aliases: "-O", default: false, - desc: "Skip Active Record files" + class_option :skip_active_record, type: :boolean, aliases: "-O", default: false, + desc: "Skip Active Record files" - class_option :skip_puma, type: :boolean, aliases: "-P", default: false, - desc: "Skip Puma related files" + class_option :skip_active_storage, type: :boolean, default: false, + desc: "Skip Active Storage files" - class_option :skip_action_cable, type: :boolean, aliases: "-C", default: false, - desc: "Skip Action Cable files" + class_option :skip_puma, type: :boolean, aliases: "-P", default: false, + desc: "Skip Puma related files" - class_option :skip_sprockets, type: :boolean, aliases: "-S", default: false, - desc: "Skip Sprockets files" + class_option :skip_action_cable, type: :boolean, aliases: "-C", default: false, + desc: "Skip Action Cable files" - class_option :skip_spring, type: :boolean, default: false, - desc: "Don't install Spring application preloader" + class_option :skip_sprockets, type: :boolean, aliases: "-S", default: false, + desc: "Skip Sprockets files" - class_option :skip_listen, type: :boolean, default: false, - desc: "Don't generate configuration that depends on the listen gem" + class_option :skip_spring, type: :boolean, default: false, + desc: "Don't install Spring application preloader" - class_option :skip_coffee, type: :boolean, default: false, - desc: "Don't use CoffeeScript" + class_option :skip_listen, type: :boolean, default: false, + desc: "Don't generate configuration that depends on the listen gem" - class_option :skip_javascript, type: :boolean, aliases: "-J", default: false, - desc: "Skip JavaScript files" + class_option :skip_coffee, type: :boolean, default: false, + desc: "Don't use CoffeeScript" - class_option :skip_turbolinks, type: :boolean, default: false, - desc: "Skip turbolinks gem" + class_option :skip_javascript, type: :boolean, aliases: "-J", default: false, + desc: "Skip JavaScript files" - class_option :skip_test, type: :boolean, aliases: "-T", default: false, - desc: "Skip test files" + class_option :skip_turbolinks, type: :boolean, default: false, + desc: "Skip turbolinks gem" - class_option :skip_system_test, type: :boolean, default: false, - desc: "Skip system test files" + class_option :skip_test, type: :boolean, aliases: "-T", default: false, + desc: "Skip test files" - class_option :dev, type: :boolean, default: false, - desc: "Setup the #{name} with Gemfile pointing to your Rails checkout" + class_option :skip_system_test, type: :boolean, default: false, + desc: "Skip system test files" - class_option :edge, type: :boolean, default: false, - desc: "Setup the #{name} with Gemfile pointing to Rails repository" + class_option :dev, type: :boolean, default: false, + desc: "Setup the #{name} with Gemfile pointing to your Rails checkout" - class_option :rc, type: :string, default: nil, - desc: "Path to file containing extra configuration options for rails command" + class_option :edge, type: :boolean, default: false, + desc: "Setup the #{name} with Gemfile pointing to Rails repository" - class_option :no_rc, type: :boolean, default: false, - desc: "Skip loading of extra configuration options from .railsrc file" + class_option :rc, type: :string, default: nil, + desc: "Path to file containing extra configuration options for rails command" - class_option :help, type: :boolean, aliases: "-h", group: :rails, - desc: "Show this help message and quit" + class_option :no_rc, type: :boolean, default: false, + desc: "Skip loading of extra configuration options from .railsrc file" + + class_option :help, type: :boolean, aliases: "-h", group: :rails, + desc: "Show this help message and quit" end def initialize(*args) @@ -193,11 +196,29 @@ module Rails end def include_all_railties? # :doc: - options.values_at(:skip_active_record, :skip_action_mailer, :skip_test, :skip_sprockets, :skip_action_cable).none? + [ + options.values_at( + :skip_active_record, + :skip_action_mailer, + :skip_test, + :skip_sprockets, + :skip_action_cable + ), + skip_active_storage? + ].flatten.none? end def comment_if(value) # :doc: - options[value] ? "# " : "" + question = "#{value}?" + + comment = + if respond_to?(question, true) + send(question) + else + options[value] + end + + comment ? "# " : "" end def keeps? # :doc: @@ -208,6 +229,10 @@ module Rails !options[:skip_active_record] && options[:database] == "sqlite3" end + def skip_active_storage? # :doc: + options[:skip_active_storage] || options[:skip_active_record] + end + class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out) def initialize(name, version, comment, options = {}, commented_out = false) super diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 46954f64b5..15c5b973ca 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -114,7 +114,7 @@ module Rails template "cable.yml" unless options[:skip_action_cable] template "puma.rb" unless options[:skip_puma] template "spring.rb" if spring_install? - template "storage.yml" + template "storage.yml" unless skip_active_storage? directory "environments" directory "initializers" @@ -139,7 +139,7 @@ module Rails template "config/cable.yml" end - if !active_storage_config_exist + if !skip_active_storage? && !active_storage_config_exist template "config/storage.yml" end @@ -355,6 +355,10 @@ module Rails build(:system_test) if depends_on_system_test? end + def create_storage_files + build(:storage) unless skip_active_storage? + end + def create_tmp_files build(:tmp) end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 95e8be96b6..ee9db83ca2 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -20,9 +20,10 @@ ruby <%= "'#{RUBY_VERSION}'" -%> # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' - +<% unless skip_active_storage? -%> # Use ActiveStorage variant # gem 'mini_magick', '~> 4.8' +<% end -%> # Use Capistrano for deployment # gem 'capistrano-rails', group: :development 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 62fd04f113..5183bcd256 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 @@ -12,7 +12,9 @@ // <% unless options[:skip_javascript] -%> //= require rails-ujs +<% unless skip_active_storage? -%> //= require activestorage +<% end -%> <% unless options[:skip_turbolinks] -%> //= require turbolinks <% end -%> diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index dde09edb94..9e03e86771 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -8,10 +8,10 @@ require "rails" require "active_model/railtie" require "active_job/railtie" <%= comment_if :skip_active_record %>require "active_record/railtie" +<%= comment_if :skip_active_storage %>require "active_storage/engine" require "action_controller/railtie" <%= comment_if :skip_action_mailer %>require "action_mailer/railtie" require "action_view/railtie" -require "active_storage/engine" <%= comment_if :skip_action_cable %>require "action_cable/engine" <%= comment_if :skip_sprockets %>require "sprockets/railtie" <%= comment_if :skip_test %>require "rails/test_unit/railtie" diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index 98689cc30d..2746aedd6f 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -27,8 +27,10 @@ Rails.application.configure do config.cache_store = :null_store end + <%- unless skip_active_storage? -%> # Store uploaded files on the local file system (see config/storage.yml for options) config.active_storage.service = :local + <%- end -%> <%- unless options.skip_action_mailer? -%> # Don't care if the mailer can't send. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 2e0b555f6f..4c0f36db98 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -44,9 +44,11 @@ Rails.application.configure do # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + <%- unless skip_active_storage? -%> # Store uploaded files on the local file system (see config/storage.yml for options) config.active_storage.service = :local + <%- end -%> <%- unless options[:skip_action_cable] -%> # Mount Action Cable outside main process or domain # config.action_cable.mount_path = nil diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt index a53978bc6e..a19f490d91 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt @@ -28,8 +28,11 @@ Rails.application.configure do # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + <%- unless skip_active_storage? -%> # Store uploaded files on the local file system in a temporary directory config.active_storage.service = :test + + <%- end -%> <%- unless options.skip_action_mailer? -%> config.action_mailer.perform_caching = false diff --git a/railties/lib/rails/generators/rails/app/templates/gitignore b/railties/lib/rails/generators/rails/app/templates/gitignore index 83a7b211aa..bd6b34346a 100644 --- a/railties/lib/rails/generators/rails/app/templates/gitignore +++ b/railties/lib/rails/generators/rails/app/templates/gitignore @@ -21,8 +21,10 @@ !/tmp/.keep <% end -%> +<% unless skip_active_storage? -%> # Ignore uploaded files in development /storage/* +<% end -%> <% unless options.skip_yarn? -%> /node_modules diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index d9ca4712d0..bc2dcf008e 100644 --- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -87,7 +87,7 @@ task default: :test end PASSTHROUGH_OPTIONS = [ - :skip_active_record, :skip_action_mailer, :skip_javascript, :skip_action_cable, :skip_sprockets, :database, + :skip_active_record, :skip_active_storage, :skip_action_mailer, :skip_javascript, :skip_action_cable, :skip_sprockets, :database, :javascript, :skip_yarn, :api, :quiet, :pretend, :skip ] diff --git a/railties/lib/rails/generators/rails/plugin/templates/gitignore b/railties/lib/rails/generators/rails/plugin/templates/gitignore index e15863d860..7a68da5c4b 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/gitignore +++ b/railties/lib/rails/generators/rails/plugin/templates/gitignore @@ -11,5 +11,8 @@ pkg/ <%= dummy_path %>/node_modules/ <%= dummy_path %>/yarn-error.log <% end -%> +<% unless skip_active_storage? -%> +<%= dummy_path %>/storage/ +<% end -%> <%= dummy_path %>/tmp/ <% end -%> diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb index 47b56ae3df..06ffe2f1ed 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/application.rb @@ -8,10 +8,10 @@ require "rails" require "active_model/railtie" require "active_job/railtie" <%= comment_if :skip_active_record %>require "active_record/railtie" +<%= comment_if :skip_active_storage %>require "active_storage/engine" require "action_controller/railtie" <%= comment_if :skip_action_mailer %>require "action_mailer/railtie" require "action_view/railtie" -require "active_storage/engine" <%= comment_if :skip_action_cable %>require "action_cable/engine" <%= comment_if :skip_sprockets %>require "sprockets/railtie" <%= comment_if :skip_test %>require "rails/test_unit/railtie" diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js index e54c6461cc..f3d80c87f5 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js @@ -10,4 +10,7 @@ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // +<% unless skip_active_storage? -%> +//= require activestorage +<% end -%> //= require_tree . diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 160ad1a928..0e2988952b 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -75,6 +75,7 @@ DEFAULT_APP_FILES = %w( log package.json public + storage test/application_system_test_case.rb test/test_helper.rb test/fixtures @@ -89,6 +90,7 @@ DEFAULT_APP_FILES = %w( tmp tmp/cache tmp/cache/assets + tmp/storage ) class AppGeneratorTest < Rails::Generators::TestCase @@ -296,6 +298,65 @@ class AppGeneratorTest < Rails::Generators::TestCase end end + def test_active_storage_mini_magick_gem + run_generator + assert_file "Gemfile", /^# gem 'mini_magick'/ + end + + def test_app_update_does_not_generate_active_storage_contents_when_skip_active_storage_is_given + app_root = File.join(destination_root, "myapp") + run_generator [app_root, "--skip-active-storage"] + + FileUtils.cd(app_root) do + quietly { system("bin/rails app:update") } + end + + assert_file "#{app_root}/config/environments/development.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_file "#{app_root}/config/environments/production.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_file "#{app_root}/config/environments/test.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_no_file "#{app_root}/config/storage.yml" + + assert_file "#{app_root}/Gemfile" do |content| + assert_no_match(/gem 'mini_magick'/, content) + end + end + + def test_app_update_does_not_generate_active_storage_contents_when_skip_active_record_is_given + app_root = File.join(destination_root, "myapp") + run_generator [app_root, "--skip-active-record"] + + FileUtils.cd(app_root) do + quietly { system("bin/rails app:update") } + end + + assert_file "#{app_root}/config/environments/development.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_file "#{app_root}/config/environments/production.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_file "#{app_root}/config/environments/test.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_no_file "#{app_root}/config/storage.yml" + + assert_file "#{app_root}/Gemfile" do |content| + assert_no_match(/gem 'mini_magick'/, content) + end + end + def test_application_names_are_not_singularized run_generator [File.join(destination_root, "hats")] assert_file "hats/config/environment.rb", /Rails\.application\.initialize!/ diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 38130ceb68..06d223e26d 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -230,7 +230,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase end def test_ensure_that_tests_work - run_generator + run_generator [destination_root, "--skip-active-storage"] FileUtils.cd destination_root quietly { system "bundle install" } assert_match(/1 runs, 1 assertions, 0 failures, 0 errors/, `bin/test 2>&1`) @@ -240,8 +240,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase run_generator [destination_root, "--full", "--skip_active_record"] FileUtils.cd destination_root quietly { system "bundle install" } - # FIXME: Active Storage will provoke a test error without ActiveRecord (fix by allowing to skip active storage) - assert_match(/1 runs, 0 assertions, 0 failures, 1 errors/, `bundle exec rake test 2>&1`) + assert_match(/1 runs, 1 assertions, 0 failures, 0 errors/, `bundle exec rake test 2>&1`) end def test_ensure_that_migration_tasks_work_with_mountable_option diff --git a/railties/test/generators/plugin_test_runner_test.rb b/railties/test/generators/plugin_test_runner_test.rb index 89c3f1e496..48a3bcadcd 100644 --- a/railties/test/generators/plugin_test_runner_test.rb +++ b/railties/test/generators/plugin_test_runner_test.rb @@ -7,7 +7,7 @@ class PluginTestRunnerTest < ActiveSupport::TestCase def setup @destination_root = Dir.mktmpdir("bukkits") - Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --skip-bundle` } + Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --skip-bundle --skip-active-storage` } plugin_file "test/dummy/db/schema.rb", "" end diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index 654d16de65..cd86dd662f 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -189,6 +189,97 @@ module SharedGeneratorTests end end + def test_generator_for_active_storage + run_generator + + assert_file "#{application_path}/app/assets/javascripts/application.js" do |content| + assert_match(/^\/\/= require activestorage/, content) + end + + assert_file "#{application_path}/config/environments/development.rb" do |content| + assert_match(/config\.active_storage/, content) + end + + assert_file "#{application_path}/config/environments/production.rb" do |content| + assert_match(/config\.active_storage/, content) + end + + assert_file "#{application_path}/config/environments/test.rb" do |content| + assert_match(/config\.active_storage/, content) + end + + assert_file "#{application_path}/config/storage.yml" + assert_directory "#{application_path}/db/migrate" + assert_directory "#{application_path}/storage" + assert_directory "#{application_path}/tmp/storage" + + assert_file ".gitignore" do |content| + assert_match(/\/storage\//, content) + end + end + + def test_generator_if_skip_active_storage_is_given + run_generator [destination_root, "--skip-active-storage"] + + assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_storage\/engine["']/ + + assert_file "#{application_path}/app/assets/javascripts/application.js" do |content| + assert_no_match(/^\/\/= require activestorage/, content) + end + + assert_file "#{application_path}/config/environments/development.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_file "#{application_path}/config/environments/production.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_file "#{application_path}/config/environments/test.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_no_file "#{application_path}/config/storage.yml" + assert_no_directory "#{application_path}/db/migrate" + assert_no_directory "#{application_path}/storage" + assert_no_directory "#{application_path}/tmp/storage" + + assert_file ".gitignore" do |content| + assert_no_match(/\/storage\//, content) + end + end + + def test_generator_does_not_generate_active_storage_contents_if_skip_active_record_is_given + run_generator [destination_root, "--skip-active-record"] + + assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_storage\/engine["']/ + + assert_file "#{application_path}/app/assets/javascripts/application.js" do |content| + assert_no_match(/^\/\/= require activestorage/, content) + end + + assert_file "#{application_path}/config/environments/development.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_file "#{application_path}/config/environments/production.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_file "#{application_path}/config/environments/test.rb" do |content| + assert_no_match(/config\.active_storage/, content) + end + + assert_no_file "#{application_path}/config/storage.yml" + assert_no_directory "#{application_path}/db/migrate" + assert_no_directory "#{application_path}/storage" + assert_no_directory "#{application_path}/tmp/storage" + + assert_file ".gitignore" do |content| + assert_no_match(/\/storage\//, content) + end + end + def test_generator_if_skip_action_mailer_is_given run_generator [destination_root, "--skip-action-mailer"] assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/ -- cgit v1.2.3 From 0835527d6bb970cedd33633503506e41156ab780 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Mon, 7 Aug 2017 04:31:14 +0000 Subject: `rails new` runs `rails active_storage:install` Omit `rails activestorage:install` for jdbcmysql, jdbc and shebang tests AppGeneratorTest#test_config_jdbcmysql_database rails aborted! LoadError: Could not load 'active_record/connection_adapters/mysql_adapter'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile. (compressed) bin/rails:4:in `
' Tasks: TOP => activestorage:install => environment (See full trace by running task with --trace) AppGeneratorTest#test_config_jdbc_database rails aborted! LoadError: Could not load 'active_record/connection_adapters/jdbc_adapter'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile. (compressed) bin/rails:4:in `
' Tasks: TOP => activestorage:install => environment (See full trace by running task with --trace) AppGeneratorTest#test_shebang_is_added_to_rails_file /home/ubuntu/.rbenv/versions/2.4.1/bin/ruby: no Ruby script found in input (LoadError) Prevent PendingMigrationError in tests * Run `bin/rails db:migrate RAILS_ENV=test` in test_cases before start tests to prevent PendingMigrationError * FileUtils.rm_r("db/migrate") * --skip-active-storage Fix failed tests in `railties/test/railties/engine_test.rb` Related to #30111 Imporve `SharedGeneratorTests#test_default_frameworks_are_required_when_others_are_removed` - Explicitly skip active_storage - Ensure that skipped frameworks are commented - Ensure that default frameworks are not commented Fix error `Errno::ENOSPC: No space left on device - sendfile` Since `rails new` runs `rails active_storage:install` that boots an app. Since adding Bootsnap 0312a5c67e35b960e33677b5358c539f1047e4e1 during booting an app, it creates the cache: 264K tmp/cache/bootsnap-load-path-cache 27M tmp/cache/bootsnap-compile-cache * teardown_app must remove app --- .../test/support/integration/dummy_app_template.rb | 2 - activejob/test/support/integration/helper.rb | 1 + railties/lib/rails/generators/app_base.rb | 6 +++ .../rails/generators/rails/app/app_generator.rb | 1 + railties/test/application/bin_setup_test.rb | 4 ++ .../test/application/integration_test_case_test.rb | 7 +++- railties/test/application/rackup_test.rb | 1 + railties/test/application/rake/dbs_test.rb | 4 ++ railties/test/application/test_runner_test.rb | 5 +++ railties/test/application/test_test.rb | 5 +++ railties/test/generators/app_generator_test.rb | 13 +++--- .../scaffold_controller_generator_test.rb | 2 + railties/test/generators/shared_generator_tests.rb | 29 +++++++++---- .../test/generators/test_runner_in_engine_test.rb | 2 +- railties/test/isolation/abstract_unit.rb | 1 + railties/test/railties/engine_test.rb | 47 +++++++++++++--------- 16 files changed, 92 insertions(+), 38 deletions(-) diff --git a/activejob/test/support/integration/dummy_app_template.rb b/activejob/test/support/integration/dummy_app_template.rb index ac382bd1b7..7ea78c3350 100644 --- a/activejob/test/support/integration/dummy_app_template.rb +++ b/activejob/test/support/integration/dummy_app_template.rb @@ -4,8 +4,6 @@ if ENV["AJ_ADAPTER"] == "delayed_job" generate "delayed_job:active_record", "--quiet" end -rails_command("db:migrate") - initializer "activejob.rb", <<-CODE require "#{File.expand_path("jobs_manager.rb", __dir__)}" JobsManager.current_manager.setup diff --git a/activejob/test/support/integration/helper.rb b/activejob/test/support/integration/helper.rb index a058da141f..a02d874e2e 100644 --- a/activejob/test/support/integration/helper.rb +++ b/activejob/test/support/integration/helper.rb @@ -18,6 +18,7 @@ Rails::Generators::AppGenerator.start args require "#{dummy_app_path}/config/environment.rb" ActiveRecord::Migrator.migrations_paths = [ Rails.root.join("db/migrate").to_s ] +ActiveRecord::Tasks::DatabaseTasks.migrate require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 2809c433f6..4f3ecd9189 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -459,6 +459,12 @@ module Rails end end + def run_active_storage + unless skip_active_storage? + rails_command "active_storage:install" + end + end + def empty_directory_with_keep_file(destination, config = {}) empty_directory(destination, config) keep_file(destination) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 15c5b973ca..1c32fad3ea 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -461,6 +461,7 @@ module Rails public_task :apply_rails_template, :run_bundle public_task :run_webpack, :generate_spring_binstubs + public_task :run_active_storage def run_after_bundle_callbacks @after_bundle_callbacks.each(&:call) diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb index 54934dbe24..9fac0435e4 100644 --- a/railties/test/application/bin_setup_test.rb +++ b/railties/test/application/bin_setup_test.rb @@ -16,6 +16,8 @@ module ApplicationTests def test_bin_setup Dir.chdir(app_path) do + FileUtils.rm_rf("db/migrate") + app_file "db/schema.rb", <<-RUBY ActiveRecord::Schema.define(version: 20140423102712) do create_table(:articles) {} @@ -37,6 +39,8 @@ module ApplicationTests def test_bin_setup_output Dir.chdir(app_path) do + FileUtils.rm_rf("db/migrate") + app_file "db/schema.rb", "" output = `bin/setup 2>&1` diff --git a/railties/test/application/integration_test_case_test.rb b/railties/test/application/integration_test_case_test.rb index 9edc907fce..c08761092b 100644 --- a/railties/test/application/integration_test_case_test.rb +++ b/railties/test/application/integration_test_case_test.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "env_helpers" module ApplicationTests class IntegrationTestCaseTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, EnvHelpers setup do build_app @@ -39,13 +40,14 @@ module ApplicationTests end RUBY + with_rails_env("test") { rails("db:migrate") } output = rails("test") assert_match(/0 failures, 0 errors/, output) end end class IntegrationTestDefaultApp < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, EnvHelpers setup do build_app @@ -66,6 +68,7 @@ module ApplicationTests end RUBY + with_rails_env("test") { rails("db:migrate") } output = rails("test") assert_match(/0 failures, 0 errors/, output) end diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb index 383f18a7da..1dcc2826f0 100644 --- a/railties/test/application/rackup_test.rb +++ b/railties/test/application/rackup_test.rb @@ -26,6 +26,7 @@ module ApplicationTests test "config.ru can be racked up" do Dir.chdir app_path do + FileUtils.rm_rf("db/migrate") @app = rackup assert_welcome get("/") end diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index fd22477539..009f2887c9 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -287,6 +287,8 @@ module ApplicationTests ENV.delete "RAILS_ENV" ENV.delete "RACK_ENV" + Dir.chdir(app_path) { FileUtils.rm_rf("db/migrate") } + app_file "db/schema.rb", <<-RUBY ActiveRecord::Schema.define(version: "1") do create_table :users do |t| @@ -308,6 +310,8 @@ module ApplicationTests end test "db:setup sets ar_internal_metadata" do + Dir.chdir(app_path) { FileUtils.rm_rf("db/migrate") } + app_file "db/schema.rb", "" rails "db:setup" diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb index e92a0466dd..30bd283b48 100644 --- a/railties/test/application/test_runner_test.rb +++ b/railties/test/application/test_runner_test.rb @@ -11,6 +11,7 @@ module ApplicationTests def setup build_app create_schema + remove_migrations end def teardown @@ -727,6 +728,10 @@ module ApplicationTests app_file "db/schema.rb", "" end + def remove_migrations + Dir.chdir(app_path) { FileUtils.rm_rf("db/migrate") } + end + def create_test_file(path = :unit, name = "test", pass: true) app_file "test/#{path}/#{name}_test.rb", <<-RUBY require 'test_helper' diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index 0a51e98656..50238ed682 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -8,6 +8,7 @@ module ApplicationTests def setup build_app + remove_migrations end def teardown @@ -320,6 +321,10 @@ Expected: ["id", "name"] end private + def remove_migrations + Dir.chdir(app_path) { FileUtils.rm_rf("db/migrate") } + end + def assert_unsuccessful_run(name, message) result = run_test_file(name) assert_not_equal 0, $?.to_i diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 0e2988952b..c5a59edab2 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -68,6 +68,7 @@ DEFAULT_APP_FILES = %w( config/spring.rb config/storage.yml db + db/migrate db/seeds.rb lib lib/tasks @@ -408,7 +409,7 @@ class AppGeneratorTest < Rails::Generators::TestCase end def test_config_jdbcmysql_database - run_generator([destination_root, "-d", "jdbcmysql"]) + run_generator([destination_root, "-d", "jdbcmysql", "--skip-active-storage"]) assert_file "config/database.yml", /mysql/ assert_gem "activerecord-jdbcmysql-adapter" end @@ -426,7 +427,7 @@ class AppGeneratorTest < Rails::Generators::TestCase end def test_config_jdbc_database - run_generator([destination_root, "-d", "jdbc"]) + run_generator([destination_root, "-d", "jdbc", "--skip-active-storage"]) assert_file "config/database.yml", /jdbc/ assert_file "config/database.yml", /mssql/ assert_gem "activerecord-jdbc-adapter" @@ -803,7 +804,7 @@ class AppGeneratorTest < Rails::Generators::TestCase template end - sequence = ["git init", "install", "exec spring binstub --all", "echo ran after_bundle"] + sequence = ["git init", "install", "exec spring binstub --all", "active_storage:install", "echo ran after_bundle"] @sequence_step ||= 0 ensure_bundler_first = -> command, options = nil do assert_equal sequence[@sequence_step], command, "commands should be called in sequence #{sequence}" @@ -813,12 +814,14 @@ class AppGeneratorTest < Rails::Generators::TestCase generator([destination_root], template: path).stub(:open, check_open, template) do generator.stub(:bundle_command, ensure_bundler_first) do generator.stub(:run, ensure_bundler_first) do - quietly { generator.invoke_all } + generator.stub(:rails_command, ensure_bundler_first) do + quietly { generator.invoke_all } + end end end end - assert_equal 4, @sequence_step + assert_equal 5, @sequence_step end def test_system_tests_directory_generated diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb index 513b037043..fd5aa817b4 100644 --- a/railties/test/generators/scaffold_controller_generator_test.rb +++ b/railties/test/generators/scaffold_controller_generator_test.rb @@ -207,6 +207,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase Dir.chdir(engine_path) do quietly { `bin/rails g controller dashboard foo` } + quietly { `bin/rails db:migrate RAILS_ENV=test` } assert_match(/2 runs, 2 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`) end end @@ -218,6 +219,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase Dir.chdir(engine_path) do quietly { `bin/rails g controller dashboard foo` } + quietly { `bin/rails db:migrate RAILS_ENV=test` } assert_match(/2 runs, 2 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`) end end diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index cd86dd662f..ed09847443 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -63,7 +63,7 @@ module SharedGeneratorTests end def test_shebang_is_added_to_rails_file - run_generator [destination_root, "--ruby", "foo/bar/baz", "--full"] + run_generator [destination_root, "--ruby", "foo/bar/baz", "--full", "--skip-active-storage"] assert_file "bin/rails", /#!foo\/bar\/baz/ end @@ -129,13 +129,26 @@ module SharedGeneratorTests end def test_default_frameworks_are_required_when_others_are_removed - run_generator [destination_root, "--skip-active-record", "--skip-action-mailer", "--skip-action-cable", "--skip-sprockets"] - assert_file "#{application_path}/config/application.rb", /require\s+["']rails["']/ - assert_file "#{application_path}/config/application.rb", /require\s+["']active_model\/railtie["']/ - assert_file "#{application_path}/config/application.rb", /require\s+["']active_job\/railtie["']/ - assert_file "#{application_path}/config/application.rb", /require\s+["']action_controller\/railtie["']/ - assert_file "#{application_path}/config/application.rb", /require\s+["']action_view\/railtie["']/ - assert_file "#{application_path}/config/application.rb", /require\s+["']active_storage\/engine["']/ + run_generator [ + destination_root, + "--skip-active-record", + "--skip-active-storage", + "--skip-action-mailer", + "--skip-action-cable", + "--skip-sprockets" + ] + + assert_file "#{application_path}/config/application.rb", /^require\s+["']rails["']/ + assert_file "#{application_path}/config/application.rb", /^require\s+["']active_model\/railtie["']/ + assert_file "#{application_path}/config/application.rb", /^require\s+["']active_job\/railtie["']/ + assert_file "#{application_path}/config/application.rb", /^# require\s+["']active_record\/railtie["']/ + assert_file "#{application_path}/config/application.rb", /^# require\s+["']active_storage\/engine["']/ + assert_file "#{application_path}/config/application.rb", /^require\s+["']action_controller\/railtie["']/ + assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_mailer\/railtie["']/ + assert_file "#{application_path}/config/application.rb", /^require\s+["']action_view\/railtie["']/ + assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_cable\/engine["']/ + assert_file "#{application_path}/config/application.rb", /^# require\s+["']sprockets\/railtie["']/ + assert_file "#{application_path}/config/application.rb", /^require\s+["']rails\/test_unit\/railtie["']/ end def test_generator_without_skips diff --git a/railties/test/generators/test_runner_in_engine_test.rb b/railties/test/generators/test_runner_in_engine_test.rb index 0e15b5e388..2acd96ecd4 100644 --- a/railties/test/generators/test_runner_in_engine_test.rb +++ b/railties/test/generators/test_runner_in_engine_test.rb @@ -7,7 +7,7 @@ class TestRunnerInEngineTest < ActiveSupport::TestCase def setup @destination_root = Dir.mktmpdir("bukkits") - Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --full --skip-bundle` } + Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --full --skip-bundle --skip-active-storage` } plugin_file "test/dummy/db/schema.rb", "" end diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 29daaacdb2..7522237a38 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -153,6 +153,7 @@ module TestHelpers def teardown_app ENV["RAILS_ENV"] = @prev_rails_env if @prev_rails_env + FileUtils.rm_rf(tmp_path) end # Make a very basic app, without creating the whole directory structure. diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index e6964b4b18..132b3b3a6e 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -32,6 +32,11 @@ module RailtiesTest require "#{app_path}/config/environment" end + def migrations + migration_root = File.expand_path(ActiveRecord::Migrator.migrations_paths.first, app_path) + ActiveRecord::Migrator.migrations(migration_root) + end + test "serving sprocket's assets" do @plugin.write "app/assets/javascripts/engine.js.erb", "<%= :alert %>();" add_to_env_config "development", "config.assets.digest = false" @@ -82,31 +87,30 @@ module RailtiesTest end RUBY - add_to_config "ActiveRecord::Base.timestamped_migrations = false" - boot_rails Dir.chdir(app_path) do output = `bundle exec rake bukkits:install:migrations` - assert File.exist?("#{app_path}/db/migrate/2_create_users.bukkits.rb") - assert File.exist?("#{app_path}/db/migrate/3_add_last_name_to_users.bukkits.rb") - assert_match(/Copied migration 2_create_users\.bukkits\.rb from bukkits/, output) - assert_match(/Copied migration 3_add_last_name_to_users\.bukkits\.rb from bukkits/, output) - assert_match(/NOTE: Migration 3_create_sessions\.rb from bukkits has been skipped/, output) - assert_equal 3, Dir["#{app_path}/db/migrate/*.rb"].length + ["CreateUsers", "AddLastNameToUsers", "CreateSessions"].each do |migration_name| + assert migrations.detect { |migration| migration.name == migration_name } + end + assert_match(/Copied migration \d+_create_users\.bukkits\.rb from bukkits/, output) + assert_match(/Copied migration \d+_add_last_name_to_users\.bukkits\.rb from bukkits/, output) + assert_match(/NOTE: Migration \d+_create_sessions\.rb from bukkits has been skipped/, output) - output = `bundle exec rake railties:install:migrations`.split("\n") + migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length - assert_no_match(/2_create_users/, output.join("\n")) + assert_equal migrations.length, migrations_count - bukkits_migration_order = output.index(output.detect { |o| /NOTE: Migration 3_create_sessions\.rb from bukkits has been skipped/ =~ o }) - assert_not_nil bukkits_migration_order, "Expected migration to be skipped" - - migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length - `bundle exec rake railties:install:migrations` + output = `bundle exec rake railties:install:migrations`.split("\n") assert_equal migrations_count, Dir["#{app_path}/db/migrate/*.rb"].length + + assert_no_match(/\d+_create_users/, output.join("\n")) + + bukkits_migration_order = output.index(output.detect { |o| /NOTE: Migration \d+_create_sessions\.rb from bukkits has been skipped/ =~ o }) + assert_not_nil bukkits_migration_order, "Expected migration to be skipped" end end @@ -173,8 +177,8 @@ module RailtiesTest Dir.chdir(app_path) do output = `bundle exec rake railties:install:migrations`.split("\n") - assert_match(/Copied migration \d+_create_users\.core_engine\.rb from core_engine/, output.second) - assert_match(/Copied migration \d+_create_keys\.api_engine\.rb from api_engine/, output.last) + assert_match(/Copied migration \d+_create_users\.core_engine\.rb from core_engine/, output.first) + assert_match(/Copied migration \d+_create_keys\.api_engine\.rb from api_engine/, output.second) end end @@ -203,9 +207,12 @@ module RailtiesTest Dir.chdir(@plugin.path) do output = `bundle exec rake app:bukkits:install:migrations` - assert File.exist?("#{app_path}/db/migrate/0_add_first_name_to_users.bukkits.rb") - assert_match(/Copied migration 0_add_first_name_to_users\.bukkits\.rb from bukkits/, output) - assert_equal 1, Dir["#{app_path}/db/migrate/*.rb"].length + + migration_with_engine_path = migrations.detect { |migration| migration.name == "AddFirstNameToUsers" } + assert migration_with_engine_path + assert_match(/\/db\/migrate\/\d+_add_first_name_to_users\.bukkits\.rb/, migration_with_engine_path.filename) + assert_match(/Copied migration \d+_add_first_name_to_users\.bukkits\.rb from bukkits/, output) + assert_equal migrations.length, Dir["#{app_path}/db/migrate/*.rb"].length end end -- cgit v1.2.3 From f4af77ab5d6f5bd3b045f676978bc2a4677cee38 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Wed, 11 Oct 2017 10:08:10 +0300 Subject: Rails::Generators::Actions#execute_command allows option `capture` --- railties/lib/rails/generators/actions.rb | 8 +++++++- railties/test/generators/actions_test.rb | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index 9800e5750a..3362bf629a 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -221,6 +221,7 @@ module Rails # rake("db:migrate") # rake("db:migrate", env: "production") # rake("gems:install", sudo: true) + # rake("gems:install", capture: true) def rake(command, options = {}) execute_command :rake, command, options end @@ -230,6 +231,7 @@ module Rails # rails_command("db:migrate") # rails_command("db:migrate", env: "production") # rails_command("gems:install", sudo: true) + # rails_command("gems:install", capture: true) def rails_command(command, options = {}) execute_command :rails, command, options end @@ -292,7 +294,11 @@ module Rails log executor, command env = options[:env] || ENV["RAILS_ENV"] || "development" sudo = options[:sudo] && !Gem.win_platform? ? "sudo " : "" - in_root { run("#{sudo}#{extify(executor)} #{command} RAILS_ENV=#{env}", verbose: false) } + config = { verbose: false } + + config.merge!(capture: options[:capture]) if options[:capture] + + in_root { run("#{sudo}#{extify(executor)} #{command} RAILS_ENV=#{env}", config) } end # Add an extension to the given name based on the platform. diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index 3ecfb4edd9..f421207025 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -308,6 +308,14 @@ class ActionsTest < Rails::Generators::TestCase end end + test "rake command with capture option should run rake command with capture" do + assert_called_with(generator, :run, ["rake log:clear RAILS_ENV=development", verbose: false, capture: true]) do + with_rails_env nil do + action :rake, "log:clear", capture: true + end + end + end + test "rails command should run rails_command with default env" do assert_called_with(generator, :run, ["rails log:clear RAILS_ENV=development", verbose: false]) do with_rails_env nil do @@ -346,6 +354,14 @@ class ActionsTest < Rails::Generators::TestCase end end + test "rails command with capture option should run rails_command with capture" do + assert_called_with(generator, :run, ["rails log:clear RAILS_ENV=development", verbose: false, capture: true]) do + with_rails_env nil do + action :rails_command, "log:clear", capture: true + end + end + end + def test_capify_should_run_the_capify_command content = capture(:stderr) do assert_called_with(generator, :run, ["capify .", verbose: false]) do -- cgit v1.2.3 From cb8553c95d345e40b448cf8e10aa033ff0ede4f2 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Wed, 11 Oct 2017 10:11:35 +0300 Subject: Execution of `active_storage:install` should respect `--quiet` during `rails new` --- railties/lib/rails/generators/app_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 4f3ecd9189..59ca4c849f 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -461,7 +461,7 @@ module Rails def run_active_storage unless skip_active_storage? - rails_command "active_storage:install" + rails_command "active_storage:install", capture: options[:quiet] end end -- cgit v1.2.3 From 165d5b601d44495452dcebba5a61b31b3be36da7 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 7 Nov 2017 07:35:54 +0900 Subject: Fix merge conflict and rubocop offences --- .../test/dispatch/routing_assertions_test.rb | 37 +++++++++++----------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/actionpack/test/dispatch/routing_assertions_test.rb b/actionpack/test/dispatch/routing_assertions_test.rb index a8f00af6de..a5198f2f13 100644 --- a/actionpack/test/dispatch/routing_assertions_test.rb +++ b/actionpack/test/dispatch/routing_assertions_test.rb @@ -1,4 +1,3 @@ -<<<<<<< HEAD # frozen_string_literal: true require "abstract_unit" @@ -23,16 +22,16 @@ class RoutingAssertionsTest < ActionController::TestCase engine.routes.draw do resources :books - scope 'secure', :constraints => { :protocol => 'https://' } do - resources :books, :controller => 'secure_books' + scope "secure", constraints: { protocol: "https://" } do + resources :books, controller: "secure_books" end - scope 'block', :constraints => lambda { |r| r.ssl? } do - resources :books, :controller => 'block_books' + scope "block", constraints: lambda { |r| r.ssl? } do + resources :books, controller: "block_books" end - scope 'query', :constraints => lambda { |r| r.params[:use_query] == 'true' } do - resources :books, :controller => 'query_books' + scope "query", constraints: lambda { |r| r.params[:use_query] == "true" } do + resources :books, controller: "query_books" end end @@ -113,43 +112,43 @@ class RoutingAssertionsTest < ActionController::TestCase end def test_assert_recognizes_with_engine - assert_recognizes({ :controller => 'books', :action => 'index' }, '/shelf/books') - assert_recognizes({ :controller => 'books', :action => 'show', :id => '1' }, '/shelf/books/1') + assert_recognizes({ controller: "books", action: "index" }, "/shelf/books") + assert_recognizes({ controller: "books", action: "show", id: "1" }, "/shelf/books/1") end def test_assert_recognizes_with_engine_and_extras - assert_recognizes({ :controller => 'books', :action => 'index', :page => '1' }, '/shelf/books', { :page => '1' }) + assert_recognizes({ controller: "books", action: "index", page: "1" }, "/shelf/books", page: "1") end def test_assert_recognizes_with_engine_and_method - assert_recognizes({ :controller => 'books', :action => 'create' }, { :path => '/shelf/books', :method => :post }) - assert_recognizes({ :controller => 'books', :action => 'update', :id => '1' }, { :path => '/shelf/books/1', :method => :put }) + assert_recognizes({ controller: "books", action: "create" }, { path: "/shelf/books", method: :post }) + assert_recognizes({ controller: "books", action: "update", id: "1" }, { path: "/shelf/books/1", method: :put }) end def test_assert_recognizes_with_engine_and_hash_constraint assert_raise(Assertion) do - assert_recognizes({ :controller => 'secure_books', :action => 'index' }, 'http://test.host/shelf/secure/books') + assert_recognizes({ controller: "secure_books", action: "index" }, "http://test.host/shelf/secure/books") end - assert_recognizes({ :controller => 'secure_books', :action => 'index', :protocol => 'https://' }, 'https://test.host/shelf/secure/books') + assert_recognizes({ controller: "secure_books", action: "index", protocol: "https://" }, "https://test.host/shelf/secure/books") end def test_assert_recognizes_with_engine_and_block_constraint assert_raise(Assertion) do - assert_recognizes({ :controller => 'block_books', :action => 'index' }, 'http://test.host/shelf/block/books') + assert_recognizes({ controller: "block_books", action: "index" }, "http://test.host/shelf/block/books") end - assert_recognizes({ :controller => 'block_books', :action => 'index' }, 'https://test.host/shelf/block/books') + assert_recognizes({ controller: "block_books", action: "index" }, "https://test.host/shelf/block/books") end def test_assert_recognizes_with_engine_and_query_constraint assert_raise(Assertion) do - assert_recognizes({ :controller => 'query_books', :action => 'index', :use_query => 'false' }, '/shelf/query/books', { :use_query => 'false' }) + assert_recognizes({ controller: "query_books", action: "index", use_query: "false" }, "/shelf/query/books", use_query: "false") end - assert_recognizes({ :controller => 'query_books', :action => 'index', :use_query => 'true' }, '/shelf/query/books', { :use_query => 'true' }) + assert_recognizes({ controller: "query_books", action: "index", use_query: "true" }, "/shelf/query/books", use_query: "true") end def test_assert_recognizes_raises_message_with_engine err = assert_raise(Assertion) do - assert_recognizes({ :controller => 'secure_books', :action => 'index' }, 'http://test.host/shelf/secure/books', {}, "This is a really bad msg") + assert_recognizes({ controller: "secure_books", action: "index" }, "http://test.host/shelf/secure/books", {}, "This is a really bad msg") end assert_match err.message, "This is a really bad msg" -- cgit v1.2.3 From 90fe2a42f0b68a66e970169d38e91a0126de7d3e Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Tue, 26 Sep 2017 00:10:17 +0300 Subject: Fix `bin/rails db:migrate` with specified `VERSION` Ensure that `bin/rails db:migrate` with specified `VERSION` reverts all migrations only if `VERSION` is `0`. Raise error if target migration doesn't exist. --- activerecord/CHANGELOG.md | 8 ++ activerecord/lib/active_record/migration.rb | 2 +- .../lib/active_record/railties/databases.rake | 19 ++- .../lib/active_record/tasks/database_tasks.rb | 15 +- activerecord/test/cases/migrator_test.rb | 20 +++ .../test/cases/tasks/database_tasks_test.rb | 149 +++++++++++++++++++- railties/test/application/rake/migrations_test.rb | 156 ++++++++++++++++++++- 7 files changed, 355 insertions(+), 14 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 4aa7ecfc7e..e6a41ec281 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,11 @@ +* Fix `bin/rails db:migrate` with specified `VERSION`. + `bin/rails db:migrate` with empty VERSION behaves as without `VERSION`. + Check a format of `VERSION`: Allow a migration version number + or name of a migration file. Raise error if format of `VERSION` is invalid. + Raise error if target migration doesn't exist. + + *bogdanvlviv* + * Fixed a bug where column orders for an index weren't written to db/schema.rb when using the sqlite adapter. diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 1485687053..d12a979a7f 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -1224,7 +1224,7 @@ module ActiveRecord # Return true if a valid version is not provided. def invalid_target? - !target && @target_version && @target_version > 0 + @target_version && @target_version != 0 && !target end def execute_migration_in_transaction(migration, direction) diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 723272b4b2..3bca2982e0 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -97,16 +97,27 @@ db_namespace = namespace :db do task up: [:environment, :load_config] do raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty? - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - ActiveRecord::Migrator.run(:up, ActiveRecord::Tasks::DatabaseTasks.migrations_paths, version) + ActiveRecord::Tasks::DatabaseTasks.check_target_version + + ActiveRecord::Migrator.run( + :up, + ActiveRecord::Tasks::DatabaseTasks.migrations_paths, + ActiveRecord::Tasks::DatabaseTasks.target_version + ) db_namespace["_dump"].invoke end # desc 'Runs the "down" for a given migration VERSION.' task down: [:environment, :load_config] do raise "VERSION is required - To go down one migration, use db:rollback" if !ENV["VERSION"] || ENV["VERSION"].empty? - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - ActiveRecord::Migrator.run(:down, ActiveRecord::Tasks::DatabaseTasks.migrations_paths, version) + + ActiveRecord::Tasks::DatabaseTasks.check_target_version + + ActiveRecord::Migrator.run( + :down, + ActiveRecord::Tasks::DatabaseTasks.migrations_paths, + ActiveRecord::Tasks::DatabaseTasks.target_version + ) db_namespace["_dump"].invoke end diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index ff388ff1f6..4657e51e6d 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -164,13 +164,12 @@ module ActiveRecord end def migrate - raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty? + check_target_version verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true - version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil scope = ENV["SCOPE"] verbose_was, Migration.verbose = Migration.verbose, verbose - Migrator.migrate(migrations_paths, version) do |migration| + Migrator.migrate(migrations_paths, target_version) do |migration| scope.blank? || scope == migration.scope end ActiveRecord::Base.clear_cache! @@ -178,6 +177,16 @@ module ActiveRecord Migration.verbose = verbose_was end + def check_target_version + if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"])) + raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`" + end + end + + def target_version + ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty? + end + def charset_current(environment = env) charset ActiveRecord::Base.configurations[environment] end diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb index ee10be119c..1047ba1367 100644 --- a/activerecord/test/cases/migrator_test.rb +++ b/activerecord/test/cases/migrator_test.rb @@ -66,6 +66,26 @@ class MigratorTest < ActiveRecord::TestCase list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] ActiveRecord::Migrator.new(:up, list, 3).run end + + assert_raises(ActiveRecord::UnknownMigrationVersionError) do + list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] + ActiveRecord::Migrator.new(:up, list, -1).run + end + + assert_raises(ActiveRecord::UnknownMigrationVersionError) do + list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] + ActiveRecord::Migrator.new(:up, list, 0).run + end + + assert_raises(ActiveRecord::UnknownMigrationVersionError) do + list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] + ActiveRecord::Migrator.new(:up, list, 3).migrate + end + + assert_raises(ActiveRecord::UnknownMigrationVersionError) do + list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] + ActiveRecord::Migrator.new(:up, list, -1).migrate + end end def test_finds_migrations diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb index 1495d2ab89..5a094ead42 100644 --- a/activerecord/test/cases/tasks/database_tasks_test.rb +++ b/activerecord/test/cases/tasks/database_tasks_test.rb @@ -357,8 +357,15 @@ module ActiveRecord ActiveRecord::Migration.expects(:verbose=).with(ActiveRecord::Migration.verbose) ActiveRecord::Tasks::DatabaseTasks.migrate + ENV["VERBOSE"] = "" + ENV["VERSION"] = "" + ActiveRecord::Migrator.expects(:migrate).with("custom/path", nil) + ActiveRecord::Migration.expects(:verbose=).with(true) + ActiveRecord::Migration.expects(:verbose=).with(ActiveRecord::Migration.verbose) + ActiveRecord::Tasks::DatabaseTasks.migrate + ENV["VERBOSE"] = "yes" - ENV["VERSION"] = "unknown" + ENV["VERSION"] = "0" ActiveRecord::Migrator.expects(:migrate).with("custom/path", 0) ActiveRecord::Migration.expects(:verbose=).with(true) ActiveRecord::Migration.expects(:verbose=).with(ActiveRecord::Migration.verbose) @@ -367,15 +374,47 @@ module ActiveRecord ENV["VERBOSE"], ENV["VERSION"] = verbose, version end - def test_migrate_raise_error_on_empty_version + def test_migrate_raise_error_on_invalid_version_format version = ENV["VERSION"] - ENV["VERSION"] = "" + + ENV["VERSION"] = "unknown" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "0.1.11" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "1.1.11" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "0 " + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "1." + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "1_" e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate } - assert_equal "Empty VERSION provided", e.message + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "1_name" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate } + assert_match(/Invalid format of target version/, e.message) ensure ENV["VERSION"] = version end + def test_migrate_raise_error_on_failed_check_target_version + ActiveRecord::Tasks::DatabaseTasks.stubs(:check_target_version).raises("foo") + + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.migrate } + assert_equal "foo", e.message + end + def test_migrate_clears_schema_cache_afterward ActiveRecord::Base.expects(:clear_cache!) ActiveRecord::Tasks::DatabaseTasks.migrate @@ -444,6 +483,108 @@ module ActiveRecord end end + class DatabaseTaskTargetVersionTest < ActiveRecord::TestCase + def test_target_version_returns_nil_if_version_does_not_exist + version = ENV.delete("VERSION") + assert_nil ActiveRecord::Tasks::DatabaseTasks.target_version + ensure + ENV["VERSION"] = version + end + + def test_target_version_returns_nil_if_version_is_empty + version = ENV["VERSION"] + + ENV["VERSION"] = "" + assert_nil ActiveRecord::Tasks::DatabaseTasks.target_version + ensure + ENV["VERSION"] = version + end + + def test_target_version_returns_converted_to_integer_env_version_if_version_exists + version = ENV["VERSION"] + + ENV["VERSION"] = "0" + assert_equal ENV["VERSION"].to_i, ActiveRecord::Tasks::DatabaseTasks.target_version + + ENV["VERSION"] = "42" + assert_equal ENV["VERSION"].to_i, ActiveRecord::Tasks::DatabaseTasks.target_version + + ENV["VERSION"] = "042" + assert_equal ENV["VERSION"].to_i, ActiveRecord::Tasks::DatabaseTasks.target_version + ensure + ENV["VERSION"] = version + end + end + + class DatabaseTaskCheckTargetVersionTest < ActiveRecord::TestCase + def test_check_target_version_does_not_raise_error_on_empty_version + version = ENV["VERSION"] + ENV["VERSION"] = "" + assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + ensure + ENV["VERSION"] = version + end + + def test_check_target_version_does_not_raise_error_if_version_is_not_setted + version = ENV.delete("VERSION") + assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + ensure + ENV["VERSION"] = version + end + + def test_check_target_version_raises_error_on_invalid_version_format + version = ENV["VERSION"] + + ENV["VERSION"] = "unknown" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "0.1.11" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "1.1.11" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "0 " + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "1." + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "1_" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + assert_match(/Invalid format of target version/, e.message) + + ENV["VERSION"] = "1_name" + e = assert_raise(RuntimeError) { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + assert_match(/Invalid format of target version/, e.message) + ensure + ENV["VERSION"] = version + end + + def test_check_target_version_does_not_raise_error_on_valid_version_format + version = ENV["VERSION"] + + ENV["VERSION"] = "0" + assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + + ENV["VERSION"] = "1" + assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + + ENV["VERSION"] = "001" + assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + + ENV["VERSION"] = "001_name.rb" + assert_nothing_raised { ActiveRecord::Tasks::DatabaseTasks.check_target_version } + ensure + ENV["VERSION"] = version + end + end + class DatabaseTasksStructureDumpTest < ActiveRecord::TestCase include DatabaseTasksSetupper diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb index 33f2b7038c..788f9160d6 100644 --- a/railties/test/application/rake/migrations_test.rb +++ b/railties/test/application/rake/migrations_test.rb @@ -37,9 +37,64 @@ module ApplicationTests assert_match(/AMigration: reverted/, output) end + test "migrate with specified VERSION in different formats" do + app_file "db/migrate/01_one_migration.rb", <<-MIGRATION + class OneMigration < ActiveRecord::Migration::Current + end + MIGRATION + + app_file "db/migrate/02_two_migration.rb", <<-MIGRATION + class TwoMigration < ActiveRecord::Migration::Current + end + MIGRATION + + app_file "db/migrate/03_three_migration.rb", <<-MIGRATION + class ThreeMigration < ActiveRecord::Migration::Current + end + MIGRATION + + rails "db:migrate" + + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/up\s+002\s+Two migration/, output) + assert_match(/up\s+003\s+Three migration/, output) + + rails "db:migrate", "VERSION=01_one_migration.rb" + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/down\s+002\s+Two migration/, output) + assert_match(/down\s+003\s+Three migration/, output) + + rails "db:migrate", "VERSION=3" + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/up\s+002\s+Two migration/, output) + assert_match(/up\s+003\s+Three migration/, output) + + rails "db:migrate", "VERSION=001" + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/down\s+002\s+Two migration/, output) + assert_match(/down\s+003\s+Three migration/, output) + end + test "migration with empty version" do - output = rails("db:migrate", "VERSION=", allow_failure: true) - assert_match(/Empty VERSION provided/, output) + app_file "db/migrate/01_one_migration.rb", <<-MIGRATION + class OneMigration < ActiveRecord::Migration::Current + end + MIGRATION + + app_file "db/migrate/02_two_migration.rb", <<-MIGRATION + class TwoMigration < ActiveRecord::Migration::Current + end + MIGRATION + + rails("db:migrate", "VERSION=") + + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/up\s+002\s+Two migration/, output) output = rails("db:migrate:redo", "VERSION=", allow_failure: true) assert_match(/Empty VERSION provided/, output) @@ -55,6 +110,34 @@ module ApplicationTests output = rails("db:migrate:down", allow_failure: true) assert_match(/VERSION is required - To go down one migration, use db:rollback/, output) + + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/up\s+002\s+Two migration/, output) + end + + test "migration with 0 version" do + app_file "db/migrate/01_one_migration.rb", <<-MIGRATION + class OneMigration < ActiveRecord::Migration::Current + end + MIGRATION + + app_file "db/migrate/02_two_migration.rb", <<-MIGRATION + class TwoMigration < ActiveRecord::Migration::Current + end + MIGRATION + + rails "db:migrate" + + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/up\s+002\s+Two migration/, output) + + rails "db:migrate", "VERSION=0" + + output = rails("db:migrate:status") + assert_match(/down\s+001\s+One migration/, output) + assert_match(/down\s+002\s+Two migration/, output) end test "model and migration generator with change syntax" do @@ -192,6 +275,75 @@ module ApplicationTests end end + test "raise error on any move when target migration does not exist" do + app_file "db/migrate/01_one_migration.rb", <<-MIGRATION + class OneMigration < ActiveRecord::Migration::Current + end + MIGRATION + + app_file "db/migrate/02_two_migration.rb", <<-MIGRATION + class TwoMigration < ActiveRecord::Migration::Current + end + MIGRATION + + rails "db:migrate" + + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/up\s+002\s+Two migration/, output) + + output = rails("db:migrate", "VERSION=3", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output) + assert_match(/No migration with version number 3/, output) + + output = rails("db:migrate:status") + assert_match(/up\s+001\s+One migration/, output) + assert_match(/up\s+002\s+Two migration/, output) + end + + test "raise error on any move when VERSION has invalid format" do + output = rails("db:migrate", "VERSION=unknown", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate", "VERSION=0.1.11", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate", "VERSION=1.1.11", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate", "VERSION='0 '", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate", "VERSION=1.", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate", "VERSION=1_", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate", "VERSION=1_name", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate:redo", "VERSION=unknown", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate:up", "VERSION=unknown", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + + output = rails("db:migrate:down", "VERSION=unknown", allow_failure: true) + assert_match(/rails aborted!/, output) + assert_match(/Invalid format of target version/, output) + end + test "migration status after rollback and redo without timestamps" do add_to_config("config.active_record.timestamped_migrations = false") -- cgit v1.2.3 From 3ff2c158372bce45ea46bd3b49c49022a4259aba Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Sun, 5 Nov 2017 22:25:37 +0000 Subject: Add cases to test combining validation conditions - Test condition that is defined by array of conditions - Test condition that is defined by combining :if and :unless - Test local condition that is defined by :if - Test local condition that is defined by :unless See http://edgeguides.rubyonrails.org/active_record_validations.html#combining-validation-conditions --- .../validations/conditional_validation_test.rb | 49 +++++++++++++++++++++- .../validations/numericality_validation_test.rb | 2 +- .../test/cases/validations/validates_test.rb | 12 ++++-- activemodel/test/models/person.rb | 4 ++ activemodel/test/models/topic.rb | 2 +- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/activemodel/test/cases/validations/conditional_validation_test.rb b/activemodel/test/cases/validations/conditional_validation_test.rb index aa027c4128..caea8b65ef 100644 --- a/activemodel/test/cases/validations/conditional_validation_test.rb +++ b/activemodel/test/cases/validations/conditional_validation_test.rb @@ -18,6 +18,22 @@ class ConditionalValidationTest < ActiveModel::TestCase assert_equal ["hoo 5"], t.errors["title"] end + def test_if_validation_using_array_of_true_methods + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: [:condition_is_true, :condition_is_true]) + t = Topic.new("title" => "uhohuhoh", "content" => "whatever") + assert t.invalid? + assert t.errors[:title].any? + assert_equal ["hoo 5"], t.errors["title"] + end + + def test_unless_validation_using_array_of_false_methods + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: [:condition_is_false, :condition_is_false]) + t = Topic.new("title" => "uhohuhoh", "content" => "whatever") + assert t.invalid? + assert t.errors[:title].any? + assert_equal ["hoo 5"], t.errors["title"] + end + def test_unless_validation_using_method_true # When the method returns true Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: :condition_is_true) @@ -26,9 +42,23 @@ class ConditionalValidationTest < ActiveModel::TestCase assert_empty t.errors[:title] end + def test_if_validation_using_array_of_true_and_false_methods + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: [:condition_is_true, :condition_is_false]) + t = Topic.new("title" => "uhohuhoh", "content" => "whatever") + assert t.valid? + assert_empty t.errors[:title] + end + + def test_unless_validation_using_array_of_true_and_felse_methods + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: [:condition_is_true, :condition_is_false]) + t = Topic.new("title" => "uhohuhoh", "content" => "whatever") + assert t.valid? + assert_empty t.errors[:title] + end + def test_if_validation_using_method_false # When the method returns false - Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: :condition_is_true_but_its_not) + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: :condition_is_false) t = Topic.new("title" => "uhohuhoh", "content" => "whatever") assert t.valid? assert_empty t.errors[:title] @@ -36,7 +66,7 @@ class ConditionalValidationTest < ActiveModel::TestCase def test_unless_validation_using_method_false # When the method returns false - Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: :condition_is_true_but_its_not) + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", unless: :condition_is_false) t = Topic.new("title" => "uhohuhoh", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? @@ -80,4 +110,19 @@ class ConditionalValidationTest < ActiveModel::TestCase assert t.errors[:title].any? assert_equal ["hoo 5"], t.errors["title"] end + + def test_validation_using_conbining_if_true_and_unless_true_conditions + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: :condition_is_true, unless: :condition_is_true) + t = Topic.new("title" => "uhohuhoh", "content" => "whatever") + assert t.valid? + assert_empty t.errors[:title] + end + + def test_validation_using_conbining_if_true_and_unless_false_conditions + Topic.validates_length_of(:title, maximum: 5, too_long: "hoo %{count}", if: :condition_is_true, unless: :condition_is_false) + t = Topic.new("title" => "uhohuhoh", "content" => "whatever") + assert t.invalid? + assert t.errors[:title].any? + assert_equal ["hoo 5"], t.errors["title"] + end end diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb index 001815e28f..fbbaf8a30c 100644 --- a/activemodel/test/cases/validations/numericality_validation_test.rb +++ b/activemodel/test/cases/validations/numericality_validation_test.rb @@ -59,7 +59,7 @@ class NumericalityValidationTest < ActiveModel::TestCase end def test_validates_numericality_of_with_integer_only_and_symbol_as_value - Topic.validates_numericality_of :approved, only_integer: :condition_is_true_but_its_not + Topic.validates_numericality_of :approved, only_integer: :condition_is_false invalid!(NIL + BLANK + JUNK) valid!(FLOATS + INTEGERS + BIGDECIMAL + INFINITY) diff --git a/activemodel/test/cases/validations/validates_test.rb b/activemodel/test/cases/validations/validates_test.rb index 77cb8ebdc1..7f32f5dc74 100644 --- a/activemodel/test/cases/validations/validates_test.rb +++ b/activemodel/test/cases/validations/validates_test.rb @@ -62,17 +62,23 @@ class ValidatesTest < ActiveModel::TestCase end def test_validates_with_if_as_local_conditions - Person.validates :karma, presence: true, email: { unless: :condition_is_true } + Person.validates :karma, presence: true, email: { if: :condition_is_false } person = Person.new person.valid? assert_equal ["can't be blank"], person.errors[:karma] end def test_validates_with_if_as_shared_conditions - Person.validates :karma, presence: true, email: true, if: :condition_is_true + Person.validates :karma, presence: true, email: true, if: :condition_is_false + person = Person.new + assert person.valid? + end + + def test_validates_with_unless_as_local_conditions + Person.validates :karma, presence: true, email: { unless: :condition_is_true } person = Person.new person.valid? - assert_equal ["can't be blank", "is not an email"], person.errors[:karma].sort + assert_equal ["can't be blank"], person.errors[:karma] end def test_validates_with_unless_shared_conditions diff --git a/activemodel/test/models/person.rb b/activemodel/test/models/person.rb index b61fdf76b1..8dd8ceadad 100644 --- a/activemodel/test/models/person.rb +++ b/activemodel/test/models/person.rb @@ -9,6 +9,10 @@ class Person def condition_is_true true end + + def condition_is_false + false + end end class Person::Gender diff --git a/activemodel/test/models/topic.rb b/activemodel/test/models/topic.rb index 2f4e92c3b2..b0af00ee45 100644 --- a/activemodel/test/models/topic.rb +++ b/activemodel/test/models/topic.rb @@ -23,7 +23,7 @@ class Topic true end - def condition_is_true_but_its_not + def condition_is_false false end -- cgit v1.2.3 From 3f1695bb9c008b7cb1840e09e640f3ec0c59a564 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 7 Nov 2017 08:44:44 +0900 Subject: Remove useless `associated_records_by_owner` `associated_records_by_owner` had returned customizing result before calling `associate_records_to_owner` for through association subclasses. Since #22115, `associate_records_to_owner` is called in the method and not returned owner and result pairs. Removing the method will reduce method call and block call nesting. --- .../associations/preloader/association.rb | 22 ++++++++-------------- .../associations/preloader/through_association.rb | 4 ++-- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index b0c41c7d5f..e77761692d 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -17,8 +17,14 @@ module ActiveRecord end def run(preloader) - associated_records_by_owner(preloader) do |owner, records| - associate_records_to_owner(owner, records) + records = load_records do |record| + owner = owners_by_key[convert_key(record[association_key_name])] + association = owner.association(reflection.name) + association.set_inverse_instance(record) + end + + owners.each do |owner| + associate_records_to_owner(owner, records[convert_key(owner[owner_key_name])] || []) end end @@ -33,18 +39,6 @@ module ActiveRecord reflection.join_foreign_key end - def associated_records_by_owner(preloader) - records = load_records do |record| - owner = owners_by_key[convert_key(record[association_key_name])] - association = owner.association(reflection.name) - association.set_inverse_instance(record) - end - - owners.each_with_object({}) do |owner, result| - yield(owner, records[convert_key(owner[owner_key_name])] || []) - end - end - def associate_records_to_owner(owner, records) raise NotImplementedError end diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index 1bb7e98231..b1813ba66b 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -12,7 +12,7 @@ module ActiveRecord reflection.source_reflection end - def associated_records_by_owner(preloader) + def run(preloader) already_loaded = owners.first.association(through_reflection.name).loaded? through_scope = through_scope() reflection_scope = target_reflection_scope @@ -43,7 +43,7 @@ module ActiveRecord result.sort_by! { |rhs| preload_index[rhs] } if reflection_scope.order_values.any? result.uniq! if reflection_scope.distinct_value end - yield(owner, result) + associate_records_to_owner(owner, result) end end -- cgit v1.2.3 From 86938c495e282e6a61c16a9e1d77582e22c0a4fc Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Mon, 6 Nov 2017 21:29:37 -0500 Subject: Fix streaming downloads from S3/Azure Storage Closes #31073. --- .../lib/active_storage/service/azure_storage_service.rb | 8 ++++---- activestorage/lib/active_storage/service/s3_service.rb | 6 +++--- activestorage/test/service/shared_service_tests.rb | 10 ++++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/activestorage/lib/active_storage/service/azure_storage_service.rb b/activestorage/lib/active_storage/service/azure_storage_service.rb index 27dd192ce6..f3877ad9c9 100644 --- a/activestorage/lib/active_storage/service/azure_storage_service.rb +++ b/activestorage/lib/active_storage/service/azure_storage_service.rb @@ -28,7 +28,7 @@ module ActiveStorage end end - def download(key) + def download(key, &block) if block_given? instrument :streaming_download, key do stream(key, &block) @@ -108,15 +108,15 @@ module ActiveStorage end # Reads the object for the given key in chunks, yielding each to the block. - def stream(key, options = {}, &block) + def stream(key) blob = blob_for(key) chunk_size = 5.megabytes offset = 0 while offset < blob.properties[:content_length] - _, io = blobs.get_blob(container, key, start_range: offset, end_range: offset + chunk_size - 1) - yield io + _, chunk = blobs.get_blob(container, key, start_range: offset, end_range: offset + chunk_size - 1) + yield chunk.force_encoding(Encoding::BINARY) offset += chunk_size end end diff --git a/activestorage/lib/active_storage/service/s3_service.rb b/activestorage/lib/active_storage/service/s3_service.rb index 3e93cdd072..958b172efb 100644 --- a/activestorage/lib/active_storage/service/s3_service.rb +++ b/activestorage/lib/active_storage/service/s3_service.rb @@ -26,7 +26,7 @@ module ActiveStorage end end - def download(key) + def download(key, &block) if block_given? instrument :streaming_download, key do stream(key, &block) @@ -85,14 +85,14 @@ module ActiveStorage end # Reads the object for the given key in chunks, yielding each to the block. - def stream(key, options = {}, &block) + def stream(key, &block) object = object_for(key) chunk_size = 5.megabytes offset = 0 while offset < object.content_length - yield object.read(options.merge(range: "bytes=#{offset}-#{offset + chunk_size - 1}")) + yield object.get(range: "bytes=#{offset}-#{offset + chunk_size - 1}").body.read.force_encoding(Encoding::BINARY) offset += chunk_size end end diff --git a/activestorage/test/service/shared_service_tests.rb b/activestorage/test/service/shared_service_tests.rb index a9e1cb6ce9..ade91ab89a 100644 --- a/activestorage/test/service/shared_service_tests.rb +++ b/activestorage/test/service/shared_service_tests.rb @@ -50,6 +50,16 @@ module ActiveStorage::Service::SharedServiceTests assert_equal FIXTURE_DATA, @service.download(FIXTURE_KEY) end + test "downloading in chunks" do + chunks = [] + + @service.download(FIXTURE_KEY) do |chunk| + chunks << chunk + end + + assert_equal [ FIXTURE_DATA ], chunks + end + test "existing" do assert @service.exist?(FIXTURE_KEY) assert_not @service.exist?(FIXTURE_KEY + "nonsense") -- cgit v1.2.3 From 38158451103be572d6e81e971797938df7bd22ea Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Tue, 7 Nov 2017 14:23:16 +0900 Subject: Fix comment in `check_class_collision` [ci skip] `ScaffoldBase` was changed to `ResourceHelpers` by 0efedf2. --- railties/lib/rails/generators/named_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 60625283ac..99165168fd 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -221,7 +221,7 @@ module Rails # def self.check_class_collision(options = {}) # :doc: define_method :check_class_collision do - name = if respond_to?(:controller_class_name) # for ScaffoldBase + name = if respond_to?(:controller_class_name) # for ResourceHelpers controller_class_name else class_name -- cgit v1.2.3 From bbe437faecca5fd6bdc2327a4bc7a31ba21afe2e Mon Sep 17 00:00:00 2001 From: Genadi Samokovarov Date: Tue, 7 Nov 2017 10:28:19 +0200 Subject: Use plain assert in assert_changes to avoid MT6 refutes Seeing the previously issued PRs about it, we can avoid the `nil` comparisons that can happen in `assert_changes` by using plain `assert` calls. This is to avoid a deprecation warning about comparing `nil` values in `assert_equal` for Minitest 5 and a crash in Minitest 6. You can see the preparations done in [`assert_equal`][ae]. You can also see that [`assert`][a] does not care about `nil`s. [ae]: https://github.com/seattlerb/minitest/blob/ca6a71ca901016db09a5ad466b4adea4b52a504a/lib/minitest/assertions.rb#L159-L188 [a]: https://github.com/seattlerb/minitest/blob/ca6a71ca901016db09a5ad466b4adea4b52a504a/lib/minitest/assertions.rb#L131-L142 --- activesupport/lib/active_support/testing/assertions.rb | 9 ++------- activesupport/test/test_case_test.rb | 5 +++-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb index 46eed73d24..b24aa36ede 100644 --- a/activesupport/lib/active_support/testing/assertions.rb +++ b/activesupport/lib/active_support/testing/assertions.rb @@ -159,7 +159,7 @@ module ActiveSupport if to == UNTRACKED error = "#{expression.inspect} didn't change" error = "#{message}.\n#{error}" if message - assert_not_equal before, after, error + assert before != after, error else error = "#{expression.inspect} didn't change to #{to}" error = "#{message}.\n#{error}" if message @@ -190,12 +190,7 @@ module ActiveSupport error = "#{expression.inspect} did change to #{after}" error = "#{message}.\n#{error}" if message - - if before.nil? - assert_nil after, error - else - assert_equal before, after, error - end + assert before == after, error retval end diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index 9bc9183668..84e4953fe2 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -179,6 +179,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase end def test_assert_changes_works_with_any_object + # Silences: instance variable @new_object not initialized. retval = silence_warnings do assert_changes :@new_object, from: nil, to: 42 do @new_object = 42 @@ -201,7 +202,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase def test_assert_changes_with_to_and_case_operator token = nil - assert_changes -> { token }, to: /\w{32}/ do + assert_changes -> { token }, to: /\w{32}/ do token = SecureRandom.hex end end @@ -236,7 +237,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase end end - assert_equal "@object.num should not change.\n\"@object.num\" did change to 1.\nExpected: 0\n Actual: 1", error.message + assert_equal "@object.num should not change.\n\"@object.num\" did change to 1", error.message end end -- cgit v1.2.3 From 5bbe6924529bc510d104b8bc3756a1e2f0a451dd Mon Sep 17 00:00:00 2001 From: Takumasa Ochi <4468155+aeroastro@users.noreply.github.com> Date: Tue, 7 Nov 2017 18:15:07 +0900 Subject: Fix typo on ActionDispatc::HTTP::FilterParameters --- actionpack/lib/action_dispatch/http/filter_parameters.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index b7141cc1b9..e50672e191 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -9,7 +9,7 @@ module ActionDispatch # sub-hashes of the params hash to filter. Filtering only certain sub-keys # from a hash is possible by using the dot notation: 'credit_card.number'. # If a block is given, each key and value of the params hash and all - # sub-hashes is passed to it, the value or key can be replaced using + # sub-hashes is passed to it, where the value or the key can be replaced using # String#replace or similar method. # # env["action_dispatch.parameter_filter"] = [:password] @@ -48,7 +48,7 @@ module ActionDispatch @filtered_env ||= env_filter.filter(@env) end - # Reconstructed a path with all sensitive GET parameters replaced. + # Reconstructs a path with all sensitive GET parameters replaced. def filtered_path @filtered_path ||= query_string.empty? ? path : "#{path}?#{filtered_query_string}" end -- cgit v1.2.3 From daf77db65d9d5e295ee3ba86605988875cb834e4 Mon Sep 17 00:00:00 2001 From: George Claghorn Date: Tue, 7 Nov 2017 09:06:23 -0500 Subject: Remove needless block parameter --- activestorage/lib/active_storage/service/s3_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activestorage/lib/active_storage/service/s3_service.rb b/activestorage/lib/active_storage/service/s3_service.rb index 958b172efb..6957119780 100644 --- a/activestorage/lib/active_storage/service/s3_service.rb +++ b/activestorage/lib/active_storage/service/s3_service.rb @@ -85,7 +85,7 @@ module ActiveStorage end # Reads the object for the given key in chunks, yielding each to the block. - def stream(key, &block) + def stream(key) object = object_for(key) chunk_size = 5.megabytes -- cgit v1.2.3 From 67db41aa7f17c2d34eb5a914ac7a6b2574930ff4 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Wed, 8 Nov 2017 12:15:27 +0900 Subject: Do not run `active_storage:install` when bundle install is skipped In order to execute the `rails` command, need to run bundle install in advance. Therefore, if skipped bundle install, `rails` command may fail and should not do it. --- railties/lib/rails/generators/app_base.rb | 6 +++++- railties/test/generators/app_generator_test.rb | 16 +++++++++++++++- railties/test/generators/shared_generator_tests.rb | 1 - railties/test/railties/engine_test.rb | 4 ++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 59ca4c849f..60e54cc365 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -461,7 +461,11 @@ module Rails def run_active_storage unless skip_active_storage? - rails_command "active_storage:install", capture: options[:quiet] + if bundle_install? + rails_command "active_storage:install", capture: options[:quiet] + else + log("Active Storage installation was skipped. Please run 'bin/rails active_storage:install' to install Active Storage files.") + end end end diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index c5a59edab2..1de79e82e2 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -68,7 +68,6 @@ DEFAULT_APP_FILES = %w( config/spring.rb config/storage.yml db - db/migrate db/seeds.rb lib lib/tasks @@ -304,6 +303,21 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "Gemfile", /^# gem 'mini_magick'/ end + def test_active_storage_install + command_check = -> command, _ do + @binstub_called ||= 0 + case command + when "active_storage:install" + @binstub_called += 1 + assert_equal 1, @binstub_called, "active_storage:install expected to be called once, but was called #{@install_called} times." + end + end + + generator.stub :rails_command, command_check do + quietly { generator.invoke_all } + end + end + def test_app_update_does_not_generate_active_storage_contents_when_skip_active_storage_is_given app_root = File.join(destination_root, "myapp") run_generator [app_root, "--skip-active-storage"] diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index ed09847443..ba8ee13526 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -222,7 +222,6 @@ module SharedGeneratorTests end assert_file "#{application_path}/config/storage.yml" - assert_directory "#{application_path}/db/migrate" assert_directory "#{application_path}/storage" assert_directory "#{application_path}/tmp/storage" diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 132b3b3a6e..fc710feb63 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -90,6 +90,8 @@ module RailtiesTest boot_rails Dir.chdir(app_path) do + # Install Active Storage migration file first so as not to affect test. + `bundle exec rake active_storage:install` output = `bundle exec rake bukkits:install:migrations` ["CreateUsers", "AddLastNameToUsers", "CreateSessions"].each do |migration_name| @@ -175,6 +177,8 @@ module RailtiesTest boot_rails Dir.chdir(app_path) do + # Install Active Storage migration file first so as not to affect test. + `bundle exec rake active_storage:install` output = `bundle exec rake railties:install:migrations`.split("\n") assert_match(/Copied migration \d+_create_users\.core_engine\.rb from core_engine/, output.first) -- cgit v1.2.3 From 8e1dca10cd98bdc8bb00592f3d90926309b22a18 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Wed, 8 Nov 2017 12:32:12 +0900 Subject: Remove unnecessary migration deletion Since isolation application is generated with the `--skip-gemfile` option, so `active_storage:install` is not executed. --- railties/test/application/bin_setup_test.rb | 4 ---- railties/test/application/rackup_test.rb | 1 - railties/test/application/rake/dbs_test.rb | 4 ---- railties/test/application/test_runner_test.rb | 5 ----- railties/test/application/test_test.rb | 5 ----- 5 files changed, 19 deletions(-) diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb index 9fac0435e4..54934dbe24 100644 --- a/railties/test/application/bin_setup_test.rb +++ b/railties/test/application/bin_setup_test.rb @@ -16,8 +16,6 @@ module ApplicationTests def test_bin_setup Dir.chdir(app_path) do - FileUtils.rm_rf("db/migrate") - app_file "db/schema.rb", <<-RUBY ActiveRecord::Schema.define(version: 20140423102712) do create_table(:articles) {} @@ -39,8 +37,6 @@ module ApplicationTests def test_bin_setup_output Dir.chdir(app_path) do - FileUtils.rm_rf("db/migrate") - app_file "db/schema.rb", "" output = `bin/setup 2>&1` diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb index 1dcc2826f0..383f18a7da 100644 --- a/railties/test/application/rackup_test.rb +++ b/railties/test/application/rackup_test.rb @@ -26,7 +26,6 @@ module ApplicationTests test "config.ru can be racked up" do Dir.chdir app_path do - FileUtils.rm_rf("db/migrate") @app = rackup assert_welcome get("/") end diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index 009f2887c9..fd22477539 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -287,8 +287,6 @@ module ApplicationTests ENV.delete "RAILS_ENV" ENV.delete "RACK_ENV" - Dir.chdir(app_path) { FileUtils.rm_rf("db/migrate") } - app_file "db/schema.rb", <<-RUBY ActiveRecord::Schema.define(version: "1") do create_table :users do |t| @@ -310,8 +308,6 @@ module ApplicationTests end test "db:setup sets ar_internal_metadata" do - Dir.chdir(app_path) { FileUtils.rm_rf("db/migrate") } - app_file "db/schema.rb", "" rails "db:setup" diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb index 30bd283b48..e92a0466dd 100644 --- a/railties/test/application/test_runner_test.rb +++ b/railties/test/application/test_runner_test.rb @@ -11,7 +11,6 @@ module ApplicationTests def setup build_app create_schema - remove_migrations end def teardown @@ -728,10 +727,6 @@ module ApplicationTests app_file "db/schema.rb", "" end - def remove_migrations - Dir.chdir(app_path) { FileUtils.rm_rf("db/migrate") } - end - def create_test_file(path = :unit, name = "test", pass: true) app_file "test/#{path}/#{name}_test.rb", <<-RUBY require 'test_helper' diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index 50238ed682..0a51e98656 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -8,7 +8,6 @@ module ApplicationTests def setup build_app - remove_migrations end def teardown @@ -321,10 +320,6 @@ Expected: ["id", "name"] end private - def remove_migrations - Dir.chdir(app_path) { FileUtils.rm_rf("db/migrate") } - end - def assert_unsuccessful_run(name, message) result = run_test_file(name) assert_not_equal 0, $?.to_i -- cgit v1.2.3 From 8d60dcd024e72be7aa90de62fe8e1005c2e254c2 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Wed, 8 Nov 2017 16:46:57 +0900 Subject: Fix output of `select_tag` with `include_blank: true` [ci skip] Since #24923, if use `select_tag` with `include_blank: true`, an empty label is added. --- actionview/lib/action_view/helpers/form_tag_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionview/lib/action_view/helpers/form_tag_helper.rb b/actionview/lib/action_view/helpers/form_tag_helper.rb index 80d53c2c6e..e86e18dd78 100644 --- a/actionview/lib/action_view/helpers/form_tag_helper.rb +++ b/actionview/lib/action_view/helpers/form_tag_helper.rb @@ -115,7 +115,7 @@ module ActionView # # # # select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: true - # # => + # # => # # select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: "All" # # => -- cgit v1.2.3 From cfe46db8e29bbd0b14e4111ea8e37ea74be058d5 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Wed, 8 Nov 2017 17:08:23 +0900 Subject: Use released `redis-namespace` instead of master version The `redis-namespace` 1.6.0 includes redis-rb 4.0 support. --- Gemfile | 3 +-- Gemfile.lock | 11 +++-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 2704e1e806..3f8cd57853 100644 --- a/Gemfile +++ b/Gemfile @@ -80,8 +80,7 @@ group :cable do gem "hiredis", require: false gem "redis", "~> 4.0", require: false - # For Redis 4.0 support. Unreleased 9cb81bf. - gem "redis-namespace", github: "resque/redis-namespace" + gem "redis-namespace" gem "websocket-client-simple", github: "matthewd/websocket-client-simple", branch: "close-race", require: false diff --git a/Gemfile.lock b/Gemfile.lock index cc3b0508c5..d0bfe589be 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -52,13 +52,6 @@ GIT sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) -GIT - remote: https://github.com/resque/redis-namespace.git - revision: 1403f511f6ae1ec9a8f330298a4cacf73fb10afc - specs: - redis-namespace (1.5.3) - redis (>= 3.0.4) - GIT remote: https://github.com/robin850/sdoc.git revision: 0e340352f3ab2f196c8a8743f83c2ee286e4f71c @@ -409,6 +402,8 @@ GEM rdoc (5.1.0) redcarpet (3.2.3) redis (4.0.1) + redis-namespace (1.6.0) + redis (>= 3.0.4) representable (3.0.4) declarative (< 0.1.0) declarative-option (< 0.2.0) @@ -563,7 +558,7 @@ DEPENDENCIES rb-inotify! redcarpet (~> 3.2.3) redis (~> 4.0) - redis-namespace! + redis-namespace resque resque-scheduler! rubocop (>= 0.47) -- cgit v1.2.3 From 2b434d6f79813dcad162b158fd2b60e34a725ba1 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Tue, 7 Nov 2017 11:33:08 +0000 Subject: Allow `Range#include?` on TWZ ranges In #11474 we prevented TWZ ranges being iterated over which matched Ruby's handling of Time ranges and as a consequence `include?` stopped working with both Time ranges and TWZ ranges. However in ruby/ruby@b061634 support was added for `include?` to use `cover?` for 'linear' objects. Since we have no way of making Ruby consider TWZ instances as 'linear' we have to override `Range#include?`. Fixes #30799. --- activesupport/CHANGELOG.md | 13 ++++++++++++ activesupport/lib/active_support/core_ext/range.rb | 1 + .../lib/active_support/core_ext/range/each.rb | 4 +++- .../core_ext/range/include_time_with_zone.rb | 23 ++++++++++++++++++++++ activesupport/test/core_ext/range_ext_test.rb | 9 ++++++--- 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 activesupport/lib/active_support/core_ext/range/include_time_with_zone.rb diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 9c27c68919..780c887b49 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,16 @@ +* Allow `Range#include?` on TWZ ranges + + In #11474 we prevented TWZ ranges being iterated over which matched + Ruby's handling of Time ranges and as a consequence `include?` + stopped working with both Time ranges and TWZ ranges. However in + ruby/ruby@b061634 support was added for `include?` to use `cover?` + for 'linear' objects. Since we have no way of making Ruby consider + TWZ instances as 'linear' we have to override `Range#include?`. + + Fixes #30799. + + *Andrew White* + * Fix acronym support in `humanize` Acronym inflections are stored with lowercase keys in the hash but diff --git a/activesupport/lib/active_support/core_ext/range.rb b/activesupport/lib/active_support/core_ext/range.rb index 51ae0ddd21..4074e91d17 100644 --- a/activesupport/lib/active_support/core_ext/range.rb +++ b/activesupport/lib/active_support/core_ext/range.rb @@ -2,5 +2,6 @@ require "active_support/core_ext/range/conversions" require "active_support/core_ext/range/include_range" +require "active_support/core_ext/range/include_time_with_zone" require "active_support/core_ext/range/overlaps" require "active_support/core_ext/range/each" diff --git a/activesupport/lib/active_support/core_ext/range/each.rb b/activesupport/lib/active_support/core_ext/range/each.rb index cdff6393d7..2f22cd0e92 100644 --- a/activesupport/lib/active_support/core_ext/range/each.rb +++ b/activesupport/lib/active_support/core_ext/range/each.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "active_support/time_with_zone" + module ActiveSupport module EachTimeWithZone #:nodoc: def each(&block) @@ -15,7 +17,7 @@ module ActiveSupport private def ensure_iteration_allowed - raise TypeError, "can't iterate from #{first.class}" if first.is_a?(Time) + raise TypeError, "can't iterate from #{first.class}" if first.is_a?(TimeWithZone) end end end diff --git a/activesupport/lib/active_support/core_ext/range/include_time_with_zone.rb b/activesupport/lib/active_support/core_ext/range/include_time_with_zone.rb new file mode 100644 index 0000000000..5f80acf68e --- /dev/null +++ b/activesupport/lib/active_support/core_ext/range/include_time_with_zone.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require "active_support/time_with_zone" + +module ActiveSupport + module IncludeTimeWithZone #:nodoc: + # Extends the default Range#include? to support ActiveSupport::TimeWithZone. + # + # (1.hour.ago..1.hour.from_now).include?(Time.current) # => true + # + def include?(value) + if first.is_a?(TimeWithZone) + cover?(value) + elsif last.is_a?(TimeWithZone) + cover?(value) + else + super + end + end + end +end + +Range.prepend(ActiveSupport::IncludeTimeWithZone) diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index 0467123e55..049fac8fd4 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -121,9 +121,12 @@ class RangeTest < ActiveSupport::TestCase def test_include_on_time_with_zone twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"] , Time.utc(2006, 11, 28, 10, 30)) - assert_raises TypeError do - ((twz - 1.hour)..twz).include?(twz) - end + assert ((twz - 1.hour)..twz).include?(twz) + end + + def test_case_equals_on_time_with_zone + twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Eastern Time (US & Canada)"] , Time.utc(2006, 11, 28, 10, 30)) + assert ((twz - 1.hour)..twz) === twz end def test_date_time_with_each -- cgit v1.2.3 From 0c2cb880e34c943275758ca6a6ff84afa7a29fba Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 8 Nov 2017 20:08:19 +0900 Subject: Don't expose internal methods in `Preloader::ThroughAssociation` `through_reflection` and `source_reflection` are used only in the class. --- .../associations/preloader/through_association.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index b1813ba66b..762275fbad 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -4,14 +4,6 @@ module ActiveRecord module Associations class Preloader module ThroughAssociation #:nodoc: - def through_reflection - reflection.through_reflection - end - - def source_reflection - reflection.source_reflection - end - def run(preloader) already_loaded = owners.first.association(through_reflection.name).loaded? through_scope = through_scope() @@ -48,6 +40,13 @@ module ActiveRecord end private + def through_reflection + reflection.through_reflection + end + + def source_reflection + reflection.source_reflection + end def preload_index @preload_index ||= @preloaded_records.each_with_object({}).with_index do |(id, result), index| -- cgit v1.2.3 From 65aa0b7e3448f849a91b6f510b78d4303ff44dbc Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 8 Nov 2017 20:28:52 +0900 Subject: Don't expose accessors which are internal used only --- activerecord/lib/active_record/associations/preloader.rb | 5 +++-- activerecord/lib/active_record/associations/preloader/association.rb | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb index e1754d4a19..5a93a89d0a 100644 --- a/activerecord/lib/active_record/associations/preloader.rb +++ b/activerecord/lib/active_record/associations/preloader.rb @@ -166,8 +166,6 @@ module ActiveRecord end class AlreadyLoaded # :nodoc: - attr_reader :owners, :reflection - def initialize(klass, owners, reflection, preload_scope) @owners = owners @reflection = reflection @@ -178,6 +176,9 @@ module ActiveRecord def preloaded_records owners.flat_map { |owner| owner.association(reflection.name).target } end + + protected + attr_reader :owners, :reflection end # Returns a class containing the logic needed to load preload the data diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index e77761692d..19c337dc39 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -4,7 +4,6 @@ module ActiveRecord module Associations class Preloader class Association #:nodoc: - attr_reader :owners, :reflection, :preload_scope, :model, :klass attr_reader :preloaded_records def initialize(klass, owners, reflection, preload_scope) @@ -28,6 +27,9 @@ module ActiveRecord end end + protected + attr_reader :owners, :reflection, :preload_scope, :model, :klass + private # The name of the key on the associated records def association_key_name -- cgit v1.2.3 From af91eff3fa395a0a57f8002b3b92e5d053cd2d7d Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 9 Nov 2017 05:08:26 +0900 Subject: Consolidate redundant `if` and `unless` with the same condition --- activerecord/test/cases/transaction_isolation_test.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/activerecord/test/cases/transaction_isolation_test.rb b/activerecord/test/cases/transaction_isolation_test.rb index b1ebccdcc3..eaafd13360 100644 --- a/activerecord/test/cases/transaction_isolation_test.rb +++ b/activerecord/test/cases/transaction_isolation_test.rb @@ -15,9 +15,7 @@ unless ActiveRecord::Base.connection.supports_transaction_isolation? end end end -end - -if ActiveRecord::Base.connection.supports_transaction_isolation? +else class TransactionIsolationTest < ActiveRecord::TestCase self.use_transactional_tests = false -- cgit v1.2.3 From 89603b41edbaaed5cab4964a30caa8bda9285879 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 9 Nov 2017 05:27:30 +0900 Subject: `Mysql2Adapter` should pass `ConcurrentTransactionTest` --- activerecord/test/cases/transactions_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 7fd125ab74..91032945a6 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -954,7 +954,7 @@ class TransactionsWithTransactionalFixturesTest < ActiveRecord::TestCase end end if Topic.connection.supports_savepoints? -if current_adapter?(:PostgreSQLAdapter) +if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter) class ConcurrentTransactionTest < TransactionTest # This will cause transactions to overlap and fail unless they are performed on # separate database connections. -- cgit v1.2.3 From d5ad63766eb9e31e3589a3571142042ab1a15bb4 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Wed, 8 Nov 2017 21:39:35 +0000 Subject: Remove redundant passing --skip-active-storage in test cases These were added in #30101, after #31084 it became redundant. --- railties/test/generators/app_generator_test.rb | 4 ++-- railties/test/generators/plugin_generator_test.rb | 2 +- railties/test/generators/plugin_test_runner_test.rb | 2 +- railties/test/generators/shared_generator_tests.rb | 2 +- railties/test/generators/test_runner_in_engine_test.rb | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 1de79e82e2..78962ee30b 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -423,7 +423,7 @@ class AppGeneratorTest < Rails::Generators::TestCase end def test_config_jdbcmysql_database - run_generator([destination_root, "-d", "jdbcmysql", "--skip-active-storage"]) + run_generator([destination_root, "-d", "jdbcmysql"]) assert_file "config/database.yml", /mysql/ assert_gem "activerecord-jdbcmysql-adapter" end @@ -441,7 +441,7 @@ class AppGeneratorTest < Rails::Generators::TestCase end def test_config_jdbc_database - run_generator([destination_root, "-d", "jdbc", "--skip-active-storage"]) + run_generator([destination_root, "-d", "jdbc"]) assert_file "config/database.yml", /jdbc/ assert_file "config/database.yml", /mssql/ assert_gem "activerecord-jdbc-adapter" diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 06d223e26d..49256883d6 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -230,7 +230,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase end def test_ensure_that_tests_work - run_generator [destination_root, "--skip-active-storage"] + run_generator FileUtils.cd destination_root quietly { system "bundle install" } assert_match(/1 runs, 1 assertions, 0 failures, 0 errors/, `bin/test 2>&1`) diff --git a/railties/test/generators/plugin_test_runner_test.rb b/railties/test/generators/plugin_test_runner_test.rb index 48a3bcadcd..89c3f1e496 100644 --- a/railties/test/generators/plugin_test_runner_test.rb +++ b/railties/test/generators/plugin_test_runner_test.rb @@ -7,7 +7,7 @@ class PluginTestRunnerTest < ActiveSupport::TestCase def setup @destination_root = Dir.mktmpdir("bukkits") - Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --skip-bundle --skip-active-storage` } + Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --skip-bundle` } plugin_file "test/dummy/db/schema.rb", "" end diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index ba8ee13526..6b746f3fed 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -63,7 +63,7 @@ module SharedGeneratorTests end def test_shebang_is_added_to_rails_file - run_generator [destination_root, "--ruby", "foo/bar/baz", "--full", "--skip-active-storage"] + run_generator [destination_root, "--ruby", "foo/bar/baz", "--full"] assert_file "bin/rails", /#!foo\/bar\/baz/ end diff --git a/railties/test/generators/test_runner_in_engine_test.rb b/railties/test/generators/test_runner_in_engine_test.rb index 2acd96ecd4..0e15b5e388 100644 --- a/railties/test/generators/test_runner_in_engine_test.rb +++ b/railties/test/generators/test_runner_in_engine_test.rb @@ -7,7 +7,7 @@ class TestRunnerInEngineTest < ActiveSupport::TestCase def setup @destination_root = Dir.mktmpdir("bukkits") - Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --full --skip-bundle --skip-active-storage` } + Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --full --skip-bundle` } plugin_file "test/dummy/db/schema.rb", "" end -- cgit v1.2.3 From 6f123341d9e8807bb83c6a8214ec54d3b52c82a3 Mon Sep 17 00:00:00 2001 From: bogdanvlviv Date: Wed, 8 Nov 2017 22:07:12 +0000 Subject: Change output log about skipping instalation of Active Storage Using of "`" is preferable over "'" to express console command in output log --- railties/lib/rails/generators/app_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 60e54cc365..bdeddff645 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -464,7 +464,7 @@ module Rails if bundle_install? rails_command "active_storage:install", capture: options[:quiet] else - log("Active Storage installation was skipped. Please run 'bin/rails active_storage:install' to install Active Storage files.") + log("Active Storage installation was skipped. Please run `bin/rails active_storage:install` to install Active Storage files.") end end end -- cgit v1.2.3 From 801fbde87deae5c01c581a6e4ef1157d27185b32 Mon Sep 17 00:00:00 2001 From: Yasuo Honda Date: Wed, 8 Nov 2017 21:22:55 +0000 Subject: Run `ConcurrentTransactionTest` if `supports_transaction_isolation?` returns true Not only postgresql or mysql2 adapter, Oracle enhanced adapter whose default isolation level is read commited, passes these two test cases. `ConcurrentTransactionTest#test_transaction_per_thread` `ConcurrentTransactionTest#test_transaction_isolation__read_committed` ```ruby $ ARCONN=oracle bin/test test/cases/transactions_test.rb:961 -v Using oracle Run options: -v --seed 18865 ConcurrentTransactionTest#test_transaction_per_thread = 0.98 s = . Finished in 1.061036s, 0.9425 runs/s, 5.6549 assertions/s. 1 runs, 6 assertions, 0 failures, 0 errors, 0 skips ``` ```ruby $ ARCONN=oracle bin/test test/cases/transactions_test.rb:979 -v Using oracle Run options: -v --seed 13341 ConcurrentTransactionTest#test_transaction_isolation__read_committed = 1.85 s = . Finished in 1.928637s, 0.5185 runs/s, 10.3700 assertions/s. 1 runs, 20 assertions, 0 failures, 0 errors, 0 skips $ ``` Also, regardless it is a file based or memory based these tests could fail with SQLite3Adapter. (Extra CR added to make lines shorter) ```ruby $ ARCONN=sqlite3 bin/test test/cases/transactions_test.rb:961 -v Using sqlite3 Run options: -v --seed 18815 ConcurrentTransactionTest#test_transaction_per_thread = /home/yahonda/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:108:in `step': SQLite3::BusyException: database is locked: UPDATE "topics" SET "approved" = ?, "updated_at" = ? WHERE "topics"."id" = ? (ActiveRecord::StatementInvalid) ``` ```ruby $ ARCONN=sqlite3 bin/test test/cases/transactions_test.rb:979 -v Using sqlite3 Run options: -v --seed 25520 ConcurrentTransactionTest#test_transaction_isolation__read_committed = 0.12 s = E /home/yahonda/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:108:in `step': SQLite3::BusyException: database is locked: UPDATE "developers" SET "salary" = ?, "updated_at" = ?, "updated_on" = ? WHERE "developers"."id" = ? (ActiveRecord::StatementInvalid) ``` --- activerecord/test/cases/transactions_test.rb | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 91032945a6..5c8ae4d3cb 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -954,27 +954,25 @@ class TransactionsWithTransactionalFixturesTest < ActiveRecord::TestCase end end if Topic.connection.supports_savepoints? -if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter) +if ActiveRecord::Base.connection.supports_transaction_isolation? class ConcurrentTransactionTest < TransactionTest # This will cause transactions to overlap and fail unless they are performed on # separate database connections. - unless in_memory_db? - def test_transaction_per_thread - threads = 3.times.map do - Thread.new do - Topic.transaction do - topic = Topic.find(1) - topic.approved = !topic.approved? - assert topic.save! - topic.approved = !topic.approved? - assert topic.save! - end - Topic.connection.close + def test_transaction_per_thread + threads = 3.times.map do + Thread.new do + Topic.transaction do + topic = Topic.find(1) + topic.approved = !topic.approved? + assert topic.save! + topic.approved = !topic.approved? + assert topic.save! end + Topic.connection.close end - - threads.each(&:join) end + + threads.each(&:join) end # Test for dirty reads among simultaneous transactions. -- cgit v1.2.3 From 2a6852c6ef272b404f97058b0afc9d460e05777c Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Thu, 9 Nov 2017 11:28:39 +0900 Subject: Correctly kill the server started with ujs test `Kernel.#spawn` execute command via the shell if contains shell metacharacters in the command. In that case, return value of `spawn` is pid of the shell, not the server. Therefore, just killing the pid will leave the process of server. In order to correctly kill the server, send a signal to the process group, not the process. --- actionview/Rakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actionview/Rakefile b/actionview/Rakefile index 9e5ef35334..8650f541b0 100644 --- a/actionview/Rakefile +++ b/actionview/Rakefile @@ -32,7 +32,7 @@ namespace :test do task :ujs do begin Dir.mkdir("log") - pid = spawn("bundle exec rackup test/ujs/config.ru -p 4567 -s puma > log/test.log 2>&1") + pid = spawn("bundle exec rackup test/ujs/config.ru -p 4567 -s puma > log/test.log 2>&1", pgroup: true) start_time = Time.now @@ -48,7 +48,7 @@ namespace :test do system("npm run lint && bundle exec ruby ../ci/qunit-selenium-runner.rb http://localhost:4567/") status = $?.exitstatus ensure - Process.kill("KILL", pid) if pid + Process.kill("KILL", -pid) if pid FileUtils.rm_rf("log") end -- cgit v1.2.3 From be6e1b8f7dbce1940f47339657faab2c1fdeaa54 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 9 Nov 2017 16:53:55 +0900 Subject: Should pass `test_no_locks_no_wait` not only on `PostgreSQLAdapter` and `OracleAdapter` --- activerecord/test/cases/locking_test.rb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 6791d50940..e857180bd1 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -611,14 +611,12 @@ unless in_memory_db? end end - if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) - def test_no_locks_no_wait - first, second = duel { Person.find 1 } - assert first.end > second.end - end - - private + def test_no_locks_no_wait + first, second = duel { Person.find 1 } + assert first.end > second.end + end + private def duel(zzz = 5) t0, t1, t2, t3 = nil, nil, nil, nil @@ -646,6 +644,5 @@ unless in_memory_db? assert t3 > t2 [t0.to_f..t1.to_f, t2.to_f..t3.to_f] end - end end end -- cgit v1.2.3 From 4022f33416a00fd6a18989aa54f60573f48be0a0 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 9 Nov 2017 17:12:07 +0900 Subject: Use `Tempfile.create` Instead of `Dir::Tmpname.make_tmpname`, an internal method which does not guarantee uniqueness, use `Tempfile.create`. --- actionpack/test/controller/log_subscriber_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index f0f106c8ba..4c59bea193 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -98,7 +98,7 @@ class ACLogSubscriberTest < ActionController::TestCase @old_logger = ActionController::Base.logger - @cache_path = File.join Dir.tmpdir, Dir::Tmpname.make_tmpname("tmp", "cache") + @cache_path = Tempfile.create(%w"tmp cache", Dir.tmpdir) @controller.cache_store = :file_store, @cache_path ActionController::LogSubscriber.attach_to :action_controller end -- cgit v1.2.3 From d1e0bc7c17b1be2766e9fca228b4c61e01988b34 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Thu, 9 Nov 2017 20:54:24 +0900 Subject: Do not show credentials in generators help Since credentials generator is executed via the credentials command and does not need to be executed directly, so it is not necessary to show it in help. --- railties/lib/rails/generators.rb | 1 + railties/test/application/generators_test.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 2d265818f7..5592e8d78e 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -218,6 +218,7 @@ module Rails rails.delete("app") rails.delete("plugin") rails.delete("encrypted_secrets") + rails.delete("credentials") hidden_namespaces.each { |n| groups.delete(n.to_s) } diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index 47c815d221..e5e557d204 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -188,10 +188,11 @@ module ApplicationTests Rails::Command.send(:remove_const, "APP_PATH") end - test "help does not show hidden namespaces" do + test "help does not show hidden namespaces and hidden commands" do FileUtils.cd(rails_root) do output = rails("generate", "--help") assert_no_match "active_record:migration", output + assert_no_match "credentials", output output = rails("destroy", "--help") assert_no_match "active_record:migration", output -- cgit v1.2.3 From 2d5700b9a3e2ac25a5ff349ca6d3dc27077cea13 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 9 Nov 2017 22:09:00 +0900 Subject: Use `Dir.mktmpdir` As `@cache_path` is expected to be a directory name, use `Dir.mktmpdir`. And omit unnecessary `Dir.tmpdir`. --- actionpack/test/controller/log_subscriber_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index 4c59bea193..cb425fb3de 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -98,7 +98,7 @@ class ACLogSubscriberTest < ActionController::TestCase @old_logger = ActionController::Base.logger - @cache_path = Tempfile.create(%w"tmp cache", Dir.tmpdir) + @cache_path = Dir.mktmpdir(%w"tmp cache") @controller.cache_store = :file_store, @cache_path ActionController::LogSubscriber.attach_to :action_controller end -- cgit v1.2.3