├── .gitignore
├── CHANGELOG.rdoc
├── Gemfile
├── LICENSE
├── README.rdoc
├── Rakefile
├── lib
├── mongoid_auto_inc.rb
└── mongoid_auto_inc
│ ├── incrementor.rb
│ └── version.rb
├── mongoid_auto_inc.gemspec
└── spec
└── mongoid_auto_inc_spec.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | .bundle
3 | Gemfile.lock
4 | pkg/*
5 | .rvmrc
6 | *.swp
7 |
--------------------------------------------------------------------------------
/CHANGELOG.rdoc:
--------------------------------------------------------------------------------
1 | = Changelog
2 |
3 | Per release changes to mongoid_auto_inc
4 |
5 | == 0.1.0 (2012 March 21)
6 | * Initial stable release.
7 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 |
3 | gem 'activesupport', '>= 3.0.0'
4 |
5 | group :development do
6 | gem 'rspec', '>= 2.0.0.beta.22'
7 | # moving mongoid to be a development dependency
8 | # having it as a gem dependency may cause issues, change the version here to test
9 | gem 'mongoid', '>= 2.4.10'
10 | # to test Mongoid 3
11 | # gem 'mongoid', git: 'git://github.com/mongoid/mongoid.git'
12 | end
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010 Jeff Smith
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | = mongoid_auto_inc
2 | Add SQL like auto-incrementing fields to your Mongoid documents.
3 |
4 | This gem is inspired by http://ihswebdesign.com/blog/autoincrement-in-mongodb-with-ruby/ and the mongomapper_id2[https://github.com/phstc/mongomapper_id2] gem.
5 | == Install
6 | In your Gemfile:
7 | gem 'mongoid_auto_inc'
8 | Followed by running bundle install, or do:
9 | gem install mongoid_auto_inc
10 | == Usage
11 | Just add auto_increment :field to your Mongoid model where :field is the name of the auto-incremented field you want to create.
12 | Example:
13 | class Book
14 | include Mongoid::Document
15 |
16 | field :title
17 | field :author
18 |
19 | auto_increment :sequence
20 | end
21 | auto_increment :sequence will create a field of type Integer named sequence for Book. Whenever an instance of the model is created (intially saved to mongoDB), the auto_increment field will automatically be set to the next number in the sequence.
22 |
23 | You can add more than one auto-incremented field per model.
24 | === Options
25 | auto_increment :sequence, :collection => :some_collection
26 | mongoid_auto_inc keeps track of the current number in the sequence by creating a separate document mongoDB to query and update. By default auto_increment will save this document to a mongoDB collection called sequences. If you wish to save to a different collection use the :collection option to specify its name.
27 |
28 | auto_increment :sequence, :seed => 3333
29 | Use the :seed option to set the initial value of the auto-incremented field. The first number assigned from the sequence will be the next number after the seed value.
30 |
31 | == Contributors
32 | Thanks to these folk for their help:
33 | * davemitchell[https://github.com/davemitchell]
34 | * meltedice[https://github.com/meltedice]
35 | * fedegl[https://github.com/fedegl]
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'bundler'
2 | Bundler::GemHelper.install_tasks
3 |
--------------------------------------------------------------------------------
/lib/mongoid_auto_inc.rb:
--------------------------------------------------------------------------------
1 | require "mongoid"
2 | require "mongoid_auto_inc/incrementor"
3 |
4 | module MongoidAutoInc
5 | extend ActiveSupport::Concern
6 |
7 | module ClassMethods
8 | def auto_increment(name, options={})
9 | field name, :type => Integer
10 | seq_name = "#{self.name.downcase}_#{name}"
11 | incrementor = MongoidAutoInc::Incrementor.new(options)
12 |
13 | before_create { self.send("#{name}=", incrementor[seq_name].inc) unless self[name.to_sym].present? }
14 | end
15 | end
16 | end
17 |
18 | module Mongoid
19 | module Document
20 | include MongoidAutoInc
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/mongoid_auto_inc/incrementor.rb:
--------------------------------------------------------------------------------
1 | # This is a modified version of the code found on this blog post:
2 | # http://ihswebdesign.com/blog/autoincrement-in-mongodb-with-ruby/
3 | module MongoidAutoInc
4 | class Incrementor
5 | class Sequence
6 | def initialize(sequence, collection_name, seed)
7 | @sequence = sequence.to_s
8 | @collection = collection_name.to_s
9 | exists? || create(seed)
10 | end
11 |
12 | def inc
13 | update_number_with("$inc" => { "number" => 1 })
14 | end
15 |
16 | def set(number)
17 | update_number_with("$set" => { "number" => number })
18 | end
19 |
20 | private
21 |
22 | def exists?
23 | collection.find(query).count > 0
24 | end
25 |
26 | def create(number = 0)
27 | collection.insert(query.merge({ "number" => number }))
28 | end
29 |
30 | def collection
31 | if ::Mongoid::VERSION < '3'
32 | Mongoid.database[@collection]
33 | else
34 | Mongoid.default_session[@collection]
35 | end
36 | end
37 |
38 | def query
39 | { "seq_name" => @sequence }
40 | end
41 |
42 | def current
43 | if ::Mongoid::VERSION < '3'
44 | collection.find_one(query)["number"]
45 | else
46 | collection.find(query).one['number']
47 | end
48 | end
49 |
50 | def update_number_with(mongo_func)
51 | opts = {
52 | "query" => query,
53 | "update" => mongo_func,
54 | "new" => true # return the modified document
55 | }
56 | if ::Mongoid::VERSION < '3'
57 | collection.find_and_modify(opts)["number"]
58 | else
59 | collection.database.command({
60 | findandmodify: collection.name
61 | }.merge(opts))['value']['number']
62 | end
63 | end
64 | end
65 |
66 | def initialize(options=nil)
67 | options ||= {}
68 | @collection = options[:collection] || "sequences"
69 | @seed = options[:seed].to_i
70 | end
71 |
72 | def [](sequence)
73 | Sequence.new(sequence, @collection, @seed)
74 | end
75 |
76 | def []=(sequence, number)
77 | Sequence.new(sequence, @collection, @seed).set(number)
78 | end
79 | end
80 | end
81 |
--------------------------------------------------------------------------------
/lib/mongoid_auto_inc/version.rb:
--------------------------------------------------------------------------------
1 | module MongoidAutoInc
2 | VERSION = "0.1.0"
3 | end
4 |
--------------------------------------------------------------------------------
/mongoid_auto_inc.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 | $:.push File.expand_path("../lib", __FILE__)
3 | require "mongoid_auto_inc/version"
4 |
5 | Gem::Specification.new do |s|
6 | s.name = "mongoid_auto_inc"
7 | s.version = MongoidAutoInc::VERSION
8 | s.platform = Gem::Platform::RUBY
9 | s.authors = ["Jeff Smith"]
10 | s.email = ["jffreyjs@gmail.com"]
11 | s.homepage = "https://github.com/jffjs/mongoid_auto_inc"
12 | s.summary = %q{Adds auto increment capabilities to Mongoid::Document}
13 | s.description = %q{Adds auto increment capabilities to Mongoid::Document}
14 |
15 | s.rubyforge_project = "mongoid_auto_inc"
16 |
17 | s.files = `git ls-files`.split("\n")
18 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20 | s.require_paths = ["lib"]
21 |
22 | s.required_ruby_version = '>= 1.8.6'
23 | s.required_rubygems_version = '>= 1.3.5'
24 | s.add_bundler_dependencies
25 | end
26 |
--------------------------------------------------------------------------------
/spec/mongoid_auto_inc_spec.rb:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # rspec spec/mongoid_auto_inc_spec.rb
3 | require 'bundler/setup'
4 | Bundler.require(:default, :development)
5 | require 'mongoid_auto_inc'
6 |
7 | describe MongoidAutoInc do
8 | before(:all) do
9 | Mongoid.master = Mongo::Connection.new.db("mongoid_auto_inc_test")
10 | end
11 |
12 | describe "auto increment" do
13 | before(:all) do
14 | class DocumentA
15 | include Mongoid::Document
16 | auto_increment :seq
17 | end
18 | end
19 |
20 | before(:each) do
21 | Mongoid.database["sequences"].remove
22 | end
23 |
24 | it "should be nil" do
25 | DocumentA.new.seq.should be_nil
26 | end
27 |
28 | it "should be 1" do
29 | DocumentA.create!.seq.should == 1
30 | end
31 |
32 | it "should be 2" do
33 | DocumentA.create!
34 | DocumentA.create!.seq.should == 2
35 | end
36 |
37 | it "should not auto increment when value is provided" do
38 | doc = DocumentA.create!(seq: 33)
39 | doc.seq.should == 33
40 | end
41 | end
42 |
43 | describe "auto increment with :collection option" do
44 | before(:all) do
45 | class DocumentB
46 | include Mongoid::Document
47 | auto_increment :seq, :collection => 'other_sequences'
48 | end
49 | end
50 |
51 | before(:each) do
52 | Mongoid.database["sequences"].remove
53 | Mongoid.database["other_sequences"].remove
54 | end
55 |
56 | it "should store sequence data to other_sequences collection" do
57 | DocumentB.create!.seq.should == 1
58 | DocumentB.create!.seq.should == 2
59 | Mongoid.database["sequences"].remove
60 | DocumentB.create!.seq.should == 3
61 | Mongoid.database["other_sequences"].remove
62 | DocumentB.create!.seq.should == 1
63 | end
64 | end
65 |
66 | describe "auto increment with :seed option" do
67 | before(:all) do
68 | class DocumentC
69 | include Mongoid::Document
70 | auto_increment :seq, :seed => 10
71 | end
72 | class DocumentD
73 | include Mongoid::Document
74 | auto_increment :seq
75 | end
76 | end
77 |
78 | before(:each) do
79 | Mongoid.database["sequences"].remove
80 | end
81 |
82 | it "should start with 11 (10 + 1)" do
83 | DocumentC.create!.seq.should == 11
84 | DocumentC.create!.seq.should == 12
85 | DocumentC.create!.seq.should == 13
86 | DocumentD.create!.seq.should == 1
87 | DocumentD.create!.seq.should == 2
88 | end
89 | end
90 | end
91 |
--------------------------------------------------------------------------------