Set default form builder for a controller#19736
Conversation
There was a problem hiding this comment.
The context in this test was missing a controller and was raising on nil.
|
@kmcphillips what about defining a method like |
|
@senny it’s not that writing a wrapper like The background to this patch is that we’re starting to use more custom form builders in Shopify (a rather large Rails project) and are hitting a complexity wall with the workarounds mentioned above. |
|
Overriding a custom Rails allows you to scope nearly everything cleanly to split an app into sections, with this notable exception. Especially since you have the ability to override the form builder globally. Shopify isn't the first project where I have wanted this feature either, FWIW. |
|
About the feature, I can see as it can be useful. This would be similar to when we define which helper module is loaded by controller (if we disable the global require). About the implementation, this is coupling Action View with Action Controller. How about instead making Action View asking Action Controller what is the form builder, we do not set it when creating the |
|
Also I can see how Simple Form can benefits of this feature. |
|
@rafaelfranca Agree. Don't like the coupling. I'll look at refactoring it to Action View. |
|
Given we will have a default form builder per action view instance and it Another thing, maybe we should call the singleton method On Mon, Apr 13, 2015, 12:51 Kevin McPhillips notifications@github.com
|
|
@rafaelfranca Great feedback. I think it's a great idea to deprecate the global I'll rename the method to be About the implementation. I can delegate That makes the implementation in the def default_form_builder_class
builder = default_form_builder || ActionView::Base.default_form_builderAnd that works. But when the view is not an instance of I'm not sure if that means this test is broken, or if this is a valid case. I can do What do you think? |
|
I think instead of delegating we should do the same we do with And we define: def default_form_builder_class
builder = @_default_form_builder || ActionView::Base.default_form_builderOr use a I think this would fix the problem with the custom view context. |
|
Ok, updated. I also added tests to both the |
Set default form builder for a controller
|
Awesome! |
|
Just to add to the discussion, deprecating the AV config might not be an option if we want people to actually use it decoupled (which means there will be no controller default to inherit from). |
|
@carlosantoniodasilva yeah, I thought that when I was merging it and forget to comment here. |
|
👍 On Tue, Apr 14, 2015 at 1:56 PM, Rafael Mendonça França <
At. |
|
Super great. Thanks! 🚀 🌙 |
|
Nice job everybody. |
|
Any chance this will end up in a 4.2.x release? |
|
No. New features are not added to stable releases |
|
I looked around for a Rails release roadmap, but I didn't find one. Should I expect this in a 4.3.x release or something else? |
|
It will be in the Rails 5 release |
Problem
Form builders can only be overridden per call of
form_for, or globally for the entire application. Often form builders will be specialized for all forms in a particular section or area. There is currently no way of defining a default form builder scoped to a particular area or context. This leads to repetition with having to pass in the form builder explicitly into every form.Solution
Define a
form_buildersingleton method on the controller which allows a from builder to be specified per controller. DRY in the views.This is modeled after how a layout is defined per controller.
This override has a higher prescidence than the
ActionViewglobaldefault_form_builderoption, but lower prescidence than the explicitbuilder:option when callingform_for.Example
Given a section specific form builder:
And an abstract controller superclass for an admin area:
Any calls to
form_forfor that controller or its subclasses will default to the form builder declared in that controller.Tested in this example app:
https://github.com/kmcphillips/rails-test-app
Workarounds
The existing but insufficient workarounds I have been able to identify are:
form_formethod to injectbuilder:into the options hash.builder:option into everyform_forcall.config.action_view.default_form_builderwhich contains specializations that may not apply to all areas.cc @arthurnn @edward