diff --git a/CHANGELOG.md b/CHANGELOG.md index 73c0768b..a844fe8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,11 @@ recommendations of [keepachangelog.com](http://keepachangelog.com/). ### Breaking Changes -- In the PT rails engine, the `paper_trail` configuration has been - removed. This configuration object was deprecated in 10.2.0. Please review - docs section [2.d. Turning PaperTrail +- Rails: Instead of an `Engine`, PT now provides a `Railtie`, which is simpler. +- Rails: The deprecated `config.paper_trail` configuration technique + has been removed. This configuration object was deprecated in 10.2.0. It only + had one key, `config.paper_trail.enabled`. Please review docs section [2.d. + Turning PaperTrail Off](https://github.com/paper-trail-gem/paper_trail/#2d-turning-papertrail-off) for alternatives. diff --git a/lib/paper_trail.rb b/lib/paper_trail.rb index a64d6a4a..51b895b9 100644 --- a/lib/paper_trail.rb +++ b/lib/paper_trail.rb @@ -8,34 +8,17 @@ # can revisit this decision. require "active_support/all" -# AR is required for, eg. has_paper_trail.rb, so we could put this `require` in -# all of those files, but it seems easier to troubleshoot if we just make sure -# AR is loaded here before loading *any* of PT. See discussion of -# performance/simplicity tradeoff for activesupport above. -require "active_record" - -require "request_store" require "paper_trail/cleaner" require "paper_trail/compatibility" require "paper_trail/config" -require "paper_trail/has_paper_trail" require "paper_trail/record_history" -require "paper_trail/reifier" require "paper_trail/request" -require "paper_trail/version_concern" require "paper_trail/version_number" require "paper_trail/serializers/json" -require "paper_trail/serializers/yaml" # An ActiveRecord extension that tracks changes to your models, for auditing or # versioning. module PaperTrail - E_RAILS_NOT_LOADED = <<-EOS.squish.freeze - PaperTrail has been loaded too early, before rails is loaded. This can - happen when another gem defines the ::Rails namespace, then PT is loaded, - all before rails is loaded. You may want to reorder your Gemfile, or defer - the loading of PT by using `require: false` and a manual require elsewhere. - EOS E_TIMESTAMP_FIELD_CONFIG = <<-EOS.squish.freeze PaperTrail.timestamp_field= has been removed, without replacement. It is no longer configurable. The timestamp column in the versions table must now be @@ -126,27 +109,18 @@ module PaperTrail end end -# We use the `on_load` "hook" instead of `ActiveRecord::Base.include` because we -# don't want to cause all of AR to be autloaded yet. See -# https://guides.rubyonrails.org/engines.html#what-are-on-load-hooks-questionmark -# to learn more about `on_load`. -ActiveSupport.on_load(:active_record) do - include PaperTrail::Model -end - -# Require frameworks -if defined?(::Rails) - # Rails module is sometimes defined by gems like rails-html-sanitizer - # so we check for presence of Rails.application. - if defined?(::Rails.application) - require "paper_trail/frameworks/rails" - else - ::Kernel.warn(::PaperTrail::E_RAILS_NOT_LOADED) - end +# PT is built on ActiveRecord, but does not require Rails. If Rails is defined, +# our Railtie makes sure not to load the AR-dependent parts of PT until AR is +# ready. A typical Rails `application.rb` has: +# +# ``` +# require 'rails/all' # Defines `Rails` +# Bundler.require(*Rails.groups) # require 'paper_trail' (this file) +# ``` +# +# Non-rails applications should take similar care to load AR before PT. +if defined?(Rails) + require "paper_trail/frameworks/rails" else require "paper_trail/frameworks/active_record" end - -if defined?(::ActiveRecord) - ::PaperTrail::Compatibility.check_activerecord(::ActiveRecord.gem_version) -end diff --git a/lib/paper_trail/frameworks/active_record.rb b/lib/paper_trail/frameworks/active_record.rb index 65565710..43eb3fb2 100644 --- a/lib/paper_trail/frameworks/active_record.rb +++ b/lib/paper_trail/frameworks/active_record.rb @@ -1,5 +1,12 @@ # frozen_string_literal: true -# This file only needs to be loaded if the gem is being used outside of Rails, -# since otherwise the model(s) will get loaded in via the `Rails::Engine`. +# Either ActiveRecord has already been loaded by the Lazy Load Hook in our +# Railtie, or else we load it now. +require "active_record" +::PaperTrail::Compatibility.check_activerecord(::ActiveRecord.gem_version) + +# Now we can load the parts of PT that depend on AR. +require "paper_trail/has_paper_trail" +require "paper_trail/reifier" require "paper_trail/frameworks/active_record/models/paper_trail/version" +ActiveRecord::Base.include PaperTrail::Model diff --git a/lib/paper_trail/frameworks/rails.rb b/lib/paper_trail/frameworks/rails.rb index f53570db..2f50e678 100644 --- a/lib/paper_trail/frameworks/rails.rb +++ b/lib/paper_trail/frameworks/rails.rb @@ -1,4 +1,3 @@ # frozen_string_literal: true -require "paper_trail/frameworks/rails/controller" -require "paper_trail/frameworks/rails/engine" +require "paper_trail/frameworks/rails/railtie" diff --git a/lib/paper_trail/frameworks/rails/controller.rb b/lib/paper_trail/frameworks/rails/controller.rb index 99881042..f69303fc 100644 --- a/lib/paper_trail/frameworks/rails/controller.rb +++ b/lib/paper_trail/frameworks/rails/controller.rb @@ -101,9 +101,3 @@ module PaperTrail end end end - -if defined?(::ActionController) - ::ActiveSupport.on_load(:action_controller) do - include ::PaperTrail::Rails::Controller - end -end diff --git a/lib/paper_trail/frameworks/rails/engine.rb b/lib/paper_trail/frameworks/rails/engine.rb deleted file mode 100644 index 0884b877..00000000 --- a/lib/paper_trail/frameworks/rails/engine.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -module PaperTrail - module Rails - # See http://guides.rubyonrails.org/engines.html - class Engine < ::Rails::Engine - paths["app/models"] << "lib/paper_trail/frameworks/active_record/models" - end - end -end diff --git a/lib/paper_trail/frameworks/rails/railtie.rb b/lib/paper_trail/frameworks/rails/railtie.rb new file mode 100644 index 00000000..3b7fc6d4 --- /dev/null +++ b/lib/paper_trail/frameworks/rails/railtie.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module PaperTrail + # Represents code to load within Rails framework. See documentation in + # `rails/railtie.rb`. + # @api private + class Railtie < ::Rails::Railtie + # PaperTrail only has one initializer. The `initializer` method can take a + # `before:` or `after:` argument, but that's only relevant for railties with + # more than one initializer. + initializer "paper_trail" do + # `on_load` is a "lazy load hook". It "declares a block that will be + # executed when a Rails component is fully loaded". (See + # `active_support/lazy_load_hooks.rb`) + ActiveSupport.on_load(:action_controller) do + require "paper_trail/frameworks/rails/controller" + + # Mix our extensions into `ActionController::Base`, which is `self` + # because of the `class_eval` in `lazy_load_hooks.rb`. + include PaperTrail::Rails::Controller + end + + ActiveSupport.on_load(:active_record) do + require "paper_trail/frameworks/active_record" + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 17c84868..6fce6544 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,7 +7,7 @@ require "byebug" require_relative "support/pt_arel_helpers" unless File.exist?(File.expand_path("dummy_app/config/database.yml", __dir__)) - warn "No database.yml detected for the dummy app, please run `rake prepare` first" + warn "No database.yml detected for the dummy app, please run `rake install_database_yml` first" end RSpec.configure do |config|