Ejemplo de relaciones de tablas en Rails

Hoy vamos a ver como replicar estas relaciones entre tablas, las de la imagen, en rails, vamos a crear las tablas, y establecer las relaciones entre ellas. Vamos a tener cuatro tablas:

esquema bbdd

  • nombres
  • administradores
  • direcciones_ip
  • servidores

El objetivo es poder definir las relaciones de forma que un administrador es una persona que tiene nombre y apellidos, ese administrador puede gestionar varios servidores, los cuales a su vez pueden ser gestionados por varios administradores, y cada servidor puede tener varias direcciones IP, pero cada dirección IP sólo puede estar en un servidor y en un interfaz.3

Si nos fijamos bien hay otra relación que no está definida entre tablas que es dirección IP e interfaz, es una relación uno a uno y como tal se puede incluir en una misma tabla, pero para nuestro ejemplo hemos separado administradores y el nombre de los mismos.

Lo primero que vamos a hacer como crear el proyecto, crear la base de datos, dar permisos a un usuario, configurar acceso al mysql en rails y crear las tablas, así que vamos a hacerlo todo seguido.

ubuntu@ronr:~$ rails new gestionips -d mysql
ubuntu@ronr:~$ mysql -u root -p
mysql> CREATE DATABASE gestionips_development;
mysql> GRANT ALL PRIVILEGES ON gestionips_development.* TO 'edu'@'localhost' IDENTIFIED BY 'password';
ubuntu@ronr:~$ vim gestionips/config/database.yml
    default: &default
    adapter: mysql2
    encoding: utf8
    pool: 5
    username: edu
    password: password
    socket: /var/run/mysqld/mysqld.sock
ubuntu@ronr:~/gestionips$ rails generate model nombre
ubuntu@ronr:~/gestionips$ rails generate model administrador
ubuntu@ronr:~/gestionips$ rails generate model direccion_ip
ubuntu@ronr:~/gestionips$ rails generate model servidor
ubuntu@ronr:~/gestionips/db/migrate$ vim 20161101142603_create_nombres.rb
  class CreateNombres < ActiveRecord::Migration[5.0]
    def change
      create_table :nombres do |t|  
        t.string("nombre", :limit => 25, :null => false)
        t.string("apellidos", :limit => 50, :null => false)
        t.timestamps
      end
    end
  end
  end
ubuntu@ronr:~/gestionips/db/migrate$ vim 20161101142608_create_administradors.rb
  class CreateAdministradors < ActiveRecord::Migration[5.0]
    def change
      create_table :administradors do |t|
        t.timestamps
      end
    end
  end
ubuntu@ronr:~/gestionips/db/migrate$ vim 20161101142620_create_direccion_ips.rb
  class CreateDireccionIps < ActiveRecord::Migration[5.0]
    def change
      create_table :direccion_ips do |t|
        t.string("ip",:limit => 15, :null => false)
        t.string("interfaz", :limit => 25, :null => false)
        t.timestamps
      end
    end
  end
ubuntu@ronr:~/gestionips/db/migrate$ vim 20161101142626_create_servidors.rb
  class CreateServidors < ActiveRecord::Migration[5.0]
    def change
      create_table :servidors do |t|
        t.string("nombre", :limit => 50, :null => false)
        t.timestamps
      end
    end
  end
ubuntu@ronr:~/gestionips$ rake db:migrate

Una vez hecho esto ya podemos concentrarnos en las relaciones, ya que lo único que hemos hecho ha sido crear las tablas vacías con los campos que se indicaban en el diagrama.

Ahora vamos a meter unos datos dummy en la base de datos para empezar a trabajar, para ello desde la consola de rails entrando como rails console desde el directorio raiz del proyecto:

