From ef19e8020d831758006a9f0472582e9c2c3b7916 Mon Sep 17 00:00:00 2001 From: Tom Clarke Date: Sun, 20 May 2012 12:41:58 -0400 Subject: Prevent concurrent compilation of templates - closes #6400 This addresses an issue where in multi-threaded environments multiple threads can attempt to compile a template at the same time, which occasionally causes particular templates to end up in a bad state. So, add synchronization such that only a single thread can attempt to compile a template at one time. --- actionpack/lib/action_view/template.rb | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index edb3d427d5..cd79468502 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/try' require 'active_support/core_ext/kernel/singleton_class' +require 'thread' module ActionView # = Action View Template @@ -122,6 +123,7 @@ module ActionView @virtual_path = details[:virtual_path] @updated_at = details[:updated_at] || Time.now @formats = Array(format).map { |f| f.is_a?(Mime::Type) ? f.ref : f } + @compile_mutex = Mutex.new end # Returns if the underlying handler supports streaming. If so, @@ -223,18 +225,28 @@ module ActionView def compile!(view) #:nodoc: return if @compiled - if view.is_a?(ActionView::CompiledTemplates) - mod = ActionView::CompiledTemplates - else - mod = view.singleton_class - end + # Templates can be used concurrently in threaded environments + # so compilation and any instance variable modification must + # be synchronized + @compile_mutex.synchronize do + # Any thread holding this lock will be compiling the template needed + # by the threads waiting. So re-check the @compiled flag to avoid + # re-compilation + return if @compiled + + if view.is_a?(ActionView::CompiledTemplates) + mod = ActionView::CompiledTemplates + else + mod = view.singleton_class + end - compile(view, mod) + compile(view, mod) - # Just discard the source if we have a virtual path. This - # means we can get the template back. - @source = nil if @virtual_path - @compiled = true + # Just discard the source if we have a virtual path. This + # means we can get the template back. + @source = nil if @virtual_path + @compiled = true + end end # Among other things, this method is responsible for properly setting -- cgit v1.2.3 From f945d157f79af44e2096fcbc9aaa22e410919dca Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 19 Jun 2012 19:08:13 -0700 Subject: run the notes tests in isolation --- railties/test/application/rake/notes_test.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb index 3f4db77897..27de75b63b 100644 --- a/railties/test/application/rake/notes_test.rb +++ b/railties/test/application/rake/notes_test.rb @@ -3,12 +3,16 @@ require "isolation/abstract_unit" module ApplicationTests module RakeTests class RakeNotesTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation + def setup build_app require "rails/all" + super end def teardown + super teardown_app end -- cgit v1.2.3 From 453188568dc31b29aa2592517ebecb90ecfab681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 19 Jun 2012 23:13:47 -0300 Subject: CORES needs to be a integer --- activesupport/lib/active_support/testing/isolation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb index 43cb16aefa..8f22df6f2b 100644 --- a/activesupport/lib/active_support/testing/isolation.rb +++ b/activesupport/lib/active_support/testing/isolation.rb @@ -39,7 +39,7 @@ module ActiveSupport include Enumerable # default to 2 cores - CORES = ENV['TEST_CORES'] || 2 + CORES = ENV['TEST_CORES'].to_i || 2 def initialize list @list = list -- cgit v1.2.3 From 39dec69712aaf954c0f00f2a32c32356d789e3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 19 Jun 2012 23:21:00 -0300 Subject: Run the logger tests in isolation --- activesupport/lib/active_support/testing/isolation.rb | 2 +- railties/test/application/rack/logger_test.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb index 8f22df6f2b..50ec50ca52 100644 --- a/activesupport/lib/active_support/testing/isolation.rb +++ b/activesupport/lib/active_support/testing/isolation.rb @@ -39,7 +39,7 @@ module ActiveSupport include Enumerable # default to 2 cores - CORES = ENV['TEST_CORES'].to_i || 2 + CORES = (ENV['TEST_CORES'] || 2).to_i def initialize list @list = list diff --git a/railties/test/application/rack/logger_test.rb b/railties/test/application/rack/logger_test.rb index a77c6f472c..46fd09cb26 100644 --- a/railties/test/application/rack/logger_test.rb +++ b/railties/test/application/rack/logger_test.rb @@ -5,6 +5,7 @@ require "rack/test" module ApplicationTests module RackTests class LoggerTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation include ActiveSupport::LogSubscriber::TestHelper include Rack::Test::Methods @@ -17,6 +18,7 @@ module ApplicationTests end def teardown + super teardown_app end -- cgit v1.2.3 From 84403ae065a213f40ccce397c7b428ad8b79ec00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=BF=E3=82=B3=E7=84=BC=E3=81=8D=E4=BB=AE=E9=9D=A2?= Date: Tue, 19 Jun 2012 20:44:45 -0700 Subject: =?UTF-8?q?Correct=20the=20AP=20test=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- activesupport/lib/active_support/log_subscriber.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb index 720954625a..8c3921c423 100644 --- a/activesupport/lib/active_support/log_subscriber.rb +++ b/activesupport/lib/active_support/log_subscriber.rb @@ -111,6 +111,7 @@ module ActiveSupport finished = Time.now event = @event_stack.pop event.end = finished + event.payload.merge!(payload) method = name.split('.').first begin -- cgit v1.2.3 From 81d5d2730d56a45e7a5912335c56851f1a829ced Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 20 Jun 2012 11:07:20 -0300 Subject: Bump minitest to 3.1.0 --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index c727f73020..4e34d42fb6 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ else gem 'arel' end -gem 'minitest', '~> 3.0.0' +gem 'minitest', '~> 3.1.0' gem 'mocha', '>= 0.11.2' gem 'rack-test', github: "brynary/rack-test" gem 'bcrypt-ruby', '~> 3.0.0' -- cgit v1.2.3 From 2773257ac64c82affae527436b08e6d627853c1d Mon Sep 17 00:00:00 2001 From: paranoiase Kang Date: Sun, 20 May 2012 14:33:58 +0900 Subject: Add prev_quarter and next_quarter method in Time/Date/DateTime --- activesupport/CHANGELOG.md | 2 ++ .../active_support/core_ext/date/calculations.rb | 11 +++++++++++ .../active_support/core_ext/time/calculations.rb | 11 +++++++++++ activesupport/test/core_ext/date_ext_test.rb | 12 ++++++++++++ activesupport/test/core_ext/date_time_ext_test.rb | 12 ++++++++++++ activesupport/test/core_ext/time_ext_test.rb | 13 +++++++++++++ .../source/active_support_core_extensions.textile | 21 +++++++++++++++++++++ 7 files changed, 82 insertions(+) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 804336da91..00fcfe2001 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* Add `Time#prev_quarter' and 'Time#next_quarter' short-hands for months_ago(3) and months_since(3). *SungHee Kang* + * Remove obsolete and unused `require_association` method from dependencies. *fxn* * Add `:instance_accessor` option for `config_accessor`. diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index 8a7eb6bc6b..7fe4161fb4 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -202,6 +202,17 @@ class Date acts_like?(:time) ? result.change(:hour => 0) : result end + # Short-hand for months_ago(3) + def prev_quarter + months_ago(3) + end + alias_method :last_quarter, :prev_quarter + + # Short-hand for months_since(3) + def next_quarter + months_since(3) + end + # Returns a new Date/DateTime representing the start of the month (1st of the month; DateTime objects will have time set to 0:00) def beginning_of_month acts_like?(:time) ? change(:day => 1, :hour => 0) : change(:day => 1) diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 92b8417150..28c8b53b78 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -186,6 +186,17 @@ class Time months_since(1) end + # Short-hand for months_ago(3) + def prev_quarter + months_ago(3) + end + alias_method :last_quarter, :prev_quarter + + # Short-hand for months_since(3) + def next_quarter + months_since(3) + end + # Returns number of days to start of this week, week starts on start_day (default is :monday). def days_to_week_start(start_day = :monday) start_day_number = DAYS_INTO_WEEK[start_day] diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index e14a137f84..088b74a29a 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -289,6 +289,18 @@ class DateExtCalculationsTest < ActiveSupport::TestCase assert_equal Date.new(2004, 2, 29), Date.new(2004, 3, 31).last_month end + def test_next_quarter_on_31st + assert_equal Date.new(2005, 11, 30), Date.new(2005, 8, 31).next_quarter + end + + def test_prev_quarter_on_31st + assert_equal Date.new(2004, 2, 29), Date.new(2004, 5, 31).prev_quarter + end + + def test_last_quarter_on_31st + assert_equal Date.new(2004, 2, 29), Date.new(2004, 5, 31).last_quarter + end + def test_yesterday_constructor assert_equal Date.current - 1, Date.yesterday end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 3da0825489..183d58482d 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -271,6 +271,18 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 3, 31).last_month end + def test_next_quarter_on_31st + assert_equal DateTime.civil(2005, 11, 30), DateTime.civil(2005, 8, 31).next_quarter + end + + def test_prev_quarter_on_31st + assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 5, 31).prev_quarter + end + + def test_last_quarter_on_31st + assert_equal DateTime.civil(2004, 2, 29), DateTime.civil(2004, 5, 31).last_quarter + end + def test_xmlschema assert_match(/^1880-02-28T15:15:10\+00:?00$/, DateTime.civil(1880, 2, 28, 15, 15, 10).xmlschema) assert_match(/^1980-02-28T15:15:10\+00:?00$/, DateTime.civil(1980, 2, 28, 15, 15, 10).xmlschema) diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 15c04bedf7..d6f285598e 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -906,4 +906,17 @@ class TimeExtMarshalingTest < ActiveSupport::TestCase assert_equal t.to_f, unmarshaled.to_f assert_equal t, unmarshaled end + + + def test_next_quarter_on_31st + assert_equal Time.local(2005, 11, 30), Time.local(2005, 8, 31).next_quarter + end + + def test_prev_quarter_on_31st + assert_equal Time.local(2004, 2, 29), Time.local(2004, 5, 31).prev_quarter + end + + def test_last_quarter_on_31st + assert_equal Time.local(2004, 2, 29), Time.local(2004, 5, 31).last_quarter + end end diff --git a/guides/source/active_support_core_extensions.textile b/guides/source/active_support_core_extensions.textile index 40ef19cfbf..99b8bdd3fd 100644 --- a/guides/source/active_support_core_extensions.textile +++ b/guides/source/active_support_core_extensions.textile @@ -3045,6 +3045,27 @@ Date.new(2000, 1, 31).next_month # => Tue, 29 Feb 2000 +prev_month+ is aliased to +last_month+. +h6. +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: + + +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: + + +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+. + h6. +beginning_of_week+, +end_of_week+ The methods +beginning_of_week+ and +end_of_week+ return the dates for the -- cgit v1.2.3