Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow modifier field to be optional #205

Merged
merged 2 commits into from
Dec 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Metrics/MethodLength:
# Offense count: 2
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 176
Max: 200
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fyi usually we just run rubocop -a ; rubocop --auto-gen-config.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, I was wondering why 176 was the old value :)


# Offense count: 4
Metrics/PerceivedComplexity:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* [#208](https://github.com/mongoid/mongoid-history/pull/208): Fix: history tracks fields declared after `track_history` - [@mikwat](https://github.com/mikwat).
* Your contribution here.
* [#205](https://github.com/mongoid/mongoid-history/pull/205): Allow modifier field to be optional - [@yads](https://github.com/yads).

### 0.7.0 (2017/11/14)

Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ when /3/
else
gem 'mongoid', version
end
gem 'mongoid-compatibility'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to become a .gemspec dependency, otherwise it will be failing at runtime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's already in the .gemspec file. Is this not it? https://github.com/mongoid/mongoid-history/blob/master/mongoid-history.gemspec#L23

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or are you saying to add a version dependency so that it works with version 0.5.1 or above?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you don't need to add it here, don't you?


group :development, :test do
gem 'bundler'
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ class Post
# telling Mongoid::History how you want to track changes
# dynamic fields will be tracked automatically (for MongoId 4.0+ you should include Mongoid::Attributes::Dynamic to your model)
track_history :on => [:title, :body], # track title and body fields only, default is :all
:modifier_field => :modifier, # adds "belongs_to :modifier" to track who made the change, default is :modifier
:modifier_field => :modifier, # adds "belongs_to :modifier" to track who made the change, default is :modifier, set to nil to not create modifier_field
:modifier_field_inverse_of => :nil, # adds an ":inverse_of" option to the "belongs_to :modifier" relation, default is not set
:modifier_field_optional => true, # marks the modifier relationship as optional (requires Mongoid 6 or higher)
:version_field => :version, # adds "field :version, :type => Integer" to track current version, default is :version
:track_create => false, # track document creation, default is false
:track_update => true, # track document updates, default is true
Expand Down
21 changes: 15 additions & 6 deletions lib/mongoid/history/trackable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ def track_history(options = {})

field history_options.options[:version_field].to_sym, type: Integer

belongs_to_modifier_options = { class_name: Mongoid::History.modifier_class_name }
belongs_to_modifier_options[:inverse_of] = options[:modifier_field_inverse_of] if history_options.options.key?(:modifier_field_inverse_of)
belongs_to history_options.options[:modifier_field].to_sym, belongs_to_modifier_options
unless history_options.options[:modifier_field].nil?
belongs_to_modifier_options = { class_name: Mongoid::History.modifier_class_name }
belongs_to_modifier_options[:inverse_of] = history_options.options[:modifier_field_inverse_of] if history_options.options.key?(:modifier_field_inverse_of)
belongs_to_modifier_options[:optional] = true if history_options.options[:modifier_field_optional] && Mongoid::Compatibility::Version.mongoid6_or_newer?
belongs_to history_options.options[:modifier_field].to_sym, belongs_to_modifier_options
end

include MyInstanceMethods
extend SingletonMethods
Expand Down Expand Up @@ -218,11 +221,12 @@ def modified_attributes_for_destroy
def history_tracker_attributes(action)
return @history_tracker_attributes if @history_tracker_attributes

modifier_field = history_trackable_options[:modifier_field]
@history_tracker_attributes = {
association_chain: traverse_association_chain,
scope: related_scope,
modifier: send(history_trackable_options[:modifier_field])
scope: related_scope
}
@history_tracker_attributes[:modifier] = send(modifier_field) if modifier_field

original, modified = transform_changes(modified_attributes_for_action(action))

Expand Down Expand Up @@ -424,7 +428,12 @@ def tracked_fields
#
# @return [ Array < String > ] the list of reserved database field names
def reserved_tracked_fields
@reserved_tracked_fields ||= ['_id', history_trackable_options[:version_field].to_s, "#{history_trackable_options[:modifier_field]}_id"]
@reserved_tracked_fields ||= begin
fields = ['_id', history_trackable_options[:version_field].to_s]
modifier_field = history_trackable_options[:modifier_field]
fields << "#{modifier_field}_id" if modifier_field
fields
end
end

def field_formats
Expand Down
10 changes: 7 additions & 3 deletions lib/mongoid/history/tracker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ module Tracker
field :version, type: Integer
field :action, type: String
field :scope, type: String
belongs_to :modifier, class_name: Mongoid::History.modifier_class_name
modifier_options = {
class_name: Mongoid::History.modifier_class_name
}
modifier_options[:optional] = true if Mongoid::Compatibility::Version.mongoid6_or_newer?
belongs_to :modifier, modifier_options

index(scope: 1)
index(association_chain: 1)
Expand Down Expand Up @@ -50,7 +54,7 @@ def undo_attr(modifier)
undo_hash = affected.easy_unmerge(modified)
undo_hash.easy_merge!(original)
modifier_field = trackable.history_trackable_options[:modifier_field]
undo_hash[modifier_field] = modifier
undo_hash[modifier_field] = modifier if modifier_field
(modified.keys - undo_hash.keys).each do |k|
undo_hash[k] = nil
end
Expand All @@ -61,7 +65,7 @@ def redo_attr(modifier)
redo_hash = affected.easy_unmerge(original)
redo_hash.easy_merge!(modified)
modifier_field = trackable.history_trackable_options[:modifier_field]
redo_hash[modifier_field] = modifier
redo_hash[modifier_field] = modifier if modifier_field
localize_keys(redo_hash)
end

Expand Down
2 changes: 1 addition & 1 deletion mongoid-history.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ Gem::Specification.new do |s|

s.add_runtime_dependency 'easy_diff'
s.add_runtime_dependency 'mongoid', '>= 3.0'
s.add_runtime_dependency 'mongoid-compatibility'
s.add_runtime_dependency 'mongoid-compatibility', '>= 0.5.1'
s.add_runtime_dependency 'activesupport'
end
43 changes: 43 additions & 0 deletions spec/unit/trackable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,16 @@ class HistoryTracker
end

describe '#track_history' do
class MyModelWithNoModifier
include Mongoid::Document
include Mongoid::History::Trackable
field :foo
end

before :all do
MyModel.track_history
@persisted_history_options = Mongoid::History.trackable_class_options
MyModelWithNoModifier.track_history modifier_field: nil
end
before(:each) { Mongoid::History.trackable_class_options = @persisted_history_options }
let(:expected_option) do
Expand Down Expand Up @@ -72,6 +79,31 @@ class HistoryTracker
expect(MyModel.history_trackable_options).to eq(expected_option)
end

describe '#modifier' do
context 'modifier_field set to nil' do
it 'should not have a modifier relationship' do
expect(MyModelWithNoModifier.reflect_on_association(:modifier)).to be_nil
end
end

context 'modifier_field_optional true' do
class MyModelWithOptionalModifier
include Mongoid::Document
include Mongoid::History::Trackable
field :foo
end

it 'marks modifier relationship optional' do
MyModelWithOptionalModifier.track_history modifier_field_optional: true
if Mongoid::Compatibility::Version.mongoid6_or_newer?
expect(MyModelWithOptionalModifier.reflect_on_association(:modifier)[:optional]).to be true
else
expect(MyModelWithOptionalModifier.reflect_on_association(:modifier)).not_to be_nil
end
end
end
end

describe '#tracked_fields' do
it 'should return the tracked field list' do
expect(MyModel.tracked_fields).to eq(regular_fields)
Expand All @@ -82,6 +114,10 @@ class HistoryTracker
it 'should return the protected field list' do
expect(MyModel.reserved_tracked_fields).to eq(reserved_fields)
end

it 'should not include modifier_field if not specified' do
expect(MyModelWithNoModifier.reserved_tracked_fields).not_to include('modifier')
end
end

describe '#tracked_fields_for_action' do
Expand Down Expand Up @@ -628,13 +664,20 @@ def self.name
before :all do
MyModel.track_history(on: :foo, track_create: true)
@persisted_history_options = Mongoid::History.trackable_class_options
MyModelWithNoModifier.track_history modifier_field: nil
end
before(:each) { Mongoid::History.trackable_class_options = @persisted_history_options }

it 'should create history' do
expect { MyModel.create!(foo: 'bar') }.to change(Tracker, :count).by(1)
end

context 'no modifier_field' do
it 'should create history' do
expect { MyModelWithNoModifier.create!(foo: 'bar').to change(Tracker, :count).by(1) }
end
end

it 'should not create history when error raised' do
expect(MyModel).to receive(:create!).and_raise(StandardError)
expect do
Expand Down