Form objects with Active Admin
In this example, I’m using form object’s implementation from Selleo/pattern, but the solution shouldn’t differ much for other popular implementations.
If you want to use a form object class with the Active Admin, there are a few things you need to take care of:
- Overwrite controller’s
build_new_resource
andfind_resource
methods.
ActiveAdmin usesbuild_new_resource
to build a new resource fornew
andcreate
actions, andfind_resource
for retrieving resource inedit
,update
andshow
.
We don’t want to use our form object inshow
, so we checkaction_name
infind_resource
.
contoller do
def build_new_resource
OrderForm.new(super)
end
def find_resource
return OrderForm.new(super) if action_name.in?(%w[edit update])
super
end
end
- Permit all params
We don’t want to duplicate our form’s responsibility with Rails’ Strong Parameters.
controller do
before_action -> { params.permit! }
end
- Either overwrite the default form, or extend it with the names of your attributes, as it won’t be able to infer them automatically from the form object’s class.
form do |f|
f.semantic_errors
f.inputs(*OrderForm.attributes_names)
f.actions
end
Repeating all of that for every page where you want to use a form object can get tedious, so here’s a dynamic concern which you can use to include those changes to your page quickly:
module UsesFormObject
module_function
def with_class(form_object_class)
Module.new do
define_singleton_method(:included) do |activeadmin_dsl|
activeadmin_dsl.instance_eval do
form do |f|
f.semantic_errors
f.inputs(*form_object_class.attributes_names)
f.actions
end
controller do
before_action -> { params.permit! }
private
define_method(:build_new_resource) do
form_object_class.new(super())
end
define_method(:find_resource) do
return form_object_class.new(super()) if action_name.in?(%w[edit update])
super()
end
end
end
end
end
end
end
You can use it like that:
ActiveAdmin.register Order do
include UsesFormObject.with_class(OrderForm)
end
Tweet