diff options
Diffstat (limited to 'activerecord/test/cases/timestamp_test.rb')
-rw-r--r-- | activerecord/test/cases/timestamp_test.rb | 262 |
1 files changed, 256 insertions, 6 deletions
diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb index bb034848e1..db474c63a4 100644 --- a/activerecord/test/cases/timestamp_test.rb +++ b/activerecord/test/cases/timestamp_test.rb @@ -1,5 +1,7 @@ require 'cases/helper' +require 'support/ddl_helper' require 'models/developer' +require 'models/computer' require 'models/owner' require 'models/pet' require 'models/toy' @@ -11,6 +13,7 @@ class TimestampTest < ActiveRecord::TestCase def setup @developer = Developer.first + @owner = Owner.first @developer.update_columns(updated_at: Time.now.prev_month) @previously_updated_at = @developer.updated_at end @@ -88,10 +91,88 @@ class TimestampTest < ActiveRecord::TestCase assert_in_delta Time.now, task.ending, 1 end + def test_touching_many_attributes_updates_them + task = Task.first + previous_starting = task.starting + previous_ending = task.ending + task.touch(:starting, :ending) + + assert_not_equal previous_starting, task.starting + assert_not_equal previous_ending, task.ending + assert_in_delta Time.now, task.starting, 1 + assert_in_delta Time.now, task.ending, 1 + end + def test_touching_a_record_without_timestamps_is_unexceptional assert_nothing_raised { Car.first.touch } end + def test_touching_a_no_touching_object + Developer.no_touching do + assert @developer.no_touching? + assert !@owner.no_touching? + @developer.touch + end + + assert !@developer.no_touching? + assert !@owner.no_touching? + assert_equal @previously_updated_at, @developer.updated_at + end + + def test_touching_related_objects + @owner = Owner.first + @previously_updated_at = @owner.updated_at + + Owner.no_touching do + @owner.pets.first.touch + end + + assert_equal @previously_updated_at, @owner.updated_at + end + + def test_global_no_touching + ActiveRecord::Base.no_touching do + assert @developer.no_touching? + assert @owner.no_touching? + @developer.touch + end + + assert !@developer.no_touching? + assert !@owner.no_touching? + assert_equal @previously_updated_at, @developer.updated_at + end + + def test_no_touching_threadsafe + Thread.new do + Developer.no_touching do + assert @developer.no_touching? + + sleep(1) + end + end + + assert !@developer.no_touching? + end + + def test_no_touching_with_callbacks + klass = Class.new(ActiveRecord::Base) do + self.table_name = "developers" + + attr_accessor :after_touch_called + + after_touch do |user| + user.after_touch_called = true + end + end + + developer = klass.first + + klass.no_touching do + developer.touch + assert_not developer.after_touch_called + end + end + def test_saving_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_update_the_parent_updated_at pet = Pet.first owner = pet.owner @@ -113,6 +194,18 @@ class TimestampTest < ActiveRecord::TestCase assert_not_equal previously_owner_updated_at, pet.owner.updated_at end + def test_saving_a_new_record_belonging_to_invalid_parent_with_touch_should_not_raise_exception + klass = Class.new(Owner) do + def self.name; 'Owner'; end + validate { errors.add(:base, :invalid) } + end + + pet = Pet.new(owner: klass.new) + pet.save! + + assert pet.owner.new_record? + end + def test_saving_a_record_with_a_belongs_to_that_specifies_touching_a_specific_attribute_the_parent_should_update_that_attribute klass = Class.new(ActiveRecord::Base) do def self.name; 'Pet'; end @@ -164,33 +257,190 @@ class TimestampTest < ActiveRecord::TestCase assert_not_equal time, owner.updated_at end + def test_touching_a_record_touches_polymorphic_record + klass = Class.new(ActiveRecord::Base) do + def self.name; 'Toy'; end + end + + wheel_klass = Class.new(ActiveRecord::Base) do + def self.name; 'Wheel'; end + belongs_to :wheelable, :polymorphic => true, :touch => true + end + + toy = klass.first + time = 3.days.ago + toy.update_columns(updated_at: time) + + wheel = wheel_klass.new + wheel.wheelable = toy + wheel.save + wheel.touch + + assert_not_equal time, toy.updated_at + end + + def test_changing_parent_of_a_record_touches_both_new_and_old_parent_record + klass = Class.new(ActiveRecord::Base) do + def self.name; 'Toy'; end + belongs_to :pet, touch: true + end + + toy1 = klass.find(1) + old_pet = toy1.pet + + toy2 = klass.find(2) + new_pet = toy2.pet + time = 3.days.ago.at_beginning_of_hour + + old_pet.update_columns(updated_at: time) + new_pet.update_columns(updated_at: time) + + toy1.pet = new_pet + toy1.save! + + old_pet.reload + new_pet.reload + + assert_not_equal time, new_pet.updated_at + assert_not_equal time, old_pet.updated_at + end + + def test_changing_parent_of_a_record_touches_both_new_and_old_polymorphic_parent_record_changes_within_same_class + car_class = Class.new(ActiveRecord::Base) do + def self.name; 'Car'; end + end + + wheel_class = Class.new(ActiveRecord::Base) do + def self.name; 'Wheel'; end + belongs_to :wheelable, :polymorphic => true, :touch => true + end + + car1 = car_class.find(1) + car2 = car_class.find(2) + + wheel = wheel_class.create!(wheelable: car1) + + time = 3.days.ago.at_beginning_of_hour + + car1.update_columns(updated_at: time) + car2.update_columns(updated_at: time) + + wheel.wheelable = car2 + wheel.save! + + assert_not_equal time, car1.reload.updated_at + assert_not_equal time, car2.reload.updated_at + end + + def test_changing_parent_of_a_record_touches_both_new_and_old_polymorphic_parent_record_changes_with_other_class + car_class = Class.new(ActiveRecord::Base) do + def self.name; 'Car'; end + end + + toy_class = Class.new(ActiveRecord::Base) do + def self.name; 'Toy'; end + end + + wheel_class = Class.new(ActiveRecord::Base) do + def self.name; 'Wheel'; end + belongs_to :wheelable, :polymorphic => true, :touch => true + end + + car = car_class.find(1) + toy = toy_class.find(3) + + wheel = wheel_class.create!(wheelable: car) + + time = 3.days.ago.at_beginning_of_hour + + car.update_columns(updated_at: time) + toy.update_columns(updated_at: time) + + wheel.wheelable = toy + wheel.save! + + assert_not_equal time, car.reload.updated_at + assert_not_equal time, toy.reload.updated_at + end + + def test_clearing_association_touches_the_old_record + klass = Class.new(ActiveRecord::Base) do + def self.name; 'Toy'; end + belongs_to :pet, touch: true + end + + toy = klass.find(1) + pet = toy.pet + time = 3.days.ago.at_beginning_of_hour + + pet.update_columns(updated_at: time) + + toy.pet = nil + toy.save! + + pet.reload + + assert_not_equal time, pet.updated_at + end + + def test_timestamp_column_values_are_present_in_the_callbacks + klass = Class.new(ActiveRecord::Base) do + self.table_name = 'people' + + before_create do + self.born_at = self.created_at + end + end + + person = klass.create first_name: 'David' + assert_not_equal person.born_at, nil + end + def test_timestamp_attributes_for_create toy = Toy.first - assert_equal toy.send(:timestamp_attributes_for_create), [:created_at, :created_on] + assert_equal [:created_at, :created_on], toy.send(:timestamp_attributes_for_create) end def test_timestamp_attributes_for_update toy = Toy.first - assert_equal toy.send(:timestamp_attributes_for_update), [:updated_at, :updated_on] + assert_equal [:updated_at, :updated_on], toy.send(:timestamp_attributes_for_update) end def test_all_timestamp_attributes toy = Toy.first - assert_equal toy.send(:all_timestamp_attributes), [:created_at, :created_on, :updated_at, :updated_on] + assert_equal [:created_at, :created_on, :updated_at, :updated_on], toy.send(:all_timestamp_attributes) end def test_timestamp_attributes_for_create_in_model toy = Toy.first - assert_equal toy.send(:timestamp_attributes_for_create_in_model), [:created_at] + assert_equal [:created_at], toy.send(:timestamp_attributes_for_create_in_model) end def test_timestamp_attributes_for_update_in_model toy = Toy.first - assert_equal toy.send(:timestamp_attributes_for_update_in_model), [:updated_at] + assert_equal [:updated_at], toy.send(:timestamp_attributes_for_update_in_model) end def test_all_timestamp_attributes_in_model toy = Toy.first - assert_equal toy.send(:all_timestamp_attributes_in_model), [:created_at, :updated_at] + assert_equal [:created_at, :updated_at], toy.send(:all_timestamp_attributes_in_model) + end +end + +class TimestampsWithoutTransactionTest < ActiveRecord::TestCase + include DdlHelper + self.use_transactional_fixtures = false + + class TimestampAttributePost < ActiveRecord::Base + attr_accessor :created_at, :updated_at + end + + def test_do_not_write_timestamps_on_save_if_they_are_not_attributes + with_example_table ActiveRecord::Base.connection, "timestamp_attribute_posts", "id integer primary key" do + post = TimestampAttributePost.new(id: 1) + post.save! # should not try to assign and persist created_at, updated_at + assert_nil post.created_at + assert_nil post.updated_at + end end end |