jtdaugherty/dbmigrations — Issue #2: Configuration file feature
Author: ExternalReality
Created: 2012-01-22 03:20:40+00:00
State: open

As a user I would like to be able to read the store path and database connection string from a configuration file or from the environment.

Implementing this brings up a few behavioral issues:

1. What should Moo read by default, the environment or the config file?
2. What command line options specify the desired behavior?
3. If the user chooses to read from a config file and does not specify a path where does Moo look?
4. What configuration format(s) are acceptable. (?? YAML ??)

```yaml
DBM_DATABASE_TYPE: "postgresql"
DBM_DATABASE: "a=beautiful; connection=string"
DBM_MIGRATION_STORE: "Path to a migration store"
```
A simple implementation using Data.Yaml in the applicative. (Data.Yaml is based on Aeson and the names haven't changed yet.)

```haskell
module Moo.ConfigParser where

import Data.Yaml
import Moo.Core

parseConfigOptions :: FilePath -> IO ConfigData
parseConfigOptions configFilePath = do
configContents <- decodeFile configFilePath

case configContents of
Nothing -> error "Failed Parsing Yaml"
Just a -> return a
```

```haskell
module Moo.Core where

import Control.Applicative ( (<$>), (<*>) )
import Data.Yaml ( FromJSON( parseJSON ), Value ( Object ), (.:) )

...

-- |ConfigOptions are those options read from configuration file
-- or environment.
data ConfigData = ConfigData { _dbTypeStr :: String
, _dbConnStr :: String
, _fileStorePath :: String
}

instance FromJSON ConfigData where
parseJSON (Object v) = ConfigData <$>
v .: "DBM_DATABASE_TYPE" <*>
v .: "DBM_DATABASE" <*>
v .: "DBM_MIGRATION_STORE"

parseJSON _ = mzero
```

```haskell
module Moo.CommandInterface

...

commandOptions :: [ OptDescr (CommandOptions -> IO CommandOptions) ]
commandOptions = [ optionConfigFile
, optionTest
, optionNoAsk
]

optionConfigFile :: OptDescr (CommandOptions -> IO CommandOptions)
optionConfigFile = Option "c" ["config-file"]
(ReqArg (\arg opt ->
return opt { _configFilePath = Just arg }) "FILE")
"Specify location of configuration file"
```

The rest would depend on the answers to the questions above I suppose.