From 84785caddf6b61ed965375d393ce540c5501c859 Mon Sep 17 00:00:00 2001 From: johnnyshields Date: Tue, 5 Dec 2017 16:27:03 +0900 Subject: [PATCH] Support :if and :unless options for callbacks which pass-thru to Rails --- CHANGELOG.md | 1 + README.md | 12 ++++++ lib/mongoid/history/trackable.rb | 7 ++-- spec/unit/callback_options_spec.rb | 59 ++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 spec/unit/callback_options_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 55147d1a..f6251517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ### 0.7.1 (Next) * [#208](https://github.com/mongoid/mongoid-history/pull/208): Fix: history tracks fields declared after `track_history` - [@mikwat](https://github.com/mikwat). +* [#209](https://github.com/mongoid/mongoid-history/pull/209): `track_history` method support for `:if` and `:unless` options - [@johnnyshields](https://github.com/johnnyshields). * Your contribution here. ### 0.7.0 (2017/11/14) diff --git a/README.md b/README.md index 63c46f08..5465198d 100644 --- a/README.md +++ b/README.md @@ -429,6 +429,18 @@ Or perhaps you are namespacing to a module: Mongoid::History.modifier_class_name = 'CMS::Author' ``` +**Conditional :if and :unless options** + +The `track_history` method supports `:if` and `:unless` options which will skip generating +the history tracker unless they are satisfied. These options can take either a method +`Symbol` or a `Proc`. They behave identical to how `:if` and `:unless` behave in Rails model callbacks. + +```ruby + track_history on: [:ip], + if: :should_i_track_history?, + unless: ->(obj){ obj.method_to_skip_history } +``` + **Using an alternate changes method** Sometimes you may wish to provide an alternate method for determining which changes should be tracked. For example, if you are using embedded documents diff --git a/lib/mongoid/history/trackable.rb b/lib/mongoid/history/trackable.rb index 34e4fc2e..7e9be776 100644 --- a/lib/mongoid/history/trackable.rb +++ b/lib/mongoid/history/trackable.rb @@ -21,9 +21,10 @@ def track_history(options = {}) delegate :history_trackable_options, to: 'self.class' delegate :track_history?, to: 'self.class' - around_update :track_update if history_options.options[:track_update] - around_create :track_create if history_options.options[:track_create] - around_destroy :track_destroy if history_options.options[:track_destroy] + callback_options = history_options.options.slice(:if, :unless) + around_update :track_update, callback_options if history_options.options[:track_update] + around_create :track_create, callback_options if history_options.options[:track_create] + around_destroy :track_destroy, callback_options if history_options.options[:track_destroy] Mongoid::History.trackable_class_options ||= {} Mongoid::History.trackable_class_options[history_options.scope] = history_options diff --git a/spec/unit/callback_options_spec.rb b/spec/unit/callback_options_spec.rb new file mode 100644 index 00000000..69953ccc --- /dev/null +++ b/spec/unit/callback_options_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +describe Mongoid::History::Options do + before :all do + ModelOne = Class.new do + include Mongoid::Document + include Mongoid::History::Trackable + store_in collection: :model_ones + field :foo + attr_accessor :bar + track_history track_create: true, + track_update: true, + track_destroy: true, + if: :bar + end + + ModelTwo = Class.new do + include Mongoid::Document + include Mongoid::History::Trackable + store_in collection: :model_twos + field :foo + attr_accessor :bar + track_history track_create: true, + track_update: true, + track_destroy: true, + unless: ->(obj){obj.bar} + end + + ModelThree = Class.new do + include Mongoid::Document + include Mongoid::History::Trackable + store_in collection: :model_threes + field :foo + attr_accessor :bar, :baz + track_history track_create: true, + track_update: true, + track_destroy: true, + if: ->(obj){obj.bar}, unless: :baz + end + end + + describe ':if' do + # TODO: ModelOne + end + + describe ':unless' do + # TODO: ModelTwo + end + + describe ':if and :unless' do + # TODO: ModelThree + end + + after :all do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :ModelThree) + end +end