Asociaciones en Ruby on Rails

ASOCIACIONES

belongs_to (PERTENECE A)

Especifico para relaciones one-to-one (1:1)  con otra clase. Este método solo puede ser usado si esta clase contiene la clave externa. Si la otra clase contiene la clave externa deberá usar has_one en su lugar.

has_one (TIENE UN)

Especifico para relaciones one-to-one (1:1) con otra clase. Este método este método solo puede ser usado si la otra clase contiene la clave externa. Si la clase actual contiene la clave externa deberá usar belongs_to en su lugar.

 

** ¿ Es una asociación belongs_to ó has_one?

Ambos expresan una relación (1:1). La diferencia es donde colocar la clave foránea, que va en la tabla de la clase que declaro la asociación belongs_to.

class User < ActiveRecord::Base
  belongs_to :account
end

class Account < ActiveRecord::Base
  has_one :user
end
CREATE TABLE users (
id bigint NOT NULL auto_increment,
account_id bigint default NULL,      #<----Foreign Key
name varchar default NULL,
PRIMARY KEY (id)
)

CREATE TABLE accounts (
id bigint NOT NULL auto_increment,
name varchar default NULL,
PRIMARY KEY (id)
)

 

has_many (TIENE MUCHOS)

Especifica una asociación de uno a muchos. (1:N). La clase referenciada debe implementar belongs_to.

has_and_belongs_to_many (TIENE Y PERTENECE A MUCHAS)

Especifica una asociación de muchos a muchos (N:M) con otra clase. Estas clases se asocian en una tabla intermedia. Ambas clases deben usar has_and_belongs_to_many para referenciar a la otra clase.

RELACIONES

RELACIÓN ONE TO ONE (1:1)

(**Ejemplo que un Usuario solo puede tener una Dirección Postal)

1.- Creamos modelos (usuario, address)

bin/rails g model Usuario name:string
bin/rails g model Address street:string

 

2.- Añadimos la columna Usuario (has_one) a la Dirección (belongs_to)

bin/rails generate migration AddUsuarioToAddresses usuario:references

Se crea la siguiente migración:

class AddUsuarioToAddresses < ActiveRecord::Migration[5.0]
  def change
    add_reference :addresses, :usuario, foreign_key: true
  end
end

 

3.- Ejecutamos la migración en la BBDD:

rake db:migrate

 

4.- ActiveRecord no sabe de la asociación de los dos modelos, Tenemos que añadir los atributos has_one y belongs_to:

class Usuario < ApplicationRecord
  has_one :address
end


class Address < ApplicationRecord
  belongs_to :usuario
end

 

5.- Ahora se podría añadir una Dirección a un Usuario:

usuarioEjemplo = Usuario.new(name:"Pepe")
direccionEjemplo = Address.new(street:"Calle Ejemplo")

#Ambas hacen la asociacion
# direccionEjemplo.usuario = usuarioEjemplo
# usuarioEjemplo.address = direccionEjemplo

usuarioEjemplo.save

Y buscar la Dirección que esta asociada al ultimo Usuario guardado:

Usuario.last.address

RELACIÓN ONE TO MANY(1:N)

1.- Creamos modelos (comentario,post)

bin/rails g model Comentario text:string
bin/rails g model Post title:string

 

2.- Añadimos la columna Post (has_many) a los Comentarios (belongs_to):

bin/rails generate migration AddPostToComentarios post:references

Se crea la siguiente migración:

class AddPostToComentarios < ActiveRecord::Migration[5.0]
  def change
    add_reference :comentarios, :post, foreign_key: true
  end
end

 

3.- Ejecutamos la migración en la BBDD:

rake db:migrate

 

4.- ActiveRecord no sabe de la asociación de los dos modelos, Tenemos que añadir los atributos has_many y belongs_to:

class Post < ApplicationRecord
  has_many :comentarios
end


class Comentario < ApplicationRecord
  belongs_to :post
end

 

Ahora se podría añadir un Comentario a un Post:

comentario1 = Comentario.new
comentario1.text = "Comentario de prueba"

post1 = Post.new
post1.title = "Primer Post"

post1.comentarios << comentario1

post1.save

Y buscar Comentarios que pertenezcan a un Post:

Post.last.comentarios # [Array de Comentarios]

 

RELACIÓN MANY TO MANY (N:M)

1.- Creamos modelos (usuario, foro)

bin/rails g model User name:string
bin/rails g model Forum name:string

 

2.- Creamos la tabla JOIN

bin/rails g migration CreateJoinTableUsersForums users forums

Se crea la siguiente migración, que tendremos que descomentar:

class CreateJoinTableUsersForums < ActiveRecord::Migration[5.0]
  def change
    create_join_table :users, :forums do |t|
      t.index [:user_id, :forum_id] #Descomentar esto
      t.index [:forum_id, :user_id] #Descomentar esto
    end
  end
end

 

3.- Ejecutamos la migración en la BBDD:

rake db:migrate

 

4.- ActiveRecord no sabe usar la tabla JOIN para asociar los dos modelos, Tenemos que añadir el atributo has_and_belongs_to_many a ambos modelos.

class User < ApplicationRecord
  has_and_belongs_to_many :forums
end

class Forum < ApplicationRecord
  has_and_belongs_to_many :users
end

 

Ahora se podría añadir un Foro a un Usuario

user.forums << Forum.find_by(name: "Ruby")

Y buscar Usuarios que pertenezcan a un Foro:

Forum.find_by(name: "Ruby").users

 

Blog Somos la Clave

Documentacion Oficial