Skip to content

Instantly share code, notes, and snippets.

@ahoward
Created August 26, 2011 14:55
Show Gist options
  • Save ahoward/1173589 to your computer and use it in GitHub Desktop.
Save ahoward/1173589 to your computer and use it in GitHub Desktop.
#
# NAME
# Sequence
#
# SYNOPSIS
# generate monotomically increasing but *pretty* ids in mongoid
#
# DESCRIPTION
# mongo is sweet, but object_ids or uuids in urls are not.
#
# following is a teeny bit of code which can be used to effectiently
# generate batches of pretty integer type ids for your records and voila:
# pretty urls.
#
# USAGE
#
# class A
# include Mongoid::Document
#
# field(:_id, :default => proc{ Sequence[A].next })
# identity(:type => String)
#
# # this is just to make find mo-betta, mongoid doesn't cast arguments to
# # find - it is not required
# #
# def A.find(*args, &block)
# args[0] = args[0].to_s if args.size == 1
# super
# end
# end
#
# p Array.new(3){ A.create.id } #=> [1,2,3]
# p [1,2,3].map{|id| A.find(id).id} #=> ["1","2","3"]
# p ["1","2","3"].map{|id| A.find(id).id} #=> ["1","2","3"]
#
class Sequence
include Mongoid::Document
field(:name)
field(:current, :default => 1)
field(:step, :default => 10)
validates_presence_of(:name)
validates_uniqueness_of(:name)
index(:name, :unique => true)
Cache = Map.new
class << Sequence
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')
end
def next
if @value.nil? or @value == @last_value
generate_next_values!
end
@value
ensure
@value += 1
end
def generate_next_values!
@last_value = inc(:current, step)
@value = @last_value - step
end
def reset!
update_attributes!(:current => 1)
ensure
@value = @last_value = nil
end
end
@ahoward
Copy link
Author

ahoward commented Aug 26, 2011

just for reference, this is multi-process safe, fast, and could easily be augmented for multi-node setups.

https://groups.google.com/forum/#!topic/mongoid/SAKmkVyA46o

@adacosta
Copy link

This isn't a good idea because the value of an id is uniqueness; which UUIDs provide. It's not safe, for example, you couldn't merge dbs and assume uniquess based on your one sequenced attribute. Friendly URLs are a different matter.

@nickhoffman
Copy link

Why not just use mongoid_slug?

@adacosta
Copy link

+1 mongoid_slug

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