Make a Rails app configurable for an (app) admin user

Hey everybody,

we’re working on a rails application where we’re currently trying to implement options to make it configurable via the admin dashboard (for an admin user). Things we want to give control over are whether…

  • an automatic translation of user input shall be fired
  • parts of the application shall be accessible to guest users
  • app title
  • app maintainer email address

Right now we’re on track with a simple settings controller and model, the latter basically representing a one-row-activerecord-object/class that can be queried for the respective settings.

So far this seems to work but of course I’ve been interested what’s best-practice in order to achieve the above. How do you make your rails app configurable in a convenient way?

best,
Andi

I’m working on a similar feature. I’ve decided to give JSON a try for managing settings. One of the reasons I choose this is that I currently prefer the flexibility of the JSON for storing arbitrary settings. Adding new key/value pair doesn’t require a db migration.

Here are two links for how to implement forms for JSON attributes:

As far as best practices go I don’t think there’s a silver bullet. It all depends on how you want these values to be stored and managed. I know Wordpress uses a table where each row represents a single setting value.

Hey Lenart,

thanks for your comment, sounds interesting. We’ve implemented version prior to what we’re on track with now using a YAML-file like

default: &default
  general: SomeName
  maintainer_email_address: foo@bar.org

which is loaded and parsed during app startup like this

require 'ostruct'

all_config = YAML.load_file("#{Rails.root}/config/app_config.yml") || {}
env_config = all_config[Rails.env] || {}
AppConfig = OpenStruct.new(env_config)

AppConfig is then available throughout the application. The downside of this approach is that you’d have to form validate through e.g. JS instead of being able to rely on conventional ActiveRecord validations. Also it is more complicated to realise things like different ‘Settings profiles’ and the like. Do you already have a concrete implementation of that approach?

I think a table approach with a column for each setting is a fine way to start, and I’ve used it successfully in the past. Just remember to seed the database, and/or provide some kind of NullConfiguration default settings in case the database is missing the data you need.

JSON is fine too, but many applications don’t need such a flexible schema for configuration settings, since the configuration keys are generally well-defined in advance. When you need new keys, migrations are relatively straightforward.

If you have an application that needs dynamic settings, then a column for each individual setting won’t work, and that’s when you’d need to consider something with a flexible schema like JSON.

If you have an application that needs dynamic settings, then a column for each individual setting won’t work, and that’s when you’d need to consider something with a flexible schema like JSON.

@Nathan: What settings do you mean when you say ‘dynamic’?

By dynamic keys, I mean keys whose names you don’t know in advance. In other words, keys that aren’t hard-coded into your code or your database schema.

Suppose you operate an online email campaign service, and you want your customers to be able to create email templates and define any placeholders they desire such that the placeholders in a template are automatically replaced with a value from a master configuration. Some common placeholder keys might be [address] or [company_name], but you can’t possibly know every placeholder every customer might want to use. Suppose a company wants a placeholder named [our_really_special_toll_free_phone_number]. You’ll need some schemaless mechanism for storing the names (and values) of the placeholders.

One way is JSON. Another way is a key/value store (perhaps a database table like Wordpress). Or, you could treat placeholders as an actual “thing” with their own placeholders table with columns like placeholder_name and placeholder_value, but that’s really just a special-case of a key-value pair. My point is simply that you wouldn’t have a configuration table with a column named our_really_special_toll_free_phone_number.

Another example might be e-commerce software that works with many different payment gateways, each of which has slightly different configuration options that need to be specified. If you can change the gateway dynamically, you’ll also need to be able to dynamically change the keys of the configuration hash.

A third example could be dynamically editable i18n data. You’re not going to want a configuration table with a separate column for each conceivable word you want to translate.

I think it’s relatively uncommon to have these kinds of “dynamic” needs in an app-wide configuration object, which is why I think a configuration table with a rigid schema is good place to start. For anything dynamic that pops up later, you’ll have to determine the best way to handle it, either via JSON or some kind of key/value table/store that allows flexibility.

Thanks Nathan, totally agree with you!