Rails User-Editable Configuration

When building out a Rails site with a large admin interface, you’ll eventually need to add some system settings that don’t relate specifically to any model. This is an Interesting Problem™, because ActiveRecord ties everything in the database to a model. I’ve recently started using the pattern of a GlobalConfig model to get around this.

First, create a GlobalConfig model with the standard generator:

rails g model global_config singleton_guard:integer

Then, do a bit of class customization:

class GlobalConfig < ActiveRecord::Base
  validates :singleton_guard, presence: true, uniqueness: true, numericality: {equal_to: 1}
  before_validation :set_singleton_guard

private
  def set_singleton_guard
    self.singleton_guard = 1
  end
end

Once you’ve got this base, you need a nice way to actually access the config model from your controllers and views. I added this bit to my ApplicationController:

class ApplicationController < ActionController::Base
  # …
private
  def global_config
    @global_config ||= GlobalConfig.first || GlobalConfig.new

    return @global_config
  end
  helper_method :global_config
end

From there, you can simply call global_config from any controller or view. By using an instance variable, we ensure that no matter how many times you access the GlobalConfig this way, it will only make one database call per request cycle.

Now that you’ve got the configuration model all set up, you can add whatever you need (e.g., rails g migration add_newsletter_signup_cta_to_global_config newsletter_signup_cta:string). Since it’s just a normal Rails model, you can set up forms and validation the same way you would for anything else. Using this pattern, clients can easily swap text, images, toggle site features, and more.

 
4
Kudos
 
4
Kudos

Now read this

Mouth Noises

I am #blessed enough to be a member of the Spec podcast network. We just hit a collective total of 5,000,000 downloads, and it made me reflect a bit on what I’m trying to accomplish with Does Not Compute, and my work as a whole. I... Continue →