¿Qué es ActiveModel?
Es una serie de módulos que se pueden utilizar para implementar funcionalidades comunes extraídas de ActiveRecord e implementarlas en modelos comunes sin que tenga interacción directa con la base de datos. Algunos de los módulos que incluye ActiveModel son los siguientes:
- ActiveModel::AttributeMethods
- ActiveModel::Callbacks
- ActiveModel::Conversion
- ActiveModel::Dirty
- ActiveModel::Lint
- ActiveModel::Model
- ActiveModel::Naming
- ActiveModel::SecurePassword
- ActiveModel::Serialization
- ActiveModel::Serializers
- ActiveModel::Translation
- ActiveModel::Validations
La sintaxis para desarrollar una clase con estas características es exactamente igual que una clase normal, solo que a esta se le incluyen los módulos de ActiveModel que vayamos a utilizar. Un ejemplo de esto es el siguiente:
class Message include ActiveModel::Validations attr_accessor :nombre, :email, :contenido validates_presence_of :nombre, :email, :contenido def initialize (nombre, email,contenido) @nombre, @email, @contenido = nombre, email, contenido final final123456789101112 classMessage include ActiveModel::Validations attr_accessor:nombre,:email,:contenido validates_presence_of:nombre,:email,:contenido def initialize(nombre,email,contenido) @nombre,@email,@contenido=nombre,email,contenido final final
Como ven en el ejemplo es una clase normal pero en ésta incluimos ActiveModel::Validations
para utilizar el módulo de validaciones de ActiveRecord que estudiamos en el capítulo anterior.
Modelo con ActiveModel (Validations)
Para este curso realizaremos un ejemplo sencillo que consiste en un simple formulario en el que agregaremos un asunto, correo y contenido, el cual vamos a validar de igual forma que en el capítulo anterior (Haciendo usos de los módulos de ActiveModel), pero estos datos no serán guardados en base de datos. Probablemente se estén preguntando cual es la utilidad de agregar un formulario sin que los datos se dirijan a un destino, pues entre otras cosas, pudiéramos enviar el mensaje por correo electrónico desde nuestro servidor o incluso enviar los datos por medio de un servicio web (Web Service) a otra aplicación que lo procese.
Empezaremos creando nuestro modelo:
class Message #incluimos los módulos que vamos a utilizar include ActiveModel::Validations #necesario para agregar las condiciones de validacion include ActiveModel::Conversion # contiene entre otras cosas el metodo to_key que usamos en el formulario #declaramos las variables del modelo attr_accessor :name, :email, :content #Agregamos las condicones a vailidar validates_presence_of :name, :email, :content validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i validates_length_of :content, :maximum => 500 # El constructor que recibe un hash con los valores del formulario # y nos crea nuestro objeto mensaje def initialize(attributes = {}) attributes.each do |name, value| send("#{name}=", value) end end # Metodo que debemos agregar a nuestro modelo # ya que no se van a guardar los datos en la base de datos def persisted? false end end1234567891011121314151617181920212223242526272829 classMessage #incluimos los módulos que vamos a utilizar include ActiveModel::Validations #necesario para agregar las condiciones de validacion include ActiveModel::Conversion# contiene entre otras cosas el metodo to_key que usamos en el formulario #declaramos las variables del modelo attr_accessor:name,:email,:content #Agregamos las condicones a vailidar validates_presence_of:name,:email,:content validates_format_of:email,:with=>/^[-a-z0-9_+\]+\@([-a-z0-9]+\)+[a-z0-9]{2,4}$/i validates_length_of:content,:maximum=>500 # El constructor que recibe un hash con los valores del formulario# y nos crea nuestro objeto mensaje def initialize(attributes={}) attributeseachdo|name,value| send("#{name}=",value) end end # Metodo que debemos agregar a nuestro modelo# ya que no se van a guardar los datos en la base de datos def persisted? false end end
Una vez creado nuestro modelo ActiveModel simplemente creamos el controlador y las vistas necesarias. Como ya dijimos en capítulos anteriores podemos crear el controlador de una forma rápida con el terminal y la siguiente línea de comando:
rails g controller mensajes1 railsgcontroller mensajes
Agregamos en el archivo de rutas la siguiente linea, para que Rails reconozca las rutas para el controlador:
resources :mensajes1 resources:mensajes
Creamos nuestro controlador:
class MensajesController < ApplicationController def index @mensaje = Mensaje.new end def create @mensaje = Mensaje.new(params[:mensaje]) if @mensaje.valid? # TODO send message here flash[:notice] = "Se envío el mensaje con éxito" redirect_to root_url else render :action => 'index' end end end123456789101112131415161718 classMensajesController<ApplicationController def index @mensaje=Mensajenew end def create @mensaje=Mensajenew(params[:mensaje]) if@mensajevalid? # TODO send message here flash[:notice]="Se envío el mensaje con éxito" redirect_to root_url else render:action=>'index' end end end
Vemos algunas diferencias mínimas con respecto a otro modelos que ya hemos creado antes con acceso a base de datos, por ejemplo: cambiamos el método save
(@mensaje.save) por el método valid?
(@mensaje.valid?) porque obviamente ya no estamos guardando en base de datos, de resto se maneja bastante parecido que con ActiveRecord.
Por último creamos nuestra vista de igual manera que en el capítulo anterior, agregando los bloques que detectan los errores del modelo:
Para finalmente tener un resultado parecido al siguiente, Cabe destacar que el diseño y los mensajes pudieran ser modificados para mejorar la presentación de la pagina.
ActiveModel (Serialization)
Para finalizar con el curso de hoy veremos como funciona el módulo para serializar un objetos con ActiveModel. En Rails es bastante sencillo convertir un objeto a JSON o XML solo necesitamos incluir en nuestra clase el módulo para serializar objetos:
include ActiveModel::Serializers::JSON include ActiveModel::Serializers::Xml12 include ActiveModel::Serializers::JSON include ActiveModel::Serializers::Xml
Luego declaramos un método donde creamos un Hash con los atributos del objeto de la siguiente forma (tomando como ejemplo el objeto del ejercicio anterior)
def attributes {'nombre' => nil,"email" =>nil, "contenido"=>nil} end123 defattributes {'nombre'=>nil,"email"=>nil,"contenido"=>nil} end
Listo ahora en el controlador solo decidimos como queremos mostrar el resultado.
#formato XML # render :xml => @mensaje.to_xml #formato JSON render :json => @mensaje.to_json12345 #formato XML # render :xml => @mensaje.to_xml #formato JSON render:json=>@mensajeto_json
y obtendremos algo como esto dependiendo del formato que lo necesitemos (El ejemplo lo muestra en formato JSON):
{ "nombre":"Ricardo Sampayo", "email":"me@RicardoSampayo.com", "contenido":"Mensaje" }12345 { "nombre":"Ricardo Sampayo", "email":"me@RicardoSampayo.com", "contenido":"Mensaje"}
Conclusión
En esta lección hemos visto un poco de una característica bien importante del framework como lo es ActiveModel, conocimos su sintaxis y una pequeña implementación que espero haya servido para reforzar sus destrezas en Rails y haya aumentado su curiosidad a probarlo.
Una vez más te recomiendo echarle un vistazo a la serie completa de Ruby desde cero, así como a las otras series de CodeHero, agradeciendo de antemano todas sus dudas y comentarios en la sección de comentarios.
¡Hasta el próximo capítulo!