Created
November 6, 2011 22:32
-
-
Save asmuth/1343701 to your computer and use it in GitHub Desktop.
Dynamic (prefixed at runtime) collection names for mongoid models
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
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("_"))
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
Hey, have you tried to utylize this extension while running pararel specs?