MongoId y Rails3
Bueno últimamente vengo posteando con bastante delay (espero que eso cambie),
en esta ocasión voy a hacer un pequeño post acerca de mis experiencias migrando
una app de rails 2.3.4 y Active record con Mysql a Rails3, MongoId y Ruby 1.9.1,
sí, así completita la cosa, la aplicación no es demasiado grande así que viene bien
para probar esta nueva arquitectura.
No voy entrar en los detalles de como instalar rails3 y esas cosas por que ya existen
varios posts acerca del tema y no me quiero repetir, pasemos derecho al tema mongoid
Mongoid es un ODM(Object-Document-Mapper) para mongoDB, tiene varias cosas buenas algunas de las que me llamaron
la atención a mí es que no necesitamos migrations para para modificar nuestros documentos
(en sql diríamos tablas) además los campos (columnas) los podemos ver directamente abriendo
el modelo.
class Order
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::XmlBuilder
field :external_id, :type => Integer
field :account_id, :type => Integer
field :order_type, :type => String
field :posted, :type => Boolean
field :send_result_notification, :type => Boolean
field :file_duration_ms, :type => Integer
field :created_at, :type => DateTime
field :updated_at, :type => DateTime
embeds_one :result, :class_name => "OrderResult"
# -----------------------------------------------------------------------------------------------
# Viejo named_scope reemplazado por mongoid queries
#
# named_scope :pendings, :conditions => "NOT EXISTS (SELECT * FROM
# order_results WHERE
# order.id = order_results.transcription_id)
# AND posted_id IS NOT NULL AND
# orders.posted = 1"
#
# ------------------------------------------------------------------------------------------------
def self.without_results
result_ids = TranscriptionResult.criteria.only(:id).map{|id| }
Order.where(:_id.nin => result_ids)
end
def self.pendings
without_results.where(:posted => true)
end
end
Otra de las ventajas es que los criterios son anidables con lo cual funcionarían
como una especie de scope de Active Record, fijensé como quedó el viejo named_scope
con mongoid, mucho más claro que antes para mi gusto.
Otra de las ventajas de mongoID en particular es que incluye ActiveModel, con lo
cual tenemos las mismas validaciones que en Rails, también podemos definir callbacks de forma similar que en Active Record.
Pasemos a explicar un poquito:
Lo que yo necesito son los transcriptions que no tengan un transcription_result asociado y dónde posted sea true.
result_ids =OrderResult.criteria.only(:id)
= > #[:id]}, @klass=OrderResult, @documents=[]>
con esto saco la lista de results, sólo me traigo los ids por que no necesito
otra cosa y le aplico un map para obtener una array con la lista de ids (cómo pueden ver eso devuelve un objeto Mongoid::Criteria) con esto ya tengo los transcriptions que no tienen results (el método without_results). Después una vez que tengo esto ya es más fácil
generar los pendings (transcriptions sin results y con posted == true).
Nota: :_id.nin quiere decir “los _id que no estén incluidos en (not included in)”
para más detalles pueden ver la doc de queries de mongoid
PD: MongoId también tiene named_scopes dejo pendiente para el próximo refactoring pasar esto a named_scope de mongoid.
Nos vemos en el próximo post.