require 'spec_helper' describe 'DataMapper::Timestamp' do supported_by :all do describe "Timestamp (shared behavior)", :shared => true do it "should not set the created_at/on fields if they're already set" do green_smoothie = GreenSmoothie.new(:name => 'Banana') time = (DateTime.now - 100) green_smoothie.created_at = time green_smoothie.created_on = time green_smoothie.save green_smoothie.created_at.should == time green_smoothie.created_on.should == time green_smoothie.created_at.should be_a_kind_of(DateTime) green_smoothie.created_on.should be_a_kind_of(Date) end it "should set the created_at/on fields on creation" do green_smoothie = GreenSmoothie.new(:name => 'Banana') green_smoothie.created_at.should be_nil green_smoothie.created_on.should be_nil green_smoothie.save green_smoothie.created_at.should be_a_kind_of(DateTime) green_smoothie.created_on.should be_a_kind_of(Date) end it "should not alter the create_at/on fields on model updates" do green_smoothie = GreenSmoothie.new(:id => 2, :name => 'Berry') green_smoothie.created_at.should be_nil green_smoothie.created_on.should be_nil green_smoothie.save original_created_at = green_smoothie.created_at original_created_on = green_smoothie.created_on green_smoothie.name = 'Strawberry' green_smoothie.save green_smoothie.created_at.should eql(original_created_at) green_smoothie.created_on.should eql(original_created_on) end it "should set the updated_at/on fields on creation and on update" do green_smoothie = GreenSmoothie.new(:name => 'Mango') green_smoothie.updated_at.should be_nil green_smoothie.updated_on.should be_nil green_smoothie.save green_smoothie.updated_at.should be_a_kind_of(DateTime) green_smoothie.updated_on.should be_a_kind_of(Date) original_updated_at = green_smoothie.updated_at original_updated_on = green_smoothie.updated_on time_tomorrow = DateTime.now + 1 date_tomorrow = Date.today + 1 DateTime.stub!(:now).and_return { time_tomorrow } Date.stub!(:today).and_return { date_tomorrow } green_smoothie.name = 'Cranberry Mango' green_smoothie.save green_smoothie.updated_at.should_not eql(original_updated_at) green_smoothie.updated_on.should_not eql(original_updated_on) green_smoothie.updated_at.should eql(time_tomorrow) green_smoothie.updated_on.should eql(date_tomorrow) end it "should only set the updated_at/on fields on dirty objects" do green_smoothie = GreenSmoothie.new(:name => 'Mango') green_smoothie.updated_at.should be_nil green_smoothie.updated_on.should be_nil green_smoothie.save green_smoothie.updated_at.should be_a_kind_of(DateTime) green_smoothie.updated_on.should be_a_kind_of(Date) original_updated_at = green_smoothie.updated_at original_updated_on = green_smoothie.updated_on time_tomorrow = DateTime.now + 1 date_tomorrow = Date.today + 1 DateTime.stub!(:now).and_return { time_tomorrow } Date.stub!(:today).and_return { date_tomorrow } green_smoothie.save green_smoothie.updated_at.should_not eql(time_tomorrow) green_smoothie.updated_on.should_not eql(date_tomorrow) green_smoothie.updated_at.should eql(original_updated_at) green_smoothie.updated_on.should eql(original_updated_on) end describe '#touch' do it 'should update the updated_at/on fields' do green_smoothie = GreenSmoothie.create(:name => 'Mango') time_tomorrow = DateTime.now + 1 date_tomorrow = Date.today + 1 DateTime.stub!(:now).and_return { time_tomorrow } Date.stub!(:today).and_return { date_tomorrow } green_smoothie.touch green_smoothie.updated_at.should eql(time_tomorrow) green_smoothie.updated_on.should eql(date_tomorrow) end it 'should not update the created_at/on fields' do green_smoothie = GreenSmoothie.create(:name => 'Mango') original_created_at = green_smoothie.created_at original_created_on = green_smoothie.created_on green_smoothie.touch green_smoothie.created_at.should equal(original_created_at) green_smoothie.created_on.should equal(original_created_on) end end end describe "explicit property declaration" do before do Object.send(:remove_const, :GreenSmoothie) if defined?(GreenSmoothie) class GreenSmoothie include DataMapper::Resource property :id, Serial property :name, String property :created_at, DateTime, :required => true property :created_on, Date, :required => true property :updated_at, DateTime, :required => true property :updated_on, Date, :required => true auto_migrate! end end it_should_behave_like "Timestamp (shared behavior)" end describe "implicit property declaration" do before do Object.send(:remove_const, :GreenSmoothie) if defined?(GreenSmoothie) class GreenSmoothie include DataMapper::Resource property :id, Serial property :name, String timestamps :at, :on auto_migrate! end end it_should_behave_like "Timestamp (shared behavior)" end describe "timestamps helper" do describe "inclusion" do before :each do @klass = Class.new do include DataMapper::Resource end end it "should provide #timestamps" do @klass.should respond_to(:timestamps) end it "should set the *at properties" do @klass.timestamps :at @klass.properties.should be_named(:created_at) @klass.properties[:created_at].should be_kind_of(DataMapper::Property::DateTime) @klass.properties.should be_named(:updated_at) @klass.properties[:updated_at].should be_kind_of(DataMapper::Property::DateTime) end it "should set the *on properties" do @klass.timestamps :on @klass.properties.should be_named(:created_on) @klass.properties[:created_on].should be_kind_of(DataMapper::Property::Date) @klass.properties.should be_named(:updated_on) @klass.properties[:updated_on].should be_kind_of(DataMapper::Property::Date) end it "should set multiple properties" do @klass.timestamps :created_at, :updated_on @klass.properties.should be_named(:created_at) @klass.properties.should be_named(:updated_on) end it "should fail on unknown property name" do lambda { @klass.timestamps :wowee }.should raise_error(DataMapper::Timestamp::InvalidTimestampName) end it "should fail on empty arguments" do lambda { @klass.timestamps }.should raise_error(ArgumentError) end end end end end