nombre=Nombre.new(:nombre => "Eduardo", :apellidos => "Collado Cabeza")
nombre.save
nombre=Nombre.new(:nombre => "Maria", :apellidos => "Altamirano García")
nombre.save
nombre=Nombre.new(:nombre => "Norma", :apellidos => "Delgado Bugarín")
nombre.save
nombre=Nombre.new(:nombre => "Carlos", :apellidos => "Díaz Cruz")
nombre.save
direccion=DireccionIp.new(:ip => "12.12.43.12", :interfaz => "eth0")
direccion.save
direccion=DireccionIp.new(:ip => "56.21.123.14", :interfaz => "eth1")
direccion.save
direccion=DireccionIp.new(:ip => "121.32.5.7", :interfaz => "eth2")
direccion.save
direccion=DireccionIp.new(:ip => "173.11.53.122", :interfaz => "eth3")
direccion.save
servidor=Servidor.new(:nombre => "SRV-Rails1")
servidor.save
servidor=Servidor.new(:nombre => "SRV-Rails2")
servidor.save
servidor=Servidor.new(:nombre => "SRV-Rails3")
servidor.save
servidor=Servidor.new(:nombre => "SRV-Rails4")
servidor.save

La tabla de administradores sólo tiene una columna que es ID, por eso no hemos rellenado nada después iremos creando según lo necesitemos, así que ya podemos empezar a trabajar.

Relación uno a uno

Entre las tablas nombres y administradores tenemos una relación uno a uno y vamos a decir que nombre tiene un administrador y que un administrador pertenece a un nombre, así que editamos ambos modelos:

ubuntu@ronr:~/gestionips/app/models$ vim nombre.rb 
  class Nombre < ApplicationRecord
    has_one :administrador
  end
ubuntu@ronr:~/gestionips/app/models$ vim administrador.rb
  class Administrador < ApplicationRecord
    belongs_to :nombre
  end

En la clase Administrador le hemos dicho que pertenece a nombre, es decir, es una llave foránea a la llave de la tabla nombre, así que tenemos que crear esa columna en la base de datos:

ubuntu@ronr:~/gestionips$ rails generate migration CrearForeignKeyEnAdministradoclass CrearForeignKeyEnAdministrador < ActiveRecord::Migration[5.0]
    def change
      add_column("administradors","nombre_id","string")
    end
  end

Y ejecutaremos el migrate

ubuntu@ronr:~/gestionips$ rake db:migrate

Si fueramos atrás en versiones y volvieramos tendríamos que volver a introducir los datos dmmy que hemos puesto antes, ya que se borrarían las tablas con drop y al recrearlas lo haría sin contenido.

En este momento entraríamos en la consola de rails para crear las cuatro relaciones uno a uno de nombre y administrador

ubuntu@ronr:~/gestionips$ rails console
irb(main):001:0> nombre=Nombre.find(1)
  Nombre Load (0.4ms)  SELECT  `nombres`.* FROM `nombres` WHERE `nombres`.`id` = 1 LIMIT 1
=> #<Nombre id: 1, nombre: "Eduardo", apellidos: "Collado Cabeza", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09">
irb(main):002:0> administrador=Administrador.new()
=> #<Administrador id: nil, created_at: nil, updated_at: nil, nombre_id: nil>
irb(main):003:0> nombre.administrador=administrador
  Administrador Load (0.4ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`nombre_id` = '1' LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.4ms)  INSERT INTO `administradors` (`created_at`, `updated_at`, `nombre_id`) VALUES ('2016-11-01 17:00:13', '2016-11-01 17:00:13', '1')
   (5.3ms)  COMMIT
=> #<Administrador id: 5, created_at: "2016-11-01 17:00:13", updated_at: "2016-11-01 17:00:13", nombre_id: "1">
irb(main):004:0> nombre=Nombre.find(2)
  Nombre Load (0.5ms)  SELECT  `nombres`.* FROM `nombres` WHERE `nombres`.`id` = 2 LIMIT 1
