mirror of
https://github.com/github/rails.git
synced 2026-01-13 00:28:26 -05:00
Compare commits
38 Commits
v3.2.19.gi
...
3-2-github
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fc14b1f71 | ||
|
|
7c89fc489d | ||
|
|
7a559d389c | ||
|
|
726e996306 | ||
|
|
eadedf7189 | ||
|
|
c831f67d8b | ||
|
|
b6f150c40c | ||
|
|
76ad4030e5 | ||
|
|
0a3c7ba903 | ||
|
|
d69e65ab34 | ||
|
|
56d2614309 | ||
|
|
0afd326c36 | ||
|
|
c957f5f609 | ||
|
|
90ded51cc1 | ||
|
|
74b7cb9868 | ||
|
|
bce8b07309 | ||
|
|
3fe553fa31 | ||
|
|
e1c7a232ca | ||
|
|
283923f530 | ||
|
|
18d37237c4 | ||
|
|
b30301bb6d | ||
|
|
d12475ba60 | ||
|
|
d106a28675 | ||
|
|
67b3fd5cb8 | ||
|
|
0342deaa22 | ||
|
|
91bbe59e17 | ||
|
|
f0895f838f | ||
|
|
c9a54ce81d | ||
|
|
f6844fc683 | ||
|
|
b09eac885e | ||
|
|
1edd8b587b | ||
|
|
7ed2b48747 | ||
|
|
8b5e2df964 | ||
|
|
7688a79035 | ||
|
|
ec80c63332 | ||
|
|
7edb47effd | ||
|
|
24bdb8141e | ||
|
|
78e6c36ba3 |
@@ -1 +1 @@
|
||||
3.2.19.github2
|
||||
3.2.19.github9
|
||||
|
||||
@@ -2,7 +2,6 @@ require 'mail'
|
||||
require 'action_mailer/collector'
|
||||
require 'active_support/core_ext/array/wrap'
|
||||
require 'active_support/core_ext/object/blank'
|
||||
require 'active_support/core_ext/proc'
|
||||
require 'active_support/core_ext/string/inflections'
|
||||
require 'active_support/core_ext/hash/except'
|
||||
require 'active_support/core_ext/module/anonymous'
|
||||
@@ -627,7 +626,7 @@ module ActionMailer #:nodoc:
|
||||
|
||||
# Call all the procs (if any)
|
||||
default_values = self.class.default.merge(self.class.default) do |k,v|
|
||||
v.respond_to?(:call) ? v.bind(self).call : v
|
||||
v.respond_to?(:call) ? instance_eval(&v) : v
|
||||
end
|
||||
|
||||
# Handle defaults
|
||||
|
||||
@@ -489,6 +489,7 @@ module ActionController
|
||||
@controller.recycle!
|
||||
@controller.process_with_new_base_test(@request, @response)
|
||||
@assigns = @controller.respond_to?(:view_assigns) ? @controller.view_assigns : {}
|
||||
@request.session['flash'] = @request.flash.to_session_value
|
||||
@request.session.delete('flash') if @request.session['flash'].blank?
|
||||
@response
|
||||
end
|
||||
|
||||
@@ -81,6 +81,7 @@ module ActionDispatch
|
||||
class Cookies
|
||||
HTTP_HEADER = "Set-Cookie".freeze
|
||||
TOKEN_KEY = "action_dispatch.secret_token".freeze
|
||||
SESSION_SERIALIZER = "action_dispatch.session_serializer".freeze
|
||||
|
||||
# Raised when storing more than 4K of session data.
|
||||
class CookieOverflow < StandardError; end
|
||||
@@ -106,13 +107,14 @@ module ActionDispatch
|
||||
secret = request.env[TOKEN_KEY]
|
||||
host = request.host
|
||||
secure = request.ssl?
|
||||
serializer = request.env[SESSION_SERIALIZER]
|
||||
|
||||
new(secret, host, secure).tap do |hash|
|
||||
new(secret, host, secure, serializer).tap do |hash|
|
||||
hash.update(request.cookies)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(secret = nil, host = nil, secure = false)
|
||||
def initialize(secret = nil, host = nil, secure = false, serializer = nil)
|
||||
@secret = secret
|
||||
@set_cookies = {}
|
||||
@delete_cookies = {}
|
||||
@@ -120,6 +122,7 @@ module ActionDispatch
|
||||
@secure = secure
|
||||
@closed = false
|
||||
@cookies = {}
|
||||
@serializer = serializer
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
@@ -211,7 +214,7 @@ module ActionDispatch
|
||||
# cookies.permanent.signed[:remember_me] = current_user.id
|
||||
# # => Set-Cookie: remember_me=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
|
||||
def permanent
|
||||
@permanent ||= PermanentCookieJar.new(self, @secret)
|
||||
@permanent ||= PermanentCookieJar.new(self, @secret, @serializer)
|
||||
end
|
||||
|
||||
# Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from
|
||||
@@ -228,7 +231,7 @@ module ActionDispatch
|
||||
#
|
||||
# cookies.signed[:discount] # => 45
|
||||
def signed
|
||||
@signed ||= SignedCookieJar.new(self, @secret)
|
||||
@signed ||= SignedCookieJar.new(self, @secret, @serializer)
|
||||
end
|
||||
|
||||
def write(headers)
|
||||
@@ -252,8 +255,8 @@ module ActionDispatch
|
||||
end
|
||||
|
||||
class PermanentCookieJar < CookieJar #:nodoc:
|
||||
def initialize(parent_jar, secret)
|
||||
@parent_jar, @secret = parent_jar, secret
|
||||
def initialize(parent_jar, secret, serializer)
|
||||
@parent_jar, @secret, @serializer = parent_jar, secret, serializer
|
||||
end
|
||||
|
||||
def []=(key, options)
|
||||
@@ -268,7 +271,7 @@ module ActionDispatch
|
||||
end
|
||||
|
||||
def signed
|
||||
@signed ||= SignedCookieJar.new(self, @secret)
|
||||
@signed ||= SignedCookieJar.new(self, @secret, @serializer)
|
||||
end
|
||||
|
||||
def method_missing(method, *arguments, &block)
|
||||
@@ -280,10 +283,10 @@ module ActionDispatch
|
||||
MAX_COOKIE_SIZE = 4096 # Cookies can typically store 4096 bytes.
|
||||
SECRET_MIN_LENGTH = 30 # Characters
|
||||
|
||||
def initialize(parent_jar, secret)
|
||||
def initialize(parent_jar, secret, serializer)
|
||||
ensure_secret_secure(secret)
|
||||
@parent_jar = parent_jar
|
||||
@verifier = ActiveSupport::MessageVerifier.new(secret)
|
||||
@verifier = ActiveSupport::MessageVerifier.new(secret, :serializer => serializer)
|
||||
end
|
||||
|
||||
def [](name)
|
||||
|
||||
@@ -4,7 +4,7 @@ module ActionDispatch
|
||||
# read a notice you put there or <tt>flash["notice"] = "hello"</tt>
|
||||
# to put a new one.
|
||||
def flash
|
||||
@env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new)
|
||||
@env[Flash::KEY] ||= Flash::FlashHash.from_session_value(session["flash"])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -77,10 +77,24 @@ module ActionDispatch
|
||||
class FlashHash
|
||||
include Enumerable
|
||||
|
||||
def initialize #:nodoc:
|
||||
@used = Set.new
|
||||
def self.from_session_value(value)
|
||||
case value
|
||||
when Hash # After github/github-rails#9, only plain Hashes are in the session
|
||||
new(value['flashes'], value['discard'])
|
||||
else
|
||||
new
|
||||
end
|
||||
end
|
||||
|
||||
def to_session_value
|
||||
return nil if empty?
|
||||
{'discard' => @used.to_a, 'flashes' => @flashes}
|
||||
end
|
||||
|
||||
def initialize(flashes = {}, discard = []) #:nodoc:
|
||||
@used = Set.new(discard)
|
||||
@closed = false
|
||||
@flashes = {}
|
||||
@flashes = flashes
|
||||
@now = nil
|
||||
end
|
||||
|
||||
@@ -93,15 +107,17 @@ module ActionDispatch
|
||||
end
|
||||
|
||||
def []=(k, v) #:nodoc:
|
||||
k = k.to_s
|
||||
keep(k)
|
||||
@flashes[k] = v
|
||||
end
|
||||
|
||||
def [](k)
|
||||
@flashes[k]
|
||||
@flashes[k.to_s]
|
||||
end
|
||||
|
||||
def update(h) #:nodoc:
|
||||
h.stringify_keys!
|
||||
h.keys.each { |k| keep(k) }
|
||||
@flashes.update h
|
||||
self
|
||||
@@ -112,11 +128,11 @@ module ActionDispatch
|
||||
end
|
||||
|
||||
def key?(name)
|
||||
@flashes.key? name
|
||||
@flashes.key? name.to_s
|
||||
end
|
||||
|
||||
def delete(key)
|
||||
@flashes.delete key
|
||||
@flashes.delete key.to_s
|
||||
self
|
||||
end
|
||||
|
||||
@@ -140,7 +156,7 @@ module ActionDispatch
|
||||
|
||||
def replace(h) #:nodoc:
|
||||
@used = Set.new
|
||||
@flashes.replace h
|
||||
@flashes.replace h.stringify_keys
|
||||
self
|
||||
end
|
||||
|
||||
@@ -235,8 +251,9 @@ module ActionDispatch
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if (session = env['rack.session']) && (flash = session['flash'])
|
||||
if (session = env['rack.session']) && (flash = Flash::FlashHash.from_session_value(session["flash"]))
|
||||
flash.sweep
|
||||
env[KEY] = flash
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
@@ -246,7 +263,7 @@ module ActionDispatch
|
||||
|
||||
if flash_hash
|
||||
if !flash_hash.empty? || session.key?('flash')
|
||||
session["flash"] = flash_hash
|
||||
session["flash"] = flash_hash.to_session_value
|
||||
new_hash = flash_hash.dup
|
||||
else
|
||||
new_hash = flash_hash
|
||||
@@ -255,7 +272,7 @@ module ActionDispatch
|
||||
env[KEY] = new_hash
|
||||
end
|
||||
|
||||
if session.key?('flash') && session['flash'].empty?
|
||||
if session['flash'] && session['flash'].empty?
|
||||
session.delete('flash')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,11 +2,11 @@ module ActionView
|
||||
# = Action View Cache Helper
|
||||
module Helpers
|
||||
module CacheHelper
|
||||
# This helper exposes a method for caching fragments of a view
|
||||
# This helper exposes a method for caching fragments of a view
|
||||
# rather than an entire action or page. This technique is useful
|
||||
# caching pieces like menus, lists of newstopics, static HTML
|
||||
# fragments, and so on. This method takes a block that contains
|
||||
# the content you wish to cache.
|
||||
# the content you wish to cache.
|
||||
#
|
||||
# See ActionController::Caching::Fragments for usage instructions.
|
||||
#
|
||||
@@ -23,7 +23,7 @@ module ActionView
|
||||
# <p>Hello users! Welcome to our website!</p>
|
||||
# <% end %>
|
||||
#
|
||||
# Static content with embedded ruby content can be cached as
|
||||
# Static content with embedded ruby content can be cached as
|
||||
# well:
|
||||
#
|
||||
# <% cache do %>
|
||||
@@ -49,10 +49,11 @@ module ActionView
|
||||
else
|
||||
# VIEW TODO: Make #capture usable outside of ERB
|
||||
# This dance is needed because Builder can't use capture
|
||||
pos = output_buffer.length
|
||||
pos = output_buffer.bytesize
|
||||
yield
|
||||
output_safe = output_buffer.html_safe?
|
||||
fragment = output_buffer.slice!(pos..-1)
|
||||
fragment = output_buffer.byteslice(pos..-1)
|
||||
self.output_buffer = output_buffer.byteslice(0...pos)
|
||||
if output_safe
|
||||
self.output_buffer = output_buffer.class.new(output_buffer)
|
||||
end
|
||||
|
||||
@@ -165,8 +165,6 @@ module ActionView
|
||||
# name instead of the prefix.
|
||||
def normalize_name(name, prefixes) #:nodoc:
|
||||
name = name.to_s.sub(handlers_regexp) do |match|
|
||||
ActiveSupport::Deprecation.warn "Passing a template handler in the template name is deprecated. " \
|
||||
"You can simply remove the handler name or pass render :handlers => [:#{match[1..-1]}] instead.", caller
|
||||
""
|
||||
end
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Upstream FlashHash tests from:
|
||||
# https://github.com/rails/rails/blob/a6ce984b49519de7701aa13d04300c9d03cf8f72/actionpack/test/controller/flash_hash_test.rb
|
||||
require 'abstract_unit'
|
||||
|
||||
module ActionDispatch
|
||||
@@ -46,6 +48,31 @@ module ActionDispatch
|
||||
assert_equal({'foo' => 'bar'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_to_session_value
|
||||
@hash['foo'] = 'bar'
|
||||
assert_equal({'flashes' => {'foo' => 'bar'}, 'discard' => []}, @hash.to_session_value)
|
||||
|
||||
@hash.discard('foo')
|
||||
assert_equal({'flashes' => {'foo' => 'bar'}, 'discard' => %w[foo]}, @hash.to_session_value)
|
||||
|
||||
@hash.now['qux'] = 1
|
||||
assert_equal({'flashes' => {'foo' => 'bar', 'qux' => 1}, 'discard' => %w[foo qux]}, @hash.to_session_value)
|
||||
|
||||
@hash.sweep
|
||||
assert_equal(nil, @hash.to_session_value)
|
||||
end
|
||||
|
||||
def test_from_session_value_on_json_serializer
|
||||
decrypted_data = "{ \"session_id\":\"d98bdf6d129618fc2548c354c161cfb5\", \"flash\":{\"discard\":[], \"flashes\":{\"message\":\"hey you\"}} }"
|
||||
session = ActiveSupport::JSON.decode(decrypted_data)
|
||||
hash = Flash::FlashHash.from_session_value(session['flash'])
|
||||
hash.sweep
|
||||
|
||||
assert_equal({'discard' => %w[message], 'flashes' => { 'message' => 'hey you'}}, hash.to_session_value)
|
||||
assert_equal "hey you", hash[:message]
|
||||
assert_equal "hey you", hash["message"]
|
||||
end
|
||||
|
||||
def test_empty?
|
||||
assert @hash.empty?
|
||||
@hash['zomg'] = 'bears'
|
||||
@@ -75,6 +102,7 @@ module ActionDispatch
|
||||
def test_discard_no_args
|
||||
@hash['hello'] = 'world'
|
||||
@hash.discard
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({}, @hash.to_hash)
|
||||
end
|
||||
@@ -83,8 +111,88 @@ module ActionDispatch
|
||||
@hash['hello'] = 'world'
|
||||
@hash['omg'] = 'world'
|
||||
@hash.discard 'hello'
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({'omg' => 'world'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_keep_sweep
|
||||
@hash['hello'] = 'world'
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({'hello' => 'world'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_update_sweep
|
||||
@hash['hello'] = 'world'
|
||||
@hash.update({'hi' => 'mom'})
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({'hello' => 'world', 'hi' => 'mom'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_update_delete_sweep
|
||||
@hash['hello'] = 'world'
|
||||
@hash.delete 'hello'
|
||||
@hash.update({'hello' => 'mom'})
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({'hello' => 'mom'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_delete_sweep
|
||||
@hash['hello'] = 'world'
|
||||
@hash['hi'] = 'mom'
|
||||
@hash.delete 'hi'
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({'hello' => 'world'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_clear_sweep
|
||||
@hash['hello'] = 'world'
|
||||
@hash.clear
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_replace_sweep
|
||||
@hash['hello'] = 'world'
|
||||
@hash.replace({'hi' => 'mom'})
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({'hi' => 'mom'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_discard_then_add
|
||||
@hash['hello'] = 'world'
|
||||
@hash['omg'] = 'world'
|
||||
@hash.discard 'hello'
|
||||
@hash['hello'] = 'world'
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({'omg' => 'world', 'hello' => 'world'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_keep_all_sweep
|
||||
@hash['hello'] = 'world'
|
||||
@hash['omg'] = 'world'
|
||||
@hash.discard 'hello'
|
||||
@hash.keep
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({'omg' => 'world', 'hello' => 'world'}, @hash.to_hash)
|
||||
end
|
||||
|
||||
def test_double_sweep
|
||||
@hash['hello'] = 'world'
|
||||
@hash.sweep
|
||||
|
||||
assert_equal({'hello' => 'world'}, @hash.to_hash)
|
||||
|
||||
@hash.sweep
|
||||
assert_equal({}, @hash.to_hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -174,13 +174,13 @@ class FlashTest < ActionController::TestCase
|
||||
|
||||
assert_equal(:foo_indeed, flash.discard(:foo)) # valid key passed
|
||||
assert_nil flash.discard(:unknown) # non existant key passed
|
||||
assert_equal({:foo => :foo_indeed, :bar => :bar_indeed}, flash.discard().to_hash) # nothing passed
|
||||
assert_equal({:foo => :foo_indeed, :bar => :bar_indeed}, flash.discard(nil).to_hash) # nothing passed
|
||||
assert_equal({"foo" => :foo_indeed, "bar" => :bar_indeed}, flash.discard().to_hash) # nothing passed
|
||||
assert_equal({"foo" => :foo_indeed, "bar" => :bar_indeed}, flash.discard(nil).to_hash) # nothing passed
|
||||
|
||||
assert_equal(:foo_indeed, flash.keep(:foo)) # valid key passed
|
||||
assert_nil flash.keep(:unknown) # non existant key passed
|
||||
assert_equal({:foo => :foo_indeed, :bar => :bar_indeed}, flash.keep().to_hash) # nothing passed
|
||||
assert_equal({:foo => :foo_indeed, :bar => :bar_indeed}, flash.keep(nil).to_hash) # nothing passed
|
||||
assert_equal({"foo" => :foo_indeed, "bar" => :bar_indeed}, flash.keep().to_hash) # nothing passed
|
||||
assert_equal({"foo" => :foo_indeed, "bar" => :bar_indeed}, flash.keep(nil).to_hash) # nothing passed
|
||||
end
|
||||
|
||||
def test_redirect_to_with_alert
|
||||
|
||||
@@ -63,6 +63,11 @@ class CookiesTest < ActionController::TestCase
|
||||
head :ok
|
||||
end
|
||||
|
||||
def set_signed_string_cookie
|
||||
cookies.signed[:foo] = 'bar'
|
||||
head :ok
|
||||
end
|
||||
|
||||
def raise_data_overflow
|
||||
cookies.signed[:foo] = 'bye!' * 1024
|
||||
head :ok
|
||||
@@ -332,6 +337,22 @@ class CookiesTest < ActionController::TestCase
|
||||
}
|
||||
end
|
||||
|
||||
class ActionDispatch::Session::CustomJsonSerializer
|
||||
def self.load(value)
|
||||
JSON.load(value) + " and loaded"
|
||||
end
|
||||
|
||||
def self.dump(value)
|
||||
JSON.dump(value + " was dumped")
|
||||
end
|
||||
end
|
||||
|
||||
def test_signed_cookie_using_serializer_object
|
||||
@request.env["action_dispatch.session_serializer"] = ActionDispatch::Session::CustomJsonSerializer
|
||||
get :set_signed_string_cookie
|
||||
assert_equal 'bar was dumped and loaded', @controller.send(:cookies).signed[:foo]
|
||||
end
|
||||
|
||||
def test_cookie_with_all_domain_option
|
||||
get :set_cookie_with_domain
|
||||
assert_response :success
|
||||
|
||||
@@ -371,7 +371,7 @@ module ActiveRecord
|
||||
begin
|
||||
record.committed!
|
||||
rescue Exception => e
|
||||
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
||||
handle_commit_exceptions(record, e)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -385,6 +385,11 @@ module ActiveRecord
|
||||
row = result.rows.first
|
||||
row && row.first
|
||||
end
|
||||
|
||||
# Handle any exceptions caught trying to send the commit message to a record
|
||||
def handle_commit_exceptions(record, e)
|
||||
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -100,14 +100,6 @@ module ActiveRecord
|
||||
end
|
||||
|
||||
def quoted_date(value)
|
||||
if value.acts_like?(:time)
|
||||
zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
|
||||
|
||||
if value.respond_to?(zone_conversion_method)
|
||||
value = value.send(zone_conversion_method)
|
||||
end
|
||||
end
|
||||
|
||||
value.to_s(:db)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -278,7 +278,7 @@ module ActiveRecord
|
||||
|
||||
# Call the after_commit callbacks
|
||||
def committed! #:nodoc:
|
||||
run_callbacks :commit
|
||||
run_callbacks :commit if destroyed? || persisted?
|
||||
ensure
|
||||
@_start_transaction_state.clear
|
||||
end
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
require "active_support/core_ext/kernel/singleton_class"
|
||||
|
||||
class Proc #:nodoc:
|
||||
def bind(object)
|
||||
block, time = self, Time.now
|
||||
object.class_eval do
|
||||
method_name = "__bind_#{time.to_i}_#{time.usec}"
|
||||
define_method(method_name, &block)
|
||||
method = instance_method(method_name)
|
||||
remove_method(method_name)
|
||||
method
|
||||
end.bind(object)
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,20 @@ require 'active_support/values/time_zone'
|
||||
|
||||
class Time
|
||||
DATE_FORMATS = {
|
||||
:db => "%Y-%m-%d %H:%M:%S",
|
||||
:db => lambda { |time|
|
||||
time = time.dup.utc.to_time.utc
|
||||
|
||||
if !defined?(ActiveRecord::Base.default_timezone) || ActiveRecord::Base.default_timezone == :local
|
||||
# our DB is in local time (ugh), so make sure the time object is
|
||||
# converted to local time before converting it to a db string
|
||||
#
|
||||
# also we have to do this ridiculous dance to ensure that we can
|
||||
# turn any given DateTime object into something in localtime.
|
||||
time = time.getlocal
|
||||
end
|
||||
|
||||
time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
},
|
||||
:number => "%Y%m%d%H%M%S",
|
||||
:time => "%H:%M",
|
||||
:short => "%d %b %H:%M",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
require 'active_support/concern'
|
||||
require 'active_support/core_ext/class/attribute'
|
||||
require 'active_support/core_ext/proc'
|
||||
require 'active_support/core_ext/string/inflections'
|
||||
require 'active_support/core_ext/array/extract_options'
|
||||
|
||||
@@ -108,7 +107,11 @@ module ActiveSupport
|
||||
when Symbol
|
||||
method(rescuer)
|
||||
when Proc
|
||||
rescuer.bind(self)
|
||||
if rescuer.arity == 0
|
||||
Proc.new { instance_exec(&rescuer) }
|
||||
else
|
||||
Proc.new { |_exception| instance_exec(_exception, &rescuer) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -338,7 +338,7 @@ module ActiveSupport
|
||||
# so transfer time values to a utc constructor if necessary
|
||||
@time = transfer_time_values_to_utc_constructor(@time) unless @time.utc?
|
||||
begin
|
||||
@time_zone.period_for_local(@time)
|
||||
@time_zone.period_for_local(@time) { |periods| periods.first }
|
||||
rescue ::TZInfo::PeriodNotFound
|
||||
# time is in the "spring forward" hour gap, so we're moving the time forward one hour and trying again
|
||||
@time += 1.hour
|
||||
|
||||
@@ -309,8 +309,8 @@ module ActiveSupport
|
||||
end
|
||||
|
||||
# Adjust the given time to the simultaneous time in UTC. Returns a Time.utc() instance.
|
||||
def local_to_utc(time, dst=true)
|
||||
tzinfo.local_to_utc(time, dst)
|
||||
def local_to_utc(time, dst=true, &block)
|
||||
tzinfo.local_to_utc(time, dst, &block)
|
||||
end
|
||||
|
||||
# Available so that TimeZone instances respond like TZInfo::Timezone instances
|
||||
@@ -319,8 +319,8 @@ module ActiveSupport
|
||||
end
|
||||
|
||||
# Available so that TimeZone instances respond like TZInfo::Timezone instances
|
||||
def period_for_local(time, dst=true)
|
||||
tzinfo.period_for_local(time, dst)
|
||||
def period_for_local(time, dst=true, &block)
|
||||
tzinfo.period_for_local(time, dst, &block)
|
||||
end
|
||||
|
||||
def self.find_tzinfo(name)
|
||||
|
||||
@@ -3,14 +3,14 @@ require 'active_support/time'
|
||||
|
||||
class DateTimeExtCalculationsTest < Test::Unit::TestCase
|
||||
def test_to_s
|
||||
datetime = DateTime.new(2005, 2, 21, 14, 30, 0, 0)
|
||||
datetime = Time.new(2005, 2, 21, 14, 30, 0).to_datetime
|
||||
assert_equal "2005-02-21 14:30:00", datetime.to_s(:db)
|
||||
assert_equal "14:30", datetime.to_s(:time)
|
||||
assert_equal "21 Feb 14:30", datetime.to_s(:short)
|
||||
assert_equal "February 21, 2005 14:30", datetime.to_s(:long)
|
||||
assert_equal "Mon, 21 Feb 2005 14:30:00 +0000", datetime.to_s(:rfc822)
|
||||
assert_equal "Mon, 21 Feb 2005 14:30:00 #{datetime.formatted_offset(false)}", datetime.to_s(:rfc822)
|
||||
assert_equal "February 21st, 2005 14:30", datetime.to_s(:long_ordinal)
|
||||
assert_match(/^2005-02-21T14:30:00(Z|\+00:00)$/, datetime.to_s)
|
||||
assert_equal "2005-02-21T14:30:00#{datetime.formatted_offset(true)}", datetime.to_s
|
||||
end
|
||||
|
||||
def test_readable_inspect
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
require 'abstract_unit'
|
||||
require 'active_support/core_ext/proc'
|
||||
|
||||
class ProcTests < Test::Unit::TestCase
|
||||
def test_bind_returns_method_with_changed_self
|
||||
block = Proc.new { self }
|
||||
assert_equal self, block.call
|
||||
bound_block = block.bind("hello")
|
||||
assert_not_equal block, bound_block
|
||||
assert_equal "hello", bound_block.call
|
||||
end
|
||||
end
|
||||
@@ -9,7 +9,7 @@ class RangeTest < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_to_s_from_times
|
||||
date_range = Time.utc(2005, 12, 10, 15, 30)..Time.utc(2005, 12, 10, 17, 30)
|
||||
date_range = Time.new(2005, 12, 10, 15, 30)..Time.new(2005, 12, 10, 17, 30)
|
||||
assert_equal "BETWEEN '2005-12-10 15:30:00' AND '2005-12-10 17:30:00'", date_range.to_s(:db)
|
||||
end
|
||||
|
||||
|
||||
@@ -541,7 +541,6 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase
|
||||
time = Time.utc(2005, 2, 21, 17, 44, 30.12345678901)
|
||||
assert_equal time.to_default_s, time.to_s
|
||||
assert_equal time.to_default_s, time.to_s(:doesnt_exist)
|
||||
assert_equal "2005-02-21 17:44:30", time.to_s(:db)
|
||||
assert_equal "21 Feb 17:44", time.to_s(:short)
|
||||
assert_equal "17:44", time.to_s(:time)
|
||||
assert_equal "20050221174430", time.to_s(:number)
|
||||
@@ -555,6 +554,10 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase
|
||||
assert_equal "Thu, 05 Feb 2009 14:30:05 -0600", Time.local(2009, 2, 5, 14, 30, 5).to_s(:rfc822)
|
||||
assert_equal "Mon, 09 Jun 2008 04:05:01 -0500", Time.local(2008, 6, 9, 4, 5, 1).to_s(:rfc822)
|
||||
end
|
||||
|
||||
# this one's a special snowflake because the db time is local
|
||||
time = Time.new(2005, 2, 21, 17, 44, 30.12345678901)
|
||||
assert_equal "2005-02-21 17:44:30", time.to_s(:db)
|
||||
end
|
||||
|
||||
def test_custom_date_format
|
||||
|
||||
@@ -107,7 +107,8 @@ class TimeWithZoneTest < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_to_s_db
|
||||
assert_equal '2000-01-01 00:00:00', @twz.to_s(:db)
|
||||
# This test assumes the local timezone of the machine is Pacific.
|
||||
assert_equal '1999-12-31 16:00:00', @twz.to_s(:db)
|
||||
end
|
||||
|
||||
def test_xmlschema
|
||||
|
||||
@@ -136,6 +136,17 @@ class TimeZoneTest < Test::Unit::TestCase
|
||||
assert_equal 'EDT', twz.zone
|
||||
end
|
||||
|
||||
def test_local_handles_non_dst_clock_set_back
|
||||
# If the clocks are set back during a transition from one non-DST observance
|
||||
# to another, the time of the transition will be ambiguous. The earlier
|
||||
# observance will be selected to mirror behaviour of DST to non-DST transitions.
|
||||
# Such a transition occurred at 02:00 local time in Moscow on 26 October 2014.
|
||||
zone = ActiveSupport::TimeZone['Moscow']
|
||||
twz = zone.local(2014,10,26,1)
|
||||
assert_equal Time.utc(2014,10,26,1), twz.time
|
||||
assert_equal Time.utc(2014,10,25,21), twz.utc
|
||||
end
|
||||
|
||||
def test_at
|
||||
zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
|
||||
secs = 946684800.0
|
||||
|
||||
@@ -181,7 +181,8 @@ module Rails
|
||||
"action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
|
||||
"action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
|
||||
"action_dispatch.logger" => Rails.logger,
|
||||
"action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner
|
||||
"action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner,
|
||||
"action_dispatch.session_serializer" => config.session_options[:serializer],
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user