Skip to content

Commit

Permalink
Fix #3541 breaking on reload with parent_controller set
Browse files Browse the repository at this point in the history
  • Loading branch information
mshibuya committed Aug 12, 2022
1 parent 94f16fb commit 33e9214
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 12 deletions.
2 changes: 1 addition & 1 deletion lib/rails_admin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def self.config(entity = nil, &block)
if entity
RailsAdmin::Config.model(entity, &block)
elsif block_given?
suppress_const_load { yield(RailsAdmin::Config) }
RailsAdmin::Config::ConstLoadSuppressor.suppressing { yield(RailsAdmin::Config) }
else
RailsAdmin::Config
end
Expand Down
10 changes: 6 additions & 4 deletions lib/rails_admin/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,12 @@ def parent_controller=(name)
@parent_controller = name

if defined?(RailsAdmin::ApplicationController) || defined?(RailsAdmin::MainController)
RailsAdmin.send(:remove_const, :ApplicationController)
RailsAdmin.send(:remove_const, :MainController)
load RailsAdmin::Engine.root.join('app/controllers/rails_admin/application_controller.rb')
load RailsAdmin::Engine.root.join('app/controllers/rails_admin/main_controller.rb')
RailsAdmin::Config::ConstLoadSuppressor.allowing do
RailsAdmin.send(:remove_const, :ApplicationController)
RailsAdmin.send(:remove_const, :MainController)
load RailsAdmin::Engine.root.join('app/controllers/rails_admin/application_controller.rb')
load RailsAdmin::Engine.root.join('app/controllers/rails_admin/main_controller.rb')
end
end
end

Expand Down
42 changes: 35 additions & 7 deletions lib/rails_admin/config/const_load_suppressor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,42 @@
module RailsAdmin
module Config
module ConstLoadSuppressor
def suppress_const_load
original = Object.method(:const_missing)
Object.define_singleton_method(:const_missing) do |name|
ConstProxy.new(name.to_s)
class << self
@original_const_missing = nil

def suppressing
raise 'Constant Loading is already suppressed' if @original_const_missing

begin
@original_const_missing = Object.method(:const_missing)
intercept_const_missing
yield
ensure
Object.define_singleton_method(:const_missing, @original_const_missing)
@original_const_missing = nil
end
end

def allowing
if @original_const_missing
begin
Object.define_singleton_method(:const_missing, @original_const_missing)
yield
ensure
intercept_const_missing
end
else
yield
end
end

private

def intercept_const_missing
Object.define_singleton_method(:const_missing) do |name|
ConstProxy.new(name.to_s)
end
end
yield
ensure
Object.define_singleton_method(:const_missing, original)
end

class ConstProxy < BasicObject
Expand Down
37 changes: 37 additions & 0 deletions spec/rails_admin/config/const_load_suppressor_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe RailsAdmin::Config::ConstLoadSuppressor do
describe '.suppressing' do
it 'suppresses constant loading' do
expect do
subject.suppressing { UnknownConstant }
end.not_to raise_error
end

it 'raises the error on recursion' do
expect do
subject.suppressing do
subject.suppressing {}
end
end.to raise_error(/already suppressed/)
end
end

describe '.allowing' do
it 'suspends constant loading suppression' do
expect do
subject.suppressing do
subject.allowing { UnknownConstant }
end
end.to raise_error NameError
end

it 'does not break when suppression is disabled' do
expect do
subject.allowing {}
end.not_to raise_error
end
end
end

0 comments on commit 33e9214

Please sign in to comment.