==What is it?
has_setting is a simple extension that enables ActiveRecord models to
store settings in a separate settings table as key/value pairs where the key and value are stored as Strings.
==History
* 0.4.2:
* bug fixes for boolean types default values
* 0.3.10:
* added boolean and booleans formatters
* 0.3.9:
* added type :strings, :floats, :ints. They store the contents of an array as a comma separated string.
* 0.3.8:
* added dependent destroy option. no more zombie settings lingering around.
* 0.3.7:
* Gem is now built using jeweler... after messing around and bumping versions and getting
strange errors, this is 'it works' feeling coming back
* 0.3.4:
* Added custom formatter support. no new formatters though...
* 0.3.1:
* Bug Fixed: has_many(:settings) is not added to ActiveRecord::Base but only to the classes with has_setting
* Bug Fixed: options are not shared between classes
* Again changed the way settings are saved. Save is now done on parent.save with an after_save callback. (like this the settings are treated as if they were attributes of the owner)
* 0.2.x:
* Added :default option
* changed way settings are saved so that unsaved parents can have settings too
* changed nameing scheme of setting names (incompatible with versions prior 0.2.x but since nobody uses the gem i dont care :-))
* 0.1.x: First Version
==Installation
sudo gem install simplificator-has_setting
==Setup
* Add a migration that looks more or less like the one in help/001_create_settings.rb
* Make sure the gem is loaded when your application starts
==Config
The model you want to hold settings (i.e. User, Profile, ...):
has_setting(:name_of_the_setting)
This will create the following methods for you on the owner class:
* name_of_the_setting=(value) a standard setter
* name_of_the_setting() a standard getter (the getter method takes an optional hash to override some options, possible values are the same as the options in has_setting())
has_setting(name, options) takes an optional hash of options. Following options are supported:
:type allows you to convert the value:
* :string (default) Uses the StringFormatter to convert from/to String (actually this formatter just leaves the value as it is)
* :int Uses the IntFormatter to convert from/to int values.
* :boolean Uses the BooleanFormatter to convert from/to boolean values.
* :float Uses the FloatFormatter to convert from/to float values.
* :ints Uses the IntsFormatter to convert from/to int[]
* :floats Uses the FloatsFormatter to convert from/to float[]
* :strings Uses the StringsFormatter to convert from/to string[]
* :booleans Uses the BooleansFormatter to convert from/to boolean[]
:default allows you to specify a default value that will be returned if the setting does not exist (i.e. has never been written). Note that the default value is _ignored_ if the setting exists, no matter what the value of the setting is. The default value is returned as is, no type conversion takes place.
==How it works
A polymorphic parent-child relation is created between Setting and the parent/owning class.
Getters/setters are added through meta-programming-magic. If the setter is invoked on a unsafed parent then the setting is not saved until the parent is saved, else setting is saved upon creation (i.e. first time the setter is called) / change (subsequent calls).
The getters/setters can be used in standard AR validations, Rails mass assignments/form helpers and so on.
==Gotchas
* Values are stored as Strings in the DB. Values are converted with one of the formatters (depending on selected :type). If you try to store an unsupported type or anything other than the type you selected there might be an exception (i.e. if you try to store "foobar" as an :type => :int)
* Currently there are no length validations on the 'name' and 'value' column of Setting. Take care not to store values to big. Especially when using the array formatters (:floats, :ints, :strings)
==Example
class Foo < ActiveRecord::Base
has_setting(:string_setting)
has_setting(:another_string_setting, :type => :string)
has_setting(:int_setting, :type => :int)
has_setting(:float_setting, :type => :float, :default => 3.3)
end
foo = Foo.create
foo.string_setting
=> nil
foo.string_setting= 'a string'
foo.string_setting
=> 'a string'
foo.int_setting = 123
foo.int_setting
=> 123
foo.int_setting = '123'
foo.int_setting
=> 123
foo.float_setting
=> 3.3
foo.float_setting = nil
foo.float_setting
=> nil
==Todo
has_setting should stay as simple as possible... still some ideas are around:
* Custom formatter (to convert arbitrary objects, i.e. Date/Time/DateTime...)
* Add validation options