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

  def set_singleton_guard
    self.singleton_guard = 1

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
  # …
  def global_config
    @global_config ||= GlobalConfig.first || GlobalConfig.new

    return @global_config
  helper_method :global_config

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.