Skip to content

Commit

Permalink
Defer loading of ActiveRecord to avoid config issues
Browse files Browse the repository at this point in the history
If FriendlyId references `ActiveRecord::Base` while it is loading as
part of a Rails application, it triggers the `on_load` event for
ActiveRecord, which as part of the loading process sets the current
configuration values of ActiveRecord. If any initializers try to
influence that configuration (e.g. changing defaults in
`new_framework_defaults.rb` for an app that's been upgraded), these
changes will have no effect because the configuration has already been
set in place.

To avoid this, we need to avoid triggering the `on_load` event by
wrapping the reference to `ActiveRecord::Base` in an initializer
block. The simplest way of doing this is with a `Railtie`, which will
be automatically loaded if FriendlyId is required as part of Rails.

Fixes #823
  • Loading branch information
lazyatom authored and parndt committed Jan 15, 2018
1 parent a29e7d7 commit 4bd4300
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 2 deletions.
1 change: 1 addition & 0 deletions lib/friendly_id.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require "friendly_id/object_utils"
require "friendly_id/configuration"
require "friendly_id/finder_methods"
require 'friendly_id/railtie' if defined?(Rails)

=begin
Expand Down
7 changes: 5 additions & 2 deletions lib/friendly_id/object_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module FriendlyId
# Instances of these classes will never be considered a friendly id.
# @see FriendlyId::ObjectUtils#friendly_id
UNFRIENDLY_CLASSES = [
ActiveRecord::Base,
Array,
FalseClass,
Hash,
Expand Down Expand Up @@ -59,11 +58,15 @@ def unfriendly_id?
true
end
end

def self.mark_as_unfriendly(klass)
klass.send(:include, FriendlyId::UnfriendlyUtils)
end
end

Object.send :include, FriendlyId::ObjectUtils

# Considered unfriendly if object is an instance of an unfriendly class or
# one of its descendants.

FriendlyId::UNFRIENDLY_CLASSES.each { |klass| klass.send(:include, FriendlyId::UnfriendlyUtils) }
FriendlyId::UNFRIENDLY_CLASSES.each { |klass| FriendlyId.mark_as_unfriendly(klass) }
9 changes: 9 additions & 0 deletions lib/friendly_id/railtie.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module FriendlyId
class Railtie < Rails::Railtie
initializer 'friendly_id.setup' do
ActiveSupport.on_load(:active_record) do
FriendlyId.mark_as_unfriendly(ActiveRecord::Base)
end
end
end
end
2 changes: 2 additions & 0 deletions test/object_utils_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class ObjectUtilsTest < TestCaseClass
end

test "ActiveRecord::Base instances should be unfriendly_ids" do
FriendlyId.mark_as_unfriendly(ActiveRecord::Base)

model_class = Class.new(ActiveRecord::Base) do
self.table_name = "authors"
end
Expand Down

0 comments on commit 4bd4300

Please sign in to comment.