=> #<Nombre id: 2, nombre: "Maria", apellidos: "Altamirano García", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09">
irb(main):005:0> administrador=Administrador.new()
=> #<Administrador id: nil, created_at: nil, updated_at: nil, nombre_id: nil>
irb(main):006:0> nombre.administrador=administrador
  Administrador Load (0.3ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`nombre_id` = '2' LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.2ms)  INSERT INTO `administradors` (`created_at`, `updated_at`, `nombre_id`) VALUES ('2016-11-01 17:00:13', '2016-11-01 17:00:13', '2')
   (12.9ms)  COMMIT
=> #<Administrador id: 6, created_at: "2016-11-01 17:00:13", updated_at: "2016-11-01 17:00:13", nombre_id: "2">
irb(main):007:0> nombre=Nombre.find(3)
  Nombre Load (0.7ms)  SELECT  `nombres`.* FROM `nombres` WHERE `nombres`.`id` = 3 LIMIT 1
=> #<Nombre id: 3, nombre: "Norma", apellidos: "Delgado Bugarín", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09">
irb(main):008:0> administrador=Administrador.new()
=> #<Administrador id: nil, created_at: nil, updated_at: nil, nombre_id: nil>
irb(main):009:0> nombre.administrador=administrador
  Administrador Load (0.4ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`nombre_id` = '3' LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.2ms)  INSERT INTO `administradors` (`created_at`, `updated_at`, `nombre_id`) VALUES ('2016-11-01 17:00:13', '2016-11-01 17:00:13', '3')
   (5.6ms)  COMMIT
=> #<Administrador id: 7, created_at: "2016-11-01 17:00:13", updated_at: "2016-11-01 17:00:13", nombre_id: "3">
irb(main):010:0> nombre=Nombre.find(4)
  Nombre Load (0.3ms)  SELECT  `nombres`.* FROM `nombres` WHERE `nombres`.`id` = 4 LIMIT 1
=> #<Nombre id: 4, nombre: "Carlos", apellidos: "Díaz Cruz", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09">
irb(main):011:0> administrador=Administrador.new()
=> #<Administrador id: nil, created_at: nil, updated_at: nil, nombre_id: nil>
irb(main):012:0> nombre.administrador=administrador
  Administrador Load (0.5ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`nombre_id` = '4' LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.5ms)  INSERT INTO `administradors` (`created_at`, `updated_at`, `nombre_id`) VALUES ('2016-11-01 17:00:14', '2016-11-01 17:00:14', '4')
   (5.2ms)  COMMIT
=> #<Administrador id: 8, created_at: "2016-11-01 17:00:14", updated_at: "2016-11-01 17:00:14", nombre_id: "4">

Se ve más claro si vemos la tabla directamente en MySQL como se ha rellenado la columna nombre_id

mysql> select * from administradors;
+----+---------------------+---------------------+-----------+
| id | created_at          | updated_at          | nombre_id |
+----+---------------------+---------------------+-----------+
|  5 | 2016-11-01 17:00:13 | 2016-11-01 17:00:13 | 1         |
|  6 | 2016-11-01 17:00:13 | 2016-11-01 17:00:13 | 2         |
|  7 | 2016-11-01 17:00:13 | 2016-11-01 17:00:13 | 3         |
|  8 | 2016-11-01 17:00:14 | 2016-11-01 17:00:14 | 4         |
+----+---------------------+---------------------+-----------+
4 rows in set (0,00 sec)

mysql> select * from nombres;
+----+---------+--------------------+---------------------+---------------------+
| id | nombre  | apellidos          | created_at          | updated_at          |
+----+---------+--------------------+---------------------+---------------------+
|  1 | Eduardo | Collado Cabeza     | 2016-11-01 16:54:09 | 2016-11-01 16:54:09 |
|  2 | Maria   | Altamirano García  | 2016-11-01 16:54:09 | 2016-11-01 16:54:09 |
|  3 | Norma   | Delgado Bugarín    | 2016-11-01 16:54:09 | 2016-11-01 16:54:09 |
|  4 | Carlos  | Díaz Cruz          | 2016-11-01 16:54:09 | 2016-11-01 16:54:09 |
+----+---------+--------------------+---------------------+---------------------+
4 rows in set (0,00 sec)

