aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionmailer/test/message_delivery_test.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb3
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb7
-rw-r--r--actionpack/test/dispatch/routing_test.rb61
-rw-r--r--activejob/CHANGELOG.md4
-rw-r--r--activejob/lib/active_job/queue_adapters/test_adapter.rb11
-rw-r--r--activejob/test/cases/test_helper_test.rb11
-rw-r--r--activerecord/lib/active_record/core.rb1
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb70
-rw-r--r--activesupport/CHANGELOG.md23
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/compatibility.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/object/with_options.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/time/compatibility.rb11
-rw-r--r--activesupport/lib/active_support/duration.rb88
-rw-r--r--activesupport/lib/active_support/message_encryptor.rb5
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb13
-rw-r--r--activesupport/test/core_ext/date_and_time_compatibility_test.rb166
-rw-r--r--activesupport/test/core_ext/duration_test.rb142
-rw-r--r--activesupport/test/core_ext/time_with_zone_test.rb29
-rw-r--r--guides/source/debugging_rails_applications.md1
-rw-r--r--railties/lib/rails/commands/destroy/destroy_command.rb4
-rw-r--r--railties/test/commands/secrets_test.rb13
-rw-r--r--railties/test/generators/app_generator_test.rb14
-rw-r--r--railties/test/generators/scaffold_generator_test.rb55
26 files changed, 634 insertions, 137 deletions
diff --git a/actionmailer/test/message_delivery_test.rb b/actionmailer/test/message_delivery_test.rb
index f4c4f43bdc..c0683be94d 100644
--- a/actionmailer/test/message_delivery_test.rb
+++ b/actionmailer/test/message_delivery_test.rb
@@ -76,14 +76,14 @@ class MessageDeliveryTest < ActiveSupport::TestCase
test "should enqueue a delivery with a delay" do
travel_to Time.new(2004, 11, 24, 01, 04, 44) do
- assert_performed_with(job: ActionMailer::DeliveryJob, at: Time.current.to_f + 600, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3]) do
- @mail.deliver_later wait: 600.seconds
+ assert_performed_with(job: ActionMailer::DeliveryJob, at: Time.current + 10.minutes, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3]) do
+ @mail.deliver_later wait: 10.minutes
end
end
end
test "should enqueue a delivery at a specific time" do
- later_time = Time.now.to_f + 3600
+ later_time = Time.current + 1.hour
assert_performed_with(job: ActionMailer::DeliveryJob, at: later_time, args: ["DelayedMailer", "test_message", "deliver_now", 1, 2, 3]) do
@mail.deliver_later wait_until: later_time
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index c4719f8a71..118dec2ad4 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -860,8 +860,7 @@ module ActionDispatch
params[key] = URI.parser.unescape(value)
end
end
- old_params = req.path_parameters
- req.path_parameters = old_params.merge params
+ req.path_parameters = params
app = route.app
if app.matches?(req) && app.dispatcher?
begin
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index a3430e210e..697abc1c48 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -192,11 +192,10 @@ module ActionDispatch
# HTTP methods in integration tests. +#process+ is only required when using a
# request method that doesn't have a method defined in the integration tests.
#
- # This method returns a Response object, which one can use to
- # inspect the details of the response. Furthermore, if this method was
+ # This method returns a response status. Furthermore, if this method was
# called from an ActionDispatch::IntegrationTest object, then that
- # object's <tt>@response</tt> instance variable will point to the same
- # response object.
+ # object's <tt>@response</tt> instance variable will point to Response object
+ # which one can use to inspect the details of the response.
#
# Example:
# process :get, '/author', params: { since: 201501011400 }
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index d563df91df..64818e6ca1 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -4962,3 +4962,64 @@ class FlashRedirectTest < ActionDispatch::IntegrationTest
assert_equal "bar", response.body
end
end
+
+class TestRecognizePath < ActionDispatch::IntegrationTest
+ class PageConstraint
+ attr_reader :key, :pattern
+
+ def initialize(key, pattern)
+ @key = key
+ @pattern = pattern
+ end
+
+ def matches?(request)
+ request.path_parameters[key] =~ pattern
+ end
+ end
+
+ stub_controllers do |routes|
+ Routes = routes
+ routes.draw do
+ get "/hash/:foo", to: "pages#show", constraints: { foo: /foo/ }
+ get "/hash/:bar", to: "pages#show", constraints: { bar: /bar/ }
+
+ get "/proc/:foo", to: "pages#show", constraints: proc { |r| r.path_parameters[:foo] =~ /foo/ }
+ get "/proc/:bar", to: "pages#show", constraints: proc { |r| r.path_parameters[:bar] =~ /bar/ }
+
+ get "/class/:foo", to: "pages#show", constraints: PageConstraint.new(:foo, /foo/)
+ get "/class/:bar", to: "pages#show", constraints: PageConstraint.new(:bar, /bar/)
+ end
+ end
+
+ APP = build_app Routes
+ def app
+ APP
+ end
+
+ def test_hash_constraints_dont_leak_between_routes
+ expected_params = { controller: "pages", action: "show", bar: "bar" }
+ actual_params = recognize_path("/hash/bar")
+
+ assert_equal expected_params, actual_params
+ end
+
+ def test_proc_constraints_dont_leak_between_routes
+ expected_params = { controller: "pages", action: "show", bar: "bar" }
+ actual_params = recognize_path("/proc/bar")
+
+ assert_equal expected_params, actual_params
+ end
+
+ def test_class_constraints_dont_leak_between_routes
+ expected_params = { controller: "pages", action: "show", bar: "bar" }
+ actual_params = recognize_path("/class/bar")
+
+ assert_equal expected_params, actual_params
+ end
+
+ private
+
+ def recognize_path(*args)
+ Routes.recognize_path(*args)
+ end
+end
diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md
index d561745611..41505fbf83 100644
--- a/activejob/CHANGELOG.md
+++ b/activejob/CHANGELOG.md
@@ -6,10 +6,6 @@
*Yuji Yaginuma*
-* Push skipped jobs to `enqueued_jobs` when using `perform_enqueued_jobs` with a `only` filter in tests
-
- *Alexander Pauly*
-
* Removed deprecated support to passing the adapter class to `.queue_adapter`.
*Rafael Mendonça França*
diff --git a/activejob/lib/active_job/queue_adapters/test_adapter.rb b/activejob/lib/active_job/queue_adapters/test_adapter.rb
index ec825f12cd..1b633b210e 100644
--- a/activejob/lib/active_job/queue_adapters/test_adapter.rb
+++ b/activejob/lib/active_job/queue_adapters/test_adapter.rb
@@ -24,27 +24,30 @@ module ActiveJob
end
def enqueue(job) #:nodoc:
+ return if filtered?(job)
+
job_data = job_to_hash(job)
enqueue_or_perform(perform_enqueued_jobs, job, job_data)
end
def enqueue_at(job, timestamp) #:nodoc:
+ return if filtered?(job)
+
job_data = job_to_hash(job, at: timestamp)
enqueue_or_perform(perform_enqueued_at_jobs, job, job_data)
end
private
-
def job_to_hash(job, extras = {})
{ job: job.class, args: job.serialize.fetch("arguments"), queue: job.queue_name }.merge!(extras)
end
def enqueue_or_perform(perform, job, job_data)
- if !perform || filtered?(job)
- enqueued_jobs << job_data
- else
+ if perform
performed_jobs << job_data
Base.execute job.serialize
+ else
+ enqueued_jobs << job_data
end
end
diff --git a/activejob/test/cases/test_helper_test.rb b/activejob/test/cases/test_helper_test.rb
index 2e6357f824..81e75b4374 100644
--- a/activejob/test/cases/test_helper_test.rb
+++ b/activejob/test/cases/test_helper_test.rb
@@ -56,17 +56,6 @@ class EnqueuedJobsTest < ActiveJob::TestCase
end
end
- def test_assert_enqueued_jobs_when_performing_with_only_option
- assert_nothing_raised do
- assert_enqueued_jobs 1, only: HelloJob do
- perform_enqueued_jobs only: LoggingJob do
- HelloJob.perform_later("sean")
- LoggingJob.perform_later("yves")
- end
- end
- end
- end
-
def test_assert_no_enqueued_jobs_with_no_block
assert_nothing_raised do
assert_no_enqueued_jobs
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 0028dc0edb..8f78330d4a 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -559,7 +559,6 @@ module ActiveRecord
@marked_for_destruction = false
@destroyed_by_association = nil
@new_record = true
- @txn = nil
@_start_transaction_state = {}
@transaction_state = nil
end
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index 14fb2fbbfa..a6c22ac672 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -10,8 +10,6 @@ require "concurrent/atomic/cyclic_barrier"
class DefaultScopingTest < ActiveRecord::TestCase
fixtures :developers, :posts, :comments
- self.use_transactional_tests = false
-
def test_default_scope
expected = Developer.all.merge!(order: "salary DESC").to_a.collect(&:salary)
received = DeveloperOrderedBySalary.all.collect(&:salary)
@@ -61,17 +59,6 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal "Jamis", DeveloperCalledJamis.create!.name
end
- unless in_memory_db?
- def test_default_scoping_with_threads
- 2.times do
- Thread.new {
- assert_includes DeveloperOrderedBySalary.all.to_sql, "salary DESC"
- DeveloperOrderedBySalary.connection.close
- }.join
- end
- end
- end
-
def test_default_scope_with_inheritance
wheres = InheritedPoorDeveloperCalledJamis.all.where_values_hash
assert_equal "Jamis", wheres["name"]
@@ -435,29 +422,6 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal comment, CommentWithDefaultScopeReferencesAssociation.find_by(id: comment.id)
end
- unless in_memory_db?
- def test_default_scope_is_threadsafe
- threads = []
- assert_not_equal 1, ThreadsafeDeveloper.unscoped.count
-
- barrier_1 = Concurrent::CyclicBarrier.new(2)
- barrier_2 = Concurrent::CyclicBarrier.new(2)
-
- threads << Thread.new do
- Thread.current[:default_scope_delay] = -> { barrier_1.wait; barrier_2.wait }
- assert_equal 1, ThreadsafeDeveloper.all.to_a.count
- ThreadsafeDeveloper.connection.close
- end
- threads << Thread.new do
- Thread.current[:default_scope_delay] = -> { barrier_2.wait }
- barrier_1.wait
- assert_equal 1, ThreadsafeDeveloper.all.to_a.count
- ThreadsafeDeveloper.connection.close
- end
- threads.each(&:join)
- end
- end
-
test "additional conditions are ANDed with the default scope" do
scope = DeveloperCalledJamis.where(name: "David")
assert_equal 2, scope.where_clause.ast.children.length
@@ -506,3 +470,37 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_match gender_pattern, Lion.female.to_sql
end
end
+
+class DefaultScopingWithThreadTest < ActiveRecord::TestCase
+ self.use_transactional_tests = false
+
+ def test_default_scoping_with_threads
+ 2.times do
+ Thread.new {
+ assert_includes DeveloperOrderedBySalary.all.to_sql, "salary DESC"
+ DeveloperOrderedBySalary.connection.close
+ }.join
+ end
+ end
+
+ def test_default_scope_is_threadsafe
+ threads = []
+ assert_not_equal 1, ThreadsafeDeveloper.unscoped.count
+
+ barrier_1 = Concurrent::CyclicBarrier.new(2)
+ barrier_2 = Concurrent::CyclicBarrier.new(2)
+
+ threads << Thread.new do
+ Thread.current[:default_scope_delay] = -> { barrier_1.wait; barrier_2.wait }
+ assert_equal 1, ThreadsafeDeveloper.all.to_a.count
+ ThreadsafeDeveloper.connection.close
+ end
+ threads << Thread.new do
+ Thread.current[:default_scope_delay] = -> { barrier_2.wait }
+ barrier_1.wait
+ assert_equal 1, ThreadsafeDeveloper.all.to_a.count
+ ThreadsafeDeveloper.connection.close
+ end
+ threads.each(&:join)
+ end
+end unless in_memory_db?
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index de1418bb86..969d36c303 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,19 @@
+* Remove implicit coercion deprecation of durations
+
+ In #28204 we deprecated implicit conversion of durations to a numeric which
+ represented the number of seconds in the duration because of unwanted side
+ effects with calculations on durations and dates. This unfortunately had
+ the side effect of forcing a explicit cast when configuring third-party
+ libraries like expiration in Redis, e.g:
+
+ redis.expire("foo", 5.minutes)
+
+ To work around this we've removed the deprecation and added a private class
+ that wraps the numeric and can perform calculation involving durations and
+ ensure that they remain a duration irrespective of the order of operations.
+
+ *Andrew White*
+
* Update `titleize` regex to allow apostrophes
In 4b685aa the regex in `titleize` was updated to not match apostrophes to
@@ -192,6 +208,13 @@
## Rails 5.1.0.beta1 (February 23, 2017) ##
+* Fixed bug in `DateAndTime::Compatibility#to_time` that caused it to
+ raise `RuntimeError: can't modify frozen Time` when called on any frozen `Time`.
+ Properly pass through the frozen `Time` or `ActiveSupport::TimeWithZone` object
+ when calling `#to_time`.
+
+ *Kevin McPhillips* & *Andrew White*
+
* Cache `ActiveSupport::TimeWithZone#to_datetime` before freezing.
*Adam Rice*
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index 5eee04a34e..e09cee3335 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -156,7 +156,7 @@ module ActiveSupport
expires_in = options[:expires_in].to_i
if expires_in > 0 && !options[:raw]
# Set the memcache expire a few minutes in the future to support race condition ttls on read
- expires_in += 300
+ expires_in += 5.minutes
end
rescue_error_with false do
@data.send(method, key, value, expires_in, options)
diff --git a/activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb b/activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb
index db95ae0db5..ab80392460 100644
--- a/activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb
+++ b/activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb
@@ -10,13 +10,5 @@ module DateAndTime
# this behavior, but new apps will have an initializer that sets
# this to true, because the new behavior is preferred.
mattr_accessor(:preserve_timezone, instance_writer: false) { false }
-
- def to_time
- if preserve_timezone
- @_to_time_with_instance_offset ||= getlocal(utc_offset)
- else
- @_to_time_with_system_offset ||= getlocal
- end
- end
end
end
diff --git a/activesupport/lib/active_support/core_ext/date_time/compatibility.rb b/activesupport/lib/active_support/core_ext/date_time/compatibility.rb
index 30bb7f4a60..eb8b8b2c65 100644
--- a/activesupport/lib/active_support/core_ext/date_time/compatibility.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/compatibility.rb
@@ -1,5 +1,15 @@
require "active_support/core_ext/date_and_time/compatibility"
class DateTime
- prepend DateAndTime::Compatibility
+ include DateAndTime::Compatibility
+
+ remove_possible_method :to_time
+
+ # Either return an instance of `Time` with the same UTC offset
+ # as +self+ or an instance of `Time` representing the same time
+ # in the the local system timezone depending on the setting of
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
+ def to_time
+ preserve_timezone ? getlocal(utc_offset) : getlocal
+ end
end
diff --git a/activesupport/lib/active_support/core_ext/object/with_options.rb b/activesupport/lib/active_support/core_ext/object/with_options.rb
index cf39b1d312..4afb20ebfd 100644
--- a/activesupport/lib/active_support/core_ext/object/with_options.rb
+++ b/activesupport/lib/active_support/core_ext/object/with_options.rb
@@ -62,6 +62,17 @@ class Object
#
# Hence the inherited default for `if` key is ignored.
#
+ # NOTE: You cannot call class methods implicitly inside of with_options,
+ # refer the methods using the class name instead, like so:
+ #
+ # class Phone < ActiveRecord::Base
+ # enum phone_number_type: [home: 0, office: 1, mobile: 2]
+ #
+ # with_options presence: true do
+ # validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
+ # end
+ # end
+ #
def with_options(options, &block)
option_merger = ActiveSupport::OptionMerger.new(self, options)
block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
diff --git a/activesupport/lib/active_support/core_ext/time/compatibility.rb b/activesupport/lib/active_support/core_ext/time/compatibility.rb
index ca4b9574d5..45e86b77ce 100644
--- a/activesupport/lib/active_support/core_ext/time/compatibility.rb
+++ b/activesupport/lib/active_support/core_ext/time/compatibility.rb
@@ -1,5 +1,14 @@
require "active_support/core_ext/date_and_time/compatibility"
+require "active_support/core_ext/module/remove_method"
class Time
- prepend DateAndTime::Compatibility
+ include DateAndTime::Compatibility
+
+ remove_possible_method :to_time
+
+ # Either return +self+ or the time in the local system timezone depending
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
+ def to_time
+ preserve_timezone ? self : getlocal
+ end
end
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index d26bbac511..99080e34a1 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -1,4 +1,5 @@
require "active_support/core_ext/array/conversions"
+require "active_support/core_ext/module/delegation"
require "active_support/core_ext/object/acts_like"
require "active_support/core_ext/string/filters"
require "active_support/deprecation"
@@ -9,6 +10,66 @@ module ActiveSupport
#
# 1.month.ago # equivalent to Time.now.advance(months: -1)
class Duration
+ class Scalar < Numeric #:nodoc:
+ attr_reader :value
+ delegate :to_i, :to_f, :to_s, to: :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def coerce(other)
+ [Scalar.new(other), self]
+ end
+
+ def -@
+ Scalar.new(-value)
+ end
+
+ def <=>(other)
+ if Scalar === other || Duration === other
+ value <=> other.value
+ elsif Numeric === other
+ value <=> other
+ else
+ nil
+ end
+ end
+
+ def +(other)
+ calculate(:+, other)
+ end
+
+ def -(other)
+ calculate(:-, other)
+ end
+
+ def *(other)
+ calculate(:*, other)
+ end
+
+ def /(other)
+ calculate(:/, other)
+ end
+
+ private
+ def calculate(op, other)
+ if Scalar === other
+ Scalar.new(value.public_send(op, other.value))
+ elsif Duration === other
+ Duration.seconds(value).public_send(op, other)
+ elsif Numeric === other
+ Scalar.new(value.public_send(op, other))
+ else
+ raise_type_error(other)
+ end
+ end
+
+ def raise_type_error(other)
+ raise TypeError, "no implicit conversion of #{other.class} into #{self.class}"
+ end
+ end
+
SECONDS_PER_MINUTE = 60
SECONDS_PER_HOUR = 3600
SECONDS_PER_DAY = 86400
@@ -91,12 +152,11 @@ module ActiveSupport
end
def coerce(other) #:nodoc:
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- Implicit coercion of ActiveSupport::Duration to a Numeric
- is deprecated and will raise a TypeError in Rails 5.2.
- MSG
-
- [other, value]
+ if Scalar === other
+ [other, self]
+ else
+ [Scalar.new(other), self]
+ end
end
# Compares one Duration with another or a Numeric to this Duration.
@@ -132,19 +192,23 @@ module ActiveSupport
# Multiplies this Duration by a Numeric and returns a new Duration.
def *(other)
- if Numeric === other
+ if Scalar === other || Duration === other
+ Duration.new(value * other.value, parts.map { |type, number| [type, number * other.value] })
+ elsif Numeric === other
Duration.new(value * other, parts.map { |type, number| [type, number * other] })
else
- value * other
+ raise_type_error(other)
end
end
# Divides this Duration by a Numeric and returns a new Duration.
def /(other)
- if Numeric === other
+ if Scalar === other || Duration === other
+ Duration.new(value / other.value, parts.map { |type, number| [type, number / other.value] })
+ elsif Numeric === other
Duration.new(value / other, parts.map { |type, number| [type, number / other] })
else
- value / other
+ raise_type_error(other)
end
end
@@ -274,5 +338,9 @@ module ActiveSupport
def method_missing(method, *args, &block)
value.send(method, *args, &block)
end
+
+ def raise_type_error(other)
+ raise TypeError, "no implicit conversion of #{other.class} into #{self.class}"
+ end
end
end
diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb
index 69109d2005..24053b4fe5 100644
--- a/activesupport/lib/active_support/message_encryptor.rb
+++ b/activesupport/lib/active_support/message_encryptor.rb
@@ -50,6 +50,11 @@ module ActiveSupport
# key by using <tt>ActiveSupport::KeyGenerator</tt> or a similar key
# derivation function.
#
+ # First additional parameter is used as the signature key for +MessageVerifier+.
+ # This allows you to specify keys to encrypt and sign data.
+ #
+ # ActiveSupport::MessageEncryptor.new('secret', 'signature_secret')
+ #
# Options:
# * <tt>:cipher</tt> - Cipher to use. Can be any cipher returned by
# <tt>OpenSSL::Cipher.ciphers</tt>. Default is 'aes-256-cbc'.
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index e31983cf26..b0dd6b7e8c 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -411,6 +411,17 @@ module ActiveSupport
@to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
end
+ # Returns an instance of +Time+, either with the same UTC offset
+ # as +self+ or in the local system timezone depending on the setting
+ # of +ActiveSupport.to_time_preserves_timezone+.
+ def to_time
+ if preserve_timezone
+ @to_time_with_instance_offset ||= getlocal(utc_offset)
+ else
+ @to_time_with_system_offset ||= getlocal
+ end
+ end
+
# So that +self+ <tt>acts_like?(:time)</tt>.
def acts_like_time?
true
@@ -429,7 +440,7 @@ module ActiveSupport
def freeze
# preload instance variables before freezing
- period; utc; time; to_datetime
+ period; utc; time; to_datetime; to_time
super
end
diff --git a/activesupport/test/core_ext/date_and_time_compatibility_test.rb b/activesupport/test/core_ext/date_and_time_compatibility_test.rb
index 4c90460032..6c6205a4d2 100644
--- a/activesupport/test/core_ext/date_and_time_compatibility_test.rb
+++ b/activesupport/test/core_ext/date_and_time_compatibility_test.rb
@@ -16,11 +16,13 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase
def test_time_to_time_preserves_timezone
with_preserve_timezone(true) do
with_env_tz "US/Eastern" do
- time = Time.new(2016, 4, 23, 15, 11, 12, 3600).to_time
+ source = Time.new(2016, 4, 23, 15, 11, 12, 3600)
+ time = source.to_time
assert_instance_of Time, time
assert_equal @utc_time, time.getutc
assert_equal @utc_offset, time.utc_offset
+ assert_equal source.object_id, time.object_id
end
end
end
@@ -28,11 +30,43 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase
def test_time_to_time_does_not_preserve_time_zone
with_preserve_timezone(false) do
with_env_tz "US/Eastern" do
- time = Time.new(2016, 4, 23, 15, 11, 12, 3600).to_time
+ source = Time.new(2016, 4, 23, 15, 11, 12, 3600)
+ time = source.to_time
assert_instance_of Time, time
assert_equal @utc_time, time.getutc
assert_equal @system_offset, time.utc_offset
+ assert_not_equal source.object_id, time.object_id
+ end
+ end
+ end
+
+ def test_time_to_time_frozen_preserves_timezone
+ with_preserve_timezone(true) do
+ with_env_tz "US/Eastern" do
+ source = Time.new(2016, 4, 23, 15, 11, 12, 3600).freeze
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @utc_time, time.getutc
+ assert_equal @utc_offset, time.utc_offset
+ assert_equal source.object_id, time.object_id
+ assert_predicate time, :frozen?
+ end
+ end
+ end
+
+ def test_time_to_time_frozen_does_not_preserve_time_zone
+ with_preserve_timezone(false) do
+ with_env_tz "US/Eastern" do
+ source = Time.new(2016, 4, 23, 15, 11, 12, 3600).freeze
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @utc_time, time.getutc
+ assert_equal @system_offset, time.utc_offset
+ assert_not_equal source.object_id, time.object_id
+ assert_not_predicate time, :frozen?
end
end
end
@@ -40,7 +74,8 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase
def test_datetime_to_time_preserves_timezone
with_preserve_timezone(true) do
with_env_tz "US/Eastern" do
- time = DateTime.new(2016, 4, 23, 15, 11, 12, Rational(1, 24)).to_time
+ source = DateTime.new(2016, 4, 23, 15, 11, 12, Rational(1, 24))
+ time = source.to_time
assert_instance_of Time, time
assert_equal @utc_time, time.getutc
@@ -52,7 +87,8 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase
def test_datetime_to_time_does_not_preserve_time_zone
with_preserve_timezone(false) do
with_env_tz "US/Eastern" do
- time = DateTime.new(2016, 4, 23, 15, 11, 12, Rational(1, 24)).to_time
+ source = DateTime.new(2016, 4, 23, 15, 11, 12, Rational(1, 24))
+ time = source.to_time
assert_instance_of Time, time
assert_equal @utc_time, time.getutc
@@ -61,17 +97,47 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase
end
end
+ def test_datetime_to_time_frozen_preserves_timezone
+ with_preserve_timezone(true) do
+ with_env_tz "US/Eastern" do
+ source = DateTime.new(2016, 4, 23, 15, 11, 12, Rational(1, 24)).freeze
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @utc_time, time.getutc
+ assert_equal @utc_offset, time.utc_offset
+ assert_not_predicate time, :frozen?
+ end
+ end
+ end
+
+ def test_datetime_to_time_frozen_does_not_preserve_time_zone
+ with_preserve_timezone(false) do
+ with_env_tz "US/Eastern" do
+ source = DateTime.new(2016, 4, 23, 15, 11, 12, Rational(1, 24)).freeze
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @utc_time, time.getutc
+ assert_equal @system_offset, time.utc_offset
+ assert_not_predicate time, :frozen?
+ end
+ end
+ end
+
def test_twz_to_time_preserves_timezone
with_preserve_timezone(true) do
with_env_tz "US/Eastern" do
- time = ActiveSupport::TimeWithZone.new(@utc_time, @zone).to_time
+ source = ActiveSupport::TimeWithZone.new(@utc_time, @zone)
+ time = source.to_time
assert_instance_of Time, time
assert_equal @utc_time, time.getutc
assert_instance_of Time, time.getutc
assert_equal @utc_offset, time.utc_offset
- time = ActiveSupport::TimeWithZone.new(@date_time, @zone).to_time
+ source = ActiveSupport::TimeWithZone.new(@date_time, @zone)
+ time = source.to_time
assert_instance_of Time, time
assert_equal @date_time, time.getutc
@@ -84,19 +150,69 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase
def test_twz_to_time_does_not_preserve_time_zone
with_preserve_timezone(false) do
with_env_tz "US/Eastern" do
- time = ActiveSupport::TimeWithZone.new(@utc_time, @zone).to_time
+ source = ActiveSupport::TimeWithZone.new(@utc_time, @zone)
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @utc_time, time.getutc
+ assert_instance_of Time, time.getutc
+ assert_equal @system_offset, time.utc_offset
+
+ source = ActiveSupport::TimeWithZone.new(@date_time, @zone)
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @date_time, time.getutc
+ assert_instance_of Time, time.getutc
+ assert_equal @system_offset, time.utc_offset
+ end
+ end
+ end
+
+ def test_twz_to_time_frozen_preserves_timezone
+ with_preserve_timezone(true) do
+ with_env_tz "US/Eastern" do
+ source = ActiveSupport::TimeWithZone.new(@utc_time, @zone).freeze
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @utc_time, time.getutc
+ assert_instance_of Time, time.getutc
+ assert_equal @utc_offset, time.utc_offset
+ assert_not_predicate time, :frozen?
+
+ source = ActiveSupport::TimeWithZone.new(@date_time, @zone).freeze
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @date_time, time.getutc
+ assert_instance_of Time, time.getutc
+ assert_equal @utc_offset, time.utc_offset
+ assert_not_predicate time, :frozen?
+ end
+ end
+ end
+
+ def test_twz_to_time_frozen_does_not_preserve_time_zone
+ with_preserve_timezone(false) do
+ with_env_tz "US/Eastern" do
+ source = ActiveSupport::TimeWithZone.new(@utc_time, @zone).freeze
+ time = source.to_time
assert_instance_of Time, time
assert_equal @utc_time, time.getutc
assert_instance_of Time, time.getutc
assert_equal @system_offset, time.utc_offset
+ assert_not_predicate time, :frozen?
- time = ActiveSupport::TimeWithZone.new(@date_time, @zone).to_time
+ source = ActiveSupport::TimeWithZone.new(@date_time, @zone).freeze
+ time = source.to_time
assert_instance_of Time, time
assert_equal @date_time, time.getutc
assert_instance_of Time, time.getutc
assert_equal @system_offset, time.utc_offset
+ assert_not_predicate time, :frozen?
end
end
end
@@ -104,7 +220,8 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase
def test_string_to_time_preserves_timezone
with_preserve_timezone(true) do
with_env_tz "US/Eastern" do
- time = "2016-04-23T15:11:12+01:00".to_time
+ source = "2016-04-23T15:11:12+01:00"
+ time = source.to_time
assert_instance_of Time, time
assert_equal @utc_time, time.getutc
@@ -116,11 +233,40 @@ class DateAndTimeCompatibilityTest < ActiveSupport::TestCase
def test_string_to_time_does_not_preserve_time_zone
with_preserve_timezone(false) do
with_env_tz "US/Eastern" do
- time = "2016-04-23T15:11:12+01:00".to_time
+ source = "2016-04-23T15:11:12+01:00"
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @utc_time, time.getutc
+ assert_equal @system_offset, time.utc_offset
+ end
+ end
+ end
+
+ def test_string_to_time_frozen_preserves_timezone
+ with_preserve_timezone(true) do
+ with_env_tz "US/Eastern" do
+ source = "2016-04-23T15:11:12+01:00".freeze
+ time = source.to_time
+
+ assert_instance_of Time, time
+ assert_equal @utc_time, time.getutc
+ assert_equal @utc_offset, time.utc_offset
+ assert_not_predicate time, :frozen?
+ end
+ end
+ end
+
+ def test_string_to_time_frozen_does_not_preserve_time_zone
+ with_preserve_timezone(false) do
+ with_env_tz "US/Eastern" do
+ source = "2016-04-23T15:11:12+01:00".freeze
+ time = source.to_time
assert_instance_of Time, time
assert_equal @utc_time, time.getutc
assert_equal @system_offset, time.utc_offset
+ assert_not_predicate time, :frozen?
end
end
end
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index 2b1a715b7a..1648a9b270 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -96,24 +96,20 @@ class DurationTest < ActiveSupport::TestCase
assert_instance_of ActiveSupport::Duration, 2.seconds - 1.second
assert_equal 1.second, 2.seconds - 1
assert_instance_of ActiveSupport::Duration, 2.seconds - 1
+ assert_equal 1.second, 2 - 1.second
+ assert_instance_of ActiveSupport::Duration, 2.seconds - 1
end
def test_multiply
assert_equal 7.days, 1.day * 7
assert_instance_of ActiveSupport::Duration, 1.day * 7
-
- assert_deprecated do
- assert_equal 86400, 1.day * 1.second
- end
+ assert_equal 86400, 1.day * 1.second
end
def test_divide
assert_equal 1.day, 7.days / 7
assert_instance_of ActiveSupport::Duration, 7.days / 7
-
- assert_deprecated do
- assert_equal 1, 1.day / 1.day
- end
+ assert_equal 1, 1.day / 1.day
end
def test_date_added_with_multiplied_duration
@@ -121,9 +117,7 @@ class DurationTest < ActiveSupport::TestCase
end
def test_plus_with_time
- assert_deprecated do
- assert_equal 1 + 1.second, 1.second + 1, "Duration + Numeric should == Numeric + Duration"
- end
+ assert_equal 1 + 1.second, 1.second + 1, "Duration + Numeric should == Numeric + Duration"
end
def test_time_plus_duration_returns_same_time_datatype
@@ -142,13 +136,6 @@ class DurationTest < ActiveSupport::TestCase
assert_equal 'expected a time or date, got ""', e.message, "ensure ArgumentError is not being raised by dependencies.rb"
end
- def test_implicit_coercion_is_deprecated
- assert_deprecated { 1 + 1.second }
- assert_deprecated { 1 - 1.second }
- assert_deprecated { 1 * 1.second }
- assert_deprecated { 1 / 1.second }
- end
-
def test_fractional_weeks
assert_equal((86400 * 7) * 1.5, 1.5.weeks)
assert_equal((86400 * 7) * 1.7, 1.7.weeks)
@@ -286,20 +273,125 @@ class DurationTest < ActiveSupport::TestCase
def test_comparable
assert_equal(-1, (0.seconds <=> 1.second))
assert_equal(-1, (1.second <=> 1.minute))
-
- assert_deprecated do
- assert_equal(-1, (1 <=> 1.minute))
- end
-
+ assert_equal(-1, (1 <=> 1.minute))
assert_equal(0, (0.seconds <=> 0.seconds))
assert_equal(0, (0.seconds <=> 0.minutes))
assert_equal(0, (1.second <=> 1.second))
assert_equal(1, (1.second <=> 0.second))
assert_equal(1, (1.minute <=> 1.second))
+ assert_equal(1, (61 <=> 1.minute))
+ end
- assert_deprecated do
- assert_equal(1, (61 <=> 1.minute))
+ def test_implicit_coercion
+ assert_equal 2.days, 2 * 1.day
+ assert_instance_of ActiveSupport::Duration, 2 * 1.day
+ assert_equal Time.utc(2017, 1, 3), Time.utc(2017, 1, 1) + 2 * 1.day
+ assert_equal Date.civil(2017, 1, 3), Date.civil(2017, 1, 1) + 2 * 1.day
+ end
+
+ def test_scalar_coerce
+ scalar = ActiveSupport::Duration::Scalar.new(10)
+ assert_instance_of ActiveSupport::Duration::Scalar, 10 + scalar
+ assert_instance_of ActiveSupport::Duration, 10.seconds + scalar
+ end
+
+ def test_scalar_delegations
+ scalar = ActiveSupport::Duration::Scalar.new(10)
+ assert_kind_of Float, scalar.to_f
+ assert_kind_of Integer, scalar.to_i
+ assert_kind_of String, scalar.to_s
+ end
+
+ def test_scalar_unary_minus
+ scalar = ActiveSupport::Duration::Scalar.new(10)
+
+ assert_equal(-10, -scalar)
+ assert_instance_of ActiveSupport::Duration::Scalar, -scalar
+ end
+
+ def test_scalar_compare
+ scalar = ActiveSupport::Duration::Scalar.new(10)
+
+ assert_equal(1, scalar <=> 5)
+ assert_equal(0, scalar <=> 10)
+ assert_equal(-1, scalar <=> 15)
+ assert_equal(nil, scalar <=> "foo")
+ end
+
+ def test_scalar_plus
+ scalar = ActiveSupport::Duration::Scalar.new(10)
+
+ assert_equal 20, 10 + scalar
+ assert_instance_of ActiveSupport::Duration::Scalar, 10 + scalar
+ assert_equal 20, scalar + 10
+ assert_instance_of ActiveSupport::Duration::Scalar, scalar + 10
+ assert_equal 20, 10.seconds + scalar
+ assert_instance_of ActiveSupport::Duration, 10.seconds + scalar
+ assert_equal 20, scalar + 10.seconds
+ assert_instance_of ActiveSupport::Duration, scalar + 10.seconds
+
+ exception = assert_raises(TypeError) do
+ scalar + "foo"
+ end
+
+ assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
+ end
+
+ def test_scalar_minus
+ scalar = ActiveSupport::Duration::Scalar.new(10)
+
+ assert_equal 10, 20 - scalar
+ assert_instance_of ActiveSupport::Duration::Scalar, 20 - scalar
+ assert_equal 5, scalar - 5
+ assert_instance_of ActiveSupport::Duration::Scalar, scalar - 5
+ assert_equal 10, 20.seconds - scalar
+ assert_instance_of ActiveSupport::Duration, 20.seconds - scalar
+ assert_equal 5, scalar - 5.seconds
+ assert_instance_of ActiveSupport::Duration, scalar - 5.seconds
+
+ exception = assert_raises(TypeError) do
+ scalar - "foo"
+ end
+
+ assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
+ end
+
+ def test_scalar_multiply
+ scalar = ActiveSupport::Duration::Scalar.new(5)
+
+ assert_equal 10, 2 * scalar
+ assert_instance_of ActiveSupport::Duration::Scalar, 2 * scalar
+ assert_equal 10, scalar * 2
+ assert_instance_of ActiveSupport::Duration::Scalar, scalar * 2
+ assert_equal 10, 2.seconds * scalar
+ assert_instance_of ActiveSupport::Duration, 2.seconds * scalar
+ assert_equal 10, scalar * 2.seconds
+ assert_instance_of ActiveSupport::Duration, scalar * 2.seconds
+
+ exception = assert_raises(TypeError) do
+ scalar * "foo"
end
+
+ assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
+ end
+
+ def test_scalar_divide
+ scalar = ActiveSupport::Duration::Scalar.new(10)
+
+ assert_equal 10, 100 / scalar
+ assert_instance_of ActiveSupport::Duration::Scalar, 100 / scalar
+ assert_equal 5, scalar / 2
+ assert_instance_of ActiveSupport::Duration::Scalar, scalar / 2
+ assert_equal 10, 100.seconds / scalar
+ assert_instance_of ActiveSupport::Duration, 2.seconds * scalar
+ assert_equal 5, scalar / 2.seconds
+ assert_instance_of ActiveSupport::Duration, scalar / 2.seconds
+
+ exception = assert_raises(TypeError) do
+ scalar / "foo"
+ end
+
+ assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
end
def test_twelve_months_equals_one_year
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index 3cc29ca040..c3afe68378 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -431,11 +431,29 @@ class TimeWithZoneTest < ActiveSupport::TestCase
assert_equal time, Time.at(time)
end
- def test_to_time
- with_env_tz "US/Eastern" do
- assert_equal Time, @twz.to_time.class
- assert_equal Time.local(1999, 12, 31, 19), @twz.to_time
- assert_equal Time.local(1999, 12, 31, 19).utc_offset, @twz.to_time.utc_offset
+ def test_to_time_with_preserve_timezone
+ with_preserve_timezone(true) do
+ with_env_tz "US/Eastern" do
+ time = @twz.to_time
+
+ assert_equal Time, time.class
+ assert_equal time.object_id, @twz.to_time.object_id
+ assert_equal Time.local(1999, 12, 31, 19), time
+ assert_equal Time.local(1999, 12, 31, 19).utc_offset, time.utc_offset
+ end
+ end
+ end
+
+ def test_to_time_without_preserve_timezone
+ with_preserve_timezone(false) do
+ with_env_tz "US/Eastern" do
+ time = @twz.to_time
+
+ assert_equal Time, time.class
+ assert_equal time.object_id, @twz.to_time.object_id
+ assert_equal Time.local(1999, 12, 31, 19), time
+ assert_equal Time.local(1999, 12, 31, 19).utc_offset, time.utc_offset
+ end
end
end
@@ -518,6 +536,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase
@twz.period
@twz.time
@twz.to_datetime
+ @twz.to_time
end
end
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index ba0cdbf3af..33dee6a868 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -606,7 +606,6 @@ You can also inspect for an object method this way:
@new_record = true
@readonly = false
@transaction_state = nil
-@txn = nil
```
You can also use `display` to start watching variables. This is a good way of
diff --git a/railties/lib/rails/commands/destroy/destroy_command.rb b/railties/lib/rails/commands/destroy/destroy_command.rb
index c802910b5d..794673851d 100644
--- a/railties/lib/rails/commands/destroy/destroy_command.rb
+++ b/railties/lib/rails/commands/destroy/destroy_command.rb
@@ -14,9 +14,9 @@ module Rails
return help unless generator
require_application_and_environment!
- Rails.application.load_generators
+ load_generators
- Rails::Generators.invoke generator, args, behavior: :revoke, destination_root: Rails.root
+ Rails::Generators.invoke generator, args, behavior: :revoke, destination_root: Rails::Command.root
end
end
end
diff --git a/railties/test/commands/secrets_test.rb b/railties/test/commands/secrets_test.rb
index 13fcf6c8a4..00b0343397 100644
--- a/railties/test/commands/secrets_test.rb
+++ b/railties/test/commands/secrets_test.rb
@@ -17,8 +17,21 @@ class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase
assert_match "No $EDITOR to open decrypted secrets in", run_edit_command(editor: "")
end
+ test "edit secrets" do
+ run_setup_command
+
+ # Run twice to ensure encrypted secrets can be reread after first edit pass.
+ 2.times do
+ assert_match(/external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289…/, run_edit_command)
+ end
+ end
+
private
def run_edit_command(editor: "cat")
Dir.chdir(app_path) { `EDITOR="#{editor}" bin/rails secrets:edit` }
end
+
+ def run_setup_command
+ Dir.chdir(app_path) { `bin/rails secrets:setup` }
+ end
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 986afb6d2a..79fe4e4eb7 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -133,7 +133,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_rails_update_generates_correct_session_key
+ def test_app_update_generates_correct_session_key
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
@@ -156,7 +156,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_no_file "config/initializers/cors.rb"
end
- def test_rails_update_keep_the_cookie_serializer_if_it_is_already_configured
+ def test_app_update_keep_the_cookie_serializer_if_it_is_already_configured
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
@@ -168,7 +168,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_rails_update_set_the_cookie_serializer_to_marshal_if_it_is_not_already_configured
+ def test_app_update_set_the_cookie_serializer_to_marshal_if_it_is_not_already_configured
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
@@ -183,7 +183,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_rails_update_dont_set_file_watcher
+ def test_app_update_dont_set_file_watcher
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
@@ -197,7 +197,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_rails_update_does_not_create_new_framework_defaults_by_default
+ def test_app_update_does_not_create_new_framework_defaults_by_default
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
@@ -215,7 +215,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_rails_update_does_not_create_rack_cors
+ def test_app_update_does_not_create_rack_cors
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
@@ -227,7 +227,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_rails_update_does_not_remove_rack_cors_if_already_present
+ def test_app_update_does_not_remove_rack_cors_if_already_present
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index 436fbd5d73..b9c2e791da 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -558,4 +558,59 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_match(/6 runs, 8 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`)
end
end
+
+ def test_scaffold_on_invoke_inside_mountable_engine
+ Dir.chdir(destination_root) { `bundle exec rails plugin new bukkits --mountable` }
+ engine_path = File.join(destination_root, "bukkits")
+
+ Dir.chdir(engine_path) do
+ quietly { `bin/rails generate scaffold User name:string age:integer` }
+
+ assert File.exist?("app/models/bukkits/user.rb")
+ assert File.exist?("test/models/bukkits/user_test.rb")
+ assert File.exist?("test/fixtures/bukkits/users.yml")
+
+ assert File.exist?("app/controllers/bukkits/users_controller.rb")
+ assert File.exist?("test/controllers/bukkits/users_controller_test.rb")
+
+ assert File.exist?("app/views/bukkits/users/index.html.erb")
+ assert File.exist?("app/views/bukkits/users/edit.html.erb")
+ assert File.exist?("app/views/bukkits/users/show.html.erb")
+ assert File.exist?("app/views/bukkits/users/new.html.erb")
+ assert File.exist?("app/views/bukkits/users/_form.html.erb")
+
+ assert File.exist?("app/helpers/bukkits/users_helper.rb")
+
+ assert File.exist?("app/assets/javascripts/bukkits/users.js")
+ assert File.exist?("app/assets/stylesheets/bukkits/users.css")
+ end
+ end
+
+ def test_scaffold_on_revoke_inside_mountable_engine
+ Dir.chdir(destination_root) { `bundle exec rails plugin new bukkits --mountable` }
+ engine_path = File.join(destination_root, "bukkits")
+
+ Dir.chdir(engine_path) do
+ quietly { `bin/rails generate scaffold User name:string age:integer` }
+ quietly { `bin/rails destroy scaffold User` }
+
+ assert_not File.exist?("app/models/bukkits/user.rb")
+ assert_not File.exist?("test/models/bukkits/user_test.rb")
+ assert_not File.exist?("test/fixtures/bukkits/users.yml")
+
+ assert_not File.exist?("app/controllers/bukkits/users_controller.rb")
+ assert_not File.exist?("test/controllers/bukkits/users_controller_test.rb")
+
+ assert_not File.exist?("app/views/bukkits/users/index.html.erb")
+ assert_not File.exist?("app/views/bukkits/users/edit.html.erb")
+ assert_not File.exist?("app/views/bukkits/users/show.html.erb")
+ assert_not File.exist?("app/views/bukkits/users/new.html.erb")
+ assert_not File.exist?("app/views/bukkits/users/_form.html.erb")
+
+ assert_not File.exist?("app/helpers/bukkits/users_helper.rb")
+
+ assert_not File.exist?("app/assets/javascripts/bukkits/users.js")
+ assert_not File.exist?("app/assets/stylesheets/bukkits/users.css")
+ end
+ end
end