@@ -13,20 +13,19 @@ def add_deferred_block(&block)
1313 def method_missing ( method , *args , &block )
1414 if !@model
1515 @model = RailsAdmin ::Config ::Model . new ( @entity )
16- # Configuration defined in the model class should take precedence
17- # over configuration defined in initializers/rails_admin.rb.
16+ # When evaluating multiple configuration blocks, the order of
17+ # execution is important. As one would expect (in my opinion),
18+ # options defined within a resource should take precedence over
19+ # more general options defined in an initializer. This way,
20+ # general settings for a number of resources could be specified
21+ # in the initializer, while models could override these settings
22+ # later, if required.
1823 #
19- # Due to the way the Rails initialization process works,
20- # configuration blocks found in app/models/MODEL.rb are added to
21- # @deferred_bocks before blocks defined in initializers/rails_admin.rb.
22- # Executing blocks in the order of addition would yield unexpected
23- # behaviour, as blocks from the initializer would overwrite settings
24- # defined in model classes.
25- #
26- # In order to maintain the expected precedence (model configuration over
27- # initializer configuration), all blocks are executed in reverse order.
28- #
29- # Given the following code containing initialization blocks:
24+ # CAVEAT: It cannot be guaranteed that blocks defined in an initializer
25+ # will be loaded (and adde to @deferred_blocks) first. For instance, if
26+ # the initializer references a model class before defining
27+ # a RailsAdmin configuration block, the configuration from the
28+ # resource will get added to @deferred_blocks first:
3029 #
3130 # # app/models/some_model.rb
3231 # class SomeModel
@@ -36,20 +35,15 @@ def method_missing(method, *args, &block)
3635 # end
3736 #
3837 # # config/initializers/rails_admin.rb
39- # config.model SomeModel do
38+ # model = 'SomeModel'.constantize # blocks from SomeModel get loaded
39+ # model.config model do # blocks from initializer gets loaded
4040 # :
4141 # end
4242 #
43- # The block from app/models/some_model.rb will be added to
44- # @deferred_blocks in front of the one from config/initializers/rails_admin.rb.
45- # In order to give precedence to the block from SomeModel,
46- # execute blocks in reverse order.
47- #
48- # CAVEAT: if, for some reason, a model would specify multiple configuration
49- # blocks, later blocks would be executed before earlier blocks - which could
50- # result in unexpected behaviour. However (and therefore), defining multiple
51- # configuration blocks within a single model class are discouraged.
52- @deferred_blocks . flatten . reverse . each do |block |
43+ # Thus, sort all blocks to excute for a resource by Proc.source_path,
44+ # to guarantee that blocks from 'config/initializers' evaluate before
45+ # blocks defined within a model class.
46+ @deferred_blocks . flatten . sort_by { |p | p . source_location . first =~ /config\/ initializers/ ? 0 : 1 } . each do |block |
5347 @model . instance_eval ( &block )
5448 end
5549 end
0 commit comments