mongoid_atomic 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +87 -0
- data/VERSION +1 -0
- data/lib/mongoid_atomic.rb +50 -0
- data/spec/models/user.rb +9 -0
- data/spec/mongoid_atomic_spec.rb +92 -0
- data/spec/spec_helper.rb +25 -0
- metadata +90 -0
data/README.rdoc
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
= Mongoid::Atomic
|
2
|
+
|
3
|
+
Atomic updates for your Mongoid models.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
Add to Gemfile:
|
8
|
+
|
9
|
+
gem 'mongoid_atomic'
|
10
|
+
|
11
|
+
== Getting Started
|
12
|
+
|
13
|
+
Include the module in models where you want it:
|
14
|
+
|
15
|
+
class User
|
16
|
+
include Mongoid::Document
|
17
|
+
include Mongoid::Atomic
|
18
|
+
|
19
|
+
field :username
|
20
|
+
field :groups, :type => Array, :default => ['users']
|
21
|
+
field :post_count, :type => Integer
|
22
|
+
end
|
23
|
+
|
24
|
+
== Easy and Human Readable Atomic Updates!
|
25
|
+
|
26
|
+
A simple example. To increment a post count:
|
27
|
+
|
28
|
+
u = User.where(:name => 'Bill').first
|
29
|
+
u.atomic_inc(:post_count)
|
30
|
+
|
31
|
+
.. which might fit nicely in your Post model:
|
32
|
+
|
33
|
+
class Post
|
34
|
+
include Mongoid::Document
|
35
|
+
...
|
36
|
+
references_one :user
|
37
|
+
...
|
38
|
+
after_create :update_post_count
|
39
|
+
...
|
40
|
+
private
|
41
|
+
def update_post_count
|
42
|
+
self.user.atomic_inc :post_count
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
.. or join a group:
|
47
|
+
|
48
|
+
...
|
49
|
+
u.atomic_push(:groups, 'posters')
|
50
|
+
|
51
|
+
|
52
|
+
.. or remove a field:
|
53
|
+
|
54
|
+
...
|
55
|
+
u.atomic_unset(:deprecated_field)
|
56
|
+
|
57
|
+
.. or change your name:
|
58
|
+
|
59
|
+
...
|
60
|
+
u.atomic_set(:username, 'bill')
|
61
|
+
|
62
|
+
.. or do all of it at once:
|
63
|
+
|
64
|
+
...
|
65
|
+
u.atomic_update :inc => {:post_count => 1}, :set => {:username => 'bobby'}, :pushAll => {:groups => %w[rubyists developers]}
|
66
|
+
|
67
|
+
== A Note About Attribute Consistency
|
68
|
+
|
69
|
+
No effort is made to ensure consistency between the server and instance attributes. There's a good reason for this: the operations are performed inside of the Mongo server and we often don't care about the result. If you need to ensure the consistency of your attributes after an update, call the Mongoid reload method. Example:
|
70
|
+
|
71
|
+
>> u = User.first
|
72
|
+
=> #<User....>
|
73
|
+
|
74
|
+
>> u.post_count
|
75
|
+
=> 0
|
76
|
+
|
77
|
+
>> u.atomic_inc :post_count
|
78
|
+
=> nil
|
79
|
+
|
80
|
+
>> u.post_count
|
81
|
+
=> 0
|
82
|
+
|
83
|
+
>> u.reload
|
84
|
+
=> #<User....>
|
85
|
+
|
86
|
+
>> u.post_count
|
87
|
+
>= 1
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Mongoid::Atomic
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
def atomic_update(options)
|
5
|
+
doc = {}
|
6
|
+
options.each do |k,v|
|
7
|
+
next unless %w[inc set unset push pushAll addToSet pop pull pullAll].include? k.to_s
|
8
|
+
doc["$#{k}"] = v
|
9
|
+
end
|
10
|
+
collection.update({'_id' => self._id}, doc)
|
11
|
+
end
|
12
|
+
|
13
|
+
def atomic_inc(field, by=1)
|
14
|
+
atomic_update :inc => { field => by }
|
15
|
+
end
|
16
|
+
alias :atomic_increment :atomic_inc
|
17
|
+
|
18
|
+
def atomic_set(field, value)
|
19
|
+
atomic_update :set => { field => value }
|
20
|
+
end
|
21
|
+
|
22
|
+
def atomic_unset(field)
|
23
|
+
atomic_update :unset => { field => 1 }
|
24
|
+
end
|
25
|
+
|
26
|
+
def atomic_push(field, value)
|
27
|
+
atomic_update :push => { field => value }
|
28
|
+
end
|
29
|
+
|
30
|
+
def atomic_push_all(field, array)
|
31
|
+
atomic_update :pushAll => { field => array.to_a }
|
32
|
+
end
|
33
|
+
|
34
|
+
def atomic_add_to_set(field, value)
|
35
|
+
atomic_update :addToSet => { field => value }
|
36
|
+
end
|
37
|
+
|
38
|
+
def atomic_pop(field, index=1)
|
39
|
+
atomic_update :pop => { field => index.to_i }
|
40
|
+
end
|
41
|
+
|
42
|
+
def atomic_pull(field, value)
|
43
|
+
atomic_update :pull => { field => value }
|
44
|
+
end
|
45
|
+
|
46
|
+
def atomic_pull_all(field, array)
|
47
|
+
atomic_update :pullAll => { field => array.to_a }
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/spec/models/user.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Atomic do
|
4
|
+
|
5
|
+
context "user" do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@bob = User.create(:username => 'Bob', :groups => %w[users moderators admins])
|
9
|
+
@nancy = User.create(:username => 'Nancy', :groups => %w[users peons])
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should increment" do
|
13
|
+
@bob.atomic_inc :post_count
|
14
|
+
@bob.reload.post_count.should eql 1
|
15
|
+
@bob.atomic_inc :post_count
|
16
|
+
@bob.reload.post_count.should eql 2
|
17
|
+
@bob.atomic_inc :post_count, -2
|
18
|
+
@bob.reload.post_count.should eql 0
|
19
|
+
@nancy.atomic_inc :post_count, 10
|
20
|
+
@nancy.reload.post_count.should eql 10
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should set" do
|
24
|
+
@bob.atomic_set :username, 'Robby'
|
25
|
+
@bob.reload.username.should eql 'Robby'
|
26
|
+
@nancy.atomic_set :groups, %w[users women]
|
27
|
+
@nancy.reload.groups.should eql %w[users women]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should unset" do
|
31
|
+
@bob.atomic_unset :groups
|
32
|
+
@bob.reload.groups.should eql nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should push" do
|
36
|
+
@bob.atomic_push :groups, 'bobs'
|
37
|
+
@bob.reload.groups.should eql %w[users moderators admins bobs]
|
38
|
+
@nancy.atomic_unset :groups
|
39
|
+
@nancy.atomic_push :groups, 'women'
|
40
|
+
@nancy.atomic_push :groups, 'nancies'
|
41
|
+
@nancy.reload.groups.should eql %w[women nancies]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should push all" do
|
45
|
+
@bob.atomic_push_all :groups, %w[executives bosses idiots]
|
46
|
+
@bob.reload.groups.should eql %w[users moderators admins executives bosses idiots]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should add to set" do
|
50
|
+
@bob.atomic_add_to_set :groups, 'bobs'
|
51
|
+
@bob.reload.groups.should eql %w[users moderators admins bobs]
|
52
|
+
@bob.atomic_add_to_set :groups, 'users'
|
53
|
+
@bob.reload.groups.should eql %w[users moderators admins bobs]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should pop" do
|
57
|
+
@bob.atomic_pop :groups
|
58
|
+
@bob.reload.groups.should eql %w[users moderators]
|
59
|
+
@bob.atomic_pop :groups, -1
|
60
|
+
@bob.reload.groups.should eql %w[moderators]
|
61
|
+
@nancy.atomic_pop :groups, 1
|
62
|
+
@nancy.reload.groups.should eql %w[users]
|
63
|
+
@nancy.atomic_set :groups, %w[beautiful brunette woman starts_with_n]
|
64
|
+
@nancy.atomic_pop :groups, 1
|
65
|
+
@nancy.reload.groups.should eql %w[beautiful brunette woman]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should pull" do
|
69
|
+
@bob.atomic_pull :groups, 'users'
|
70
|
+
@bob.reload.groups.should eql %w[moderators admins]
|
71
|
+
@nancy.atomic_pull :groups, 'peons'
|
72
|
+
@nancy.reload.groups.should eql %w[users]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should pull all" do
|
76
|
+
@bob.atomic_pull_all :groups, %w[users admins]
|
77
|
+
@bob.reload.groups.should eql %w[moderators]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should update multiple field at the same time" do
|
81
|
+
@bob.atomic_update :inc => {:post_count => 1}, :set => {:username => 'bobby'}, :pushAll => {:groups => %w[bosses idiots]}
|
82
|
+
@bob.reload
|
83
|
+
@bob.post_count.should eql 1
|
84
|
+
@bob.groups.should eql %w[users moderators admins bosses idiots]
|
85
|
+
@bob.username.should eql 'bobby'
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
3
|
+
|
4
|
+
Bundler.require(:default)
|
5
|
+
|
6
|
+
Mongoid.config.master = Mongo::Connection.new.db("mongoid_atomic_test")
|
7
|
+
|
8
|
+
require File.expand_path("../../lib/mongoid_atomic", __FILE__)
|
9
|
+
Dir["#{File.dirname(__FILE__)}/models/*.rb"].each { |f| require f }
|
10
|
+
|
11
|
+
DatabaseCleaner.orm = "mongoid"
|
12
|
+
|
13
|
+
Rspec.configure do |config|
|
14
|
+
config.before(:all) do
|
15
|
+
DatabaseCleaner.strategy = :truncation
|
16
|
+
end
|
17
|
+
|
18
|
+
config.before(:each) do
|
19
|
+
DatabaseCleaner.start
|
20
|
+
end
|
21
|
+
|
22
|
+
config.after(:each) do
|
23
|
+
DatabaseCleaner.clean
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongoid_atomic
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jason Coene
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-17 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: mongoid
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: -1848230040
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
- beta4
|
35
|
+
version: 2.0.0.beta4
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
38
|
+
description: A collection of instance methods to more easily perform atomic updates to your Mongoid models.
|
39
|
+
email: jcoene@gmail.com
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files:
|
45
|
+
- README.rdoc
|
46
|
+
files:
|
47
|
+
- README.rdoc
|
48
|
+
- VERSION
|
49
|
+
- lib/mongoid_atomic.rb
|
50
|
+
- spec/models/user.rb
|
51
|
+
- spec/mongoid_atomic_spec.rb
|
52
|
+
- spec/spec_helper.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/jcoene/mongoid_atomic
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options:
|
59
|
+
- --charset=UTF-8
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
hash: 3
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 3
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.3.7
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Atomic updates for your Mongoid models.
|
87
|
+
test_files:
|
88
|
+
- spec/models/user.rb
|
89
|
+
- spec/mongoid_atomic_spec.rb
|
90
|
+
- spec/spec_helper.rb
|