match_mongo_chunk_size/lib/mongoid-sequence.rb
2012-08-10 09:06:48 -06:00

126 lines
2.3 KiB
Ruby

require 'mongoid'
module Mongoid
module Sequence
def Sequence.version
'1.0.0'
end
ClassMethods = proc do
def sequence(fieldname, *args, &block)
options = args.extract_options!.to_options!
sequence_name = (
options.delete(:sequence) || sequence_name_for(fieldname)
)
args.push(options)
before_create do |doc|
doc[fieldname] = SequenceGenerator.for(sequence_name).next
end
field(fieldname, *args, &block)
SequenceGenerator.for(sequence_name)
end
def sequence_for(fieldname)
SequenceGenerator.for(sequence_name_for(fieldname))
end
def sequence_name_for(fieldname)
SequenceGenerator.sequence_name_for(self, fieldname)
end
end
InstanceMethods = proc do
def sequence_for(fieldname)
self.class.sequence_for(fieldname)
end
end
def Sequence.included(other)
other.send(:instance_eval, &ClassMethods)
other.send(:class_eval, &InstanceMethods)
super
end
end
class SequenceGenerator
include Mongoid::Document
field(:name, :type => String)
field(:value, :default => 0, :type => Integer)
validates_presence_of(:name)
validates_uniqueness_of(:name)
validates_presence_of(:value)
index({:name => 1}, {:unique => true})
Cache = Hash.new
class << self
def for(name)
name = name.to_s
Cache[name] ||= (
begin
create!(:name => name)
rescue
where(:name => name).first || create!(:name => name)
end
)
end
alias_method('[]', 'for')
def sequence_name_for(klass, fieldname)
"#{ klass.name.underscore }-#{ fieldname }"
end
end
after_destroy do |sequence|
Cache.delete(sequence.name)
end
def next
inc(:value, 1)
end
def current_value
reload.value
end
def reset!
update_attributes!(:value => 0)
end
end
end
if $0 == __FILE__
Mongoid.configure do |config|
config.connect_to('mongoid-sequence')
end
class A
include Mongoid::Document
include Mongoid::Sequence
p sequence(:number)
end
A.sequence_for(:number).destroy
a = A.create!
p a
end