Relación uno a muchos

Ahora vamos a ver la relación entre servidores y direcciones IP. Un servidor puede tener varias direcciones IP, pero cada dirección IP sólo puede estar en un servidor.

Aquí hay que decir que los métodos disponibles son los siguientes:

  • servidor.direccion_ip
  • servidor.direccion_ip << direccion_ip (añadir al array)
  • servidor.direccion_ip = direccion_ip, direccion_ip (introducimos todo el array)
  • servidor.direccion_ip.delete(direccion_ip) (borramos el objeto)
  • servidor.direccion_ip.destroy(direccion_ip) (borramos el objeto y de la base de datos)
  • servidor.direccion_ip.clear (borramos todo)
  • servidor.direccion_ip.empty? (preguntamos si está vacío el array)
  • servidor.direccion_ip.size (preguntamos el tamaño del array)

Si lo trasladamos a lenguaje Rails tenemos que un servidor has_many :direccionesip

Así procedemos a configurar el fichero

ubuntu@ronr:~/gestionips/app/models$ vim servidor.rb 
  class Servidor < ApplicationRecord
    has_many :direccion_ip
  end
ubuntu@ronr:~/gestionips/app/models$ vim direccion_ip.rb
  class DireccionIp < ApplicationRecord
    belongs_to :servidor
  end

Y como tenemos belongs_to en direccion_ip significa que tenemos que crear una Foreign Key apuntando a servidor mediante una nueva migración

 

ubuntu@ronr:~/gestionips$ rails generate migration CrearForeignKeyEnDireccionIp
ubuntu@ronr:~/gestionips$ vim db/migrate/20161101172341_crear_foreign_key_en_direccion_ip.rb
  class CrearForeignKeyEnDireccionIp < ActiveRecord::Migration[5.0]
    def change
      add_column("direccion_ips","servidor_id","string")
    end
  end
ubuntu@ronr:~/gestionips$ rake db:migrate

Y entramos en la consola de rails. Vamos a asignar todas las IPs que tenemos en los datos dummy al primer servidor

ubuntu@ronr:~/gestionips$ rails console
Running via Spring preloader in process 7156
Loading development environment (Rails 5.0.0.1)
irb(main):001:0> servidor=Servidor.find(1)
  Servidor Load (0.4ms)  SELECT  `servidors`.* FROM `servidors` WHERE `servidors`.`id` = 1 LIMIT 1
=> #<Servidor id: 1, nombre: "SRV-Rails1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09">
irb(main):002:0> direccionip = DireccionIp.find(1)
  DireccionIp Load (0.4ms)  SELECT  `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`id` = 1 LIMIT 1
=> #<DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09", servidor_id: nil>
irb(main):003:0> servidor.direccion_ip << direccionip
   (0.3ms)  BEGIN
  SQL (0.6ms)  UPDATE `direccion_ips` SET `updated_at` = '2016-11-01 17:29:50', `servidor_id` = '1' WHERE `direccion_ips`.`id` = 1
   (4.2ms)  COMMIT
  DireccionIp Load (0.7ms)  SELECT `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`servidor_id` = '1'
