Ruby
Bridging ActiveRecord and Mongoid
When we pick technologies for clients, we use the right tool for the job and quite often roll custom solutions when necessary. In a recent project, we used both SQL ( ActiveRecord over Postgres) and NoSQL (Mongoid over MongoDB) solutions for the data persistence layer, modeled after the client's data characteristics, and it worked out quite well.
While working on this project, we found ourselves needing to traverse between the ActiveRecord side and the Mongoid side quite often as "1..many" relationships, so we wrote this piece of glue code to make that easier.
class ActiveRecord::Base
def self.has_many_documents(association_name)
class_eval %<
def #{association_name}
#{association_name.to_s.singularize.classify}.where(#{name.underscore}_id: id)
end
>
end
end
module Mongoid::ActiveRecordBridge
extend ActiveSupport::Concern
included do
def self.belongs_to_record(association_name, options={})
association_class = options[:class_name] || association_name.to_s.singularize.classify
class_eval %<
field :#{association_name}_id, type: Integer
index(#{association_name}_id: 1)
def #{association_name}
@#{association_name} ||= #{association_class}.where(id: #{association_name}_id).first if #{association_name}_id
end
def #{association_name}=(object)
@#{association_name} = object
self.#{association_name}_id = object.try :id
end
>
end
end
Put this in an initializer, then in your ActiveRecord model, you can use "has_many_documents", and in your Mongoid document, you can use "belongs_to_record" and it just works! You could easily expand this to include "1..1" and "many..many" relationships.
class Property < ActiveRecord::Base
...
has_many_documents :default_rules
...
end
class Rule
include Mongoid::Document
include Mongoid::ActiveRecordBridge
...
belongs_to_record :property
belongs_to_record :updated_by, class_name: 'User'
belongs_to_record :approved_by, class_name: 'User'
...
end