lib/hanami/extensions/action/slice_configured_action.rb in hanami-2.0.0.beta1.1 vs lib/hanami/extensions/action/slice_configured_action.rb in hanami-2.0.0.beta2

- old
+ new

@@ -46,10 +46,53 @@ end end def configure_action(action_class) action_class.config.settings.each do |setting| - action_class.config.public_send :"#{setting}=", actions_config.public_send(:"#{setting}") + # Configure the action from config on the slice, _unless it has already been configured + # by a parent slice_, and re-configuring it for this slice would make no change. + # + # In the case of most slices, its actions config is likely to be the same as its parent + # (since each slice copies its `config` from its parent), and if we re-apply the config + # here, then it may possibly overwrite config customisations explicitly made in parent + # action classes. + # + # For example, given an app-level base action class, with custom config: + # + # module MyApp + # class Action < Hanami::Action + # config.default_response_format = :json + # end + # end + # + # And then an action in a slice inheriting from it: + # + # module MySlice + # module Actions + # class SomeAction < MyApp::Action + # end + # end + # end + # + # In this case, `SliceConfiguredAction` will be extended two times: + # + # 1. When `MyApp::Action` is defined + # 2. Again when `MySlice::Actions::SomeAction` is defined + # + # If we blindly re-configure all action settings each time `SliceConfiguredAction` is + # extended, then at the point of (2) above, we'd end up overwriting the custom + # `config.default_response_format` explicitly configured in the `MyApp::Action` base + # class, leaving `MySlice::Actions::SomeAction` with `config.default_response_format` of + # `:html` (the default at `Hanami.app.config.actions.default_response_format`), and not + # the `:json` value configured in its immediate superclass. + # + # This would be surprising behavior, and we want to avoid it. + slice_value = slice.config.actions.public_send(:"#{setting}") + parent_value = slice.parent.config.actions.public_send(:"#{setting}") if slice.parent + + next if slice.parent && slice_value == parent_value + + action_class.config.public_send(:"#{setting}=", slice_value) end end def extend_behavior(action_class) if actions_config.sessions.enabled?