aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/test_request.rb22
-rw-r--r--actionpack/test/dispatch/test_request_test.rb27
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb2
-rw-r--r--activerecord/test/cases/schema_loading_test.rb53
-rw-r--r--activesupport/CHANGELOG.md22
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/time.rb16
-rw-r--r--activesupport/lib/active_support/duration.rb6
-rw-r--r--activesupport/test/core_ext/duration_test.rb14
-rw-r--r--guides/source/debugging_rails_applications.md2
10 files changed, 141 insertions, 25 deletions
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index e9b25339dc..0a58ce2b96 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -164,7 +164,7 @@ module ActionDispatch
end
def format_from_path_extension
- path = @env['action_dispatch.original_path'] || @env['PATH_INFO']
+ path = get_header('action_dispatch.original_path') || get_header('PATH_INFO')
if match = path && path.match(/\.(\w+)\z/)
Mime[match.captures.first]
end
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
index ad1a7f7109..46523a8600 100644
--- a/actionpack/lib/action_dispatch/testing/test_request.rb
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -22,23 +22,23 @@ module ActionDispatch
private_class_method :default_env
def request_method=(method)
- @env['REQUEST_METHOD'] = method.to_s.upcase
+ set_header('REQUEST_METHOD', method.to_s.upcase)
end
def host=(host)
- @env['HTTP_HOST'] = host
+ set_header('HTTP_HOST', host)
end
def port=(number)
- @env['SERVER_PORT'] = number.to_i
+ set_header('SERVER_PORT', number.to_i)
end
def request_uri=(uri)
- @env['REQUEST_URI'] = uri
+ set_header('REQUEST_URI', uri)
end
def path=(path)
- @env['PATH_INFO'] = path
+ set_header('PATH_INFO', path)
end
def action=(action_name)
@@ -46,24 +46,24 @@ module ActionDispatch
end
def if_modified_since=(last_modified)
- @env['HTTP_IF_MODIFIED_SINCE'] = last_modified
+ set_header('HTTP_IF_MODIFIED_SINCE', last_modified)
end
def if_none_match=(etag)
- @env['HTTP_IF_NONE_MATCH'] = etag
+ set_header('HTTP_IF_NONE_MATCH', etag)
end
def remote_addr=(addr)
- @env['REMOTE_ADDR'] = addr
+ set_header('REMOTE_ADDR', addr)
end
def user_agent=(user_agent)
- @env['HTTP_USER_AGENT'] = user_agent
+ set_header('HTTP_USER_AGENT', user_agent)
end
def accept=(mime_types)
- @env.delete('action_dispatch.request.accepts')
- @env['HTTP_ACCEPT'] = Array(mime_types).collect(&:to_s).join(",")
+ delete_header('action_dispatch.request.accepts')
+ set_header('HTTP_ACCEPT', Array(mime_types).collect(&:to_s).join(","))
end
end
end
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
index 51c469a61a..3c19cbd68a 100644
--- a/actionpack/test/dispatch/test_request_test.rb
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -88,6 +88,33 @@ class TestRequestTest < ActiveSupport::TestCase
assert_equal 'GoogleBot', req.user_agent
end
+ test "setter methods" do
+ req = ActionDispatch::TestRequest.create({})
+ get = 'GET'
+
+ [
+ 'request_method=', 'host=', 'request_uri=', 'path=', 'if_modified_since=', 'if_none_match=',
+ 'remote_addr=', 'user_agent=', 'accept='
+ ].each do |method|
+ req.send(method, get)
+ end
+
+ req.port = 8080
+ req.accept = 'hello goodbye'
+
+ assert_equal(get, req.get_header('REQUEST_METHOD'))
+ assert_equal(get, req.get_header('HTTP_HOST'))
+ assert_equal(8080, req.get_header('SERVER_PORT'))
+ assert_equal(get, req.get_header('REQUEST_URI'))
+ assert_equal(get, req.get_header('PATH_INFO'))
+ assert_equal(get, req.get_header('HTTP_IF_MODIFIED_SINCE'))
+ assert_equal(get, req.get_header('HTTP_IF_NONE_MATCH'))
+ assert_equal(get, req.get_header('REMOTE_ADDR'))
+ assert_equal(get, req.get_header('HTTP_USER_AGENT'))
+ assert_nil(req.get_header('action_dispatch.request.accepts'))
+ assert_equal('hello goodbye', req.get_header('HTTP_ACCEPT'))
+ end
+
private
def assert_cookies(expected, cookie_jar)
assert_equal(expected, cookie_jar.instance_variable_get("@cookies"))
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 1040327a5d..1e37ffefc6 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -150,7 +150,7 @@ module ActiveRecord
# The version column used for optimistic locking. Defaults to +lock_version+.
def locking_column
- reset_locking_column unless defined?(@locking_column)
+ @locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
@locking_column
end
diff --git a/activerecord/test/cases/schema_loading_test.rb b/activerecord/test/cases/schema_loading_test.rb
new file mode 100644
index 0000000000..2815ccd842
--- /dev/null
+++ b/activerecord/test/cases/schema_loading_test.rb
@@ -0,0 +1,53 @@
+require 'thread'
+require "cases/helper"
+
+module SchemaLoadCounter
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ attr_accessor :load_schema_calls
+
+ def load_schema!
+ self.load_schema_calls ||= 0
+ self.load_schema_calls +=1
+ super
+ end
+ end
+end
+
+class SchemaLoadingTest < ActiveRecord::TestCase
+ def test_basic_model_is_loaded_once
+ klass = define_model
+ klass.new
+ assert_equal 1, klass.load_schema_calls
+ end
+
+ def test_model_with_custom_lock_is_loaded_once
+ klass = define_model do |c|
+ c.table_name = :lock_without_defaults_cust
+ c.locking_column = :custom_lock_version
+ end
+ klass.new
+ assert_equal 1, klass.load_schema_calls
+ end
+
+ def test_model_with_changed_custom_lock_is_loaded_twice
+ klass = define_model do |c|
+ c.table_name = :lock_without_defaults_cust
+ end
+ klass.new
+ klass.locking_column = :custom_lock_version
+ klass.new
+ assert_equal 2, klass.load_schema_calls
+ end
+
+ private
+
+ def define_model
+ Class.new(ActiveRecord::Base) do
+ include SchemaLoadCounter
+ self.table_name = :lock_without_defaults
+ yield self if block_given?
+ end
+ end
+end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index d1b3147cef..cc27b6a0fc 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,25 @@
+* Change `ActiveSupport::Duration` creation with numeric methods like `1.week`
+ to create durations with more predictable and ISO8601-conformant parts.
+
+ This is to remove astonishment from getting `3600 seconds` from `1.hour`.
+
+ It should not affect current apps as duration's `value` (number of seconds) remains the same,
+ only hash of `parts` (and `inspect` value) is changed and only when it's constructed by calling
+ methods on integers. Manual construction of Durations isn't affected.
+ Inside the ActiveSupport::Duration itself most operations rely only on number of seconds.
+
+ Before:
+
+ [1.hour.inspect, 1.hour.value, 1.hour.parts] # => ["3600 seconds", 3600, [[:seconds, 3600]]]
+ [1.week.inspect, 1.week.value, 1.week.parts] # => ["7 days", 604800, [[:days, 7]]]
+
+ After:
+
+ [1.hour.inspect, 1.hour.value, 1.hour.parts] # => ["1 hour", 3600, [[:hours, 1]]]
+ [1.week.inspect, 1.week.value, 1.week.parts] # => ["1 week", 604800, [[:weeks, 1]]]
+
+ *Andrey Novikov*
+
## Rails 5.0.0.beta4 (April 27, 2016) ##
* Time zones: Ensure that the UTC offset reflects DST changes that occurred
diff --git a/activesupport/lib/active_support/core_ext/numeric/time.rb b/activesupport/lib/active_support/core_ext/numeric/time.rb
index 6c4a975495..c6ece22f8d 100644
--- a/activesupport/lib/active_support/core_ext/numeric/time.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/time.rb
@@ -25,17 +25,17 @@ class Numeric
# Returns a Duration instance matching the number of minutes provided.
#
- # 2.minutes # => 120 seconds
+ # 2.minutes # => 2 minutes
def minutes
- ActiveSupport::Duration.new(self * 60, [[:seconds, self * 60]])
+ ActiveSupport::Duration.new(self * 60, [[:minutes, self]])
end
alias :minute :minutes
# Returns a Duration instance matching the number of hours provided.
#
- # 2.hours # => 7_200 seconds
+ # 2.hours # => 2 hours
def hours
- ActiveSupport::Duration.new(self * 3600, [[:seconds, self * 3600]])
+ ActiveSupport::Duration.new(self * 3600, [[:hours, self]])
end
alias :hour :hours
@@ -49,17 +49,17 @@ class Numeric
# Returns a Duration instance matching the number of weeks provided.
#
- # 2.weeks # => 14 days
+ # 2.weeks # => 2 weeks
def weeks
- ActiveSupport::Duration.new(self * 7.days, [[:days, self * 7]])
+ ActiveSupport::Duration.new(self * 7.days, [[:weeks, self]])
end
alias :week :weeks
# Returns a Duration instance matching the number of fortnights provided.
#
- # 2.fortnights # => 28 days
+ # 2.fortnights # => 4 weeks
def fortnights
- ActiveSupport::Duration.new(self * 2.weeks, [[:days, self * 14]])
+ ActiveSupport::Duration.new(self * 2.weeks, [[:weeks, self * 2]])
end
alias :fortnight :fortnights
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index c717e7f357..47d09f4f5a 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -120,7 +120,7 @@ module ActiveSupport
def inspect #:nodoc:
parts.
reduce(::Hash.new(0)) { |h,(l,r)| h[l] += r; h }.
- sort_by {|unit, _ | [:years, :months, :days, :minutes, :seconds].index(unit)}.
+ sort_by {|unit, _ | [:years, :months, :weeks, :days, :hours, :minutes, :seconds].index(unit)}.
map {|unit, val| "#{val} #{val == 1 ? unit.to_s.chop : unit.to_s}"}.
to_sentence(locale: ::I18n.default_locale)
end
@@ -159,6 +159,10 @@ module ActiveSupport
if t.acts_like?(:time) || t.acts_like?(:date)
if type == :seconds
t.since(sign * number)
+ elsif type == :minutes
+ t.since(sign * number * 60)
+ elsif type == :hours
+ t.since(sign * number * 3600)
else
t.advance(type => sign * number)
end
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index 69c2c0d936..ce69364c68 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -66,8 +66,9 @@ class DurationTest < ActiveSupport::TestCase
assert_equal '10 years, 2 months, and 1 day', (10.years + 2.months + 1.day).inspect
assert_equal '10 years, 2 months, and 1 day', (10.years + 1.month + 1.day + 1.month).inspect
assert_equal '10 years, 2 months, and 1 day', (1.day + 10.years + 2.months).inspect
- assert_equal '7 days', 1.week.inspect
- assert_equal '14 days', 1.fortnight.inspect
+ assert_equal '7 days', 7.days.inspect
+ assert_equal '1 week', 1.week.inspect
+ assert_equal '2 weeks', 1.fortnight.inspect
end
def test_inspect_locale
@@ -87,6 +88,15 @@ class DurationTest < ActiveSupport::TestCase
assert_equal 1 + 1.second, 1.second + 1, "Duration + Numeric should == Numeric + Duration"
end
+ def test_time_plus_duration_returns_same_time_datatype
+ twz = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone['Moscow'] , Time.utc(2016,4,28,00,45))
+ now = Time.now.utc
+ %w( second minute hour day week month year ).each do |unit|
+ assert_equal((now + 1.send(unit)).class, Time, "Time + 1.#{unit} must be Time")
+ assert_equal((twz + 1.send(unit)).class, ActiveSupport::TimeWithZone, "TimeWithZone + 1.#{unit} must be TimeWithZone")
+ end
+ end
+
def test_argument_error
e = assert_raise ArgumentError do
1.second.ago('')
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index b5634a693f..f0d0f9753a 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -727,7 +727,7 @@ For example, in the previous situation
13: end
(byebug) break 11
-Succesfully created breakpoint with id 1
+Successfully created breakpoint with id 1
```