Usage:
Getting configuration values
There is one class method per configuration in the configurations table for getting the values. It has the same name as the configuration name.
For example, this is how one would get the value of the configuration entry “email_address":
Configuration.email_address
Setting configuration values
Setting configuration values is similar to getting them. There is one class method for setting per configuration entry in the configurations table. It has the name of same name as the configuration name but with an equal sign.
For example, to set the email address configuration entry to "test@test.com" one would do this:
Configuration.email_address = ‘test@test.com’
Creating configuration values
One uses the methods ActiveRecord provides to create a new configuration value.
For example, to create a new integer configuration entry called ‘max_hops’, one would do the following:
config = Configuration.new(name: ‘max_hops’, value: 3, value_type: ‘integer’)
config.save
Notes about the cache
The values of the configuration are cached. Each value is placed in the cache when a getter is called and the value is not cached or when a new configuration is created using ActiveRecord methods. Each cached value expires after an hour. The values are also removed from the cache when its configuration setter is called.
Design decisions of note:
Creating methods at runtime
Creating the methods at runtime allowed me to name the methods the same as the name of the specific configurations they represented, which makes the class a lot more intuitive to use. One drawback to this approach is that if new entries are added to the database outside of the Configuration class the entries won’t be picked up until the next time the Configuration class is loaded. I did add an after_create block to the class so that any new configuration entries created with the class would immediately have getters and setters available just like the configuration entries that were loaded when the class was loaded.
Using class methods for the getters and setters
I created class methods instead of instance methods for the getters and setters because I did not want to burden the user of the class to have to create a Configuration object.
Storing the value type as a string in the configurations table
I stored the value the as a string in the configurations table (in the column value_type) so that the getters generated by the class would return objects of the expected class. The four types of values expected were pointed out in the request for the model, so I assumed that it was important that the getters return the correct types.
Setting an expiration on the cache
An expiration was set on the cache to help mitigate the possible occurrence of the database being out of sync with the class. This would occur if the database table was changed outside of the Configurations class.
Using save! as opposed to save in the setters I wanted the setters to return the value that was being set, but I also wanted a way to communicate that something went wrong. The best way to communicate that something has gone wrong is with an exception. That is why I chose the save! method (It throws an exception if there is a problem setting the value in the database, as opposed to just returning false.).
Creating a String#to_b
I am careful about monkey-patching, especially monkey-patching a class like String. But adding a to_b method is a common monkey-patch for String and it doesn’t modify the behavior of any existing String methods. Having a to_b method allowed me to simply pass symbols to the method that created the getter methods in order to make sure they returned the proper data types.