=> #<ActiveRecord::Associations::CollectionProxy [#<DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:50", servidor_id: "1">]>
irb(main):004:0> direccionip = DireccionIp.find(2)
  DireccionIp Load (0.7ms)  SELECT  `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`id` = 2 LIMIT 1
=> #<DireccionIp id: 2, ip: "56.21.123.14", interfaz: "eth1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09", servidor_id: nil>
irb(main):005:0> servidor.direccion_ip << direccionip
   (0.4ms)  BEGIN
  SQL (0.5ms)  UPDATE `direccion_ips` SET `updated_at` = '2016-11-01 17:29:58', `servidor_id` = '1' WHERE `direccion_ips`.`id` = 2
   (7.9ms)  COMMIT
=> #<ActiveRecord::Associations::CollectionProxy [#<DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:50", servidor_id: "1">, #<DireccionIp id: 2, ip: "56.21.123.14", interfaz: "eth1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:58", servidor_id: "1">]>
irb(main):006:0> direccionip = DireccionIp.find(3)
  DireccionIp Load (0.5ms)  SELECT  `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`id` = 3 LIMIT 1
=> #<DireccionIp id: 3, ip: "121.32.5.7", interfaz: "eth2", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09", servidor_id: nil>
irb(main):007:0> servidor.direccion_ip << direccionip
   (0.2ms)  BEGIN
  SQL (0.6ms)  UPDATE `direccion_ips` SET `updated_at` = '2016-11-01 17:30:03', `servidor_id` = '1' WHERE `direccion_ips`.`id` = 3
   (7.4ms)  COMMIT
=> #<ActiveRecord::Associations::CollectionProxy [#<DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:50", servidor_id: "1">, #<DireccionIp id: 2, ip: "56.21.123.14", interfaz: "eth1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:58", servidor_id: "1">, #<DireccionIp id: 3, ip: "121.32.5.7", interfaz: "eth2", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:30:03", servidor_id: "1">]>
irb(main):008:0> direccionip = DireccionIp.find(4)
  DireccionIp Load (0.4ms)  SELECT  `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`id` = 4 LIMIT 1
=> #<DireccionIp id: 4, ip: "173.11.53.122", interfaz: "eth3", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09", servidor_id: nil>
irb(main):009:0> servidor.direccion_ip << direccionip
   (0.2ms)  BEGIN
  SQL (0.5ms)  UPDATE `direccion_ips` SET `updated_at` = '2016-11-01 17:30:08', `servidor_id` = '1' WHERE `direccion_ips`.`id` = 4
   (7.6ms)  COMMIT
=> #<ActiveRecord::Associations::CollectionProxy [#<DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:50", servidor_id: "1">, #<DireccionIp id: 2, ip: "56.21.123.14", interfaz: "eth1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:58", servidor_id: "1">, #<DireccionIp id: 3, ip: "121.32.5.7", interfaz: "eth2", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:30:03", servidor_id: "1">, #<DireccionIp id: 4, ip: "173.11.53.122", interfaz: "eth3", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:30:08", servidor_id: "1">]>

Y si vemos en MySQL vemos que todas las IPs se han asignado al servidor_id 1, es decir, al primero:

mysql> mysql> select * from direccion_ips;
+----+---------------+----------+---------------------+---------------------+-------------+
| id | ip            | interfaz | created_at          | updated_at          | servidor_id |
+----+---------------+----------+---------------------+---------------------+-------------+
|  1 | 12.12.43.12   | eth0     | 2016-11-01 16:54:09 | 2016-11-01 17:29:50 | 1           |
|  2 | 56.21.123.14  | eth1     | 2016-11-01 16:54:09 | 2016-11-01 17:29:58 | 1           |
|  3 | 121.32.5.7    | eth2     | 2016-11-01 16:54:09 | 2016-11-01 17:30:03 | 1           |
|  4 | 173.11.53.122 | eth3     | 2016-11-01 16:54:09 | 2016-11-01 17:30:08 | 1           |
+----+---------------+----------+---------------------+---------------------+-------------+
4 rows in set (0,00 sec)

Relación muchos a muchos

Para establecer esta relación y cumplir las formas normales es necesario crear una tabla join intermedia. Esta tabla estará compuesta únicamente por las dos claves foráneas y no tendrá tampoco la clave primaria (id) que crea por defecto Rails, así que habrá que quitársela con :id => false en la migración.

El nombre de la tabla será igual al nombre de las dos tablas unidas por guión y dispuestas por orden alfabético, en nuestro caso será administradors_servidors (el plural este tan raro es el que hace Rails añadiendo simplemente una s)

ubuntu@ronr:~/gestionips$ rails generate migration CreateAdministradors_ServidorsJoin
ubuntu@ronr:~/gestionips$ ubuntu@ronr:~/gestionips$ vim db/migrate/20161101175712_create_administradors_servidors_join.rb
  class CreateAdministradorsServidorsJoin < ActiveRecord::Migration[5.0]
    def change
      create_table :administradors_servidors, :id => false do |t|
        t.integer("administrador_id")
        t.integer("servidor_id")
      end
      add_index :administradors_servidors, ["administrador_id","servidor_id"], :name => 'admin_index'
    end
  end
ubuntu@ronr:~/gestionips$ rake db:migrate

En el index hemos tenido que añadir

, :name => 'admin_index'

porque nos daba este error en el rake db:migrate

Index name 'index_administradors_servidors_on_administrador_id_and_servidor_id' on table 'administradors_servidors' is too long; the limit is 64 characters
/home/ubuntu/gestionips/db/migrate/20161101175712_create_administradors_servidors_join.rb:7:in `change'

