Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Adding https://github.com/phstc/mongomapper_id2 capabilities #200

Closed
wants to merge 3 commits into from

2 participants

@phstc

This pull request adds auto incremented id for MongoMapper documents. According http://groups.google.com/group/mongomapper/browse_thread/thread/ecf1ab92d9ad6f11/115b72f2a6e44d29#115b72f2a6e44d29 and https://github.com/phstc/mongomapper_id2

This pull request includes only auto_incremented id, the base62 capabilities I will send in another pull request

@jnunemaker
Owner

This kind of functionality is better as a plugin as not everyone will need it.

@phstc

About Base62 I totally agree. But with auto incremented ID, I think that it's good for MongoMapper. It's a optional feature "auto_increment!" IMHO

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
1  lib/mongo_mapper.rb
@@ -48,6 +48,7 @@ module Plugins
autoload :Timestamps, 'mongo_mapper/plugins/timestamps'
autoload :Userstamps, 'mongo_mapper/plugins/userstamps'
autoload :Validations, 'mongo_mapper/plugins/validations'
+ autoload :AutoIncrement, 'mongo_mapper/plugins/auto_increment'
module Associations
autoload :Base, 'mongo_mapper/plugins/associations/base'
View
1  lib/mongo_mapper/document.rb
@@ -34,6 +34,7 @@ def self.included(model)
plugin Plugins::Userstamps
plugin Plugins::Validations
plugin Plugins::Callbacks # for now callbacks needs to be after validations
+ plugin Plugins::AutoIncrement
end
super
end
View
30 lib/mongo_mapper/extensions/fixnum.rb
@@ -0,0 +1,30 @@
+# encoding: UTF-8
+module MongoMapper
+ module Extensions
+ module Fixnum
+ BASE62_CHARS = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
+ # based on http://flowcoder.com/148
+ # The encode is skipping the first 'a' when will change the digits size 62, 62 * 62
+ # FIXME 1.to_base62.should eql 'a' NOT 'b'
+ # FIXME 62.to_base62.should eql '99' NOT 'ba'
+ # FIXME 3844.to_base62.should eql '99' NOT 'baa'
+ # FIXME 238328.to_base62.should eql '999' NOT 'baaa'
+ # @pablocantero
+ def to_base62
+ i = self
+ return '0' if i == 0
+ s = ''
+ while i > 0
+ s << BASE62_CHARS[i.modulo(62)]
+ i /= 62
+ end
+ s.reverse!
+ s
+ end
+ end
+ end
+end
+
+class Fixnum
+ include MongoMapper::Extensions::Fixnum
+end
View
70 lib/mongo_mapper/plugins/auto_increment.rb
@@ -0,0 +1,70 @@
+# encoding: UTF-8
+# @pablocantero
+module MongoMapper
+ module Plugins
+ # Based on http://ihswebdesign.com/blog/autoincrement-in-mongodb-with-ruby/
+ module AutoIncrement
+ module ClassMethods
+ def auto_increment!
+ # rewrite "model.key :_id, ObjectId" from plugins/keys.rb
+ key :_id, Integer
+ class_eval { before_create class_eval { :update_auto_increment }}
+ end
+ end
+ module InstanceMethods
+ private
+ def update_auto_increment
+ self._id = MongoMapper::Plugins::AutoIncrement::Incrementor[self.class.name].inc
+ end
+ end
+ class Incrementor
+ class Sequence
+ def initialize(sequence)
+ @sequence = sequence.to_s
+ exists? || create
+ end
+ def exists?
+ collection.find(query).count > 0
+ end
+ def db
+ MongoMapper.database # replace this if you're not using MongoMapper
+ end
+ def query
+ { "seq_name" => @sequence }
+ end
+ def collection
+ db['sequences']
+ end
+ def current
+ collection.find_one(query)["number"]
+ end
+ def inc
+ update_number_with("$inc" => { "number" => 1 })
+ end
+ def create(number = 0)
+ collection.insert(query.merge({ "number" => number }))
+ end
+ def set(number)
+ update_number_with("$set" => { "number" => number })
+ end
+ def update_number_with(mongo_func)
+ opts = {
+ "query" => query,
+ "update" => mongo_func,
+ "new" => true # return the modified document
+ }
+ collection.find_and_modify(opts)["number"]
+ end
+ end
+ class << self
+ def [](sequence)
+ Sequence.new(sequence)
+ end
+ def []=(sequence, number)
+ Sequence.new(sequence).set(number)
+ end
+ end
+ end
+ end
+ end
+end
View
30 test/functional/test_auto_increment.rb
@@ -0,0 +1,30 @@
+require 'test_helper'
+# @pablocantero
+class AutoIncrementTest < Test::Unit::TestCase
+ context "autoincrementing" do
+ setup do
+ @klass = Doc do
+ key :title, String
+ end
+ @klass.auto_increment!
+ end
+
+ should "set id on create" do
+ doc = @klass.new(:title => 'The Simpsons Movie')
+ doc.id.should be(nil)
+ doc.save
+ doc.id.should_not be(nil)
+ id = doc.id
+ doc.save
+ doc.id.should eql id
+ end
+
+ should "auto increment id" do
+ doc = @klass.new(:title => 'Pirates of Silicon Valley')
+ doc.save
+ doc2 = @klass.new(:title => 'Tropa de Elite')
+ doc2.save
+ (doc.id + 1).should eql doc2.id
+ end
+ end
+end
View
17 test/unit/test_extensions.rb
@@ -8,6 +8,23 @@ class SupportTest < Test::Unit::TestCase
Array.to_mongo({'1' => '2', '3' => '4'}).should == [['1', '2'], ['3', '4']]
end
end
+
+ context "Fixnum.to_base62" do
+ should "encode to Bas62" do
+ # 1
+ 1.to_base62.should eql 'b'
+ 2.to_base62.should eql 'c'
+ # 62
+ 62.to_base62.should eql 'ba'
+ 63.to_base62.should eql 'bb'
+ # 62 * 62 = 3844
+ 3844.to_base62.should eql 'baa'
+ 3845.to_base62.should eql 'bab'
+ # 62 * 62 * 62 = 238328
+ 238328.to_base62.should eql 'baaa'
+ 238329.to_base62.should eql 'baab'
+ end
+ end
context "Array.from_mongo" do
should "be array if array" do
Something went wrong with that request. Please try again.