viernes, 23 de septiembre de 2016

Relación 1 a muchos (Categorias/Clasificación de Artículos)

Se pretende clasificar los artículos creados con un scaffold en sus diferentes categorías. Un Artículo puede pertenecer a una sola Categoría, y una Categoría puede tener muchos Artículos, es por eso que nuestra relación es de 1 a muchos.

Hay 2 métodos para lograrlo, uno es la manera sencilla, creada a partir de las relaciones, la segunda, es un poco más compleja, utilizando los maps para ir almacenando las opciones al momento de desplegar las categorías.



1er MÉTODO


1.- Generar el scaffold de Category y correr la migración. Tendrá como único campo name para poder asignarle un nombre a la categoría

     rails g scaffold Category name 

     rake db:migrate



2.- Crear la relación. En caso de que no existiera la tabla Articles, se podría generar un scaffold y usar un category:references para que este, creara la relación y el campo que guardaría el ID de las categorías. En este caso, la tabla ya está creada, por lo tanto, generaremos el campo de forma manual, creando una migración para añadir este nuevo campo:

     rails generate migration add_category_id_to_articles category:references


Este comando generará automáticamente la migración que necesitamos, añadiendo una referencia en la tabla Artícles de la tabla Categories, con un campo llamado category_id, haciéndolo llave foránea y creando un índice:

(clic para agrandar)
 Después, solo será cuestión de correr la migración con rake db:migrate



3.- En la carpeta de modelos, modificaremos el recién creado (category.rb) y el de los artículos (article.rb). En el de las categorías, indicaremos como has_many los artículos debido a que una categoría puede estar presente en muchos artículos, y validaremos que el campo name sea único y no pueda quedar en blanco:


  has_many :articles
validates :name, uniqueness: {message: "Ya existe una categoría con este nombre"},
        presence: { message: "El nombre de la categoría no puede quedar vacío"}


(clic para agrandar)

Y en el de los modelo de artículos, pondremos como belongs_to a categorias, ya que se pretende, que un artículo solo pueda tener 1 categoria, al igual que validaremos que dicho campo sea llenado:

  belongs_to :category

(clic para agrandar)

**Cuando se usa has_many la referencia es en plural y cuando se usa belongs_to debe ir en singular




4.- Iremos al controlador articles_controller y dentro de la función new declararemos la variable que contendrá todas las categorías para que sean accesibles por este método:

@categories = Category.all

(clic para agrandar)



5.- Ahora, iremos a la vista del formulario de nuestros artículos, app/view/articles/ y reemplazaremos el campo que hace mención al category_id (en caso de haberse agregado) y se incluirá un collection_select el cual nos creará una lista desplegable con todas las categorías que hayamos creado. Primero se hace mención al modelo, después el campo y en seguida la variable que se declaró anteriormente, sustituyendo el ID por el nombre de la categoría y agregando un prompt que servirá como opción por defecto cuando aún no se ha seleccionado nada.


= collection_select(:article, :category_id, @categories, :id, :name, :prompt => "Seleccione Uno")

(clic para agrandar)



6.- De la misma manera en que se hizo en el punto 4, será necesario declarar la variable en el método edit para poder visualizar las categorías cuando se esté en el formulario de edición:

(clic para agrandar)


*** No olvidar agregar el campo de category_id a la lista de parámetros fuertes

Aplicando ejemplos:

Menú superior basado en categorías:


1.- En el controlador application_controller.rb crearemos un before_action debido a que necesitamos pasar información a todas las vistas (que por ende, el menú deberá integrarse en views/layouts/application.html.erb ya que esta vista es la que cargara en todas las demás). Así que nuestro before_action llama al método set_categories que definiremos, y este método recoge todas las categorías:


  before_action :set_categories

  private

  def set_categories
   @categoriesmenu = Category.all
  end


(clic para agrandar)



2.- Ahora se puede añadir la navegación en cualquier parte del proyecto accediendo a los datos de @categoriesmenu. En este caso, se crea un menú lateral con una lista, a quien además, se le añade una clase dinámica que se irá autoincrementando para que coincida con algunas clases que definí en CSS. El método para poder imprimir las categorías será con un método each recorriendo @categoriesmenu, y para la clase dinámica simplemente un contador, donde =link_to categoria.name, categoria estaría imprimiendo el nombre(name) de la categoría y funcionaría como enlace hacia la propia categoría, y {:class => "ret#{i+=1}"} sería una atributo que estaríamos pasando por haml (sí, el HTML se encuentra escrito en HAML) para añadir la clase ret concatenando la variable i (antes definida) sumándole 1:



%ul.list-group#menu-prin
     %li.list-group-item.animated.fadeInLeft.ret3=link_to "Inicio", root_path
     -i = 4
     -@categories.each do |categoria|
          %li.list-group-item.animated.fadeInLeft{:class => "ret#{i+=1}"}
               =link_to categoria.name, categoria


(clic para agrandar)

De esta manera, se ha generado nuestro menú lateral, usando las categorías que se encuentran en nuestra tabla Categories.








1 comentario:

  1. MGM Resorts International Casino Resort - Mapyro
    Find MGM Resorts 정읍 출장안마 International 군산 출장안마 Casino Resort, Las Vegas, NV, United States, photos, maps, rates, amenities: 계룡 출장안마 expert Las Vegas 수원 출장마사지 research, only at 경상남도 출장샵

    ResponderEliminar