Ahora en los dos modeles involucrados tendremos que poner has_and_belongs_to_many :el_otro_modelo.

has_and_belongs_to_many :el_otro_modelo
ubuntu@ronr:~/gestionips/app/models$ vim administrador.rb 
  class Administrador < ApplicationRecord
    belongs_to :nombre
    has_and_belongs_to_many :servidor
  end
ubuntu@ronr:~/gestionips/app/models$ vim servidor.rb 
  class Servidor < ApplicationRecord
    has_many :direccion_ip
    has_and_belongs_to_many :administrador
  end

Y ahora vamos introduciendo datos a base de buscar un administrador, un servidor y enlazarlos

irb(main):032:0> administrador=Administrador.find_by_id(6)
  Administrador Load (0.9ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`id` = 6 LIMIT 1
=> #<Administrador id: 6, created_at: "2016-11-01 17:00:13", updated_at: "2016-11-01 17:00:13", nombre_id: "2">
irb(main):033:0> servidor=Servidor.find(4)
  Servidor Load (0.8ms)  SELECT  `servidors`.* FROM `servidors` WHERE `servidors`.`id` = 4 LIMIT 1
=> #<Servidor id: 4, nombre: "SRV-Rails4", created_at: "2016-11-01 16:54:11", updated_at: "2016-11-01 16:54:11">
irb(main):034:0> administrador.servidor << servidor
   (0.6ms)  BEGIN
  SQL (0.6ms)  INSERT INTO `administradors_servidors` (`administrador_id`, `servidor_id`) VALUES (6, 4)
   (9.0ms)  COMMIT
  Servidor Load (0.9ms)  SELECT `servidors`.* FROM `servidors` INNER JOIN `administradors_servidors` ON `servidors`.`id` = `administradors_servidors`.`servidor_id` WHERE `administradors_servidors`.`administrador_id` = 6
=> #<ActiveRecord::Associations::CollectionProxy [#<Servidor id: 4, nombre: "SRV-Rails4", created_at: "2016-11-01 16:54:11", updated_at: "2016-11-01 16:54:11">, #<Servidor id: 4, nombre: "SRV-Rails4", created_at: "2016-11-01 16:54:11", updated_at: "2016-11-01 16:54:11">]>

En MySQL se vería así:

mysql> select * from administradors_servidors;
+------------------+-------------+
| administrador_id | servidor_id |
+------------------+-------------+
|                5 |           1 |
|                5 |           2 |
|                5 |           3 |
|                6 |           4 |
|                7 |           2 |
|                7 |           3 |
|                7 |           4 |
|                8 |           4 |
+------------------+-------------+
8 rows in set (0,00 sec)