Skip to content

Commit 5498659

Browse files
committed
Add opportunity for chain of configuration from initializers to concerns and models. Based on railsadminteam#1781
1 parent 12c1eaa commit 5498659

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

lib/rails_admin/config.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,9 @@ def model(entity, &block)
226226
end
227227
end
228228

229-
if block
230-
@registry[key] = RailsAdmin::Config::LazyModel.new(entity, &block)
231-
else
232-
@registry[key] ||= RailsAdmin::Config::LazyModel.new(entity)
233-
end
229+
@registry[key] ||= RailsAdmin::Config::LazyModel.new(entity)
230+
@registry[key].add_deferred_block(&block) if block
231+
@registry[key]
234232
end
235233

236234
def default_hidden_fields=(fields)

lib/rails_admin/config/lazy_model.rb

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,48 @@ module Config
55
class LazyModel < BasicObject
66
def initialize(entity, &block)
77
@entity = entity
8-
@deferred_block = block
8+
@deferred_blocks = [*block]
9+
end
10+
11+
def add_deferred_block(&block)
12+
@deferred_blocks << block
913
end
1014

1115
def target
1216
unless @model
1317
@model = ::RailsAdmin::Config::Model.new(@entity)
14-
@model.instance_eval(&@deferred_block) if @deferred_block
18+
# When evaluating multiple configuration blocks, the order of
19+
# execution is important. As one would expect (in my opinion),
20+
# options defined within a resource should take precedence over
21+
# more general options defined in an initializer. This way,
22+
# general settings for a number of resources could be specified
23+
# in the initializer, while models could override these settings
24+
# later, if required.
25+
#
26+
# CAVEAT: It cannot be guaranteed that blocks defined in an initializer
27+
# will be loaded (and adde to @deferred_blocks) first. For instance, if
28+
# the initializer references a model class before defining
29+
# a RailsAdmin configuration block, the configuration from the
30+
# resource will get added to @deferred_blocks first:
31+
#
32+
# # app/models/some_model.rb
33+
# class SomeModel
34+
# rails_admin do
35+
# :
36+
# end
37+
# end
38+
#
39+
# # config/initializers/rails_admin.rb
40+
# model = 'SomeModel'.constantize # blocks from SomeModel get loaded
41+
# model.config model do # blocks from initializer gets loaded
42+
# :
43+
# end
44+
#
45+
# Thus, sort all blocks to excute for a resource by Proc.source_path,
46+
# to guarantee that blocks from 'config/initializers' evaluate before
47+
# blocks defined within a model class.
48+
@deferred_blocks.partition { |block| block.source_location.first =~ /config\/initializers/ }
49+
.flatten.each { |block| @model.instance_eval(&block) }
1550
end
1651
@model
1752
end

0 commit comments

Comments
 (0)