1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot.git synced 2022-11-09 11:43:51 -05:00

Set timestamps before clearing changes

e7f66fb2 fixed one problem and introduced a new one. Setting timestamps
after clearing_changes_information doesn't work, since using the
created_at and updated_at setters will change the object again. I added
some additional specs for this case (our only spec related to clearing
changes used an object without timestamps).

For the timezone problem, I did a little digging and realized the
casting behavior was actually correct. The reason it was behaving in a
different way than I was expecting is because we had
`time_zone_aware_attributes` set to false, whereas the AR railtie
[sets it to true](54652d886a/activerecord/lib/active_record/railtie.rb (L71)). Setting it to true causes date and datetime attributes
[to get decorated with a TimeZoneConverter](54652d886a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb (L68..L87))
This commit is contained in:
Daniel Colson 2018-10-28 16:01:48 -04:00
parent d395fe874d
commit f56394c187
2 changed files with 96 additions and 10 deletions

View file

@ -31,8 +31,8 @@ module FactoryBot
def result(evaluation) def result(evaluation)
evaluation.object.tap do |instance| evaluation.object.tap do |instance|
stub_database_interaction_on_result(instance) stub_database_interaction_on_result(instance)
clear_changes_information(instance)
set_timestamps(instance) set_timestamps(instance)
clear_changes_information(instance)
evaluation.notify(:after_stub, instance) evaluation.notify(:after_stub, instance)
end end
end end

View file

@ -156,14 +156,9 @@ describe "defaulting `created_at`" do
expect(build_stubbed(:thing_with_timestamp).created_at).to eq Time.now expect(build_stubbed(:thing_with_timestamp).created_at).to eq Time.now
end end
it "defaults created_at for objects with created_at to the correct time with zone" do it "is doesn't mark the object as changed" do
original_timezone = ENV["TZ"] stub = build_stubbed(:thing_with_timestamp)
ENV["TZ"] = "UTC" expect(stub).not_to be_changed
Time.zone = "Eastern Time (US & Canada)"
expect(build_stubbed(:thing_with_timestamp).created_at.zone).to eq "EST"
ENV["TZ"] = original_timezone
end end
it "doesn't add created_at to objects who don't have the method" do it "doesn't add created_at to objects who don't have the method" do
@ -172,7 +167,9 @@ describe "defaulting `created_at`" do
end end
it "allows overriding created_at for objects with created_at" do it "allows overriding created_at for objects with created_at" do
expect(build_stubbed(:thing_with_timestamp, created_at: 3.days.ago).created_at).to eq 3.days.ago created_at = 3.days.ago
stubbed = build_stubbed(:thing_with_timestamp, created_at: created_at)
expect(stubbed.created_at).to eq created_at
end end
it "doesn't allow setting created_at on an object that doesn't define it" do it "doesn't allow setting created_at on an object that doesn't define it" do
@ -186,6 +183,48 @@ describe "defaulting `created_at`" do
stub.created_at = 3.days.ago stub.created_at = 3.days.ago
expect(stub.created_at).to eq 3.days.ago expect(stub.created_at).to eq 3.days.ago
end end
context "when using time_zone_aware_attributes" do
it "defaults created_at to the local time zone" do
Time.zone = "Eastern Time (US & Canada)"
ActiveRecord::Base.time_zone_aware_attributes = true
stub = build_stubbed(:thing_with_timestamp)
expect(stub.created_at.zone).to eq "EST"
end
it "casts created_at override to local time zone" do
Time.zone = "Eastern Time (US & Canada)"
ActiveRecord::Base.time_zone_aware_attributes = true
created_at = Time.now.in_time_zone("CET")
stub = build_stubbed(:thing_with_timestamp, created_at: created_at)
expect(stub.created_at.zone).to eq "EST"
end
end
context "when NOT using time_zone_aware_attributes" do
it "defaults created_at to UTC" do
Time.zone = "Eastern Time (US & Canada)"
ActiveRecord::Base.time_zone_aware_attributes = false
stub = build_stubbed(:thing_with_timestamp)
expect(stub.created_at.zone).to eq "UTC"
end
it "casts created_at override to UTC" do
Time.zone = "Eastern Time (US & Canada)"
ActiveRecord::Base.time_zone_aware_attributes = false
created_at = Time.now.in_time_zone("CET")
stub = build_stubbed(:thing_with_timestamp, created_at: created_at)
expect(stub.created_at.zone).to eq "UTC"
end
end
end end
describe "defaulting `updated_at`" do describe "defaulting `updated_at`" do
@ -207,6 +246,11 @@ describe "defaulting `updated_at`" do
expect(build_stubbed(:thing_with_timestamp).updated_at).to eq Time.current expect(build_stubbed(:thing_with_timestamp).updated_at).to eq Time.current
end end
it "is doesn't mark the object as changed" do
stub = build_stubbed(:thing_with_timestamp)
expect(stub).not_to be_changed
end
it "doesn't add updated_at to objects who don't have the method" do it "doesn't add updated_at to objects who don't have the method" do
expect(build_stubbed(:thing_without_timestamp)). expect(build_stubbed(:thing_without_timestamp)).
not_to respond_to(:updated_at) not_to respond_to(:updated_at)
@ -229,6 +273,48 @@ describe "defaulting `updated_at`" do
stub.updated_at = 3.days.ago stub.updated_at = 3.days.ago
expect(stub.updated_at).to eq 3.days.ago expect(stub.updated_at).to eq 3.days.ago
end end
context "when using time_zone_aware_attributes" do
it "defaults updated_at to the local time zone" do
Time.zone = "Eastern Time (US & Canada)"
ActiveRecord::Base.time_zone_aware_attributes = true
stub = build_stubbed(:thing_with_timestamp)
expect(stub.updated_at.zone).to eq "EST"
end
it "casts updated_at override to local time zone" do
Time.zone = "Eastern Time (US & Canada)"
ActiveRecord::Base.time_zone_aware_attributes = true
updated_at = Time.now.in_time_zone("CET")
stub = build_stubbed(:thing_with_timestamp, updated_at: updated_at)
expect(stub.updated_at.zone).to eq "EST"
end
end
context "when NOT using time_zone_aware_attributes" do
it "defaults updated_at to UTC" do
Time.zone = "Eastern Time (US & Canada)"
ActiveRecord::Base.time_zone_aware_attributes = false
stub = build_stubbed(:thing_with_timestamp)
expect(stub.updated_at.zone).to eq "UTC"
end
it "casts updated_at override to UTC" do
Time.zone = "Eastern Time (US & Canada)"
ActiveRecord::Base.time_zone_aware_attributes = false
updated_at = Time.now.in_time_zone("CET")
stub = build_stubbed(:thing_with_timestamp, updated_at: updated_at)
expect(stub.updated_at.zone).to eq "UTC"
end
end
end end
describe "defaulting `id`" do describe "defaulting `id`" do