-
-
Save ShogunPanda/1086265 to your computer and use it in GitHub Desktop.
adds a feature to set sequence number to Mongoid::Document
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
# encoding: utf-8 | |
module Mongoid | |
# Include this module to add automatic sequence feature (also works for _id field, so SQL-Like autoincrement primary key can easily be simulated) | |
# usage: | |
# class KlassName | |
# include Mongoid::Document | |
# include Mongoid::Sequence | |
# ... | |
# field :number, :type=>Integer | |
# sequence :number | |
# ... | |
module Sequence | |
extend ActiveSupport::Concern | |
module ClassMethods | |
def sequence(_field) | |
# REPLACE FIELD DEFAULT VALUE | |
_field = _field.to_s | |
field(_field, fields[_field].options.merge(:default => lambda{ self.class.set_from_sequence(_field)})) | |
end | |
def set_from_sequence(_field) | |
sequences = self.db.collection("__sequences") | |
counter_id = "#{self.class.name.underscore}_#{_field}" | |
# Increase the sequence value and also avoids conflicts | |
catch(:value) do | |
value = nil | |
begin | |
value = sequences.find_and_modify( | |
:query => {"_id" => counter_id}, | |
:update=> {"$inc" => {"value" => 1}}, | |
:new => true, | |
:upsert => true | |
).send("[]", "value") | |
end while self.first({:conditions => {_field => value}}) | |
throw :value, value | |
end | |
end | |
def reset_sequence(_field) | |
sequences = self.db.collection("__sequences") | |
counter_id = "#{self.class.name.underscore}_#{_field}" | |
sequences.find_and_modify(:query => {"_id" => counter_id}, :update=> {"$set" => {"value" => 0}}, :new => true, :upsert => true) | |
end | |
end | |
end | |
end |
@paulsfds I believe that's the default behavior when you field :my_id, :type => Integer
... the sequencing code doesn't play with any of that. Please open an issue with this if you think it's something else :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@goncalossilva I'm playing around with this gem again (I had forgotten about it for a month), and it seems to be working but I noticed one issue. The model's find() method only takes an integer, and it errors out if you try and pass it a string.
1.9.2-p290 :022 > Sample.find(1)
=> #<Sample _id: 1, _type: nil, name: nil>
1.9.2-p290 :024 > Sample.find("1")
BSON::InvalidObjectId: illegal ObjectId format: 1
The default Mongoid implementation of find takes only a string. A workaround is to just force the param to be an integer like so:
@sample = Sample.find(params[:id].to_i)
I noticed that in your gem, the id actually becomes an integer whereas in Mongoid, the id is a BSON::ObjectId object. This may be the problem, is there a way to store the sequential numbers (for ids) as BSON::ObjectId instead of as in integer?
1.9.2-p290 :027 > Sample.find(1)._id
=> 1
1.9.2-p290 :028 > Sample.find(1)._id.is_a?(Integer)
=> true
1.9.2-p290 :009 > Event.first._id
=> BSON::ObjectId('4f98e4271d41c827cb000007')
1.9.2-p290 :010 > Event.first._id.is_a?(Integer)
=> false