Skip to content

Instantly share code, notes, and snippets.

@asmuth
Created November 6, 2011 22:32
Show Gist options
  • Save asmuth/1343701 to your computer and use it in GitHub Desktop.
Save asmuth/1343701 to your computer and use it in GitHub Desktop.
Dynamic (prefixed at runtime) collection names for mongoid models
# uber-hacky dynamic collection names for MongoID models:
#
# class MyModel
# include Mongoid::PrefixableDocument # ...instead of Mongoid::Document
# include Mongoid::Timestamps
#
# field :foobar, :type => Integer
#
# def my_method; 123; end
#
# freeze_stack! # this needs to be the last line in your model!
#
# end
#
# m = MyModel.new
# => #<MyModelWrap _prefix: none, _id: 12312312, _type: nil >
# m.collection_name
# => "my_model"
#
# m = MyModel.prefix("foobar").new
# => #<FoobarMyModelWrap _prefix: foobar, _id: 12312312, _type: nil >
# m.collection_name
# => "foobar_my_model"
#
# ~paul (paul@paulasmuth.com)
module Mongoid
module PrefixableDocument
def self.included(base)
base.class_eval do
@@wrapped_stack = []
@@wrapped_class = base
def self.prefix(_prefix=nil)
@@wrapped_class.clone.tap do |wrapper_klass|
wrapper_klass.class_eval do
@@wrapped_prefix = _prefix
include Mongoid::Document
def self.inspect
"#<#{@@wrapped_class.name} _prefix: #{@@wrapped_prefix||'none'}>"
end
def prefixed_inspect(inspection)
"#<#{@@wrapped_class.name} _prefix: #{@@wrapped_prefix||'none'}, _id: #{id}, #{inspection * ', '}>"
end
end
wrapper_klass.store_in([_prefix,@@wrapped_class.name.pluralize.downcase].compact.join("_"))
@@wrapped_stack.each{ |m,a| wrapper_klass.send(m,*a) }
end
end
def self.method_missing(_method, *args)
if @@wrapped_stack.frozen?
self.prefix.send(_method, *args)
else
@@wrapped_stack << [_method, args]
end
end
def self.freeze_stack!
@@wrapped_stack.freeze
end
end
end
end
module Inspection
def inspect
inspection = []
inspection.concat(inspect_fields).concat(inspect_dynamic_fields)
return prefixed_inspect(inspection) if respond_to?(:prefixed_inspect)
"#<#{self.class.name} _id: #{id}, #{inspection * ', '}>"
end
end
end
@swistaczek
Copy link

Hey, have you tried to utylize this extension while running pararel specs?

@jackbot
Copy link

jackbot commented Aug 6, 2014

Works nicely, thanks!

Just a note, with MongoId 4.0.0 store_in has changed slightly, so line 54 needs to be

wrapper_klass.store_in(collection: [_prefix,@@wrapped_class.name.pluralize.downcase].compact.join("_"))

@jygeer
Copy link

jygeer commented May 15, 2015

I inherited some code that used this gist. Word to the wise, don't use this with more than one class! Direct assignment of class variables in a mixins will have bad results. Replace the assignments:

      @@wrapped_stack = []
      @@wrapped_class = base

with

      base.send :class_variable_set, :@@wrapped_stack, []
      base.send :class_variable_set, :@@wrapped_class, base

Similarly, use :class_variable_get instead of direct reference of any @@ variable.
https://gist.github.com/jygeer/4492c261916d8d3a384f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment