RefData Elixir CI

RefData is a library for Phoenix projects that lets you provide reference data for your forms (e.g. Gender) without using a database table. It has been written as tool for POC development but can be used in PROD for fields that are common and do not form part of complex queries.

It's primary purpose is supporting the use of Phoenix.HTML.select.

The library is a supervised GenServer that starts as its own application when your applications starts. It will hold all of your defined reference data in memory for fast retrieval when needed.

Version 0.2.0 is a breaking change see CHANGELOG

Installation

The package can be installed by adding ref_data to your list of dependencies in mix.exs:

def deps do
  [
    {:ref_data, "~> 0.2.0"}
  ]
end

Config

RefData defaults to looking for json objects at the root of the project in a directory called ref_data. You can customise the path to your data by adding an entry in your config.exs file.

use Mix.Config

...

config :ref_data,
  path: "path/to/your/dir"

...

Defining Data

RefData supports a number of different definitions. The simplest definitons are a json object that uses the type of reference data as the key and a list of values is generated as a list of key value pairs. RefData will convert the definitions into Maps e.g.

{ 
  "gender": [
    "Male", 
    "Female"
  ]
}

Is converted into a map and held in state by teh GenServer:

%{ 
  name: "gender", 
  data: [
    [key: "Male", value: "Male"], 
    [key: "Female", value: "Female"]
  ]
}

RefData also supports more descriptive definitions so that you can assign your own key value pairs. E.g. if you wish to support keys with different values you can provide the details:

{ 
  "name": "active", 
  "data": [
    {"key": "Enable", "value": "true"}, 
    {"key": "Disable", "value": "false"}
  ]
}

This will be standardised as a map and stored in state:

%{ 
  name: "active", 
  data: [
    [key: "Enable", value: true], 
    [key: "Disable", value: false]
  ]
}

You can also define grouped data by creating a list of key value pairs of data. This can be doen using teh simple json syntax:

{
    "countries_grouped": 
    [
        { "Asia": ["Australia", "New Zealand"]},
        { "Americas": ["Canada", "USA"]}
    ]
}
%{ 
  name: "countries_grouped", 
  data: [
    [ "Oceania": 
      [key: "Australia", value: "Australia"],
      [key: "New Zealand", value: "New Zealand"],
    ]
    [ "Amercias": 
      [key: "Canada", value: "Canada"],
      [key: "USA", value: "USA"],
    ]
  ]
}

Alternatively, you can use teh more detailed json definition to customise the values:

{
    "name": "countries_grouped",
    "data": [
        { "Asia": [
            {"key":"Australia", "value": "Aussie"},
            {"key":"New Zealand", "value": "Kiwi"}]
        },
        { "Americas": [
            {"key":"Canada", "value": "Canuck"}, 
            {"key":"USA", "value": "Yank"}]
        }
    ]
}

It will produce the standard map using your custom values

%{ 
  name: "countries_grouped", 
  data: [
    [ "Oceania": 
      [key: "Australia", value: "Aussie"],
      [key: "New Zealand", value: "Kiwi"],
    ]
    [ "Amercias": 
      [key: "Canada", value: "Canuck"],
      [key: "USA", value: "Yank"],
    ]
  ]
}

Using RefData

Assuming you use RefData in a module named MyApp.MyRefData

defmodule MyApp.MyRefData do
  use RefData

end

My future plans include integrating GetText and CLDR and the configuration for these features will be in this module. Below are some usage examples:

MyRefData.list_all_keys/0 will list all keys for data held in memory

iex(1)> MyRefData.list_all_keys
["months", "gender"]

MyRefData.get/1 given a key it will return a list of data in the format required by Phoenix.HTML.select. If the json defines grouped data it will return the appropriate format.

iex(1)> MyRefData.get("gender")
[
  [key: "Male", value: "Male"],
  [key: "Female", value: "Female"],
  [key: "Non-binary", value: "Non-binary"]
]
iex(1)> MyRefData.get("countries")
[
  Asia: [
    [key: "Australia", value: "Australia"],
    [key: "New Zealand", value: "New Zealand"]
  ],
  Americas: [
    [key: "Canada", value: "Canada"], 
    [key: "USA", value: "Usa"]]
]

MyRefData.get/2

When given a key and a switch you are able to disable data by passing in a list of values to disable.

iex(1)> MyRefData.get("gender", disabled: ["Female"])
[
  [key: "Male", value: "Male"],
  [key: "Female", value: "Female", disabled: true],
  [key: "Non-binary", value: "Non-binary"]
]