Skip to content

Instantly share code, notes, and snippets.

@timting
Created February 13, 2012 22:57
Show Gist options
  • Save timting/1821272 to your computer and use it in GitHub Desktop.
Save timting/1821272 to your computer and use it in GitHub Desktop.
# encoding: utf-8
module Mongoid #:nodoc:
# Include this module to add automatic sequence feature
# usage:
# Class KlassName
# include Mongoid::Document
# include Mongoid::Sequence
# ...
# field :number, :type=>Integer
# sequence :number
# ...
module Sequence
extend ActiveSupport::Concern
class Holder
include Document
field :seq, :type => Integer, :default => 30000
end
included do
set_callback :validate, :before, :set_sequence
end
module ClassMethods
attr_accessor :sequence_fields
def sequence(field)
self.sequence_fields ||= []
self.sequence_fields << field
end
end
def set_sequence
if self.class.sequence_fields.is_a?(Array)
self.class.sequence_fields.each do |field|
next if self[field]
# load schema info (TODO: find better way)
Holder.first unless Holder._collection
# TODO: should be Holder._collection.find_and_modify.
# But as it seems the currnet MongoId::Collection doesn't support find_and_modify, this logic calls Mongo::Collection directly for now
if Holder.where({"_id" => "#{self.class.name.underscore}_#{field}"}).first
next_sequence = Holder._collection.master.collection.find_and_modify(:query => {"_id" => "#{self.class.name.underscore}_#{field}"},
:update=> {"$inc"=> {"seq"=>1}},
:new => true,
:upsert => true)
else
next_sequence = Holder._collection.master.collection.find_and_modify(:query => {"_id" => "#{self.class.name.underscore}_#{field}"},
:update=> {"$inc"=> {"seq"=>30000}},
:new => true,
:upsert => true)
end
self[field] = next_sequence["seq"]
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment