==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