Está en la página 1de 51

Relaciones N a N _

Definiciones Iniciales
Configuraciones

Un proyecto nuevo en Rails puede partir de las siguientes maneras

● rails new blog


● rails __5.2.3__ new blog
● rails new blog --database=postgresql
Generadores

Rails ofrece el subcomando “generate”, algunas opciones son:

● rails generate scaffold


● rails generate scaffold_controller
● rails generate migration
Usar scaffold en un recurso
rails g scaffold Post title:string content:text author:string

Crea un modelo Post con atributos: Genera los archivos necesarios, con código
base, entre ellos:

● title: string ● Modelo


● content: text ● Migración
● author: string ● Controlador
Relaciones N a N
Relaciones N a N
Relaciones en Rails

El método más común es usar relaciones del tipo HABTM (has and belongs
to many)
Tabla Join
$ rails g migration CreateJoinTablePostTag post tag

class CreateJoinTablePostTag < ActiveRecord::Migration[5.2]


def change
create_join_table :posts, :tags do |t|
# t.index [:post_id, :tag_id]
# t.index [:tag_id, :post_id]
end
end
end
Relación en modelos

Usamos has_and_belongs_to_many para


relacionar dos modelos

class Post < ApplicationRecord


has_and_belongs_to_many :tags
end
Operaciones N a N
Relaciones N a N
Existen dos formas de implementarlas:

Relaciones intransitivas: Relaciones transitivas:

● Es un tipo de relación directa entre dos ● Es un tipo de relación indirecta, donde se


modelos usa un modelo intermedio
Consola de Rails

Podemos usar “rails console” que abre el modo interactivo, donde podemos
probar nuestro desarrollo usando código ruby
Asociación de recursos
Desde la consola de rails, podemos probar la asignación de recursos

post = Post.create(...)
tag = Tag.create(...)

# asignamos el tag, a la lista de tags asociados a post

post.tags << tag


Asociación Transitiva

Dos modelos se relacionan entre sí usando un tercer modelo intermedio


Asociación Transitiva en Rails

En Rails usamos “has_many :through” para definir una relación N a N


usando un modelo intermedio
Asociación Transitiva en Rails

Para transformar una relación directa a una indirecta, se agregan los ID de los modelos en cuestión

class ChangePostsTagsTable < ActiveRecord::Migration[5.2]


def change
rename_table 'posts_tags', 'post_tags'
add_column :post_tags, :id, :primary_key
add_column :post_tags, :available, :boolean, default: true
end
end
Operaciones desde consola

Podemos realizar algunas operaciones desde la consola de Rails :

Listamos todos los tags asociados a un post

post = Post.last
post.tags

Eliminamos los tags asociados a un post

post.tags.destroy_all
Asignar un recurso directamente

Podemos guardar una relación entre post y tag creando un registro del
modelo PostTag

PostTag.create(post_id, tag_id)
Crear una relación transitiva directamente

create_table :posts do |t|


t.string :title
t.text :content
t.string :author
Creamos un archivo de migración: t.timestamps
end
rails g migration CreatePostTagRelationship
create_table :tags do |t|
Y agregamos el contenido dentro del método t.string :title
t.timestamps
change:
end

create_table :post_tags do |t|


t.belongs_to :post, index: true
t.belongs_to :tag, index: true
t.boolean :available, default: true
t.timestamps
end
Relaciones dependientes

En versiones anteriores a Rails 5, en las relaciones del tipo has_many :through era posible eliminar
en cascada los elementos asociados, usando “dependent: :destroy”

class Post < ApplicationRecord


has_many :post_tags
has_many :tags, through: :post_tags, dependent: :destroy
end
Creación de recursos
Servidor local
Rutas de modelos intermedios

Rails.application.routes.draw do
resources :tags
resources :posts
resources :post_tags
end
Rutas de modelos intermedios

El controlador de la tabla intermedia no necesariamente


debe tener todas las rutas REST y podemos definir solo
aquellas que nos sirvan.
Scaffold de controlador

Usamos scaffold para generar los archivos del modelo intermedio

rails g scaffold_controller PostTags


Visualizar tags
Mejorando las vistas
Recursos anidados

Podemos asignar directamente los Tags en la creación de un post:

<div class="field">
<%= form.label :tags %>
<%= form.collection_check_boxes(:tag_ids,
Tag.all,
:id,
:title) do |b| %>
<%= b.label class:"label-checkbox" do%>
<%=b.check_box + b.text%>
<%end%>
<% end %>
</div>
Recursos anidados

Podemos desasociar los recursos intermedios con sólo desmarcar los


checkboxes. Internamente Rails se encargará de eliminar la relación
entre los dos modelos.
Strong Parameters

strong params funcionan a modo de "filtro" y permiten restringir y


permitir que valores estamos recibiendo desde el exterior
Restringiendo recursos
N + 1 queries

Es un problema que implica múltiples llamadas a la base de datos y


que afecta en el rendimiento del sistema
N + 1 queries

Problema graficado en código

posts = Post.order(:published_at).limit(10)

posts.each do |post|
puts "#{post.author.name} wrote #{post.title}"
end
N + 1 queries

Problema solucionado:

posts = Post.order(:published_at).includes(:author).limit(10)

posts.each do |post|
puts "#{post.author.name} wrote #{post.title}"
end
Includes vs Joins

La gran diferencia es que internamente includes ejecuta un LEFT


OUTER JOIN y joins un INNER JOIN
Gemas de utilidad

● bundler-audit identifica vulnerabilidades en dependencias


● bullet identificafracciones de código con problemas de N + 1 queries
● peek monitoreo general de aplicaciones rails
Restricción de recursos

Autenticación: Autorización:

● Permitir acceso de usuarios al sistema ● Niveles de acceso y roles


(login)
Integrar Devise

● Agregar “gem devise” al Gemfile


● Instalar la gema con “bundle install”
● Generar los archivos necesarios con “rails g devise:install”
● Crear el nuevo modelo User “rails generate devise User”
● Escribir los cambios en la base de datos “rails db:migrate”
Restringir recurso

Restringimos el acceso a usuario no logueados con: “before_action :authenticate_user!“

class TagsController < ApplicationController


before_action :authenticate_user!
before_action :set_tag, only: [:show, :edit, :update, :destroy]

...

end
Gemas de utilidad

● Pundit manejo de permisos mediante Policies


● CanCanCan manejo de permisos medante Abilities
● Rolify manejo de roles en rails
Testing
Testing

Hacer testing nos ayuda a detectar problemas en etapas tempranas


Integrar Rspec

● Agregar “gem rspec-rails” al Gemfile


● Agregar “gem rails-controller-testing” al Gemfile
● Instalar las dependencias con “bundle install”
● Crear el archivos compartidos con “rails generate rspec:install”
● Escribir los cambios en la base de datos “rails db:migrate”
Specs

Son porciones de código que describen funcionalidades


Testing en controladores

Iniciamos con:

rails generate rspec:controller Posts

Luego agregamos tests:

RSpec.describe PostsController, type: :controller do


describe "GET index" do
...
end
end
Testing en controladores
Testing en modelos

Iniciamos con:

rails generate rspec:model Post

Luego agregamos tests:

RSpec.describe PostsController, type: :model do


describe "GET index" do
...
end
end
Tests en modelos

Muchas veces definiremos nuestros tests y luego implementaremos


los cambios.
Testing en modelos
Testing en modelos

También podría gustarte