Estaba buscando algún plugin para Rails para manejar los parámetros (preferencias, opciones, settings, etc.) de una web que estoy haciendo.
En el wiki de Rails encontré este ConfigurationGenerator que parecía muy atractivo, y que se adaptaba exactamente a lo que yo estaba necesitando, pero no pude encontrar el código de él por ningún lado, ni he obtenido respuesta a un post que coloqué en el foro de Rails sobre este generador.
Luego conseguí este otro Settings plugin, que me pareció fantástico, pero no era exactamente lo que yo quería.
Así que decidí emprender la tarea de hacer mi propio modelo para el manejo de los parámetros de mi aplicación web, tomando como base un poco de esos otros pulgins que ya había visto.
Lo que me interesaba era tener una tabla que siempre tendría un sólo registro, y con una columna para cada opción que hubiese en los parámetros. Eso me permitiría guardar cada opción en el tipo de dato y tamaño de columna adecuado. Además me interesaba poder acceder a cualquier parámetro, desde cualquier lugar de la aplicación, con algo simple como:
Parametros.opción
Los parámetros con que arranqué eran el nombre de la aplicación y un texto del tipo "about us", o "quienes somos", para la página principal de la web. La migración quedó asi:
class AgregarParametros < ActiveRecord::Migration
def self.up
# Archivo de parámetros de la aplicación
create_table :parametros do |table|
table.column :aplicacion, :string, :limit => 100
table.column :quienes_somos, :text
table.column :updated_at, :datetime
end
execute "Insert into parametros (aplicacion, quienes_somos) Values ('App. web', 'Somos...')"
end
def self.down
drop_table :parametros
end
end
Este archivo contendrá siempre un registro único, ni más, ni menos, así que se incluye automáticamente durante la migración misma, con valores iniciales cualesquiera. Los valores reales se asignaran en la aplicación web.
Y el modelo de Rails quedó de esta manera:
class Parametros < ActiveRecord::Base
set_table_name "parametros"
validates_presence_of :aplicacion, :quienes_somos
private_class_method :new, :create, :destroy, :destroy_all, :delete, :delete_all
@@p = find(:first)
def self.method_missing(method, *args)
opcion = method.to_s
if opcion.include? '='
# Asignar un valor a la opción
nombre_var = opcion.gsub('=', '')
valor = args.first
@@p[nombre_var] = valor
else
# Retornar el valor de la opción
@@p[opcion]
end
end
def self.save
@@p.save
end
def self.update_attributes(atributos)
@@p.update_attributes(atributos)
end
def self.errors
@@p.errors
end
end
Me interesaba accesar los parámetros con la forma en plural Parametros
(en contra de las convenciones de Rails), y la tabla que uso tiene el mismo nombre en plural (esta vez si como lo indican las convenciones de Rails), así que debí incluir set_table_name "parametros"
para saltarme la convención del nombre del modelo.
Haría uso de la clase directamente, sin instanciarla, así que debía prevenir que se crearan objetos de la clase con la línea private_class_method :new, :create
. A esa lista se agregan :destroy, :destroy_all, :delete, :delete_all
porque ciertamente no me interesa que se borre ese registro único de la tabla de parámetros. La lista de métodos se puede alargar a cualquier otro del que se quiera bloquear el acceso.
No quería ir a la base de datos cada vez que necesitara un parámetro, así que usé una variable de clase para hacer un cache de los valores, que sería inicializada la primera vez que se llame a los parámetros, con el contenido de ese registro único de la tabla: @@p = find(:first)
Los métodos save
, update_attributes
y errors
se definen como métodos de clase, con self
, para poder llamarlos sin tener necesidad de instanciar la clase.
Se pueden asignar todos los valores a los parámetros, uno por uno, y al final llamar a save
para grabarlos en una sola operación en la base de datos. O se puede llamar a update_attributes
con un "hash" como parámetro, con todos los valores de los parámetros a grabar (al grabar desde una forma, en una página de parámetros, por ejemplo). El método errors
se define para poder utilizar el "helper" error_messages_for 'parametros'
en una forma.
Para actualizar los parámetros se puede hacer algo como lo que sigue. En el controlador adecuado:
def parametros
@parametros = Parametros
end
def grabar_param
@parametros = Parametros
if @parametros.update_attributes(params[:parametros])
flash[:notice] = 'Parámetros grabados'
redirect_to :action => "index"
else
render :action => "parametros"
end
end
Y en la vista hacer:
<h1>Parámetros de la web</h1>
<br>
<%= start_form_tag :action => 'grabar_param' %>
<%= error_messages_for 'parametros' %>
<p><label for="parametros_aplicacion">Nombre de la web:</label><br/>
<%= text_field_tag 'parametros[aplicacion]', @parametros.aplicacion %></p>
<p><label for="parametros_quienes_somos">Quienes somos:</label><br/>
<%= text_area_tag "parametros[quienes_somos]", @parametros.quienes_somos %></p>
<br>
<%= submit_tag 'Aceptar' %>
<%= end_form_tag %>
Esta es la mejor manera que se me ha ocurrido para manejar los parámetros de la manera que yo quería. Si conocen de una manera mejor, estaré gustoso de escucharla.
¿Te gustó este artículo? Digg it!