@@ -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