Creando nuestro primer Controlador

Como bien mencioné en el artículo anterior, el controlador de Facts es algo extenso, por lo cuál requiere un artículo completo dedicado al mismo. Al final generamos el controlador, por lo cuál debería de estar ubicado en app/controllers/facts_controller.rb. Abre el archivo, es hora de hacer magia.

Las acciones básicas de toda aplicación CRUD son:

  1. Create
  2. Read
  3. Update
  4. Delete

En Rails, existen y se llaman exactamente así, solo que hay algunas variaciones que veremos más adelante. Comencemos con la primera acción que deseamos en nuestro controlador: una lista de facts.

Para esto, simplemente crea el método index, donde listaremos todos los objetos de nuestra tabla Facts:

def index
  @facts = Fact.all
end

Nota: Siempre en el método index debes usar el nombre en plural, ya que posteriormente iteraremos sobre cada objeto de manera individual en nuestra vista índice.

Si bien lo veremos más adelante, para que te hagas una idea, la iteración sería así:

@facts.each do |fact|

Sin embargo, si usamos el método anterior, estaremos listando los objetos de manera ascendente, es decir, los últimos objetos creados serían los últimos mostrados, ¡no es lo que queremos!.

Por suerte, es muy fácil de solucionar, podemos hacer uso de un método de consultas de ActiveRecord (QueryMethod) llamado order.

Si modificamos nuestro método actual para mostrar los objetos de manera descendiente, se vería así:

def index
  @facts = Fact.all.order("created_at DESC")
end

Nuestro siguiente método será show, donde podremos visualizar Facts de manera individual.

def show
  @fact = Fact.find(params[:id])
end

Nuestras URLs tienen parámetros, por lo cuál estamos haciendo uso de el id (entero que identifica cada uno de nuestros Facts) para mostrar los datos de ese Fact. Un ejemplo podría ser http://localhost:3000/facts/1, aquí el 1 es el parámetro id con el cuál haremos la consulta a nuestra base de datos, así que obtendremos la información de ese Fact en concreto.

El siguiente método que crearemos será new:

def new
  @fact = Fact.new
end

Nos servirá para renderizar nuestra vista new y decirle a Rails que vamos a crear un nuevo objeto.

Para guardar el objeto en nuestra base de datos, usamos el método create:

def create
  @fact = Fact.new(fact_params)
  @fact.user = current_user
  
  if @fact.save
    redirect_to @fact, :notice => "Fact created successfully!"
  else
    render "new"
  end
end

Es algo más extenso que los anteriores así que nos detendremos a explicarlo:

  1. Creamos un nuevo objeto y aceptamos únicamente los parámetros permitidos (fact_params) el cuál es un método que aún no creamos; lo haremos a continuación.
  2. Asignamos un usuario a el fact que vamos a crear, en este caso lo hacemos mediante el helper de Devise: current_user, el cuál retorna el usuario de la sesión actual.
  3. Un par de condicionales, si el fact es guardado con éxito en la base de datos redireccionaremos al usuario a la vista de este y le notificaremos que fue creado satisfactoriamente. Si no fue creado, mostraremos la vista new nuevamente con los errores que impidieron que fuera creado.

El método fact_params lo usaremos en nuestro método update, así que es una buena idea crearlo ahora mismo:

private
  
  def fact_params
    params.require(:fact).permit(:title, :description)
  end

Como puedes ver, está incluido en un bloque private, de esta manera es únicamente accesible dentro de esta clase. El código se explica bastante bien por su cuenta, únicamente permitimos un titulo y una descripción, si por alguno motivo es algo distinto, no será guardado.

Continuando con los métodos, creamos edit:

def edit
  @fact = Fact.find(params[:id])
end

Muestra nuestra vista de edit para el fact que hemos pasado como parámetro, un ejemplo de esta URL sería http://localhost:3000/facts/1/edit. Sin embargo, estamos repitiendo código y esto no es para nada acorde con la manera en que escribes aplicaciones en Rails, por lo tanto crearemos otro método en private:

def find_fact
  @fact = Fact.find(params[:id])
end

Ahora, tenemos que editar nuestro controlador, justo debajo de class FactsController < ApplicationController añade la siguiente línea

before_action :find_fact, only: [:show, :edit, :update, :destroy]

De esta manera le indicamos a Rails que antes de cualquier acción, encuentre nuestro Fact, pero únicamente en los métodos show, edit, update y destroy.

Ya que estamos, añade también la siguiente línea debajo de la anterior, asegura que un usuario se encuentre autentificado antes de crear, editar o eliminar un fact, una vez más, es un helper proporcionado por Devise.

before_action :authenticate_user!, except: [:index, :show]

Ahora, actualicemos nuestros métodos show y edit:

def show
end

def edit
end

Se ven mucho más claros, ¿no lo crees?.

Para actualizar un fact, hacemos uso del método update:

def update
  if @fact.update(fact_params)
    redirect_to @fact, :notice => "Fact updated successfully"
  else
    render "edit"
  end
end

Este método es muy similar a create, trata de entender que hace.

Nuestro último método por el momento será el de destroy, para eliminar Facts.

def destroy
  @fact.destroy
  redirect_to facts_path, :notice => "Fact deleted successfully!"
end

Eliminamos el fact y redirigimos a nuestro índice con la lista de facts, bastante simple, ¿no lo crees?.

Para terminar por ahora, debemos editar nuestro routes.rb para añadir rutas que usen nuestro controlador:

Rails.application.routes.draw do
  devise_for :users
  root "facts#index"
  resources :facts
end

Usamos resources para decirle a Rails que haremos todas las operaciones básicas (CRUD), y no tener que crear una por una.

En el próximo artículo trabajaremos en el aspecto visual de nuestra aplicación, añadiremos Semantic UI para hacerla atractiva y podrás ver tu aplicación funcionando por primera vez. Puedes ver el código finalizado del controlador aquí: https://gist.github.com/Oxyrus/6b908d92c8d593e64a036f7443c147f5