From 2a7225f7cab91efbf695d588707bc6c69e06d01e Mon Sep 17 00:00:00 2001 From: Ben Atkins Date: Fri, 21 Feb 2014 18:20:40 -0500 Subject: [PATCH] close #329; Add :touch_with_version method to PaperTrail::Model::InstanceMethods --- CHANGELOG.md | 2 + README.md | 7 ++ lib/paper_trail/has_paper_trail.rb | 16 +++ spec/models/widget_spec.rb | 108 +++++++++++------- .../20110208155312_set_up_test_tables.rb | 4 +- 5 files changed, 91 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b131bc1..5f6df0d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## 3.0.1 (Unreleased) + - [#329](https://github.com/airblade/paper_trail/issues/329) - Add `touch_with_version` method to `PaperTrail::Model::InstanceMethods`, + to allow for generating a version `touch`ing a model. - [#328](https://github.com/airblade/paper_trail/pull/328) / [#326](https://github.com/airblade/paper_trail/issues/326)/ [#307](https://github.com/airblade/paper_trail/issues/307) - `Model.paper_trail_enabled_for_model?` and `model_instance.without_versioning` is now thread-safe. diff --git a/README.md b/README.md index 3a139444..c90dbdce 100644 --- a/README.md +++ b/README.md @@ -126,11 +126,18 @@ widget.previous_version # Returns the widget (not a version) as it became next. widget.next_version +# Generates a version for a `touch` event (`widget.touch` does NOT generate a version) +widget.touch_with_version + # Turn PaperTrail off for all widgets. Widget.paper_trail_off! # Turn PaperTrail on for all widgets. Widget.paper_trail_on! + +# Check wheter PaperTrail is enabled for all widgets +Widget.paper_trail_enabled_for_model? +widget.paper_trail_enabled_for_model? ``` And a `PaperTrail::Version` instance has these methods: diff --git a/lib/paper_trail/has_paper_trail.rb b/lib/paper_trail/has_paper_trail.rb index 8efd0720..e1103c73 100644 --- a/lib/paper_trail/has_paper_trail.rb +++ b/lib/paper_trail/has_paper_trail.rb @@ -216,6 +216,22 @@ module PaperTrail self.class.paper_trail_on! if paper_trail_was_enabled end + # Mimicks behavior of `touch` method from `ActiveRecord::Persistence`, but generates a version + # + # TODO: lookinto leveraging the `after_touch` callback from `ActiveRecord` to allow the + # regular `touch` method go generate a version as normal. May make sense to switch the `record_update` + # method to leverage an `after_update` callback anyways (likely for v3.1.0) + def touch_with_version(name = nil) + raise ActiveRecordError, "can not touch on a new record object" unless persisted? + + attributes = timestamp_attributes_for_update_in_model + attributes << name if name + current_time = current_time_from_proper_timezone + + attributes.each { |column| write_attribute(column, current_time) } + save! + end + private def source_version diff --git a/spec/models/widget_spec.rb b/spec/models/widget_spec.rb index 576e771d..0d951ba7 100644 --- a/spec/models/widget_spec.rb +++ b/spec/models/widget_spec.rb @@ -5,9 +5,9 @@ describe Widget do it { should be_versioned } end - describe "`versioning` option" do - let(:widget) { Widget.create :name => 'Bob', :an_integer => 1 } + let(:widget) { Widget.create :name => 'Bob', :an_integer => 1 } + describe "`versioning` option" do context :enabled, :versioning => true do it 'should enable versioning for models wrapped within a block' do widget.versions.size.should == 1 @@ -21,60 +21,80 @@ describe Widget do end end - describe "class methods" do - subject { Widget } + describe "Methods" do + describe "Instance", :versioning => true do + describe :touch_with_version do + it { should respond_to(:touch_with_version) } - describe :paper_trail_off! do - it { should respond_to(:paper_trail_off!) } + it "should generate a version" do + count = widget.versions.size + widget.touch_with_version + widget.versions.size.should == count + 1 + end - it 'should set the `paper_trail_enabled_for_model?` to `false`' do - subject.paper_trail_enabled_for_model?.should be_true - subject.paper_trail_off! - subject.paper_trail_enabled_for_model?.should be_false + it "should increment the `:updated_at` timestamp" do + time_was = widget.updated_at + widget.touch_with_version + widget.updated_at.should > time_was + end end end - describe :paper_trail_off do - it { should respond_to(:paper_trail_off) } + describe "Class" do + subject { Widget } - it 'should set the invoke `paper_trail_off!`' do - subject.should_receive(:warn) - subject.should_receive(:paper_trail_off!) - subject.paper_trail_off + describe :paper_trail_off! do + it { should respond_to(:paper_trail_off!) } + + it 'should set the `paper_trail_enabled_for_model?` to `false`' do + subject.paper_trail_enabled_for_model?.should be_true + subject.paper_trail_off! + subject.paper_trail_enabled_for_model?.should be_false + end end - it 'should display a deprecation warning' do - subject.should_receive(:warn).with("DEPRECATED: use `paper_trail_on!` instead of `paper_trail_on`. Support for `paper_trail_on` will be removed in PaperTrail 3.1") - subject.paper_trail_on - end - end + describe :paper_trail_off do + it { should respond_to(:paper_trail_off) } - describe :paper_trail_on! do - before { subject.paper_trail_off! } + it 'should set the invoke `paper_trail_off!`' do + subject.should_receive(:warn) + subject.should_receive(:paper_trail_off!) + subject.paper_trail_off + end - it { should respond_to(:paper_trail_on!) } - - it 'should set the `paper_trail_enabled_for_model?` to `true`' do - subject.paper_trail_enabled_for_model?.should be_false - subject.paper_trail_on! - subject.paper_trail_enabled_for_model?.should be_true - end - end - - describe :paper_trail_on do - before { subject.paper_trail_off! } - - it { should respond_to(:paper_trail_on) } - - it 'should set the invoke `paper_trail_on!`' do - subject.should_receive(:warn) - subject.should_receive(:paper_trail_on!) - subject.paper_trail_on + it 'should display a deprecation warning' do + subject.should_receive(:warn).with("DEPRECATED: use `paper_trail_on!` instead of `paper_trail_on`. Support for `paper_trail_on` will be removed in PaperTrail 3.1") + subject.paper_trail_on + end end - it 'should display a deprecation warning' do - subject.should_receive(:warn).with("DEPRECATED: use `paper_trail_on!` instead of `paper_trail_on`. Support for `paper_trail_on` will be removed in PaperTrail 3.1") - subject.paper_trail_on + describe :paper_trail_on! do + before { subject.paper_trail_off! } + + it { should respond_to(:paper_trail_on!) } + + it 'should set the `paper_trail_enabled_for_model?` to `true`' do + subject.paper_trail_enabled_for_model?.should be_false + subject.paper_trail_on! + subject.paper_trail_enabled_for_model?.should be_true + end + end + + describe :paper_trail_on do + before { subject.paper_trail_off! } + + it { should respond_to(:paper_trail_on) } + + it 'should set the invoke `paper_trail_on!`' do + subject.should_receive(:warn) + subject.should_receive(:paper_trail_on!) + subject.paper_trail_on + end + + it 'should display a deprecation warning' do + subject.should_receive(:warn).with("DEPRECATED: use `paper_trail_on!` instead of `paper_trail_on`. Support for `paper_trail_on` will be removed in PaperTrail 3.1") + subject.paper_trail_on + end end end end diff --git a/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb b/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb index cd656c2b..da60aa57 100644 --- a/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +++ b/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb @@ -10,9 +10,9 @@ class SetUpTestTables < ActiveRecord::Migration t.time :a_time t.date :a_date t.boolean :a_boolean - t.datetime :created_at, :updated_at t.string :sacrificial_column t.string :type + t.timestamps end create_table :versions, :force => true do |t| @@ -54,7 +54,7 @@ class SetUpTestTables < ActiveRecord::Migration create_table :wotsits, :force => true do |t| t.integer :widget_id t.string :name - t.datetime :created_at, :updated_at + t.timestamps end create_table :fluxors, :force => true do |t|