Cuando decides cambiar de Postgres a MongoDB en un proyecto Rails, la migración de modelos es uno de los pasos más críticos. Aquí se aborda cómo reemplazar la herencia de ActiveRecord por la composición de módulos de MongoID, transformando tres modelos independientes: category, note y participant.
¿Por qué eliminar application record al migrar a MongoID?
El archivo application_record.rb cumple un rol fundamental en ActiveRecord: actúa como una clase abstracta que permite definir comportamientos dinámicos y single table inheritance (herencia entre tablas). Sin embargo, MongoID maneja estos comportamientos de forma natural, por lo que este archivo deja de ser necesario [01:00].
La diferencia clave está en el enfoque arquitectónico. ActiveRecord usa herencia para conectar los modelos con la base de datos, mientras que MongoID usa composición de módulos [01:22]. Esto significa que tus modelos pueden heredar de cualquier otra clase y aún funcionar como modelos de MongoID, algo imposible con ActiveRecord en sistemas de herencia simple.
Una vez eliminado application_record.rb, es necesario remover todas las dependencias de herencia en los modelos que lo utilizaban.
¿Cómo se define un modelo de MongoID con sus campos?
Para convertir un modelo, se reemplaza la herencia por la inclusión del módulo Mongoid::Document [02:02]. Este módulo establece que la clase es un modelo de MongoID. Además, se incluye Mongoid::Timestamps para generar automáticamente los campos created_at y updated_at [02:16].
¿Cómo se migra el modelo category?
A diferencia de ActiveRecord, que define su esquema en archivos de migración separados, MongoID define la estructura de datos directamente en el modelo [02:30]. Para category, los campos se declaran así:
ruby
class Category
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :description, type: String
has_many :tasks
validates :name, presence: true
end
- El campo
id lo maneja MongoID internamente.
- No existe un tipo
text en MongoID; String sirve tanto para cadenas cortas como largas [03:24].
- Las validaciones y asociaciones como
has_many y validates son compatibles porque MongoID utiliza internamente ActiveModel como referencia [03:44].
¿Qué cambia en el modelo note con belongs_to?
El modelo note tiene asociaciones de tipo belongs_to hacia user y task [04:22]. En MongoID, no es necesario declarar explícitamente las llaves foráneas como user_id o task_id, ya que belongs_to las crea automáticamente [04:34].
ruby
class Note
include Mongoid::Document
include Mongoid::Timestamps
field :body, type: String
belongs_to :user
belongs_to :task
end
Solo fue necesario agregar el campo body de forma explícita.
¿Cómo reemplazar el método enum de ActiveRecord en MongoID?
El modelo participant presenta un desafío particular: utiliza el método enum de ActiveRecord para definir roles [05:14]. Este método genera accesores y scopes de forma automática, pero en MongoDB no es tan natural [05:34].
La solución consiste en crear una constante con los pares clave-valor y un método público que la exponga:
ruby
class Participant
include Mongoid::Document
include Mongoid::Timestamps
ROLES = { owner: 0, editor: 1, viewer: 2 }.freeze
field :role, type: Integer
belongs_to :user
belongs_to :task
def self.roles
ROLES
end
end
- Se declara el campo
role con tipo Integer [06:22].
- El método de clase
roles permite acceder a la constante sin alterar la implementación del resto del proyecto [06:08].
- Aunque existe una gema llamada
mongoid-enum, en este caso se optó por código puro para no saturar el proyecto con dependencias innecesarias [05:50].
El orden recomendado para organizar la definición de un modelo es: módulos, campos, relaciones y validaciones [04:00]. Esta estructura facilita la lectura y el mantenimiento del código.
¿Has migrado proyectos de ActiveRecord a MongoID? Comparte tu experiencia y los retos que encontraste en el proceso.