Using the “Form Pattern” with an ActiveAdmin controller

Using the “Form Pattern” with an ActiveAdmin controller

Background:

ActiveAdmin is Rails Engine that provides an Admin Framework with tons of functionality. ActiveAdmin wraps around ActiveRecord Models and provides a standardized CRUD (create-read-update-delete) interface. Sometimes you may want a form that isn’t tied to an existing model in your Rails, to accomplish this, you can use a Form

Example:

The closest to a real world example I can think of is a form that schedules a job.

If we have a job like this:

# app/jobs/compute_job.rb

class ComputeJob

  attr_reader :widget_name, :threshold

  def initialize(widget_name, threshold)
    @widget_name = widget_name
    @threshold = threshold
  end

  def perform
    # ... job implementation
  end

end

We create a Form object to wrap around the job. The implementation of the save method includes the job creation and queueing.

# app/forms/compute_job_form.rb

class ComputeJobForm
  include ActiveModel::Model

  attr_accessor :widget_name, :threshold

  validates_presence_of :widget_name, :threshold

  # Implements ActiveModel save method by creating a compute job
  def save
    return false unless valid?
    Delayed::Job.enqueue(job)
    true
  end

  private

  def job
    ComputeJob.new(widget_name, threshold)
  end

end

The final step is to create our ActiveAdmin controller.

# app/admin/computer_job.rb

ActiveAdmin.register ComputeJobForm, as: 'Compute Job' do

  menu priority: 5, label: 'Create Compute Job', parent: 'Tools'

  actions :all, only: [:new, :create, :index]

  controller do

    def index
      redirect_to new_resource_path
    end

    def create
      super do |success, failure|
        success.html {
          flash[:notice] = "New 'Compute Job' Scheduled for #{resource.widget_name}"
          redirect_to new_resource_path
        }
      end
    end
  end

  form do |f|
    panel 'New Compute Job to run in the Cloud' do
      f.semantic_errors(*f.object.errors.keys)
      f.inputs name: 'Options', class: 'inputs' do
        f.input :widget_name, as: :string, required: true
        f.input :threshold, as: :string, required: true

        f.submit 'Create Compute Job'
      end
    end
  end

end

A few things to note

  1. Because there is no ‘index’ action, we automatically redirect to the ‘new’ page

  2. In the create action, we also force a redirect the new action.

  3. We can reference the instance of the form object as resource in our controller action just like we would if they were ActiveRecord objects.

In closing, there are many things you can do with ActiveAdmin that I have uncovered in my current project. Come back to this blog as I’ll try to explore some more.


References:
ActiveAdmin
7 Patterns to Refactor Fat ActiveRecord Models
#416 Form Objects (pro) – RailsCasts