From f0de1cf0965bb8d55334aa3ca34cee21b6b3f5dc Mon Sep 17 00:00:00 2001 From: Vadim Lazebny Date: Sat, 1 Apr 2017 12:17:27 +0300 Subject: [PATCH] PaperTrail + Inheritance --- .../paper_trail/auditing_adapter.rb | 19 +- .../paper_trail_test/subclass_in_namespace.rb | 4 + .../paper_trail_test_subclass.rb | 2 + spec/factories.rb | 8 + .../history/rails_admin_paper_trail_spec.rb | 200 +++++++++++------- 5 files changed, 149 insertions(+), 84 deletions(-) create mode 100644 spec/dummy_app/app/active_record/paper_trail_test/subclass_in_namespace.rb create mode 100644 spec/dummy_app/app/active_record/paper_trail_test_subclass.rb diff --git a/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb b/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb index c1e15231f1..a17338ff63 100644 --- a/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +++ b/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb @@ -97,12 +97,9 @@ def listing_for_model_or_object(model, object, query, sort, sort_reverse, all, p sort_reverse = 'true' end - model_name = model.model.name - current_page = page.presence || '1' - versions = version_class_for(model_name).where item_type: model_name - versions = versions.where item_id: object.id if object + versions = object.nil? ? versions_for_model(model) : object.versions versions = versions.where('event LIKE ?', "%#{query}%") if query.present? versions = versions.order(sort_reverse == 'true' ? "#{sort} DESC" : sort) versions = all ? versions : versions.send(Kaminari.config.page_method_name, current_page).per(per_page) @@ -114,6 +111,20 @@ def listing_for_model_or_object(model, object, query, sort, sort_reverse, all, p paginated_proxies end + def versions_for_model(model) + model_name = model.model.name + base_class_name = model.model.base_class.name + + options = + if base_class_name == model_name + {item_type: model_name} + else + {item_type: base_class_name, item_id: model.model.all} + end + + version_class_for(model_name).where(options) + end + def version_class_for(model_name) klass = model_name.constantize. try(:version_class_name). diff --git a/spec/dummy_app/app/active_record/paper_trail_test/subclass_in_namespace.rb b/spec/dummy_app/app/active_record/paper_trail_test/subclass_in_namespace.rb new file mode 100644 index 0000000000..15d8d28403 --- /dev/null +++ b/spec/dummy_app/app/active_record/paper_trail_test/subclass_in_namespace.rb @@ -0,0 +1,4 @@ +class PaperTrailTest < ActiveRecord::Base + class SubclassInNamespace < self + end +end diff --git a/spec/dummy_app/app/active_record/paper_trail_test_subclass.rb b/spec/dummy_app/app/active_record/paper_trail_test_subclass.rb new file mode 100644 index 0000000000..790dba3d9d --- /dev/null +++ b/spec/dummy_app/app/active_record/paper_trail_test_subclass.rb @@ -0,0 +1,2 @@ +class PaperTrailTestSubclass < PaperTrailTest +end diff --git a/spec/factories.rb b/spec/factories.rb index dff9a23a33..edb3506873 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -81,5 +81,13 @@ factory :paper_trail_test do sequence(:name) { |n| "name #{n}" } + + factory :paper_trail_test_subclass, + parent: :paper_trail_test, + class: 'PaperTrailTestSubclass' + + factory :paper_trail_test_subclass_in_namespace, + parent: :paper_trail_test, + class: 'PaperTrailTest::SubclassInNamespace' end end diff --git a/spec/integration/history/rails_admin_paper_trail_spec.rb b/spec/integration/history/rails_admin_paper_trail_spec.rb index 9d42c099a5..994412bea9 100644 --- a/spec/integration/history/rails_admin_paper_trail_spec.rb +++ b/spec/integration/history/rails_admin_paper_trail_spec.rb @@ -15,115 +15,155 @@ end end - describe 'on object creation', type: :request do - subject { page } - before do - @user = FactoryGirl.create :user - RailsAdmin::Config.authenticate_with { warden.authenticate! scope: :user } - RailsAdmin::Config.current_user_method(&:current_user) - login_as @user - with_versioning do - visit new_path(model_name: 'paper_trail_test') - fill_in 'paper_trail_test[name]', with: 'Jackie Robinson' - click_button 'Save' - @object = RailsAdmin::AbstractModel.new('PaperTrailTest').first + shared_examples :paper_on_object_creation do + describe 'on object creation', type: :request do + subject { page } + before do + @user = FactoryGirl.create :user + RailsAdmin::Config.authenticate_with { warden.authenticate! scope: :user } + RailsAdmin::Config.current_user_method(&:current_user) + login_as @user + with_versioning do + visit new_path(model_name: paper_model_name) + fill_in paper_field_name, with: 'Jackie Robinson' + click_button 'Save' + @object = RailsAdmin::AbstractModel.new(paper_class_name).first + end end - end - it 'records a version' do - expect(@object.versions.size).to eq 1 - expect(@object.versions.first.whodunnit).to eq @user.id.to_s + it 'records a version' do + expect(@object.versions.size).to eq 1 + expect(@object.versions.first.whodunnit).to eq @user.id.to_s + end end end - describe 'model history fetch' do - before(:each) do - PaperTrail::Version.delete_all - @model = RailsAdmin::AbstractModel.new('PaperTrailTest') - @user = FactoryGirl.create :user - @paper_trail_test = FactoryGirl.create :paper_trail_test - with_versioning do - PaperTrail.whodunnit = @user.id - 30.times do |i| - @paper_trail_test.update!(name: "updated name #{i}") + shared_examples :paper_history do + describe 'model history fetch' do + before(:each) do + PaperTrail::Version.delete_all + @model = RailsAdmin::AbstractModel.new(paper_class_name) + @user = FactoryGirl.create :user + @paper_trail_test = FactoryGirl.create(paper_factory) + with_versioning do + PaperTrail.whodunnit = @user.id + 30.times do |i| + @paper_trail_test.update!(name: "updated name #{i}") + end end end - end - - it 'creates versions' do - expect(PaperTrail::Version.count).to eq(30) - end - - describe 'model history fetch with auditing adapter' do - before(:all) do - @adapter = RailsAdmin::Extensions::PaperTrail::AuditingAdapter.new(nil, 'User', 'PaperTrail::Version') - end - - it 'fetches on page of history' do - versions = @adapter.listing_for_model @model, nil, false, false, false, nil, 20 - expect(versions.total_count).to eq(30) - expect(versions.count).to eq(20) - end - it 'respects RailsAdmin::Config.default_items_per_page' do - RailsAdmin.config.default_items_per_page = 15 - versions = @adapter.listing_for_model @model, nil, false, false, false, nil - expect(versions.total_count).to eq(30) - expect(versions.count).to eq(15) + it 'creates versions' do + expect(PaperTrail::Version.count).to eq(30) end - it 'sets correct next page' do - versions = @adapter.listing_for_model @model, nil, false, false, false, 2, 10 - expect(versions.next_page).to eq(3) - end + describe 'model history fetch with auditing adapter' do + before(:all) do + @adapter = RailsAdmin::Extensions::PaperTrail::AuditingAdapter.new(nil, 'User', 'PaperTrail::Version') + end - it 'can fetch all history' do - versions = @adapter.listing_for_model @model, nil, false, false, true, nil, 20 - expect(versions.total_count).to eq(30) - expect(versions.count).to eq(30) - end + it 'fetches on page of history' do + versions = @adapter.listing_for_model @model, nil, false, false, false, nil, 20 + expect(versions.total_count).to eq(30) + expect(versions.count).to eq(20) + end - describe 'returned version objects' do - before(:each) do - @padinated_listing = @adapter.listing_for_model @model, nil, false, false, false, nil - @version = @padinated_listing.first + it 'respects RailsAdmin::Config.default_items_per_page' do + RailsAdmin.config.default_items_per_page = 15 + versions = @adapter.listing_for_model @model, nil, false, false, false, nil + expect(versions.total_count).to eq(30) + expect(versions.count).to eq(15) end - it '#username returns user email' do - expect(@version.username).to eq(@user.email) + it 'sets correct next page' do + versions = @adapter.listing_for_model @model, nil, false, false, false, 2, 10 + expect(versions.next_page).to eq(3) end - it '#message returns event' do - expect(@version.message).to eq('update') + it 'can fetch all history' do + versions = @adapter.listing_for_model @model, nil, false, false, true, nil, 20 + expect(versions.total_count).to eq(30) + expect(versions.count).to eq(30) end - describe 'changed item attributes' do - it '#item returns item.id' do - expect(@version.item).to eq(@paper_trail_test.id) + describe 'returned version objects' do + before(:each) do + @padinated_listing = @adapter.listing_for_model @model, nil, false, false, false, nil + @version = @padinated_listing.first end - it '#table returns item class name' do - expect(@version.table.to_s).to eq('PaperTrailTest') + it '#username returns user email' do + expect(@version.username).to eq(@user.email) end - end - context 'with Kaminari' do - before do - @paged = @adapter.listing_for_model @model, nil, false, false, false, nil - Kaminari.config.page_method_name = :per_page_kaminari + it '#message returns event' do + expect(@version.message).to eq('update') end - after do - Kaminari.config.page_method_name = :page + describe 'changed item attributes' do + it '#item returns item.id' do + expect(@version.item).to eq(@paper_trail_test.id) + end + + it '#table returns item class name' do + expect(@version.table.to_s).to eq('PaperTrailTest') + end end - it "supports pagination when Kaminari's page_method_name is customized" do - expect(PaperTrail::Version).to receive(:per_page_kaminari).twice.and_return(@paged) - @adapter.listing_for_model @model, nil, false, false, false, nil - @adapter.listing_for_object @model, @paper_trail_test, nil, false, false, false, nil + context 'with Kaminari' do + before do + @paged = @adapter.listing_for_model @model, nil, false, false, false, nil + Kaminari.config.page_method_name = :per_page_kaminari + end + + after do + Kaminari.config.page_method_name = :page + end + + it "supports pagination when Kaminari's page_method_name is customized" do + expect(PaperTrail::Version).to receive(:per_page_kaminari).twice.and_return(@paged) + @adapter.listing_for_model @model, nil, false, false, false, nil + @adapter.listing_for_object @model, @paper_trail_test, nil, false, false, false, nil + end end end end end end + + context 'PaperTrailTest' do + let(:paper_class_name) { 'PaperTrailTest' } + let(:paper_factory) { :paper_trail_test } + + it_behaves_like :paper_on_object_creation do + let(:paper_model_name) { 'paper_trail_test' } + let(:paper_field_name) { 'paper_trail_test[name]' } + end + + it_behaves_like :paper_history + end + + context 'PaperTrailTestSubclass' do + let(:paper_class_name) { 'PaperTrailTestSubclass' } + let(:paper_factory) { :paper_trail_test_subclass } + + it_behaves_like :paper_on_object_creation do + let(:paper_model_name) { 'paper_trail_test_subclass' } + let(:paper_field_name) { 'paper_trail_test_subclass[name]' } + end + + it_behaves_like :paper_history + end + + context 'PaperTrailTest::SubclassInNamespace' do + let(:paper_class_name) { 'PaperTrailTest::SubclassInNamespace' } + let(:paper_factory) { :paper_trail_test_subclass_in_namespace } + + it_behaves_like :paper_on_object_creation do + let(:paper_model_name) { 'paper_trail_test~subclass_in_namespace' } + let(:paper_field_name) { 'paper_trail_test_subclass_in_namespace[name]' } + end + + it_behaves_like :paper_history + end end