Controladores - La C en MVC

Controladores - La C en MVC

Los controladores son el pegamento entre la lógica de negocios y las vistas en el patrón de diseño MVC – Model, View, Controller.

Cuando el ruteo de Rails determiná qué controlador va a usar para un pedido, nuestro controlador se va a encargar de darle sentido a este pedido y devolver una salida correspondiente.

Cada controlador es una clase Ruby que hereda de la clase de Rails ApplicationController.

Métodos y Acciones

El ruteo determina qué controlador y acción debe ejecutar. Rails crea una instancia del controlador y ejecuta el método con el mismo nombre de la acción correspondiente.

Capitán Obvio dice: Solo los métodos públicos de un Controlador son ejecutables como acción.
Buena práctica: Bajar la visibilidad de los métodos que no son creados con la intención de ser acciones como métodos auxiliares o filtros.

Parámetros

Desde el controlador podemos acceder a todos los parámetros enviados en el pedido HTTP. Los dos tipos de parámetros son:

  • Query String Parameters – Los enviados a través de la URL (lo que está en la URL después del signo “?”).
  • Post Data – Información de un pedido POST HTTP, generalmente enviado desde un form html.

Ambos tipos de parámetros están disponibles a través del hash params.

El hash params puede contener Arrays y Hashes:

Array
GET /clients?ids[]=1&ids[]=2&ids[]=3
> params[:id] = ["1", "2", "3"]
Hash

<form method="post">
  <input type="text" name="client[name]" value="Acme" />
  <input type="text" name="client[phone]" value="8881234" />
</form>
> params[:client] {
    "name" => "Acme",
    "phone" => "8881234"
  }

El objeto params es de la clase HashWithIndifferentAccess de Active Support, una clase totalmente imprescindible cuya función es permitir escribit params[:key] y params['key'] y obtener el mismo valor por ambas claves…

Parámetros JSON y XML

Rails convierte automáticamente los parámetros JSON y XML al hash params.
Ejemplo JSON:

{ "company": { "name": "acme", "address": "Lo que sea" } }
>params[:company] { :name => “acme”, “address” => “Lo que sea” }

Omitir elemento raíz de JSON/XML:
En initializers – config.wrap.parameters = on
En controlador – wrap_parameters

Ruteando parámetros

En el hash params siempre encontramos las llaves :controller y :action pero deberíamos acceder a ellos con :controller_name y :action_name.

match 'clients/:status' => 'cliens#index', :foo => "bar"
GET /clients/active
> params[:status] = "active"
  params[:foo] = "bar"

Sesiones

Las aplicaciones web tienen una sesión por cada usuario en la que se pueden guardar pequeñas cantidades de información que será persistida entre pedidos.

La sesión está disponible únicamente en el Controlador y la Vista. Se puede usar uno de varios mecanismos:

  • ActionDispatch::Session::cookieStore – Guarda todo del lado del cliente
  • ActiveRecord::SessionStore – Guarda la información en la base de datos usando ActiveRecord
  • ActionDispatch::Session::CacheStore – Guarda la información en la cache de Rails
  • ActionDispatch::Session::MemCacheStore – Guarda la información en un clúster memcache (implementación legacy, usar CacheStore en su lugar)

Todos los mecanismos de guardado de sesión usan una cookie para guardar un ID único para cada sesión (obligatorio usar una cookie, Rails no permite pasar el id de sesión a través de la URL).

Cookie Store
Guarda el id y la información en la cookie. Todos los otros mecanismos guardan el id y la información se obtiene con ese id buscando en el servidor. Es muy lviano, no requiere configuración. La información de la cookie está firmada pero no encriptada, Rails no la aceptará si ha sido editada.

Permite 4Kb de información. No debería guardar objetos complejos (como instancias de modelos).

ActionDispatch::Session::CacheStore
Para casos en los que la sesión de usuario no necesita guardar información crítica o no se necesita por períodos largos de tiempo. Usa la implementación de caché de tu aplicación para guardar sesiones.
Ventaja: Usar estructura actual de caché.
Desventaja: las sesiones serán efímeras, podrían desaparecer.

Archivo:
config/initializers/session_store.rb
– Cambiar el mecanismo de almacenamiento de sesión.
– Establecer la llave de sesión (nombre de la cookie)
– Pasar una llave de dominio para especificar el nombre de dominio para la cookie

Establecer una clave secreta para el firmado de la información de sesión – config/initializers/secret_token.rb

Accediendo a la sesión

En los Controladores se puede acceder a la sesión a través de metódos de instancia de sesión.

Las sesiones se cargan de manera “lazy”, no serán cargadas a menos que accedamos a ellas.

Los valores de la sesión se guardan usando pares clave valor como en un hash.
En el controlador:

def current_user
  @current_user ||= session[:current_user_id] &&
    User.find_by_id(session[:current_user_id]
end

Guardando valores:

def create
  if user = User.authenticate(params[:username], params[:password])
    session[:current_user_id] = user.id
    redirect_to root_url
  end
end

Para eliminar algo de la sesión, simplemente asignamos el valor nil a la clave. Para reiniciar toda la sesión, usamos el método reset_session.

Flash

El flash es una parte especial de la sesión que desaparece con cada request. Ejemplo:

def destroy
  session[:user_id] = nil
  flash[:notice] = "Has cerrado sesión"
  redirect...

También es posible asignar mensajes flash en redirecciones:

redirect_to root_url, :notice => "Has cerrado sesión correctamente"

flash.keep mantiene el valor para otro request.
flash.now Accede a los valores en el mismo request.

Cookies

Cookies

Cookies

Las cookies (o galletitas) son pequeñas cantidades de información del lado del cliente que es persistida a través de pedidos y sesiones.

cookies – Funciona como un hash:

cookies[:commenter_name] = @comment.name
...
cookies.delete(:commenter_name)

Observar que para borrar el valor de una sesión, se asignaba nil a la clave. En el caso de las cookies, se debe usar cookies.delete(:llave)

Conclusión

Voy a dejar por acá este primer post sobre Controladores en Rails. Si les interesa ir siguiendo este tema, a esta altura deberían entender el flujo de un request en un controlador, y por qué y cómo guardar información en la sesión o con cookies.

Hay más para ver sobre los controladores: filtros, los objetos request y response y algo de seguridad básica. Pero lo dejo para la próxima entrega de “Apuntes Rails” :)

2 comentarios para la entrada.

  1. Avatar Garusis 8 junio. 2013 - 12:52 pm Google Chrome 27.0.1453.94 Windows 7

    Agradezco mucho tu post. Al fin he podido comprender correctamente el funcionamiento de las sesiones en general y me he dado cuenta que habia estado haciendo algo peligroso (Guardar elementos complejos en la sesion, usando como metodo el almacenamiento en cookies), asi que he tomado las respectivas medidas. Muchas gracias por la informacion.

Dejar un comentario

Notificarme los nuevos comentarios por correo electrónico. Tambien puedes suscribirte sin comentar.

  1. WordPress Apuntes Rails: Migraciones | Picando Código | 3 septiembre. 2012 - 9:40 pm

    [...] y las armaba en forma de post. La segunda instancia en esa “serie” fue sobre los Controladores.Desde entonces no he usado mucho Rails, sí otros frameworks en Ruby como Sinatra y Cuba. Sin [...]