
Accediendo a una tabla de seteos globales con ActiveRecord
Las dos clases que aparecen a continuación proveen un método simple para manipular datos de la forma (clave, valor) de manera simple y rubística. No es muy ortodoxo, pero me viene resultando útil en los proyectos en los que lo usé.
Este ‘pattern’ surgió de la necesidad de acceder y modificar seteos globales de una aplicacion, de la forma “background_color =
CREATE TABLE `settings` ( `id` int(10) unsigned NOT NULL auto_increment, `name` varchar(100) NOT NULL default '', `value` text NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) )
El primer modelo ActiveRecord que necesitamos es la clase Setting:
class Setting < ActiveRecord::Base
validates_presence_of :name
validates_uniqueness_of :name
def self.find_or_create(name)
unless setting = Setting.find_by_name(name)
setting = Setting.new("name" => name)
end
setting
end
end
Setting es una clase heredera de ActiveRecord::Base, con el agregado del método Setting.find_or_create que retorna un registro de la tabla settings dado su nombre, creándolo en caso de no existir. Vale aclarar que esta clase la tomé del código fuente de Typo.
El acceso a los registros de la tabla settings lo vamos a realizar mediante la clase WizardSettings:
class WizardSettings
def self.method_missing(method_id, *arguments)
attr_name = method_id.id2name
setting_name = attr_name.gsub(/[\?\=\!]/,'')
if attr_name =~ /^.+=$/ # writer
if arguments[0].nil? and s = Setting.find_by_name(setting_name)
s.destroy
else
s = Setting.find_or_create(setting_name)
s.value = arguments[0]
return s
end
elsif attr_name =~ /^.+\!$/ # assignment, immediate save
if arguments[0].nil?
WizardSettings.send("#{setting_name}=", nil)
else
s = Setting.find_or_create(setting_name)
s.value = arguments[0]
s.save
end
elsif attr_name =~ /^.+\?$/ # boolean
Setting.find_or_create(setting_name).value?
else
Setting.find_or_create(setting_name).value
end
end
end
Como se puede ver, WizardSettings no define métodos propios si no que redefine method_missing. Voy a explicar en detalle la implementación de este metodo en una futura versión de este documento :). Pero la idea es el acceso a los valores guardados en settings mediante WizardSettings. Supongamos que settings contiene los siguientes registros:
+----+-------------------+-----------------------------+ | id | name | value | +----+-------------------+-----------------------------+ | 1 | meta_keywords | foo, bar, baz, quux, quux0r | | 2 | date_format | %d-%m-%Y | | 3 | use_visual_editor | 1 | +----+-------------------+-----------------------------+
Ejemplo de uso de WizardSettings:
WizardSettings.use_visual_editor # -> "1" WizardSettings.use_visual_editor? # -> true WizardSettings.use_visual_editor = nil # -> nil WizardSettings.use_visual_editor? # -> false WizardSetting.nuevo_seteo # -> "" WizardSetting.nuevo_seteo! "foo" # Inserta un nuevo registro en settings WizardSetting.nuevo_seteo # -> "foo"
El código, tal como está, presenta varias desventajas e inconsistencias que serán desarrolladas en una próxima versión de éste artículo :)