From b391da6c060a9fd8ac09e03aa08035223a0b1cdd Mon Sep 17 00:00:00 2001 From: dblock Date: Wed, 20 Jun 2018 18:10:01 -0400 Subject: [PATCH] Use defaults in specs and make specs not order-dependent. Closes #222. --- .rubocop_todo.yml | 8 +- lib/mongoid/history.rb | 12 +- .../embedded_in_polymorphic_spec.rb | 79 ++-- spec/integration/integration_spec.rb | 89 +++-- spec/integration/multi_relation_spec.rb | 35 +- spec/integration/multiple_trackers_spec.rb | 31 +- .../nested_embedded_documents_spec.rb | 82 ++--- ...ted_embedded_polymorphic_documents_spec.rb | 141 +++---- spec/integration/subclasses_spec.rb | 16 +- spec/integration/track_history_order_spec.rb | 86 +++-- spec/integration/validation_failure_spec.rb | 21 +- spec/spec_helper.rb | 5 + spec/unit/attributes/base_spec.rb | 43 +-- spec/unit/attributes/create_spec.rb | 229 ++++++------ spec/unit/attributes/destroy_spec.rb | 116 +++--- spec/unit/attributes/update_spec.rb | 103 +++--- spec/unit/callback_options_spec.rb | 69 ++-- spec/unit/embedded_methods_spec.rb | 44 ++- spec/unit/history_spec.rb | 22 +- spec/unit/my_instance_methods_spec.rb | 267 ++++++++------ spec/unit/options_spec.rb | 60 +-- spec/unit/singleton_methods_spec.rb | 184 ++++++---- spec/unit/trackable_spec.rb | 345 +++++++++++------- spec/unit/tracker_spec.rb | 129 ++++--- 24 files changed, 1191 insertions(+), 1025 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f84bc839..39f8147e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2018-06-19 17:36:18 -0400 using RuboCop version 0.48.1. +# on 2018-06-20 23:31:54 -0400 using RuboCop version 0.48.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -36,10 +36,10 @@ Lint/ParenthesesAsGroupedExpression: Metrics/AbcSize: Max: 52 -# Offense count: 112 +# Offense count: 117 # Configuration parameters: CountComments, ExcludedMethods. Metrics/BlockLength: - Max: 807 + Max: 820 # Offense count: 1 # Configuration parameters: CountComments. @@ -50,7 +50,7 @@ Metrics/ClassLength: Metrics/CyclomaticComplexity: Max: 13 -# Offense count: 478 +# Offense count: 392 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Metrics/LineLength: diff --git a/lib/mongoid/history.rb b/lib/mongoid/history.rb index 5b0e1e54..47f04425 100644 --- a/lib/mongoid/history.rb +++ b/lib/mongoid/history.rb @@ -42,11 +42,15 @@ def default_settings def trackable_class_settings(trackable_class) trackable_settings[trackable_class.name.to_sym] || default_settings end + + def reset! + Mongoid::History.modifier_class_name = 'User' + Mongoid::History.trackable_class_options = {} + Mongoid::History.trackable_settings = {} + Mongoid::History.current_user_method ||= :current_user + end end end end -Mongoid::History.modifier_class_name = 'User' -Mongoid::History.trackable_class_options = {} -Mongoid::History.trackable_settings = {} -Mongoid::History.current_user_method ||= :current_user +Mongoid::History.reset! diff --git a/spec/integration/embedded_in_polymorphic_spec.rb b/spec/integration/embedded_in_polymorphic_spec.rb index f00eba55..8918c7c2 100644 --- a/spec/integration/embedded_in_polymorphic_spec.rb +++ b/spec/integration/embedded_in_polymorphic_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Mongoid::History::Tracker do - before :all do + before :each do class RealState include Mongoid::Document include Mongoid::History::Trackable @@ -9,15 +9,9 @@ class RealState field :name, type: String belongs_to :user embeds_one :address, class_name: 'Contact', as: :contactable - embeds_one :embone, as: :embedable - - track_history on: :all, # track title and body fields only, default is :all - modifier_field: :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier - modifier_field_optional: true, - version_field: :version, # adds "field :version, :type => Integer" to track current version, default is :version - track_create: true, # track document creation, default is false - track_update: true, # track document updates, default is true - track_destroy: false # track document destruction, default is false + embeds_one :embone, as: :embedable + + track_history end class Company @@ -30,13 +24,7 @@ class Company embeds_one :second_address, class_name: 'Contact', as: :contactable embeds_one :embone, as: :embedable - track_history on: :all, # track title and body fields only, default is :all - modifier_field: :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier - modifier_field_optional: true, - version_field: :version, # adds "field :version, :type => Integer" to track current version, default is :version - track_create: true, # track document creation, default is false - track_update: true, # track document updates, default is true - track_destroy: false # track document destruction, default is false + track_history end class Embone @@ -46,14 +34,7 @@ class Embone field :name embedded_in :embedable, polymorphic: true - track_history on: :all, # track title and body fields only, default is :all - modifier_field: :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier - modifier_field_optional: true, - version_field: :version, # adds "field :version, :type => Integer" to track current version, default is :version - track_create: true, # track document creation, default is false - track_update: true, # track document updates, default is true - track_destroy: false, # track document destruction, default is false - scope: :embedable + track_history scope: :embedable end class Contact @@ -65,14 +46,7 @@ class Contact field :state embedded_in :contactable, polymorphic: true - track_history on: :all, # track title and body fields only, default is :all - modifier_field: :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier - modifier_field_optional: true, - version_field: :version, # adds "field :version, :type => Integer" to track current version, default is :version - track_create: true, # track document creation, default is false - track_update: true, # track document updates, default is true - track_destroy: false, # track document destruction, default is false - scope: %i[real_state company] + track_history scope: %i[real_state company] end class User @@ -82,58 +56,57 @@ class User end end - it 'tracks history for nested embedded documents with polymorphic relations' do - user = User.new - user.save! + after :each do + Object.send(:remove_const, :RealState) + Object.send(:remove_const, :Company) + Object.send(:remove_const, :Embone) + Object.send(:remove_const, :Contact) + Object.send(:remove_const, :User) + end - real_state = user.real_states.build(name: 'rs_name') + let!(:user) { User.create! } + + it 'tracks history for nested embedded documents with polymorphic relations' do + real_state = user.real_states.build(name: 'rs_name', modifier: user) real_state.save! - real_state.build_address(address: 'Main Street #123', city: 'Highland Park', state: 'IL').save! + real_state.build_address(address: 'Main Street #123', city: 'Highland Park', state: 'IL', modifier: user).save! expect(real_state.history_tracks.count).to eq(2) expect(real_state.address.history_tracks.count).to eq(1) real_state.reload - real_state.address.update_attribute(:address, 'Second Street') + real_state.address.update_attributes!(address: 'Second Street', modifier: user) expect(real_state.history_tracks.count).to eq(3) expect(real_state.address.history_tracks.count).to eq(2) expect(real_state.history_tracks.last.action).to eq('update') - real_state.build_embone(name: 'Lorem ipsum').save! + real_state.build_embone(name: 'Lorem ipsum', modifier: user).save! expect(real_state.history_tracks.count).to eq(4) expect(real_state.embone.history_tracks.count).to eq(1) expect(real_state.embone.history_tracks.last.action).to eq('create') expect(real_state.embone.history_tracks.last.association_chain.last['name']).to eq('embone') - company = user.companies.build(name: 'co_name') + company = user.companies.build(name: 'co_name', modifier: user) company.save! - company.build_address(address: 'Main Street #456', city: 'Evanston', state: 'IL').save! + company.build_address(address: 'Main Street #456', city: 'Evanston', state: 'IL', modifier: user).save! expect(company.history_tracks.count).to eq(2) expect(company.address.history_tracks.count).to eq(1) company.reload - company.address.update_attribute(:address, 'Second Street') + company.address.update_attributes!(address: 'Second Street', modifier: user) expect(company.history_tracks.count).to eq(3) expect(company.address.history_tracks.count).to eq(2) expect(company.history_tracks.last.action).to eq('update') - company.build_second_address(address: 'Main Street #789', city: 'Highland Park', state: 'IL').save! + company.build_second_address(address: 'Main Street #789', city: 'Highland Park', state: 'IL', modifier: user).save! expect(company.history_tracks.count).to eq(4) expect(company.second_address.history_tracks.count).to eq(1) expect(company.second_address.history_tracks.last.action).to eq('create') expect(company.second_address.history_tracks.last.association_chain.last['name']).to eq('second_address') - company.build_embone(name: 'Lorem ipsum').save! + company.build_embone(name: 'Lorem ipsum', modifier: user).save! expect(company.history_tracks.count).to eq(5) expect(company.embone.history_tracks.count).to eq(1) expect(company.embone.history_tracks.last.action).to eq('create') expect(company.embone.history_tracks.last.association_chain.last['name']).to eq('embone') end - - after :all do - Object.send(:remove_const, :RealState) - Object.send(:remove_const, :Company) - Object.send(:remove_const, :Embone) - Object.send(:remove_const, :Contact) - Object.send(:remove_const, :User) - end end diff --git a/spec/integration/integration_spec.rb b/spec/integration/integration_spec.rb index db221604..86cff2af 100644 --- a/spec/integration/integration_spec.rb +++ b/spec/integration/integration_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Mongoid::History do - before :all do + before :each do class Post include Mongoid::Document include Mongoid::Timestamps @@ -29,7 +29,8 @@ class Comment field :t, as: :title field :body embedded_in :commentable, polymorphic: true - track_history on: %i[title body], scope: :post, track_create: true, track_destroy: true, modifier_field_optional: true # BUGBUG + # BUG: see https://github.com/mongoid/mongoid-history/issues/223, modifier_field_optional should not be necessary + track_history on: %i[title body], scope: :post, track_create: true, track_destroy: true, modifier_field_optional: true end class Section @@ -70,19 +71,17 @@ class Tag class Foo < Comment end + end - class Sausage - include Mongoid::Document - include Mongoid::History::Trackable - - field :flavour, localize: true - track_history on: [:flavour], track_destroy: true, modifier_field_optional: true - end - - @persisted_history_options = Mongoid::History.trackable_class_options + after :each do + Object.send(:remove_const, :Post) + Object.send(:remove_const, :Comment) + Object.send(:remove_const, :Section) + Object.send(:remove_const, :User) + Object.send(:remove_const, :Tag) + Object.send(:remove_const, :Foo) end - before(:each) { Mongoid::History.trackable_class_options = @persisted_history_options } let(:user) { User.create!(name: 'Aaron', email: 'aaron@randomemail.com', aliases: ['bob'], country: 'Canada', city: 'Toronto', address: '21 Jump Street') } let(:another_user) { User.create!(name: 'Another Guy', email: 'anotherguy@randomemail.com') } let(:post) { Post.create!(title: 'Test', body: 'Post', modifier: user, views: 100) } @@ -104,7 +103,7 @@ class Sausage end it 'should assign modifier' do - expect(comment.history_tracks.first.modifier).to eq(user) + expect(comment.history_tracks.first.modifier.id).to eq(user.id) end it 'should assign version' do @@ -190,7 +189,7 @@ class Sausage it 'should assign modifier' do post.update_attributes!(title: 'Another Test') - expect(post.history_tracks.first.modifier).to eq(user) + expect(post.history_tracks.first.modifier.id).to eq(user.id) end it 'should assign version on history tracks' do @@ -398,7 +397,7 @@ class Sausage it 'should assign modifier' do post.update_attributes!(title: 'Another Test', modifier: another_user) - expect(post.history_tracks.last.modifier).to eq(another_user) + expect(post.history_tracks.last.modifier.id).to eq(another_user.id) end end @@ -437,7 +436,7 @@ class Sausage it 'should assign modifier' do post.update_attributes!(title: 'Another Test', modifier: another_user) - expect(post.history_tracks.last.modifier).to eq(another_user) + expect(post.history_tracks.last.modifier.id).to eq(another_user.id) end end @@ -489,7 +488,7 @@ class Sausage it 'should assign modifier' do section.update_attributes!(title: 'Business', modifier: another_user) - expect(post.history_tracks.last.modifier).to eq(another_user) + expect(post.history_tracks.last.modifier.id).to eq(another_user.id) end end @@ -532,12 +531,6 @@ class Sausage let(:tag_foo) { post.tags.create!(title: 'foo', updated_by: user) } let(:tag_bar) { post.tags.create!(title: 'bar', updated_by: user) } - # it "should have cascaded the creation callbacks and set timestamps" do - # tag_foo; tag_bar # initialize - # tag_foo.created_at.should_not be_nil - # tag_foo.updated_at.should_not be_nil - # end - it 'should allow an update through the parent model' do update_hash = { 'post' => { 'tags_attributes' => { '1234' => { 'id' => tag_bar.id, 'title' => 'baz' } } } } post.update_attributes!(update_hash['post']) @@ -591,7 +584,7 @@ class Sausage post.update_attributes!(title: 'Test2') post.history_tracks.where(version: 2).last.undo!(user) post.reload - expect(post.history_tracks.where(version: 2).last.modifier).to eq(user) + expect(post.history_tracks.where(version: 2).last.modifier.id).to eq(user.id) end it 'should stay the same after undo and redo' do @@ -632,7 +625,7 @@ class Sausage comment.update_attributes!(title: 'Test2') comment.history_tracks.where(version: 2).first.undo!(user) comment.reload - expect(comment.history_tracks.where(version: 3).first.modifier).to eq(user) + expect(comment.history_tracks.where(version: 3).first.modifier.id).to eq(user.id) end it 'should stay the same after undo and redo' do @@ -806,7 +799,7 @@ class Sausage end describe 'when default scope is present' do - before do + before :each do class Post default_scope -> { where(title: nil) } end @@ -909,6 +902,10 @@ def my_changes end end + after :each do + Object.send(:remove_const, :OverriddenChangesMethod) + end + it 'should add foo to the changes history' do o = OverriddenChangesMethod.create(modifier: user) o.save! @@ -919,24 +916,38 @@ def my_changes end describe 'localized fields' do + before :each do + class Sausage + include Mongoid::Document + include Mongoid::History::Trackable + + field :flavour, localize: true + track_history on: [:flavour], track_destroy: true, modifier_field_optional: true + end + end + + after :each do + Object.send(:remove_const, :Sausage) + end + it 'should correctly undo and redo' do - if Sausage.respond_to?(:localized_fields) - sausage = Sausage.create!(flavour_translations: { 'en' => 'Apple', 'nl' => 'Appel' }, modifier: user) - sausage.update_attributes!(flavour: 'Guinness') + pending unless Sausage.respond_to?(:localized_fields) - track = sausage.history_tracks.last + sausage = Sausage.create!(flavour_translations: { 'en' => 'Apple', 'nl' => 'Appel' }, modifier: user) + sausage.update_attributes!(flavour: 'Guinness') - track.undo! user - expect(sausage.reload.flavour).to eq('Apple') + track = sausage.history_tracks.last - track.redo! user - expect(sausage.reload.flavour).to eq('Guinness') + track.undo! user + expect(sausage.reload.flavour).to eq('Apple') - sausage.destroy - expect(sausage.history_tracks.last.action).to eq('destroy') - sausage.history_tracks.last.undo! user - expect(sausage.reload.flavour).to eq('Guinness') - end + track.redo! user + expect(sausage.reload.flavour).to eq('Guinness') + + sausage.destroy + expect(sausage.history_tracks.last.action).to eq('destroy') + sausage.history_tracks.last.undo! user + expect(sausage.reload.flavour).to eq('Guinness') end end end diff --git a/spec/integration/multi_relation_spec.rb b/spec/integration/multi_relation_spec.rb index 05429cf2..363fe4a9 100644 --- a/spec/integration/multi_relation_spec.rb +++ b/spec/integration/multi_relation_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Mongoid::History::Tracker do - before :all do + before :each do class Model include Mongoid::Document include Mongoid::History::Trackable @@ -10,40 +10,33 @@ class Model belongs_to :user, inverse_of: :models has_and_belongs_to_many :external_users, class_name: 'User', inverse_of: :external_models - track_history on: %i[name user external_user_ids], # track title and body fields only, default is :all - modifier_field: :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier - modifier_field_inverse_of: nil, # no inverse modifier relationship - 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 - track_destroy: false # track document destruction, default is false + track_history on: %i[name user external_user_ids] end class User include Mongoid::Document + has_many :models, dependent: :destroy, inverse_of: :user has_and_belongs_to_many :external_model, class_name: 'Model', inverse_of: :external_users end end - it 'should be possible to undo when having multiple relations to modifier class' do - user = User.new - user.save! + after :each do + Object.send(:remove_const, :Model) + Object.send(:remove_const, :User) + end - model = Model.new - model.name = 'Foo' - model.user = user - model.modifier = user - model.save! + let(:user) { User.create! } + let(:model) { Model.create!(name: 'Foo', user: user, modifier: user) } - model.name = 'Bar' - model.save! + it 'should be possible to undo when having multiple relations to modifier class' do + model.update_attributes!(name: 'Bar', modifier: user) model.undo! user - expect(model.name).to eq('Foo') + expect(model.name).to eq 'Foo' - model.redo! user, 1 - expect(model.name).to eq('Bar') + model.redo! user, 2 + expect(model.name).to eq 'Bar' end it 'should track foreign key relations' do diff --git a/spec/integration/multiple_trackers_spec.rb b/spec/integration/multiple_trackers_spec.rb index 2c8c171a..6827ea7a 100644 --- a/spec/integration/multiple_trackers_spec.rb +++ b/spec/integration/multiple_trackers_spec.rb @@ -1,19 +1,13 @@ require 'spec_helper' describe Mongoid::History do - before :all do - Mongoid::History.tracker_class_name = nil - + before :each do class First include Mongoid::Document include Mongoid::History::Trackable field :text, type: String - track_history on: [:text], - track_create: true, - track_update: true, - track_destroy: true, - tracker_class_name: :first_history_tracker + track_history on: [:text], tracker_class_name: :first_history_tracker end class Second @@ -21,11 +15,7 @@ class Second include Mongoid::History::Trackable field :text, type: String - track_history on: [:text], - track_create: true, - track_update: true, - track_destroy: true, - tracker_class_name: :second_history_tracker + track_history on: [:text], tracker_class_name: :second_history_tracker end class User @@ -41,7 +31,7 @@ class SecondHistoryTracker end end - after :all do + after :each do Object.send(:remove_const, :First) Object.send(:remove_const, :Second) Object.send(:remove_const, :User) @@ -57,19 +47,14 @@ class SecondHistoryTracker expect(First.tracker_class).to be FirstHistoryTracker expect(Second.tracker_class).to be SecondHistoryTracker - foo = First.new(modifier: user) - foo.save! - - bar = Second.new(modifier: user) - bar.save! + foo = First.create!(modifier: user) + bar = Second.create!(modifier: user) expect(FirstHistoryTracker.count).to eq 1 expect(SecondHistoryTracker.count).to eq 1 - foo.text = "I'm foo" - foo.save - bar.text = "I'm bar" - bar.save + foo.update_attributes!(text: "I'm foo") + bar.update_attributes!(text: "I'm bar") expect(FirstHistoryTracker.count).to eq 2 expect(SecondHistoryTracker.count).to eq 2 diff --git a/spec/integration/nested_embedded_documents_spec.rb b/spec/integration/nested_embedded_documents_spec.rb index 484531c2..89901e0b 100644 --- a/spec/integration/nested_embedded_documents_spec.rb +++ b/spec/integration/nested_embedded_documents_spec.rb @@ -1,84 +1,64 @@ require 'spec_helper' describe Mongoid::History::Tracker do - before :all do - class Modelone + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable field :name, type: String - belongs_to :user, inverse_of: :modelones - embeds_many :embones - - track_history on: :all, # track title and body fields only, default is :all - modifier_field: :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier - 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 - track_destroy: false # track document destruction, default is false + belongs_to :user, inverse_of: :model_ones + embeds_many :emb_ones + + track_history end - class Embone + class EmbOne include Mongoid::Document include Mongoid::History::Trackable field :name - embeds_many :embtwos, store_as: :ems - embedded_in :modelone - - track_history on: :all, # track title and body fields only, default is :all - modifier_field: :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier - 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 - track_destroy: false, # track document destruction, default is false - scope: :model + embeds_many :emb_twos, store_as: :ems + embedded_in :model_one + + track_history end - class Embtwo + class EmbTwo include Mongoid::Document include Mongoid::History::Trackable field :name - embedded_in :embone - - track_history on: :all, # track title and body fields only, default is :all - modifier_field: :modifier, # adds "referenced_in :modifier" to track who made the change, default is :modifier - 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 - track_destroy: false, # track document destruction, default is false - scope: :modelone + embedded_in :emb_one + + track_history scope: :model_one end class User include Mongoid::Document - has_many :modelones, dependent: :destroy, inverse_of: :user + + has_many :model_ones, dependent: :destroy, inverse_of: :user end end - it 'should be able to track history for nested embedded documents' do - user = User.new - user.save! + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + Object.send(:remove_const, :EmbTwo) + Object.send(:remove_const, :User) + end + + let(:user) { User.create! } - model = Modelone.new(name: 'm1name', modifier: user) - model.user = user - model.save! - embedded1 = model.embones.create(name: 'e1name', modifier: user) - embedded2 = embedded1.embtwos.create(name: 'e2name', modifier: user) + it 'should be able to track history for nested embedded documents' do + model = ModelOne.create!(name: 'm1name', user: user, modifier: user) + embedded1 = model.emb_ones.create!(name: 'e1name', modifier: user) + embedded2 = embedded1.emb_twos.create!(name: 'e2name', modifier: user) - embedded2.name = 'a new name' - embedded2.save! + embedded2.update_attributes!(name: 'a new name') - model.history_tracks.first.undo! user + model.history_tracks[-1].undo! user expect(embedded1.reload.name).to eq('e1name') expect(embedded2.reload.name).to eq('e2name') end - - after :all do - Object.send(:remove_const, :Modelone) - Object.send(:remove_const, :Embone) - Object.send(:remove_const, :Embtwo) - Object.send(:remove_const, :User) - end end diff --git a/spec/integration/nested_embedded_polymorphic_documents_spec.rb b/spec/integration/nested_embedded_polymorphic_documents_spec.rb index 234ae994..c6dbb214 100644 --- a/spec/integration/nested_embedded_polymorphic_documents_spec.rb +++ b/spec/integration/nested_embedded_polymorphic_documents_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' describe Mongoid::History::Tracker do - before :all do - class Modelone + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable @@ -10,15 +10,10 @@ class Modelone belongs_to :user embeds_one :one_embedded, as: :embedable - track_history on: :all, - modifier_field: :modifier, - version_field: :version, - track_create: true, - track_update: true, - track_destroy: true + track_history end - class Modeltwo + class ModelTwo include Mongoid::Document include Mongoid::History::Trackable @@ -26,12 +21,7 @@ class Modeltwo belongs_to :user embeds_one :one_embedded, as: :embedable - track_history on: :all, - modifier_field: :modifier, - version_field: :version, - track_create: true, - track_update: true, - track_destroy: true + track_history end class OneEmbedded @@ -42,13 +32,7 @@ class OneEmbedded embeds_many :embedded_twos, store_as: :ems embedded_in :embedable, polymorphic: true - track_history on: :all, - modifier_field: :modifier, - version_field: :version, - track_create: true, - track_update: true, - track_destroy: true, - scope: %i[modelone modeltwo] + track_history scope: %i[model_one model_two] end class EmbeddedTwo @@ -58,79 +42,74 @@ class EmbeddedTwo field :name embedded_in :one_embedded - track_history on: :all, - modifier_field: :modifier, - version_field: :version, - track_create: true, - track_update: true, - track_destroy: true, - scope: %i[modelone modeltwo] + track_history scope: %i[model_one model_two] end class User include Mongoid::Document - has_many :modelones - has_many :modeltwos + + has_many :model_ones + has_many :model_twos end end + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :OneEmbedded) + Object.send(:remove_const, :EmbeddedTwo) + Object.send(:remove_const, :User) + end + let (:user) { User.create! } it 'tracks history for nested embedded documents with polymorphic relations' do user = User.create! - modelone = user.modelones.build(name: 'modelone', modifier: user) - modelone.save! - modelone.build_one_embedded(name: 'modelone_one_embedded', modifier: user).save! - expect(modelone.history_tracks.count).to eq(2) - expect(modelone.one_embedded.history_tracks.count).to eq(1) - - modelone.reload - modelone.one_embedded.update_attribute(:name, 'modelone_embedded_one!') - expect(modelone.history_tracks.count).to eq(3) - expect(modelone.one_embedded.history_tracks.count).to eq(2) - expect(modelone.history_tracks.last.action).to eq('update') - - modelone.build_one_embedded(name: 'Lorem ipsum', modifier: user).save! - expect(modelone.history_tracks.count).to eq(4) - expect(modelone.one_embedded.history_tracks.count).to eq(1) - expect(modelone.one_embedded.history_tracks.last.action).to eq('create') - expect(modelone.one_embedded.history_tracks.last.association_chain.last['name']).to eq('one_embedded') - - embedded_one1 = modelone.one_embedded.embedded_twos.create!(name: 'modelone_one_embedded_1', modifier: user) - expect(modelone.history_tracks.count).to eq(5) - expect(modelone.one_embedded.history_tracks.count).to eq(2) + model_one = user.model_ones.build(name: 'model_one', modifier: user) + model_one.save! + model_one.build_one_embedded(name: 'model_one_one_embedded', modifier: user).save! + expect(model_one.history_tracks.count).to eq(2) + expect(model_one.one_embedded.history_tracks.count).to eq(1) + + model_one.reload + model_one.one_embedded.update_attributes!(name: 'model_one_embedded_one!') + expect(model_one.history_tracks.count).to eq(3) + expect(model_one.one_embedded.history_tracks.count).to eq(2) + expect(model_one.history_tracks.last.action).to eq('update') + + model_one.build_one_embedded(name: 'Lorem ipsum', modifier: user).save! + expect(model_one.history_tracks.count).to eq(4) + expect(model_one.one_embedded.history_tracks.count).to eq(1) + expect(model_one.one_embedded.history_tracks.last.action).to eq('create') + expect(model_one.one_embedded.history_tracks.last.association_chain.last['name']).to eq('one_embedded') + + embedded_one1 = model_one.one_embedded.embedded_twos.create!(name: 'model_one_one_embedded_1', modifier: user) + expect(model_one.history_tracks.count).to eq(5) + expect(model_one.one_embedded.history_tracks.count).to eq(2) expect(embedded_one1.history_tracks.count).to eq(1) - modeltwo = user.modeltwos.build(name: 'modeltwo', modifier: user) - modeltwo.save! - modeltwo.build_one_embedded(name: 'modeltwo_one_embedded', modifier: user).save! - expect(modeltwo.history_tracks.count).to eq(2) - expect(modeltwo.one_embedded.history_tracks.count).to eq(1) - - modeltwo.reload - modeltwo.one_embedded.update_attribute(:name, 'modeltwo_one_embedded!') - expect(modeltwo.history_tracks.count).to eq(3) - expect(modeltwo.one_embedded.history_tracks.count).to eq(2) - expect(modeltwo.history_tracks.last.action).to eq('update') - - modeltwo.build_one_embedded(name: 'Lorem ipsum', modifier: user).save! - expect(modeltwo.history_tracks.count).to eq(4) - expect(modeltwo.one_embedded.history_tracks.count).to eq(1) - expect(modeltwo.one_embedded.history_tracks.last.action).to eq('create') - expect(modeltwo.one_embedded.history_tracks.last.association_chain.last['name']).to eq('one_embedded') - - embedded_one2 = modeltwo.one_embedded.embedded_twos.create!(name: 'modeltwo_one_embedded_1', modifier: user) - expect(modeltwo.history_tracks.count).to eq(5) - expect(modeltwo.one_embedded.history_tracks.count).to eq(2) + model_two = user.model_twos.build(name: 'model_two', modifier: user) + model_two.save! + model_two.build_one_embedded(name: 'model_two_one_embedded', modifier: user).save! + expect(model_two.history_tracks.count).to eq(2) + expect(model_two.one_embedded.history_tracks.count).to eq(1) + + model_two.reload + model_two.one_embedded.update_attributes!(name: 'model_two_one_embedded!') + expect(model_two.history_tracks.count).to eq(3) + expect(model_two.one_embedded.history_tracks.count).to eq(2) + expect(model_two.history_tracks.last.action).to eq('update') + + model_two.build_one_embedded(name: 'Lorem ipsum', modifier: user).save! + expect(model_two.history_tracks.count).to eq(4) + expect(model_two.one_embedded.history_tracks.count).to eq(1) + expect(model_two.one_embedded.history_tracks.last.action).to eq('create') + expect(model_two.one_embedded.history_tracks.last.association_chain.last['name']).to eq('one_embedded') + + embedded_one2 = model_two.one_embedded.embedded_twos.create!(name: 'model_two_one_embedded_1', modifier: user) + expect(model_two.history_tracks.count).to eq(5) + expect(model_two.one_embedded.history_tracks.count).to eq(2) expect(embedded_one2.history_tracks.count).to eq(1) end - - after :all do - Object.send(:remove_const, :Modelone) - Object.send(:remove_const, :Modeltwo) - Object.send(:remove_const, :OneEmbedded) - Object.send(:remove_const, :EmbeddedTwo) - Object.send(:remove_const, :User) - end end diff --git a/spec/integration/subclasses_spec.rb b/spec/integration/subclasses_spec.rb index fa537a93..fe092b24 100644 --- a/spec/integration/subclasses_spec.rb +++ b/spec/integration/subclasses_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Mongoid::History::Tracker do - before :all do + before :each do class Element include Mongoid::Document include Mongoid::Timestamps @@ -9,7 +9,7 @@ class Element field :body - track_history on: [:body], track_create: true, track_update: true, track_destroy: true + track_history on: [:body] end class Prompt < Element @@ -20,6 +20,12 @@ class User end end + after :each do + Object.send(:remove_const, :Element) + Object.send(:remove_const, :Prompt) + Object.send(:remove_const, :User) + end + let(:user) { User.create! } it 'tracks subclass create and update' do @@ -32,10 +38,4 @@ class User expect(prompt.body).to eq('one') expect { prompt.destroy }.to change(Tracker, :count).by(1) end - - after :all do - Object.send(:remove_const, :Element) - Object.send(:remove_const, :Prompt) - Object.send(:remove_const, :User) - end end diff --git a/spec/integration/track_history_order_spec.rb b/spec/integration/track_history_order_spec.rb index 67db3edf..dbef6aa5 100644 --- a/spec/integration/track_history_order_spec.rb +++ b/spec/integration/track_history_order_spec.rb @@ -1,52 +1,84 @@ require 'spec_helper' describe Mongoid::History::Tracker do - it 'should not track fields when track_history not called' do - class NotModel - include Mongoid::Document - include Mongoid::History::Trackable + context 'when track_history not called' do + before :each do + class NotModel + include Mongoid::Document + include Mongoid::History::Trackable - field :foo + field :foo + end end - expect(NotModel.respond_to?(:tracked?)).to be false + after :each do + Object.send(:remove_const, :NotModel) + end + + it 'should not track fields' do + expect(NotModel.respond_to?(:tracked?)).to be false + end end - it 'should track fields when track_history called inside class and before fields' do - class InsideBeforeModel - include Mongoid::Document - include Mongoid::History::Trackable + context 'boefore field' do + before :each do + class InsideBeforeModel + include Mongoid::Document + include Mongoid::History::Trackable - track_history on: :fields + track_history on: :fields - field :foo + field :foo + end end - expect(InsideBeforeModel.tracked?(:foo)).to be true + after :each do + Object.send(:remove_const, :InsideBeforeModel) + end + + it 'should track fields' do + expect(InsideBeforeModel.tracked?(:foo)).to be true + end end - it 'should track fields when track_history called inside class and after fields' do - class InsideAfterModel - include Mongoid::Document - include Mongoid::History::Trackable + context 'when track_history called inside class and after fields' do + before :each do + class InsideAfterModel + include Mongoid::Document + include Mongoid::History::Trackable - field :foo + field :foo - track_history on: :fields + track_history on: :fields + end end - expect(InsideAfterModel.tracked?(:foo)).to be true + after :each do + Object.send(:remove_const, :InsideAfterModel) + end + + it 'should track fields' do + expect(InsideAfterModel.tracked?(:foo)).to be true + end end - it 'should track fields when track_history called outside class' do - class OutsideModel - include Mongoid::Document - include Mongoid::History::Trackable + context 'when track_history called outside class' do + before :each do + class OutsideModel + include Mongoid::Document + include Mongoid::History::Trackable - field :foo + field :foo + end end - OutsideModel.track_history on: :fields - expect(OutsideModel.tracked?(:foo)).to be true + after :each do + Object.send(:remove_const, :OutsideModel) + end + + it 'should track fields' do + OutsideModel.track_history on: :fields + expect(OutsideModel.tracked?(:foo)).to be true + end end end diff --git a/spec/integration/validation_failure_spec.rb b/spec/integration/validation_failure_spec.rb index 6e7d5c61..21714f91 100644 --- a/spec/integration/validation_failure_spec.rb +++ b/spec/integration/validation_failure_spec.rb @@ -1,11 +1,7 @@ require 'spec_helper' describe Mongoid::History::Tracker do - before :all do - class User - include Mongoid::Document - end - + before :each do class Element include Mongoid::Document include Mongoid::Timestamps @@ -22,7 +18,7 @@ class Element has_many :items, dependent: :restrict end - track_history on: [:body], track_create: true, track_update: true, track_destroy: true + track_history on: [:body] end class Item @@ -35,13 +31,20 @@ class Item class Prompt < Element end - @persisted_history_options = Mongoid::History.trackable_class_options + class User + include Mongoid::Document + end + end + + after :each do + Object.send(:remove_const, :Element) + Object.send(:remove_const, :Item) + Object.send(:remove_const, :Prompt) + Object.send(:remove_const, :User) end let(:user) { User.create! } - before(:each) { Mongoid::History.trackable_class_options = @persisted_history_options } - it 'does not track delete when parent class validation fails' do prompt = Prompt.new(title: 'first', modifier: user) expect { prompt.save! }.to change(Tracker, :count).by(1) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d3d41251..9b670a15 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -17,9 +17,14 @@ RSpec.configure do |config| config.raise_errors_for_deprecations! + config.before :all do Mongoid.logger.level = Logger::INFO Mongo::Logger.logger.level = Logger::INFO if Mongoid::Compatibility::Version.mongoid5_or_newer? Mongoid.belongs_to_required_by_default = false if Mongoid::Compatibility::Version.mongoid6? end + + config.before :each do + Mongoid::History.reset! + end end diff --git a/spec/unit/attributes/base_spec.rb b/spec/unit/attributes/base_spec.rb index 63084e4c..5eaded3e 100644 --- a/spec/unit/attributes/base_spec.rb +++ b/spec/unit/attributes/base_spec.rb @@ -1,31 +1,29 @@ require 'spec_helper' describe Mongoid::History::Attributes::Base do - let(:model_one) do - Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + field :foo field :b, as: :bar - def self.name - 'ModelOne' - end end - end - before :all do class ModelTwo include Mongoid::Document + field :foo field :goo end end - after :all do + after :each do + Object.send(:remove_const, :ModelOne) Object.send(:remove_const, :ModelTwo) end - let(:obj_one) { model_one.new } + let(:obj_one) { ModelOne.new } let(:base) { described_class.new(obj_one) } subject { base } @@ -37,7 +35,7 @@ class ModelTwo describe '#trackable_class' do subject { base.send(:trackable_class) } - it { is_expected.to eq model_one } + it { is_expected.to eq ModelOne } end describe '#aliased_fields' do @@ -47,8 +45,7 @@ class ModelTwo describe '#changes_method' do before(:each) do - model_one.instance_variable_set(:@history_trackable_options, nil) - model_one.track_history changes_method: :my_changes + ModelOne.track_history changes_method: :my_changes end subject { base.send(:changes_method) } it { is_expected.to eq :my_changes } @@ -56,8 +53,7 @@ class ModelTwo describe '#changes' do before(:each) do - model_one.instance_variable_set(:@history_trackable_options, nil) - model_one.track_history + ModelOne.track_history allow(obj_one).to receive(:changes) { { 'foo' => ['Foo', 'Foo-new'] } } end subject { base.send(:changes) } @@ -65,15 +61,11 @@ class ModelTwo end describe '#format_field' do - before(:each) do - model_one.instance_variable_set(:@history_trackable_options, nil) - end - subject { base.send(:format_field, :bar, 'foo') } context 'when formatted via string' do before do - model_one.track_history format: { bar: '*%s*' } + ModelOne.track_history format: { bar: '*%s*' } end it { is_expected.to eq '*foo*' } @@ -81,7 +73,7 @@ class ModelTwo context 'when formatted via proc' do before do - model_one.track_history format: { bar: ->(v) { v * 2 } } + ModelOne.track_history format: { bar: ->(v) { v * 2 } } end it { is_expected.to eq 'foofoo' } @@ -89,7 +81,7 @@ class ModelTwo context 'when not formatted' do before do - model_one.track_history + ModelOne.track_history end it { is_expected.to eq 'foo' } @@ -100,15 +92,14 @@ class ModelTwo let(:model_two) { ModelTwo.new(foo: :bar, goo: :baz) } before :each do - model_one.instance_variable_set(:@history_trackable_options, nil) - model_one.send(relation_type, :model_two) + ModelOne.send(relation_type, :model_two) end subject { base.send("format_#{relation_type}_relation", :model_two, model_two.attributes) } context 'with permitted attributes' do before do - model_one.track_history on: { model_two: %i[foo] } + ModelOne.track_history on: { model_two: %i[foo] } end it 'should select only permitted attributes' do @@ -119,7 +110,7 @@ class ModelTwo context 'with attributes formatted via string' do before do - model_one.track_history on: { model_two: %i[foo] }, format: { model_two: { foo: '&%s&' } } + ModelOne.track_history on: { model_two: %i[foo] }, format: { model_two: { foo: '&%s&' } } end it 'should select obfuscate permitted attributes' do @@ -130,7 +121,7 @@ class ModelTwo context 'with attributes formatted via proc' do before do - model_one.track_history on: { model_two: %i[foo] }, format: { model_two: { foo: ->(v) { v.to_s * 2 } } } + ModelOne.track_history on: { model_two: %i[foo] }, format: { model_two: { foo: ->(v) { v.to_s * 2 } } } end it 'should select obfuscate permitted attributes' do diff --git a/spec/unit/attributes/create_spec.rb b/spec/unit/attributes/create_spec.rb index 2412ab23..5740b712 100644 --- a/spec/unit/attributes/create_spec.rb +++ b/spec/unit/attributes/create_spec.rb @@ -1,20 +1,23 @@ require 'spec_helper' describe Mongoid::History::Attributes::Create do - let(:model_one) do - Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones field :foo field :b, as: :bar - def self.name - 'ModelOne' - end + + track_history on: :foo end end - let(:obj_one) { model_one.new } + after :each do + Object.send(:remove_const, :ModelOne) + end + let(:base) { described_class.new(obj_one) } subject { base } @@ -22,326 +25,318 @@ def self.name subject { base.attributes } describe 'fields' do - before(:each) do - model_one.instance_variable_set(:@history_trackable_options, nil) - model_one.track_history on: :foo - end - let(:obj_one) { model_one.new(foo: 'Foo', bar: 'Bar') } + let(:obj_one) { ModelOne.new } + let(:obj_one) { ModelOne.new(foo: 'Foo', bar: 'Bar') } it { is_expected.to eq('foo' => [nil, 'Foo']) } end describe '#insert_embeds_one_changes' do context 'when untracked relation' do - before(:all) do - # Need class name constant + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one_one else embeds_one :emb_one_one, inverse_class_name: 'EmbOneOne' end + + track_history on: :fields end class EmbOneOne include Mongoid::Document + field :em_bar embedded_in :model_one end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - ModelTwo.track_history on: :fields + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmbOneOne) end - let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj_one) } - let(:emb_obj_one) { EmbOneOne.new(em_bar: 'Em-Bar') } + let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj) } + let(:emb_obj) { EmbOneOne.new(em_bar: 'Em-Bar') } it { is_expected.to eq({}) } - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmbOneOne) - end end context 'when tracked relation' do - before(:all) do - # Need class name constant + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one_one else embeds_one :emb_one_one, inverse_class_name: 'EmbOneOne' end + + track_history on: :emb_one_one end class EmbOneOne include Mongoid::Document + field :em_bar embedded_in :model_one end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - ModelTwo.track_history on: :emb_one_one - end - - let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj_one) } - let(:emb_obj_one) { EmbOneOne.new(em_bar: 'Em-Bar') } - - it { is_expected.to eq('emb_one_one' => [nil, { '_id' => emb_obj_one._id, 'em_bar' => 'Em-Bar' }]) } - - after(:all) do + after :each do Object.send(:remove_const, :ModelTwo) Object.send(:remove_const, :EmbOneOne) end + + let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj) } + let(:emb_obj) { EmbOneOne.new(em_bar: 'Em-Bar') } + + it { is_expected.to eq('emb_one_one' => [nil, { '_id' => emb_obj._id, 'em_bar' => 'Em-Bar' }]) } end context 'when paranoia_field without alias' do - before(:all) do - # Need class name constant + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one_one else embeds_one :emb_one_one, inverse_class_name: 'EmbOneOne' end + + track_history on: :emb_one_one end class EmbOneOne include Mongoid::Document include Mongoid::History::Trackable + field :em_bar field :removed_at + embedded_in :model_one + + history_settings paranoia_field: :removed_at end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - EmbOneOne.instance_variable_set(:@rackable_settings, nil) - ModelTwo.track_history on: :emb_one_one - EmbOneOne.history_settings paranoia_field: :removed_at + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmbOneOne) end - let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj_one) } - let(:emb_obj_one) { EmbOneOne.new(em_bar: 'Em-Bar', removed_at: Time.now) } + let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj) } + let(:emb_obj) { EmbOneOne.new(em_bar: 'Em-Bar', removed_at: Time.now) } it { is_expected.to eq({}) } - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmbOneOne) - end end context 'when paranoia_field with alias' do - before(:all) do - # Need class name constant + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one_one else embeds_one :emb_one_one, inverse_class_name: 'EmbOneOne' end + + track_history on: :emb_one_one end class EmbOneOne include Mongoid::Document include Mongoid::History::Trackable + field :em_bar field :rmvt, as: :removed_at + embedded_in :model_one + + history_settings paranoia_field: :removed_at end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - EmbOneOne.instance_variable_set(:@rackable_settings, nil) - ModelTwo.track_history on: :emb_one_one - EmbOneOne.history_settings paranoia_field: :removed_at + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmbOneOne) end - let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj_one) } - let(:emb_obj_one) { EmbOneOne.new(em_bar: 'Em-Bar', removed_at: Time.now) } + let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj) } + let(:emb_obj) { EmbOneOne.new(em_bar: 'Em-Bar', removed_at: Time.now) } it { is_expected.to eq({}) } - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmbOneOne) - end end context 'with permitted attributes' do - before(:all) do - # Need class name constant + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one_one else embeds_one :emb_one_one, inverse_class_name: 'EmbOneOne' end + + track_history on: [{ emb_one_one: :em_bar }] end class EmbOneOne include Mongoid::Document include Mongoid::History::Trackable + field :em_foo field :em_bar + embedded_in :model_one end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - ModelTwo.track_history on: [{ emb_one_one: :em_bar }] - end - - let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj_one) } - let(:emb_obj_one) { EmbOneOne.new(em_foo: 'Em-Foo', em_bar: 'Em-Bar') } - - it { is_expected.to eq('emb_one_one' => [nil, { '_id' => emb_obj_one._id, 'em_bar' => 'Em-Bar' }]) } - - after(:all) do + after :each do Object.send(:remove_const, :ModelTwo) Object.send(:remove_const, :EmbOneOne) end + + let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj) } + let(:emb_obj) { EmbOneOne.new(em_foo: 'Em-Foo', em_bar: 'Em-Bar') } + + it { is_expected.to eq('emb_one_one' => [nil, { '_id' => emb_obj._id, 'em_bar' => 'Em-Bar' }]) } end context 'when relation with alias' do - before(:all) do - # Need class name constant + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one_one, store_as: :eoo else embeds_one :emb_one_one, inverse_class_name: 'EmbOneOne', store_as: :eoo end + + track_history on: :emb_one_one end class EmbOneOne include Mongoid::Document + field :em_bar embedded_in :model_one end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - ModelTwo.track_history on: :emb_one_one - end - - let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj_one) } - let(:emb_obj_one) { EmbOneOne.new(em_bar: 'Em-Bar') } - - it { is_expected.to eq('emb_one_one' => [nil, { '_id' => emb_obj_one._id, 'em_bar' => 'Em-Bar' }]) } - - after(:all) do + after :each do Object.send(:remove_const, :ModelTwo) Object.send(:remove_const, :EmbOneOne) end + + let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj) } + let(:emb_obj) { EmbOneOne.new(em_bar: 'Em-Bar') } + + it { is_expected.to eq('emb_one_one' => [nil, { '_id' => emb_obj._id, 'em_bar' => 'Em-Bar' }]) } end context 'when no object' do - before(:all) do - # Need class name constant + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one_one, store_as: :eoo else embeds_one :emb_one_one, store_as: :eoo, inverse_class_name: 'EmbOneOne' end + + track_history on: :emb_one_one end class EmbOneOne include Mongoid::Document + field :em_bar embedded_in :model_one end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - ModelTwo.track_history on: :emb_one_one + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmbOneOne) end let(:obj_one) { ModelTwo.new } it { is_expected.to eq({}) } - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmbOneOne) - end end context 'when object not paranoid' do - before(:all) do - # Need class name constant + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one_one, store_as: :eoo else embeds_one :emb_one_one, store_as: :eoo, inverse_class_name: 'EmbOneOne' end + + track_history on: :emb_one_one end class EmbOneOne include Mongoid::Document include Mongoid::History::Trackable + field :em_bar field :cancelled_at + embedded_in :model_one - end - end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - EmbOneOne.instance_variable_set(:@trackable_settings, nil) - ModelTwo.track_history on: :emb_one_one - EmbOneOne.history_settings paranoia_field: :cancelled_at + history_settings paranoia_field: :cancelled_at + end end - let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj_one) } - let(:emb_obj_one) { EmbOneOne.new(em_bar: 'Em-Bar') } - - it { is_expected.to eq('emb_one_one' => [nil, { '_id' => emb_obj_one._id, 'em_bar' => 'Em-Bar' }]) } - - after(:all) do + after :each do Object.send(:remove_const, :ModelTwo) Object.send(:remove_const, :EmbOneOne) end + + let(:obj_one) { ModelTwo.new(emb_one_one: emb_obj) } + let(:emb_obj) { EmbOneOne.new(em_bar: 'Em-Bar') } + + it { is_expected.to eq('emb_one_one' => [nil, { '_id' => emb_obj._id, 'em_bar' => 'Em-Bar' }]) } end end - describe '#insert_embeds_many_changes' do - end + pending '#insert_embeds_many_changes' end end diff --git a/spec/unit/attributes/destroy_spec.rb b/spec/unit/attributes/destroy_spec.rb index 4a105f28..e0acd183 100644 --- a/spec/unit/attributes/destroy_spec.rb +++ b/spec/unit/attributes/destroy_spec.rb @@ -1,20 +1,25 @@ require 'spec_helper' describe Mongoid::History::Attributes::Destroy do - let(:model_one) do - Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones + field :foo field :b, as: :bar - def self.name - 'ModelOne' - end + + track_history on: :foo, modifier_field_optional: true end end - let(:obj_one) { model_one.new } + after :each do + Object.send(:remove_const, :ModelOne) + end + + let(:obj_one) { ModelOne.new } let(:base) { described_class.new(obj_one) } subject { base } @@ -22,41 +27,48 @@ def self.name subject { base.attributes } describe '#fields' do - before(:each) do - model_one.instance_variable_set(:@history_trackable_options, nil) - model_one.track_history on: :foo, modifier_field_optional: true + before :each do obj_one.save! end - let(:obj_one) { model_one.new(foo: 'Foo', bar: 'Bar') } + + let(:obj_one) { ModelOne.new(foo: 'Foo', bar: 'Bar') } it { is_expected.to eq('_id' => [obj_one._id, nil], 'foo' => ['Foo', nil], 'version' => [1, nil]) } end describe '#insert_embeds_one_changes' do - before(:all) do - # Need class name constant. So, defining class like this + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + embeds_one :emb_two + track_history on: :fields, modifier_field_optional: true end class EmbTwo include Mongoid::Document + field :em_foo field :em_bar + embedded_in :model_two end end - before(:each) { ModelTwo.clear_trackable_memoization } + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmbTwo) + end + let(:obj_two) { ModelTwo.new(emb_two: emb_obj_two) } let(:emb_obj_two) { EmbTwo.new(em_foo: 'Em-Foo', em_bar: 'Em-Bar') } let(:base) { described_class.new(obj_two) } context 'when relation tracked' do - before(:each) do + before :each do ModelTwo.track_history on: :emb_two, modifier_field_optional: true obj_two.save! end @@ -64,7 +76,7 @@ class EmbTwo end context 'when relation not tracked' do - before(:each) do + before :each do ModelTwo.track_history on: :fields, modifier_field_optional: true allow(ModelTwo).to receive(:dynamic_enabled?) { false } obj_two.save! @@ -73,133 +85,136 @@ class EmbTwo end context 'when relation with alias' do - before(:all) do - # Need class name constant. So, defining class like this + before :each do class ModelThree include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_threes embeds_one :emb_three, store_as: :emtr + + track_history on: :emb_three, modifier_field_optional: true end class EmbThree include Mongoid::Document + field :em_foo embedded_in :model_three end end - before(:each) do - ModelThree.instance_variable_set(:@history_trackable_options, nil) - ModelThree.track_history on: :emb_three, modifier_field_optional: true + after :each do + Object.send(:remove_const, :ModelThree) + Object.send(:remove_const, :EmbThree) + end + + before :each do obj_three.save! end let(:obj_three) { ModelThree.new(emb_three: emb_obj_three) } let(:emb_obj_three) { EmbThree.new(em_foo: 'Em-Foo') } let(:base) { described_class.new(obj_three) } - it { expect(subject['emb_three']).to eq [{ '_id' => emb_obj_three._id, 'em_foo' => 'Em-Foo' }, nil] } - after(:all) do - Object.send(:remove_const, :ModelThree) - Object.send(:remove_const, :EmbThree) - end + it { expect(subject['emb_three']).to eq [{ '_id' => emb_obj_three._id, 'em_foo' => 'Em-Foo' }, nil] } end context 'relation with permitted attributes' do - before(:each) do + before :each do ModelTwo.track_history on: [{ emb_two: :em_foo }], modifier_field_optional: true obj_two.save! end + it { expect(subject['emb_two']).to eq [{ '_id' => emb_obj_two._id, 'em_foo' => 'Em-Foo' }, nil] } end context 'when relation object not built' do - before(:each) do + before :each do ModelTwo.track_history on: :emb_two, modifier_field_optional: true obj_two.save! end + let(:obj_two) { ModelTwo.new } it { expect(subject['emb_two']).to be_nil } end - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmbTwo) - end end describe '#insert_embeds_many_changes' do context 'Case 1:' do - before(:all) do + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + embeds_many :em_twos track_history on: :fields end class EmTwo include Mongoid::Document + field :em_foo field :em_bar + embedded_in :model_two end end + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmTwo) + end + let(:obj_two) { ModelTwo.new(em_twos: [em_obj_two]) } let(:em_obj_two) { EmTwo.new(em_foo: 'Em-Foo', em_bar: 'Em-Bar') } let(:base) { described_class.new(obj_two) } context 'when relation tracked' do - before(:each) do - ModelTwo.clear_trackable_memoization + before :each do ModelTwo.track_history on: :em_twos end it { expect(subject['em_twos']).to eq [[{ '_id' => em_obj_two._id, 'em_foo' => 'Em-Foo', 'em_bar' => 'Em-Bar' }], nil] } end context 'when relation not tracked' do - before(:each) do - ModelTwo.clear_trackable_memoization + before :each do ModelTwo.track_history on: :fields end it { expect(subject['em_twos']).to be_nil } end context 'when relation with permitted attributes for tracking' do - before(:each) do - ModelTwo.clear_trackable_memoization + before :each do ModelTwo.track_history on: { em_twos: :em_foo } end it { expect(subject['em_twos']).to eq [[{ '_id' => em_obj_two._id, 'em_foo' => 'Em-Foo' }], nil] } end - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmTwo) - end end context 'when relation with alias' do - before(:all) do + before :each do class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + embeds_many :em_twos, store_as: :emws track_history on: :fields + + track_history on: :em_twos end class EmTwo include Mongoid::Document + field :em_foo embedded_in :model_two end end - before(:each) do - ModelTwo.clear_trackable_memoization - ModelTwo.track_history on: :em_twos + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmTwo) end let(:obj_two) { ModelTwo.new(em_twos: [em_obj_two]) } @@ -207,11 +222,6 @@ class EmTwo let(:base) { described_class.new(obj_two) } it { expect(subject['em_twos']).to eq [[{ '_id' => em_obj_two._id, 'em_foo' => 'Em-Foo' }], nil] } - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmTwo) - end end end end diff --git a/spec/unit/attributes/update_spec.rb b/spec/unit/attributes/update_spec.rb index 65536dd3..5a88cca3 100644 --- a/spec/unit/attributes/update_spec.rb +++ b/spec/unit/attributes/update_spec.rb @@ -4,25 +4,33 @@ describe '#attributes' do describe '#insert_embeds_one_changes' do context 'Case: relation without alias' do - before(:all) do + before :each do class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones embeds_one :emb_one + track_history on: :fields end class EmbOne include Mongoid::Document + field :em_foo field :em_bar + embedded_in :model_one end end - before(:each) do - ModelOne.clear_trackable_memoization + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + end + + before :each do allow(base).to receive(:changes) { changes } end @@ -34,17 +42,23 @@ class EmbOne subject { base.attributes } context 'with permitted attributes' do - before(:each) { ModelOne.track_history on: { emb_one: :em_foo } } + before :each do + ModelOne.track_history on: { emb_one: :em_foo } + end it { expect(subject['emb_one']).to eq [{ 'em_foo' => 'Em-Foo' }, { 'em_foo' => 'Em-Foo-new' }] } end context 'without permitted attributes' do - before(:each) { ModelOne.track_history on: :emb_one } + before :each do + ModelOne.track_history on: :emb_one + end it { expect(subject['emb_one']).to eq [{ 'em_foo' => 'Em-Foo', 'em_bar' => 'Em-Bar' }, { 'em_foo' => 'Em-Foo-new', 'em_bar' => 'Em-Bar-new' }] } end context 'when old value soft-deleted' do - before(:each) { ModelOne.track_history on: :emb_one } + before :each do + ModelOne.track_history on: :emb_one + end let(:changes) do { 'emb_one' => [{ 'em_foo' => 'Em-Foo', 'deleted_at' => Time.now }, { 'em_foo' => 'Em-Foo-new', 'em_bar' => 'Em-Bar-new' }] } end @@ -52,7 +66,9 @@ class EmbOne end context 'when new value soft-deleted' do - before(:each) { ModelOne.track_history on: :emb_one } + before :each do + ModelOne.track_history on: :emb_one + end let(:changes) do { 'emb_one' => [{ 'em_foo' => 'Em-Foo' }, { 'em_foo' => 'Em-Foo-new', 'deleted_at' => Time.now }] } end @@ -60,21 +76,16 @@ class EmbOne end context 'when not tracked' do - before(:each) do + before :each do ModelOne.track_history on: :fields allow(ModelOne).to receive(:dynamic_enabled?) { false } end it { expect(subject['emb_one']).to be_nil } end - - after(:all) do - Object.send(:remove_const, :ModelOne) - Object.send(:remove_const, :EmbOne) - end end context 'Case: relation with alias' do - before(:all) do + before :each do class ModelOne include Mongoid::Document include Mongoid::History::Trackable @@ -91,8 +102,12 @@ class EmbOne end end - before(:each) do - ModelOne.clear_trackable_memoization + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + end + + before :each do ModelOne.track_history on: :emb_one allow(base).to receive(:changes) { changes } end @@ -104,15 +119,10 @@ class EmbOne end subject { base.attributes } it { expect(subject['eon']).to eq [{ 'em_foo' => 'Em-Foo' }, { 'em_foo' => 'Em-Foo-new', 'em_bar' => 'Em-Bar-new' }] } - - after(:all) do - Object.send(:remove_const, :ModelOne) - Object.send(:remove_const, :EmbOne) - end end context 'when original and modified value same' do - before(:all) do + before :each do class DummyUpdateModel include Mongoid::Document include Mongoid::History::Trackable @@ -129,8 +139,12 @@ class DummyEmbeddedModel end end - before(:each) do - DummyUpdateModel.clear_trackable_memoization + after :each do + Object.send(:remove_const, :DummyUpdateModel) + Object.send(:remove_const, :DummyEmbeddedModel) + end + + before :each do allow(base).to receive(:changes) { changes } DummyUpdateModel.track_history on: :dummy_embedded_model end @@ -142,17 +156,12 @@ class DummyEmbeddedModel end subject { base.attributes } it { expect(subject.keys).to_not include 'dummy_embedded_model' } - - after(:all) do - Object.send(:remove_const, :DummyUpdateModel) - Object.send(:remove_const, :DummyEmbeddedModel) - end end end describe '#insert_embeds_many_changes' do context 'Case: relation without alias' do - before(:all) do + before :each do class ModelOne include Mongoid::Document include Mongoid::History::Trackable @@ -173,8 +182,7 @@ class EmbOne end end - before(:each) do - ModelOne.clear_trackable_memoization + before :each do allow(base).to receive(:changes) { changes } end @@ -183,7 +191,9 @@ class EmbOne subject { base.attributes } context 'with whitelist attributes' do - before(:each) { ModelOne.track_history on: { emb_ones: :em_foo } } + before :each do + ModelOne.track_history on: { emb_ones: :em_foo } + end let(:changes) do { 'emb_ones' => [[{ 'em_foo' => 'Em-Foo', 'em_bar' => 'Em-Bar' }], [{ 'em_foo' => 'Em-Foo-new', 'em_bar' => 'Em-Bar-new' }]] } end @@ -193,7 +203,9 @@ class EmbOne end context 'without whitelist attributes' do - before(:each) { ModelOne.track_history on: :emb_ones } + before :each do + ModelOne.track_history(on: :emb_ones) + end let(:changes) do { 'emb_ones' => [[{ 'em_foo' => 'Em-Foo', 'deleted_at' => Time.now }], [{ 'em_foo' => 'Em-Foo-new', 'em_bar' => 'Em-Bar-new' }]] } end @@ -202,14 +214,14 @@ class EmbOne end end - after(:all) do + after :each do Object.send(:remove_const, :ModelOne) Object.send(:remove_const, :EmbOne) end end context 'Case: relation with alias' do - before(:all) do + before :each do class ModelOne include Mongoid::Document include Mongoid::History::Trackable @@ -230,8 +242,7 @@ class EmbOne end end - before(:each) do - ModelOne.clear_trackable_memoization + before :each do ModelOne.track_history on: :emb_ones allow(base).to receive(:changes) { changes } end @@ -246,14 +257,14 @@ class EmbOne expect(subject['eons']).to eq [[{ 'em_foo' => 'Em-Foo' }], [{ 'em_foo' => 'Em-Foo-new', 'em_bar' => 'Em-Bar-new' }]] end - after(:all) do + after :each do Object.send(:remove_const, :ModelOne) Object.send(:remove_const, :EmbOne) end end context 'when original and modified value same' do - before(:all) do + before :each do class ModelOne include Mongoid::Document include Mongoid::History::Trackable @@ -274,8 +285,7 @@ class EmbOne end end - before(:each) do - ModelOne.clear_trackable_memoization + before :each do allow(base).to receive(:changes) { changes } ModelOne.track_history on: :emb_ones end @@ -288,7 +298,7 @@ class EmbOne subject { base.attributes } it { expect(subject.keys).to_not include 'emb_ones' } - after(:all) do + after :each do Object.send(:remove_const, :ModelOne) Object.send(:remove_const, :EmbOne) end @@ -296,7 +306,7 @@ class EmbOne end context 'when original and modified values blank' do - before(:all) do + before :each do class DummyParent include Mongoid::Document include Mongoid::History::Trackable @@ -311,8 +321,7 @@ class OtherDummyParent end end - before(:each) do - DummyParent.clear_trackable_memoization + before :each do allow(base).to receive(:changes) { changes } DummyParent.track_history on: :other_dummy_parent_ids end @@ -324,7 +333,7 @@ class OtherDummyParent subject { base.attributes } it { expect(subject.keys).to_not include 'other_dummy_parent_ids' } - after(:all) do + after :each do Object.send(:remove_const, :DummyParent) Object.send(:remove_const, :OtherDummyParent) end diff --git a/spec/unit/callback_options_spec.rb b/spec/unit/callback_options_spec.rb index aa543e1f..077e5c98 100644 --- a/spec/unit/callback_options_spec.rb +++ b/spec/unit/callback_options_spec.rb @@ -2,24 +2,25 @@ describe Mongoid::History::Options do describe ':if' do - let(:dummy_model) do - Class.new do + before :each do + class DummyModel 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, - modifier_field_optional: true, - if: :bar - def self.name - 'DummyModel' - end + + track_history modifier_field_optional: true, if: :bar end end - let(:obj) { dummy_model.new(foo: 'Foo') } + + after :each do + Object.send(:remove_const, :DummyModel) + end + + let(:obj) { DummyModel.new(foo: 'Foo') } context 'when condition evaluates to true' do before { obj.bar = true } @@ -45,24 +46,25 @@ def self.name end describe ':unless' do - let(:dummy_model) do - Class.new do + before :each do + class DummyModel 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, - modifier_field_optional: true, - unless: ->(obj) { obj.bar } - def self.name - 'DummyModel' - end + + track_history modifier_field_optional: true, unless: ->(obj) { obj.bar } end end - let(:obj) { dummy_model.new(foo: 'Foo') } + + after :each do + Object.send(:remove_const, :DummyModel) + end + + let(:obj) { DummyModel.new(foo: 'Foo') } context 'when condition evaluates to true' do before { obj.bar = true } @@ -88,24 +90,25 @@ def self.name end describe ':if and :unless' do - let(:dummy_model) do - Class.new do + before :each do + class DummyModel include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones field :foo + attr_accessor :bar, :baz - track_history track_create: true, - track_update: true, - track_destroy: true, - modifier_field_optional: true, - if: :bar, unless: ->(obj) { obj.baz } - def self.name - 'DummyModel' - end + + track_history modifier_field_optional: true, if: :bar, unless: ->(obj) { obj.baz } end end - let(:obj) { dummy_model.new(foo: 'Foo') } + + after :each do + Object.send(:remove_const, :DummyModel) + end + + let(:obj) { DummyModel.new(foo: 'Foo') } context 'when :if condition evaluates to true' do before { obj.bar = true } diff --git a/spec/unit/embedded_methods_spec.rb b/spec/unit/embedded_methods_spec.rb index 68778cb2..e0981c39 100644 --- a/spec/unit/embedded_methods_spec.rb +++ b/spec/unit/embedded_methods_spec.rb @@ -3,10 +3,11 @@ describe Mongoid::History::Trackable do describe 'EmbeddedMethods' do describe 'relation_class_of' do - before :all do - ModelOne = Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one embeds_one :emb_two, store_as: 'emt' @@ -14,36 +15,40 @@ embeds_one :emb_one, inverse_class_name: 'EmbOne' embeds_one :emb_two, store_as: 'emt', inverse_class_name: 'EmbTwo' end + track_history end - EmbOne = Class.new do + class EmbOne include Mongoid::Document + embedded_in :model_one end - EmbTwo = Class.new do + class EmbTwo include Mongoid::Document + embedded_in :model_one end end - it { expect(ModelOne.relation_class_of('emb_one')).to eq EmbOne } - it { expect(ModelOne.relation_class_of('emt')).to eq EmbTwo } - it { expect(ModelOne.relation_class_of('invalid')).to be_nil } - - after :all do + after :each do Object.send(:remove_const, :ModelOne) Object.send(:remove_const, :EmbOne) Object.send(:remove_const, :EmbTwo) end + + it { expect(ModelOne.relation_class_of('emb_one')).to eq EmbOne } + it { expect(ModelOne.relation_class_of('emt')).to eq EmbTwo } + it { expect(ModelOne.relation_class_of('invalid')).to be_nil } end describe 'relation_class_of' do - before :all do - ModelOne = Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_many :emb_ones embeds_many :emb_twos, store_as: 'emts' @@ -51,29 +56,32 @@ embeds_many :emb_ones, inverse_class_name: 'EmbOne' embeds_many :emb_twos, store_as: 'emts', inverse_class_name: 'EmbTwo' end + track_history end - EmbOne = Class.new do + class EmbOne include Mongoid::Document + embedded_in :model_one end - EmbTwo = Class.new do + class EmbTwo include Mongoid::Document + embedded_in :model_one end end - it { expect(ModelOne.relation_class_of('emb_ones')).to eq EmbOne } - it { expect(ModelOne.relation_class_of('emts')).to eq EmbTwo } - it { expect(ModelOne.relation_class_of('invalid')).to be_nil } - - after :all do + after :each do Object.send(:remove_const, :ModelOne) Object.send(:remove_const, :EmbOne) Object.send(:remove_const, :EmbTwo) end + + it { expect(ModelOne.relation_class_of('emb_ones')).to eq EmbOne } + it { expect(ModelOne.relation_class_of('emts')).to eq EmbTwo } + it { expect(ModelOne.relation_class_of('invalid')).to be_nil } end end end diff --git a/spec/unit/history_spec.rb b/spec/unit/history_spec.rb index 927b1de6..7f55507b 100644 --- a/spec/unit/history_spec.rb +++ b/spec/unit/history_spec.rb @@ -10,26 +10,28 @@ end describe '#trackable_class_settings' do - before(:each) { Mongoid::History.trackable_settings = {} } - let(:model_one) do - Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable - store_in collection: :model_ones - def self.name - 'ModelOne' - end + store_in collection: :model_ones end end + after :each do + Object.send(:remove_const, :ModelOne) + end + context 'when present' do - before(:each) { model_one.history_settings paranoia_field: :annuled_at } - it { expect(described_class.trackable_class_settings(model_one)).to eq(paranoia_field: 'annuled_at') } + before :each do + ModelOne.history_settings paranoia_field: :annuled_at + end + it { expect(described_class.trackable_class_settings(ModelOne)).to eq(paranoia_field: 'annuled_at') } end context 'when not present' do - it { expect(described_class.trackable_class_settings(model_one)).to eq(paranoia_field: 'deleted_at') } + it { expect(described_class.trackable_class_settings(ModelOne)).to eq(paranoia_field: 'deleted_at') } end end end diff --git a/spec/unit/my_instance_methods_spec.rb b/spec/unit/my_instance_methods_spec.rb index 8ed1927b..2898c6c1 100644 --- a/spec/unit/my_instance_methods_spec.rb +++ b/spec/unit/my_instance_methods_spec.rb @@ -2,13 +2,16 @@ describe Mongoid::History::Trackable do describe 'MyInstanceMethods' do - before :all do - ModelOne = Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones + field :foo field :b, as: :bar + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one embeds_one :emb_two, store_as: :emt @@ -22,58 +25,68 @@ end end - EmbOne = Class.new do + class EmbOne include Mongoid::Document include Mongoid::History::Trackable + field :f_em_foo field :fmb, as: :f_em_bar + embedded_in :model_one end - EmbTwo = Class.new do + class EmbTwo include Mongoid::Document include Mongoid::History::Trackable + field :baz embedded_in :model_one end - EmbThree = Class.new do + class EmbThree include Mongoid::Document include Mongoid::History::Trackable + field :f_em_foo field :fmb, as: :f_em_bar + embedded_in :model_one end - EmbFour = Class.new do + class EmbFour include Mongoid::Document include Mongoid::History::Trackable + field :baz embedded_in :model_one end + end - ModelOne.track_history(modifier_field_optional: true, on: %i[foo emb_one emb_threes]) - @persisted_history_options = Mongoid::History.trackable_class_options + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + Object.send(:remove_const, :EmbTwo) + Object.send(:remove_const, :EmbThree) + Object.send(:remove_const, :EmbFour) end - before(:each) { Mongoid::History.trackable_class_options = @persisted_history_options } let(:bson_class) { defined?(BSON::ObjectId) ? BSON::ObjectId : Moped::BSON::ObjectId } let(:emb_one) { EmbOne.new(f_em_foo: 'Foo', f_em_bar: 'Bar') } let(:emb_threes) { [EmbThree.new(f_em_foo: 'Foo', f_em_bar: 'Bar')] } - let(:model_one) do - ModelOne.new(foo: 'Foo', - bar: 'Bar', - emb_one: emb_one, - emb_threes: emb_threes) - end + let(:model_one) { ModelOne.new(foo: 'Foo', bar: 'Bar', emb_one: emb_one, emb_threes: emb_threes) } describe '#modified_attributes_for_create' do - before(:each) { ModelOne.clear_trackable_memoization } + before :each do + ModelOne.track_history modifier_field_optional: true, on: %i[foo emb_one emb_threes] + end + subject { model_one.send(:modified_attributes_for_create) } context 'with tracked embeds_one object' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: { emb_one: :f_em_foo }) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: { emb_one: :f_em_foo }) + end it 'should include tracked attributes only' do expect(subject['emb_one'][0]).to be_nil @@ -84,14 +97,18 @@ end context 'with untracked embeds_one object' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :fields) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :fields) + end it 'should not include embeds_one attributes' do expect(subject['emb_one']).to be_nil end end context 'with tracked embeds_many objects' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: { emb_threes: :f_em_foo }) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: { emb_threes: :f_em_foo }) + end it 'should include tracked attributes only' do expect(subject['emb_threes'][0]).to be_nil @@ -102,7 +119,9 @@ end context 'with untracked embeds_many objects' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :fields) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :fields) + end it 'should include not tracked embeds_many attributes' do expect(subject['emb_threes']).to be_nil end @@ -117,29 +136,34 @@ end describe 'embeds_one' do - before(:all) do - Mail = Class.new do + before :each do + class Mail include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :mails field :provider + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :mail_subject else embeds_one :mail_subject, inverse_class_name: 'MailSubject' end + + track_history on: :mail_subject end - MailSubject = Class.new do + class MailSubject include Mongoid::Document + field :content embedded_in :mail end end - before(:each) do - Mail.instance_variable_set(:@history_trackable_options, nil) - Mail.track_history(on: :mail_subject) + after :each do + Object.send(:remove_const, :MailSubject) + Object.send(:remove_const, :Mail) end let(:mail) { Mail.new(mail_subject: mail_subject) } @@ -156,29 +180,30 @@ end context 'when obj not soft-deleted' do - before(:each) { allow(mail_subject).to receive(:deleted_at) { nil } } + before :each do + allow(mail_subject).to receive(:deleted_at) { nil } + end let(:mail_subject) { MailSubject.new(content: 'Content') } it { is_expected.to eq [nil, { '_id' => mail_subject._id, 'content' => 'Content' }] } end context 'when obj soft-deleted' do - before(:each) { allow(mail_subject).to receive(:deleted_at) { Time.now } } + before :each do + allow(mail_subject).to receive(:deleted_at) { Time.now } + end let(:mail_subject) { MailSubject.new(content: 'Content') } it { is_expected.to be_nil } end - - after(:all) do - Object.send(:remove_const, :MailSubject) - Object.send(:remove_const, :Mail) - end end describe 'paranoia' do - before(:all) do - ModelParanoia = Class.new do + before :each do + class ModelParanoia include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_paranoias + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_many :emb_para_ones else @@ -186,20 +211,26 @@ end end - EmbParaOne = Class.new do + class EmbParaOne include Mongoid::Document + field :em_foo field :deleted_at + embedded_in :model_paranoia end end + after :each do + Object.send(:remove_const, :ModelParanoia) + Object.send(:remove_const, :EmbParaOne) + end + let(:emb_para_one) { EmbParaOne.new(em_foo: 'Em-Foo') } let(:model_paranoia) { ModelParanoia.new(emb_para_ones: [emb_para_one]) } context 'when does not respond to paranoia_field' do - before(:each) do - ModelParanoia.instance_variable_set(:@history_trackable_options, nil) + before :each do ModelParanoia.track_history(on: :emb_para_ones) end @@ -214,8 +245,7 @@ end context 'when responds to paranoia_field' do - before(:each) do - ModelParanoia.instance_variable_set(:@history_trackable_options, nil) + before :each do ModelParanoia.track_history(on: :emb_para_ones) allow(emb_para_one).to receive(:deleted_at) { Time.now } allow(emb_para_one_2).to receive(:deleted_at) { nil } @@ -232,18 +262,12 @@ expect(subject['emb_para_ones'][1]).to eq [{ '_id' => emb_para_one_2._id, 'em_foo' => 'Em-Foo-2' }] end end - - after(:all) do - Object.send(:remove_const, :ModelParanoia) - Object.send(:remove_const, :EmbParaOne) - end end end describe '#modified_attributes_for_update' do - before(:each) do + before :each do model_one.save! - ModelOne.clear_trackable_memoization allow(ModelOne).to receive(:dynamic_enabled?) { false } allow(model_one).to receive(:changes) { changes } end @@ -251,80 +275,104 @@ subject { model_one.send(:modified_attributes_for_update) } context 'when embeds_one attributes passed in options' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: { emb_one: :f_em_foo }) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: { emb_one: :f_em_foo }) + end let(:changes) { { 'emb_one' => [{ 'f_em_foo' => 'Foo', 'fmb' => 'Bar' }, { 'f_em_foo' => 'Foo-new', 'fmb' => 'Bar-new' }] } } it { expect(subject['emb_one'][0]).to eq('f_em_foo' => 'Foo') } it { expect(subject['emb_one'][1]).to eq('f_em_foo' => 'Foo-new') } end context 'when embeds_one relation passed in options' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :emb_one) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :emb_one) + end let(:changes) { { 'emb_one' => [{ 'f_em_foo' => 'Foo', 'fmb' => 'Bar' }, { 'f_em_foo' => 'Foo-new', 'fmb' => 'Bar-new' }] } } it { expect(subject['emb_one'][0]).to eq('f_em_foo' => 'Foo', 'fmb' => 'Bar') } it { expect(subject['emb_one'][1]).to eq('f_em_foo' => 'Foo-new', 'fmb' => 'Bar-new') } end context 'when embeds_one relation not tracked' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :fields) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :fields) + end let(:changes) { { 'emb_one' => [{ 'f_em_foo' => 'Foo' }, { 'f_em_foo' => 'Foo-new' }] } } it { expect(subject['emb_one']).to be_nil } end context 'when embeds_many attributes passed in options' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: { emb_threes: :f_em_foo }) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: { emb_threes: :f_em_foo }) + end let(:changes) { { 'emb_threes' => [[{ 'f_em_foo' => 'Foo', 'fmb' => 'Bar' }], [{ 'f_em_foo' => 'Foo-new', 'fmb' => 'Bar-new' }]] } } it { expect(subject['emb_threes']).to eq [[{ 'f_em_foo' => 'Foo' }], [{ 'f_em_foo' => 'Foo-new' }]] } end context 'when embeds_many relation passed in options' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :emb_threes) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :emb_threes) + end let(:changes) { { 'emb_threes' => [[{ 'f_em_foo' => 'Foo', 'fmb' => 'Bar' }], [{ 'f_em_foo' => 'Foo-new', 'fmb' => 'Bar-new' }]] } } it { expect(subject['emb_threes']).to eq [[{ 'f_em_foo' => 'Foo', 'fmb' => 'Bar' }], [{ 'f_em_foo' => 'Foo-new', 'fmb' => 'Bar-new' }]] } end context 'when embeds_many relation not tracked' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :fields) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :fields) + end let(:changes) { { 'emb_threes' => [[{ 'f_em_foo' => 'Foo' }], [{ 'f_em_foo' => 'Foo-new' }]] } } it { expect(subject['emb_threes']).to be_nil } end context 'when field tracked' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :foo) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :foo) + end let(:changes) { { 'foo' => ['Foo', 'Foo-new'], 'b' => ['Bar', 'Bar-new'] } } it { is_expected.to eq('foo' => ['Foo', 'Foo-new']) } end context 'when field not tracked' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: []) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: []) + end let(:changes) { { 'foo' => ['Foo', 'Foo-new'] } } it { is_expected.to eq({}) } end describe 'embeds_one' do - before(:all) do - Email = Class.new do + before :each do + class Email include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :emails field :provider + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :email_subject else embeds_one :email_subject, inverse_class_name: 'EmailSubject' end + + track_history on: :email_subject end - EmailSubject = Class.new do + class EmailSubject include Mongoid::Document include Mongoid::History::Trackable + field :content embedded_in :email_subject end end - before(:each) do - Email.instance_variable_set(:@history_trackable_options, nil) - Email.track_history(on: :email_subject) + after :each do + Object.send(:remove_const, :EmailSubject) + Object.send(:remove_const, :Email) + end + + before :each do allow(Email).to receive(:dynamic_enabled?) { false } allow(email).to receive(:changes) { changes } end @@ -354,91 +402,92 @@ end it { is_expected.to eq [{ 'content' => 'Content' }, { 'content' => 'Content-new' }] } end - - after(:all) do - Object.send(:remove_const, :EmailSubject) - Object.send(:remove_const, :Email) - end end describe 'paranoia_field' do context 'when embeds_one has alias' do - before(:all) do - # Here i need class name constant in trackable.rb. So, not using `let` to define classes - ModelTwo = Class.new do + before :each do + class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_two_one else embeds_one :emb_two_one, inverse_class_name: 'EmbTwoOne' end + + track_history on: :emb_two_one end - EmbTwoOne = Class.new do + class EmbTwoOne include Mongoid::Document include Mongoid::History::Trackable + field :foo field :cncl, as: :cancelled_at + embedded_in :model_two + + history_settings paranoia_field: :cancelled_at end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - ModelTwo.instance_variable_set(:@trackable_settings, nil) - EmbTwoOne.instance_variable_set(:@trackable_settings, nil) - - ModelTwo.track_history on: :emb_two_one - EmbTwoOne.history_settings paranoia_field: :cancelled_at + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmbTwoOne) + end + before :each do allow(ModelTwo).to receive(:dynamic_enabled?) { false } allow(model_two_obj).to receive(:changes) { changes } end let(:model_two_obj) { ModelTwo.new } let(:changes) { { 'emb_two_one' => [{ 'foo' => 'Foo', 'cncl' => Time.now }, { 'foo' => 'Foo-new' }] } } + subject { model_two_obj.send(:modified_attributes_for_update)['emb_two_one'] } it { is_expected.to eq [{}, { 'foo' => 'Foo-new' }] } - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmbTwoOne) - end end context 'when embeds_many has alias' do - before(:all) do - # Here i need class name constant in trackable.rb. So, not using `let` to define classes - ModelTwo = Class.new do + before :each do + class ModelTwo include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_twos + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_many :emb_two_ones else embeds_many :emb_two_ones, inverse_class_name: 'EmbTwoOne' end + + track_history on: :emb_two_ones end - EmbTwoOne = Class.new do + class EmbTwoOne include Mongoid::Document include Mongoid::History::Trackable + field :foo field :cncl, as: :cancelled_at + embedded_in :model_two + + history_settings paranoia_field: :cancelled_at end end - before(:each) do - ModelTwo.instance_variable_set(:@history_trackable_options, nil) - ModelTwo.instance_variable_set(:@trackable_settings, nil) - EmbTwoOne.instance_variable_set(:@trackable_settings, nil) - - ModelTwo.track_history on: :emb_two_ones - EmbTwoOne.history_settings paranoia_field: :cancelled_at + after :each do + Object.send(:remove_const, :ModelTwo) + Object.send(:remove_const, :EmbTwoOne) + end + before :each do allow(ModelTwo).to receive(:dynamic_enabled?) { false } allow(model_two_obj).to receive(:changes) { changes } end @@ -447,25 +496,21 @@ let(:changes) { { 'emb_two_ones' => [[{ 'foo' => 'Foo', 'cncl' => Time.now }], [{ 'foo' => 'Foo-new' }]] } } subject { model_two_obj.send(:modified_attributes_for_update)['emb_two_ones'] } it { is_expected.to eq [[], [{ 'foo' => 'Foo-new' }]] } - - after(:all) do - Object.send(:remove_const, :ModelTwo) - Object.send(:remove_const, :EmbTwoOne) - end end end end describe '#modified_attributes_for_destroy' do - before(:each) do + before :each do allow(ModelOne).to receive(:dynamic_enabled?) { false } model_one.save! - ModelOne.clear_trackable_memoization end subject { model_one.send(:modified_attributes_for_destroy) } context 'with tracked embeds_one object' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: { emb_one: :f_em_foo }) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: { emb_one: :f_em_foo }) + end it 'should include tracked attributes only' do expect(subject['emb_one'][0].keys.size).to eq 2 expect(subject['emb_one'][0]['_id']).to eq emb_one._id @@ -476,14 +521,18 @@ end context 'with untracked embeds_one object' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :fields) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :fields) + end it 'should not include embeds_one attributes' do expect(subject['emb_one']).to be_nil end end context 'with tracked embeds_many objects' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: { emb_threes: :f_em_foo }) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: { emb_threes: :f_em_foo }) + end it 'should include tracked attributes only' do expect(subject['emb_threes'][0][0].keys.count).to eq 2 expect(subject['emb_threes'][0][0]['_id']).to eq emb_threes.first._id @@ -494,19 +543,13 @@ end context 'with untracked embeds_many objects' do - before(:each) { ModelOne.track_history(modifier_field_optional: true, on: :fields) } + before :each do + ModelOne.track_history(modifier_field_optional: true, on: :fields) + end it 'should include not tracked embeds_many attributes' do expect(subject['emb_threes']).to be_nil end end end - - after :all do - Object.send(:remove_const, :ModelOne) - Object.send(:remove_const, :EmbOne) - Object.send(:remove_const, :EmbTwo) - Object.send(:remove_const, :EmbThree) - Object.send(:remove_const, :EmbFour) - end end end diff --git a/spec/unit/options_spec.rb b/spec/unit/options_spec.rb index 814a7712..616e49fd 100644 --- a/spec/unit/options_spec.rb +++ b/spec/unit/options_spec.rb @@ -1,13 +1,16 @@ require 'spec_helper' describe Mongoid::History::Options do - before :all do - ModelOne = Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones + field :foo field :b, as: :bar + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one embeds_one :emb_two, store_as: :emtw @@ -19,36 +22,51 @@ embeds_many :emb_threes, inverse_class_name: 'EmbThree' embeds_many :emb_fours, store_as: :emfs, inverse_class_name: 'EmbFour' end + track_history end - EmbOne = Class.new do + class EmbOne include Mongoid::Document + field :f_em_foo field :fmb, as: :f_em_bar + embedded_in :model_one end - EmbTwo = Class.new do + class EmbTwo include Mongoid::Document + field :f_em_baz embedded_in :model_one end - EmbThree = Class.new do + class EmbThree include Mongoid::Document + field :f_em_foo field :fmb, as: :f_em_bar + embedded_in :model_one end - EmbFour = Class.new do + class EmbFour include Mongoid::Document + field :f_em_baz embedded_in :model_one end end + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + Object.send(:remove_const, :EmbTwo) + Object.send(:remove_const, :EmbThree) + Object.send(:remove_const, :EmbFour) + end + let(:options) { {} } let(:service) { described_class.new(ModelOne, options) } @@ -68,7 +86,8 @@ describe '#parse' do describe '#default_options' do let(:expected_options) do - { on: :all, + { + on: :all, except: %i[created_at updated_at], tracker_class_name: nil, modifier_field: :modifier, @@ -78,7 +97,8 @@ track_create: true, track_update: true, track_destroy: true, - format: nil } + format: nil + } end it { expect(service.send(:default_options)).to eq expected_options } end @@ -136,7 +156,8 @@ describe '#parse_tracked_fields_and_relations' do context 'when options not passed' do let(:expected_options) do - { on: %i[foo b], + { + on: %i[foo b], except: %w[created_at updated_at], tracker_class_name: nil, modifier_field: :modifier, @@ -149,7 +170,8 @@ fields: %w[foo b], dynamic: [], relations: { embeds_one: {}, embeds_many: {} }, - format: {} } + format: {} + } end it { expect(service.prepared).to eq expected_options } end @@ -266,10 +288,12 @@ context 'with relations' do let(:options) { { on: :embedded_relations } } it do - expect(subject[:relations]).to eq(embeds_many: { 'emb_threes' => %w[_id f_em_foo fmb], - 'emfs' => %w[_id f_em_baz] }, - embeds_one: { 'emb_one' => %w[_id f_em_foo fmb], - 'emtw' => %w[_id f_em_baz] }) + expect(subject[:relations]).to eq( + embeds_many: { 'emb_threes' => %w[_id f_em_foo fmb], + 'emfs' => %w[_id f_em_baz] }, + embeds_one: { 'emb_one' => %w[_id f_em_foo fmb], + 'emtw' => %w[_id f_em_baz] } + ) end end end @@ -323,12 +347,4 @@ end end end - - after :all do - Object.send(:remove_const, :ModelOne) - Object.send(:remove_const, :EmbOne) - Object.send(:remove_const, :EmbTwo) - Object.send(:remove_const, :EmbThree) - Object.send(:remove_const, :EmbFour) - end end diff --git a/spec/unit/singleton_methods_spec.rb b/spec/unit/singleton_methods_spec.rb index 4b07877e..74be0ab8 100644 --- a/spec/unit/singleton_methods_spec.rb +++ b/spec/unit/singleton_methods_spec.rb @@ -2,12 +2,14 @@ describe Mongoid::History::Trackable do describe 'SingletonMethods' do - before :all do - MyTrackableModel = Class.new do + before :each do + class MyTrackableModel include Mongoid::Document include Mongoid::History::Trackable + field :foo field :b, as: :bar + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :my_embed_one_model embeds_one :my_untracked_embed_one_model @@ -17,27 +19,37 @@ embeds_one :my_untracked_embed_one_model, inverse_class_name: 'MyUntrackedEmbedOneModel' embeds_many :my_embed_many_models, inverse_class_name: 'MyEmbedManyModel' end + + track_history on: %i[foo my_embed_one_model my_embed_many_models my_dynamic_field] end - MyEmbedOneModel = Class.new do + class MyEmbedOneModel include Mongoid::Document + field :baz embedded_in :my_trackable_model end - MyUntrackedEmbedOneModel = Class.new do + class MyUntrackedEmbedOneModel include Mongoid::Document + field :baz embedded_in :my_trackable_model end - MyEmbedManyModel = Class.new do + class MyEmbedManyModel include Mongoid::Document + field :bla embedded_in :my_trackable_model end + end - MyTrackableModel.track_history(on: %i[foo my_embed_one_model my_embed_many_models my_dynamic_field]) + after :each do + Object.send(:remove_const, :MyTrackableModel) + Object.send(:remove_const, :MyEmbedOneModel) + Object.send(:remove_const, :MyUntrackedEmbedOneModel) + Object.send(:remove_const, :MyEmbedManyModel) end describe '#tracked?' do @@ -51,97 +63,116 @@ end describe '#dynamic_field?' do - before(:all) do + before :each do class EmbOne include Mongoid::Document + embedded_in :my_model end end + after :each do + Object.send(:remove_const, :EmbOne) + end + context 'when dynamic enabled' do context 'with embeds one relation' do - let(:my_model) do - Class.new do + before :each do + class MyModel include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :my_models + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one else embeds_one :emb_one, inverse_class_name: 'EmbOne' end + track_history end end + after :each do + Object.send(:remove_const, :MyModel) + end + it 'should track dynamic field' do - # Using `let` to define class and use that class inside `before` block to stub a method raises following error. - # RuntimeError: - # let declaration `my_model` accessed in a `before(:context)` hook at: - # /Users/vmc/projects/mongoid-history/spec/unit/singleton_methods_spec.rb:51:in `block (6 levels) in ' - # - # `let` and `subject` declarations are not intended to be called - # in a `before(:context)` hook, as they exist to define state that - # is reset between each example, while `before(:context)` exists to - # define state that is shared across examples in an example group. - allow(my_model).to receive(:dynamic_enabled?) { true } - expect(my_model.dynamic_field?(:foo)).to be true + allow(MyModel).to receive(:dynamic_enabled?) { true } + expect(MyModel.dynamic_field?(:foo)).to be true end it 'should not track embeds_one relation' do - allow(my_model).to receive(:dynamic_enabled?) { true } - expect(my_model.dynamic_field?(:emb_one)).to be false + allow(MyModel).to receive(:dynamic_enabled?) { true } + expect(MyModel.dynamic_field?(:emb_one)).to be false end end context 'with embeds one relation and alias' do - let(:my_model) do - Class.new do + before :each do + class MyModel include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :my_models + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one, store_as: :emo else embeds_one :emb_one, inverse_class_name: 'EmbOne', store_as: :emo end + track_history end end + after :each do + Object.send(:remove_const, :MyModel) + end + it 'should not track embeds_one relation' do - allow(my_model).to receive(:dynamic_enabled?) { true } - expect(my_model.dynamic_field?(:emo)).to be false + allow(MyModel).to receive(:dynamic_enabled?) { true } + expect(MyModel.dynamic_field?(:emo)).to be false end end context 'with embeds many relation' do - let(:my_model) do - Class.new do + before :each do + class MyModel include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :my_models + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_many :emb_ones else embeds_many :emb_ones, inverse_class_name: 'EmbOne' end + track_history end end + after :each do + Object.send(:remove_const, :MyModel) + end + it 'should not track embeds_many relation' do - allow(my_model).to receive(:dynamic_enabled?) { true } - expect(my_model.dynamic_field?(:emb_ones)).to be false + allow(MyModel).to receive(:dynamic_enabled?) { true } + expect(MyModel.dynamic_field?(:emb_ones)).to be false end end context 'with embeds many relation and alias' do - let(:my_model) do - Class.new do + before :each do + class MyModel include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :my_models + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_many :emb_ones, store_as: :emos else @@ -151,16 +182,16 @@ class EmbOne end end + after :each do + Object.send(:remove_const, :MyModel) + end + it 'should not track embeds_many relation' do - allow(my_model).to receive(:dynamic_enabled?) { true } - expect(my_model.dynamic_field?(:emos)).to be false + allow(MyModel).to receive(:dynamic_enabled?) { true } + expect(MyModel.dynamic_field?(:emos)).to be false end end end - - after(:all) do - Object.send(:remove_const, :EmbOne) - end end describe '#tracked_fields' do @@ -189,10 +220,11 @@ class EmbOne end describe '#tracked_embeds_one_attributes' do - before(:all) do - ModelOne = Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_one :emb_one embeds_one :emb_two, store_as: :emt @@ -204,26 +236,36 @@ class EmbOne end end - EmbOne = Class.new do + class EmbOne include Mongoid::Document + field :em_foo field :em_bar + embedded_in :model_one end - EmbTwo = Class.new do + class EmbTwo include Mongoid::Document + field :em_bar embedded_in :model_one end - EmbThree = Class.new do + class EmbThree include Mongoid::Document + field :em_baz embedded_in :model_one end end - before(:each) { ModelOne.instance_variable_set(:@history_trackable_options, nil) } + + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + Object.send(:remove_const, :EmbTwo) + Object.send(:remove_const, :EmbThree) + end context 'when relation tracked' do before(:each) { ModelOne.track_history(on: :emb_one) } @@ -244,13 +286,6 @@ class EmbOne before(:each) { ModelOne.track_history(on: :fields) } it { expect(ModelOne.tracked_embeds_one_attributes('emb_one')).to be_nil } end - - after(:all) do - Object.send(:remove_const, :ModelOne) - Object.send(:remove_const, :EmbOne) - Object.send(:remove_const, :EmbTwo) - Object.send(:remove_const, :EmbThree) - end end describe '#tracked_embeds_many?' do @@ -264,10 +299,11 @@ class EmbOne end describe '#tracked_embeds_many_attributes' do - before(:all) do - ModelOne = Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_many :emb_ones embeds_many :emb_twos, store_as: :emts @@ -279,26 +315,36 @@ class EmbOne end end - EmbOne = Class.new do + class EmbOne include Mongoid::Document + field :em_foo field :em_bar + embedded_in :model_one end - EmbTwo = Class.new do + class EmbTwo include Mongoid::Document + field :em_bar embedded_in :model_one end - EmbThree = Class.new do + class EmbThree include Mongoid::Document + field :em_baz embedded_in :model_one end end - before(:each) { ModelOne.instance_variable_set(:@history_trackable_options, nil) } + + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + Object.send(:remove_const, :EmbTwo) + Object.send(:remove_const, :EmbThree) + end context 'when relation tracked' do before(:each) { ModelOne.track_history(on: :emb_ones) } @@ -319,30 +365,25 @@ class EmbOne before(:each) { ModelOne.track_history(on: :fields) } it { expect(ModelOne.tracked_embeds_many_attributes('emb_ones')).to be_nil } end - - after(:all) do - Object.send(:remove_const, :ModelOne) - Object.send(:remove_const, :EmbOne) - Object.send(:remove_const, :EmbTwo) - Object.send(:remove_const, :EmbThree) - end end describe '#trackable_scope' do - let(:model_one) do - Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones + track_history end end - it { expect(model_one.trackable_scope).to eq(:model_one) } + it { expect(ModelOne.trackable_scope).to eq(:model_one) } end describe '#clear_trackable_memoization' do - before do + before :each do MyTrackableModel.instance_variable_set(:@reserved_tracked_fields, %w[_id _type]) MyTrackableModel.instance_variable_set(:@history_trackable_options, on: %w[fields]) MyTrackableModel.instance_variable_set(:@trackable_settings, paranoia_field: 'deleted_at') @@ -361,12 +402,5 @@ class EmbOne expect(MyTrackableModel.instance_variable_get(:@tracked_embeds_many)).to be_nil end end - - after :all do - Object.send(:remove_const, :MyTrackableModel) - Object.send(:remove_const, :MyEmbedOneModel) - Object.send(:remove_const, :MyUntrackedEmbedOneModel) - Object.send(:remove_const, :MyEmbedManyModel) - end end end diff --git a/spec/unit/trackable_spec.rb b/spec/unit/trackable_spec.rb index b687957e..175a8666 100644 --- a/spec/unit/trackable_spec.rb +++ b/spec/unit/trackable_spec.rb @@ -1,10 +1,11 @@ require 'spec_helper' describe Mongoid::History::Trackable do - before :all do + before :each do class MyModel include Mongoid::Document include Mongoid::History::Trackable + field :foo end @@ -23,7 +24,7 @@ class User end end - after :all do + after :each do Object.send(:remove_const, :MyModel) Object.send(:remove_const, :MyDynamicModel) Object.send(:remove_const, :HistoryTracker) @@ -43,20 +44,27 @@ class User end describe '#track_history' do - class MyModelWithNoModifier - include Mongoid::Document - include Mongoid::History::Trackable - field :foo + before :each do + class MyModelWithNoModifier + include Mongoid::Document + include Mongoid::History::Trackable + + field :foo + end end - before :all do + after :each do + Object.send(:remove_const, :MyModelWithNoModifier) + end + + before :each 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 - { on: %i[foo], + { + on: %i[foo], except: %w[created_at updated_at], tracker_class_name: nil, modifier_field: :modifier, @@ -69,8 +77,10 @@ class MyModelWithNoModifier fields: %w[foo], relations: { embeds_one: {}, embeds_many: {} }, dynamic: [], - format: {} } + format: {} + } end + let(:regular_fields) { ['foo'] } let(:reserved_fields) { %w[_id version modifier_id] } @@ -102,10 +112,17 @@ class MyModelWithNoModifier end context 'modifier_field_optional true' do - class MyModelWithOptionalModifier - include Mongoid::Document - include Mongoid::History::Trackable - field :foo + before :each do + class MyModelWithOptionalModifier + include Mongoid::Document + include Mongoid::History::Trackable + + field :foo + end + end + + after :each do + Object.send(:remove_const, :MyModelWithOptionalModifier) end it 'marks modifier relationship optional' do @@ -206,14 +223,19 @@ class MyNonDatabaseModel end describe '#field_format' do - before :all do - ModelOne = Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + field :foo end end + after :each do + Object.send(:remove_const, :ModelOne) + end + let(:format) { '***' } before do @@ -231,10 +253,6 @@ class MyNonDatabaseModel expect(ModelOne.field_format(:bar)).to be_nil end end - - after :all do - Object.send(:remove_const, :ModelOne) - end end context 'sub-model' do @@ -243,6 +261,10 @@ class MySubModel < MyModel end end + after :each do + Object.send(:remove_const, :MySubModel) + end + it 'should have default options' do expect(Mongoid::History.trackable_class_options[:my_model].prepared).to eq(expected_option) end @@ -278,16 +300,25 @@ class MySubModel < MyModel expect(MyModel.new.track_history?).to eq(true) end - it 'should be disabled only for the class that calls disable_tracking' do - class MyModel2 - include Mongoid::Document - include Mongoid::History::Trackable - track_history + context 'with multiple classes' do + before :each do + class MyModel2 + include Mongoid::Document + include Mongoid::History::Trackable + + track_history + end end - MyModel.disable_tracking do - expect(Mongoid::History.enabled?).to eq(true) - expect(MyModel2.new.track_history?).to eq(true) + after :each do + Object.send(:remove_const, :MyModel2) + end + + it 'should be disabled only for the class that calls disable_tracking' do + MyModel.disable_tracking do + expect(Mongoid::History.enabled?).to eq(true) + expect(MyModel2.new.track_history?).to eq(true) + end end end end @@ -322,17 +353,26 @@ class MyModel2 end end - it 'should be disabled only for the class that calls disable_tracking' do - class MyModel2 - include Mongoid::Document - include Mongoid::History::Trackable - track_history + context 'with multiple classes' do + before :each do + class MyModel2 + include Mongoid::Document + include Mongoid::History::Trackable + + track_history + end end - Mongoid::History.disable do - MyModel.disable_tracking do - expect(Mongoid::History.enabled?).to eq(false) - expect(MyModel2.new.track_history?).to eq(false) + after :each do + Object.send(:remove_const, :MyModel2) + end + + it 'should be disabled only for the class that calls disable_tracking' do + Mongoid::History.disable do + MyModel.disable_tracking do + expect(Mongoid::History.enabled?).to eq(false) + expect(MyModel2.new.track_history?).to eq(false) + end end end end @@ -363,48 +403,74 @@ class MyModel2 end describe ':changes_method' do - let(:custom_tracker) do - CustomTracker = Class.new(MyModel) do - field :key + it 'should be set in parent class' do + expect(MyModel.history_trackable_options[:changes_method]).to eq :changes + end + + context 'subclass' do + before :each do + # BUGBUG: if this is not prepared, it inherits the subclass settings + MyModel.history_trackable_options - track_history on: :key, changes_method: :my_changes, track_create: true + class CustomTracker < MyModel + field :key - def my_changes - changes.merge('key' => "Save history-#{key}") + track_history on: :key, changes_method: :my_changes, track_create: true + + def my_changes + changes.merge('key' => "Save history-#{key}") + end end end - end - it 'should default to :changes' do - m = MyModel.create!(modifier: user) - expect(m).to receive(:changes).exactly(3).times.and_call_original - expect(m).not_to receive(:my_changes) - m.save - end + after :each do + Object.send(:remove_const, :CustomTracker) + end - it 'should allow an alternate method to be specified' do - class MyModel3 < MyModel - track_history changes_method: :my_changes + it 'should not override in parent class' do + expect(MyModel.history_trackable_options[:changes_method]).to eq :changes + expect(CustomTracker.history_trackable_options[:changes_method]).to eq :my_changes + end - def my_changes - {} - end + it 'should default to :changes' do + m = MyModel.create!(modifier: user) + expect(m).to receive(:changes).exactly(3).times.and_call_original + expect(m).not_to receive(:my_changes) + m.save! end - m = MyModel3.create!(modifier: user) - expect(m).to receive(:changes).twice.and_call_original - expect(m).to receive(:my_changes).once.and_call_original - m.save - end + context 'with another model' do + before :each do + class MyModel3 < MyModel + track_history changes_method: :my_changes - it 'should allow an alternate method to be specified on object creation' do - m = if Mongoid::Compatibility::Version.mongoid7_or_newer? # BUGBUG - custom_tracker.create!(key: 'on object creation', modifier: user) - else - custom_tracker.create!(key: 'on object creation') + def my_changes + {} + end end - history_track = m.history_tracks.last - expect(history_track.modified['key']).to eq('Save history-on object creation') + end + + after :each do + Object.send(:remove_const, :MyModel3) + end + + it 'should allow an alternate method to be specified' do + m = MyModel3.create!(modifier: user) + expect(m).to receive(:changes).twice.and_call_original + expect(m).to receive(:my_changes).once.and_call_original + m.save + end + end + + it 'should allow an alternate method to be specified on object creation' do + m = if Mongoid::Compatibility::Version.mongoid7_or_newer? # BUGBUG + CustomTracker.create!(key: 'on object creation', modifier: user) + else + CustomTracker.create!(key: 'on object creation') + end + history_track = m.history_tracks.last + expect(history_track.modified['key']).to eq('Save history-on object creation') + end end end end @@ -412,10 +478,11 @@ def my_changes describe '#history_settings' do before(:each) { Mongoid::History.trackable_settings = nil } - let(:model_one) do - Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones if Mongoid::Compatibility::Version.mongoid7_or_newer? @@ -425,44 +492,36 @@ def my_changes embeds_one :emb_one, inverse_class_name: 'EmbOne' embeds_many :emb_twos, inverse_class_name: 'EmbTwo' end - - def self.name - 'ModelOne' - end end - end - let(:emb_one) do - Class.new do + class EmbOne include Mongoid::Document include Mongoid::History::Trackable - embedded_in :model_one - def self.name - 'EmbOne' - end + embedded_in :model_one end - end - let(:emb_two) do - Class.new do + class EmbTwo include Mongoid::Document include Mongoid::History::Trackable - embedded_in :model_one - def self.name - 'EmbTwo' - end + embedded_in :model_one end end + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + Object.send(:remove_const, :EmbTwo) + end + let(:default_options) { { paranoia_field: 'deleted_at' } } context 'when options not passed' do before(:each) do - model_one.history_settings - emb_one.history_settings - emb_two.history_settings + ModelOne.history_settings + EmbOne.history_settings + EmbTwo.history_settings end it 'should use default options' do @@ -474,9 +533,9 @@ def self.name context 'when extra invalid options passed' do before(:each) do - model_one.history_settings foo: :bar - emb_one.history_settings em_foo: :em_bar - emb_two.history_settings em_foo: :em_baz + ModelOne.history_settings foo: :bar + EmbOne.history_settings em_foo: :em_bar + EmbTwo.history_settings em_foo: :em_baz end it 'should ignore invalid options' do @@ -488,9 +547,9 @@ def self.name context 'when valid options passed' do before(:each) do - model_one.history_settings paranoia_field: :disabled_at - emb_one.history_settings paranoia_field: :deactivated_at - emb_two.history_settings paranoia_field: :omitted_at + ModelOne.history_settings paranoia_field: :disabled_at + EmbOne.history_settings paranoia_field: :deactivated_at + EmbTwo.history_settings paranoia_field: :omitted_at end it 'should override default options' do @@ -501,7 +560,7 @@ def self.name end context 'when string keys' do - before(:each) { model_one.history_settings 'paranoia_field' => 'erased_at' } + before(:each) { ModelOne.history_settings 'paranoia_field' => 'erased_at' } it 'should convert option keys to symbols' do expect(Mongoid::History.trackable_settings[:ModelOne]).to eq(paranoia_field: 'erased_at') @@ -509,33 +568,36 @@ def self.name end context 'when paranoia field has alias' do - before(:each) do - Mongoid::History.trackable_settings = nil - model_two.history_settings paranoia_field: :neglected_at - end - - let(:model_two) do - Class.new do + before :each do + class ModelTwo include Mongoid::Document include Mongoid::History::Trackable - field :nglt, as: :neglected_at - def self.name - 'ModelTwo' - end + field :nglt, as: :neglected_at end end + after :each do + Object.send(:remove_const, :ModelTwo) + end + + before :each do + ModelTwo.history_settings paranoia_field: :neglected_at + end + it { expect(Mongoid::History.trackable_settings[:ModelTwo]).to eq(paranoia_field: 'nglt') } end end describe '#tracker_class' do - before :all do - MyTrackerClass = Class.new + before :each do + class MyTrackerClass + end end - before { MyModel.instance_variable_set(:@history_trackable_options, nil) } + after :each do + Object.send(:remove_const, :MyTrackerClass) + end context 'when options contain tracker_class_name' do context 'when underscored' do @@ -555,12 +617,14 @@ def self.name end describe '#modified_attributes_for_update' do - before(:all) do - ModelOne = Class.new do + before :each do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones field :foo + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_many :emb_ones else @@ -568,19 +632,22 @@ def self.name end end - EmbOne = Class.new do + class EmbOne include Mongoid::Document include Mongoid::History::Trackable + field :em_foo embedded_in :model_one end end - before(:each) do + after :each do + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + end + + before :each do model_one.save! - ModelOne.instance_variable_set(:@history_trackable_options, nil) - ModelOne.instance_variable_set(:@trackable_settings, nil) - EmbOne.instance_variable_set(:@trackable_settings, nil) end let(:model_one) { ModelOne.new(foo: 'Foo') } @@ -626,38 +693,28 @@ def self.name describe 'fields' do context 'when custom method for changes' do before(:each) do - ModelOne.clear_trackable_memoization ModelOne.track_history(on: :foo, changes_method: :my_changes_method) allow(ModelOne).to receive(:dynamic_enabled?) { false } allow(model_one).to receive(:my_changes_method) { changes } end + let(:changes) { { 'foo' => ['Foo', 'Foo-new'], 'bar' => ['Bar', 'Bar-new'] } } it { is_expected.to eq('foo' => ['Foo', 'Foo-new']) } end end - - after(:all) do - Object.send(:remove_const, :ModelOne) - Object.send(:remove_const, :EmbOne) - end end context 'when options not contain tracker_class_name' do before { MyModel.track_history } it { expect(MyModel.tracker_class).to eq Tracker } end - - after :all do - Object.send(:remove_const, :MyTrackerClass) - end end describe '#track_update' do - before :all do + before :each do MyModel.track_history(on: :foo, track_update: true) - @persisted_history_options = Mongoid::History.trackable_class_options end - before(:each) { Mongoid::History.trackable_class_options = @persisted_history_options } + let!(:m) { MyModel.create!(foo: 'bar', modifier: user) } it 'should create history' do @@ -673,11 +730,10 @@ def self.name end describe '#track_destroy' do - before :all do + before :each do MyModel.track_history(on: :foo, track_destroy: true) - @persisted_history_options = Mongoid::History.trackable_class_options end - before(:each) { Mongoid::History.trackable_class_options = @persisted_history_options } + let!(:m) { MyModel.create!(foo: 'bar', modifier: user) } it 'should create history' do @@ -693,12 +749,23 @@ def self.name end describe '#track_create' do - before :all do + before :each do + class MyModelWithNoModifier + include Mongoid::Document + include Mongoid::History::Trackable + + field :foo + end + end + + after :each do + Object.send(:remove_const, :MyModelWithNoModifier) + end + + before :each 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', modifier: user) }.to change(Tracker, :count).by(1) diff --git a/spec/unit/tracker_spec.rb b/spec/unit/tracker_spec.rb index c27d55d8..0139f3af 100644 --- a/spec/unit/tracker_spec.rb +++ b/spec/unit/tracker_spec.rb @@ -1,41 +1,42 @@ require 'spec_helper' describe Mongoid::History::Tracker do - before do - @tracker_class_name = Mongoid::History.tracker_class_name - Mongoid::History.tracker_class_name = nil - end + context 'when included' do + before :each do + Mongoid::History.tracker_class_name = nil - it 'should set tracker_class_name when included' do - class MyTracker - include Mongoid::History::Tracker + class MyTracker + include Mongoid::History::Tracker + end + end + + after :each do + Object.send(:remove_const, :MyTracker) + end + + it 'should set tracker_class_name when included' do + expect(Mongoid::History.tracker_class_name).to eq(:my_tracker) end - expect(Mongoid::History.tracker_class_name).to eq(:my_tracker) - end - it 'should set fields defaults' do - class MyTrackerTwo - include Mongoid::History::Tracker + it 'should set fields defaults' do + expect(MyTracker.new.association_chain).to eq([]) + expect(MyTracker.new.original).to eq({}) + expect(MyTracker.new.modified).to eq({}) end - expect(MyTrackerTwo.new.association_chain).to eq([]) - expect(MyTrackerTwo.new.original).to eq({}) - expect(MyTrackerTwo.new.modified).to eq({}) end describe '#tracked_edits' do - before(:all) do - TrackerOne = Class.new do - def self.name - 'TrackerOne' - end - + before :each do + class TrackerOne include Mongoid::History::Tracker end - ModelOne = Class.new do + class ModelOne include Mongoid::Document include Mongoid::History::Trackable + store_in collection: :model_ones + if Mongoid::Compatibility::Version.mongoid7_or_newer? embeds_many :emb_ones else @@ -43,16 +44,22 @@ def self.name end end - EmbOne = Class.new do + class EmbOne include Mongoid::Document + field :em_foo embedded_in :model_one end end + after :each do + Object.send(:remove_const, :TrackerOne) + Object.send(:remove_const, :ModelOne) + Object.send(:remove_const, :EmbOne) + end + context 'when embeds_many' do - before(:each) do - ModelOne.instance_variable_set(:@history_trackable_options, nil) + before :each do ModelOne.track_history(on: :emb_ones) allow(tracker).to receive(:trackable_parent_class) { ModelOne } end @@ -60,23 +67,29 @@ def self.name let(:tracker) { TrackerOne.new } describe '#prepare_tracked_edits_for_embeds_many' do - before(:each) do - tracker.instance_variable_set(:@tracked_edits, nil) + before :each do allow(tracker).to receive(:tracked_changes) { changes } end + let(:emb_one) { EmbOne.new } let(:emb_one_2) { EmbOne.new } let(:emb_one_3) { EmbOne.new } let(:changes) { {} } + subject { tracker.tracked_edits['embeds_many']['emb_ones'] } context 'when all values present' do let(:changes) do - { 'emb_ones' => { from: [{ '_id' => emb_one._id, 'em_foo' => 'Em-Foo' }, - { '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }], - to: [{ '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2-new' }, - { '_id' => emb_one_3._id, 'em_foo' => 'Em-Foo-3' }] } } + { + 'emb_ones' => { + from: [{ '_id' => emb_one._id, 'em_foo' => 'Em-Foo' }, + { '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }], + to: [{ '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2-new' }, + { '_id' => emb_one_3._id, 'em_foo' => 'Em-Foo-3' }] + } + } end + it 'should include :add, :remove, and :modify' do expect(subject['add']).to eq [{ '_id' => emb_one_3._id, 'em_foo' => 'Em-Foo-3' }] expect(subject['remove']).to eq [{ '_id' => emb_one._id, 'em_foo' => 'Em-Foo' }] @@ -88,8 +101,12 @@ def self.name context 'when value :from blank' do let(:changes) do - { 'emb_ones' => { to: [{ '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2-new' }, - { '_id' => emb_one_3._id, 'em_foo' => 'Em-Foo-3' }] } } + { + 'emb_ones' => { + to: [{ '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2-new' }, + { '_id' => emb_one_3._id, 'em_foo' => 'Em-Foo-3' }] + } + } end it 'should include :add' do expect(subject['add'].size).to eq 2 @@ -102,8 +119,12 @@ def self.name context 'when value :to blank' do let(:changes) do - { 'emb_ones' => { from: [{ '_id' => emb_one._id, 'em_foo' => 'Em-Foo' }, - { '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }] } } + { + 'emb_ones' => { + from: [{ '_id' => emb_one._id, 'em_foo' => 'Em-Foo' }, + { '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }] + } + } end it 'should include :remove' do expect(subject['add']).to be_nil @@ -116,8 +137,12 @@ def self.name context 'when no id common in :from and :to' do let(:changes) do - { 'emb_ones' => { from: [{ '_id' => emb_one._id, 'em_foo' => 'Em-Foo' }], - to: [{ '_id' => emb_one_3._id, 'em_foo' => 'Em-Foo-3' }] } } + { + 'emb_ones' => { + from: [{ '_id' => emb_one._id, 'em_foo' => 'Em-Foo' }], + to: [{ '_id' => emb_one_3._id, 'em_foo' => 'Em-Foo-3' }] + } + } end it 'should include :add, and :remove' do expect(subject['add']).to eq [{ '_id' => emb_one_3._id, 'em_foo' => 'Em-Foo-3' }] @@ -128,10 +153,14 @@ def self.name context 'when _id attribute not set' do let(:changes) do - { 'emb_ones' => { from: [{ 'em_foo' => 'Em-Foo' }, - { '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }], - to: [{ 'em_foo' => 'Em-Foo-2-new' }, - { 'em_foo' => 'Em-Foo-3' }] } } + { + 'emb_ones' => { + from: [{ 'em_foo' => 'Em-Foo' }, + { '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }], + to: [{ 'em_foo' => 'Em-Foo-2-new' }, + { 'em_foo' => 'Em-Foo-3' }] + } + } end it 'should include :add, and :remove' do expect(subject['add']).to eq([{ 'em_foo' => 'Em-Foo-2-new' }, { 'em_foo' => 'Em-Foo-3' }]) @@ -142,8 +171,12 @@ def self.name context 'when no change in an object' do let(:changes) do - { 'emb_ones' => { from: [{ '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }], - to: [{ '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }] } } + { + 'emb_ones' => { + from: [{ '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }], + to: [{ '_id' => emb_one_2._id, 'em_foo' => 'Em-Foo-2' }] + } + } end it 'should include not :add, :remove, and :modify' do expect(subject['add']).to be_nil @@ -153,15 +186,5 @@ def self.name end end end - - after(:all) do - Object.send(:remove_const, :TrackerOne) - Object.send(:remove_const, :ModelOne) - Object.send(:remove_const, :EmbOne) - end - end - - after do - Mongoid::History.tracker_class_name = @tracker_class_name end end