mongoid-multitenancy 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +55 -0
- data/LICENSE.TXT +20 -0
- data/README.md +156 -0
- data/Rakefile +8 -0
- data/lib/mongoid-multitenancy.rb +1 -0
- data/lib/mongoid/multitenancy.rb +35 -0
- data/lib/mongoid/multitenancy/document.rb +64 -0
- data/lib/mongoid/multitenancy/version.rb +5 -0
- data/mongoid-multitenancy.gemspec +26 -0
- data/spec/models/article.rb +15 -0
- data/spec/models/client.rb +5 -0
- data/spec/mongoid-multitenancy_spec.rb +109 -0
- data/spec/spec_helper.rb +38 -0
- metadata +178 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
mongoid-multitenancy (0.1)
|
5
|
+
mongoid (~> 3)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (3.2.9)
|
11
|
+
activesupport (= 3.2.9)
|
12
|
+
builder (~> 3.0.0)
|
13
|
+
activesupport (3.2.9)
|
14
|
+
i18n (~> 0.6)
|
15
|
+
multi_json (~> 1.0)
|
16
|
+
builder (3.0.4)
|
17
|
+
database_cleaner (0.9.1)
|
18
|
+
diff-lcs (1.1.3)
|
19
|
+
i18n (0.6.1)
|
20
|
+
mongoid (3.0.14)
|
21
|
+
activemodel (~> 3.1)
|
22
|
+
moped (~> 1.1)
|
23
|
+
origin (~> 1.0)
|
24
|
+
tzinfo (~> 0.3.22)
|
25
|
+
mongoid-rspec (1.5.5)
|
26
|
+
mongoid (>= 3.0.1)
|
27
|
+
rake
|
28
|
+
rspec (>= 2.9)
|
29
|
+
moped (1.3.1)
|
30
|
+
multi_json (1.5.0)
|
31
|
+
origin (1.0.11)
|
32
|
+
rake (10.0.3)
|
33
|
+
redcarpet (2.2.2)
|
34
|
+
rspec (2.12.0)
|
35
|
+
rspec-core (~> 2.12.0)
|
36
|
+
rspec-expectations (~> 2.12.0)
|
37
|
+
rspec-mocks (~> 2.12.0)
|
38
|
+
rspec-core (2.12.1)
|
39
|
+
rspec-expectations (2.12.0)
|
40
|
+
diff-lcs (~> 1.1.3)
|
41
|
+
rspec-mocks (2.12.0)
|
42
|
+
tzinfo (0.3.35)
|
43
|
+
yard (0.8.3)
|
44
|
+
|
45
|
+
PLATFORMS
|
46
|
+
ruby
|
47
|
+
|
48
|
+
DEPENDENCIES
|
49
|
+
database_cleaner (~> 0.9)
|
50
|
+
mongoid-multitenancy!
|
51
|
+
mongoid-rspec (~> 1.5)
|
52
|
+
rake (~> 10.0)
|
53
|
+
redcarpet (~> 2.2)
|
54
|
+
rspec (~> 2.12)
|
55
|
+
yard (~> 0.8)
|
data/LICENSE.TXT
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Perfect Memory
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
# mongoid-multitenancy
|
2
|
+
|
3
|
+
mongoid-multitenancy adds the ability to scope [Mongoid](https://github.com/mongoid/mongoid) models to a tenant in a **shared database strategy**. Tenants are represented by a tenant model, such as `Client`. mongoid-multitenancy will help you set the current tenant on each request and ensures all 'tenant models' are always properly scoped to the current tenant: when viewing, searching and creating.
|
4
|
+
|
5
|
+
It is directly inspired by the [acts_as_tenant gem](https://github.com/ErwinM/acts_as_tenant) for Active Record.
|
6
|
+
|
7
|
+
In addition, mongoid-multitenancy:
|
8
|
+
|
9
|
+
* allows you to set the current tenant
|
10
|
+
* redefines some mongoid functions like `index`, `validates_with` and `delete_all` to take in account the multitenancy
|
11
|
+
* makes the tenant field immutable once it is persisted
|
12
|
+
* is thread safe.
|
13
|
+
|
14
|
+
Installation
|
15
|
+
===============
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'mongoid_multitenancy'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install mongoid_multitenancy
|
28
|
+
|
29
|
+
Usage
|
30
|
+
===============
|
31
|
+
|
32
|
+
There are two steps in adding multi-tenancy to your app with acts_as_tenant:
|
33
|
+
|
34
|
+
1. setting the current tenant and
|
35
|
+
2. scoping your models.
|
36
|
+
|
37
|
+
Setting the current tenant
|
38
|
+
--------------------------
|
39
|
+
There are two ways to set the current tenant: (1) by setting the current tenant manually, or (2) by setting the current tenant for a block.
|
40
|
+
|
41
|
+
**Setting the current tenant in a controller, manually**
|
42
|
+
|
43
|
+
Mongoid::MultiTenancy.current_tenant = client_instance
|
44
|
+
|
45
|
+
Setting the current_tenant yourself requires you to use a before_filter to set the Mongoid::MultiTenancy.current_tenant variable.
|
46
|
+
|
47
|
+
**Setting the current tenant for a block**
|
48
|
+
|
49
|
+
Mongoid::MultiTenancy.with_tenant(client_instance) do
|
50
|
+
# Current tenant is set for all code in this block
|
51
|
+
end
|
52
|
+
|
53
|
+
This approach is useful when running background processes for a specified tenant. For example, by putting this in your worker's run method,
|
54
|
+
any code in this block will be scoped to the current tenant. All methods that set the current tenant are thread safe.
|
55
|
+
|
56
|
+
**Note:** If the current tenant is not set by one of these methods, mongoid-multitenancy will apply a global scope to your models, not related to any tenant. So make sure you use one of the two methods to tell mongoid-multitenancy about the current tenant.
|
57
|
+
|
58
|
+
Scoping your models
|
59
|
+
-------------------
|
60
|
+
class Client
|
61
|
+
include Mongoid::Document
|
62
|
+
|
63
|
+
field :name, :type => String
|
64
|
+
validates_uniqueness_of :name
|
65
|
+
end
|
66
|
+
|
67
|
+
class Article
|
68
|
+
include Mongoid::Document
|
69
|
+
include Mongoid::Multitenancy::Document
|
70
|
+
|
71
|
+
tenant(:client)
|
72
|
+
|
73
|
+
field :title, :type => String
|
74
|
+
end
|
75
|
+
|
76
|
+
Adding `tenant` to your model declaration will scope that model to the current tenant **BUT ONLY if a current tenant has been set**.
|
77
|
+
The association passed to the `tenant` function must be valid.
|
78
|
+
|
79
|
+
Some examples to illustrate this behavior:
|
80
|
+
|
81
|
+
# This manually sets the current tenant for testing purposes. In your app this is handled by the gem.
|
82
|
+
Mongoid::MultiTenancy.current_tenant = Client.find_by(:name => 'Perfect Memory') # => <#Client _id:50ca04b86c82bfc125000025, :name: "Perfect Memory">
|
83
|
+
|
84
|
+
# All searches are scoped by the tenant, the following searches will only return objects belonging to the current client.
|
85
|
+
Article.all # => all articles where client_id => 50ca04b86c82bfc125000025
|
86
|
+
|
87
|
+
# New objects are scoped to the current tenant
|
88
|
+
Article.new(:title => 'New blog') # => <#Article _id: nil, title: 'New blog', :client_id: 50ca04b86c82bfc125000025>
|
89
|
+
|
90
|
+
# It makes the tenant field immutable once it is persisted to avoid inconsistency
|
91
|
+
article.persited? # => true
|
92
|
+
article.client = another_client
|
93
|
+
article.valid? # => false
|
94
|
+
|
95
|
+
Rails
|
96
|
+
-------------------
|
97
|
+
|
98
|
+
If you are using Rails, you may want to set the current tenant at each request.
|
99
|
+
|
100
|
+
**Manually set the current tenant in ApplicationController using the host request**
|
101
|
+
|
102
|
+
class ApplicationController < ActionController::Base
|
103
|
+
before_filter :set_current_client
|
104
|
+
|
105
|
+
def set_current_client
|
106
|
+
current_client = Client.find_by_host(request.host)
|
107
|
+
Mongoid::MultiTenancy.current_tenant = current_client
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
Setting the current_tenant yourself requires you to use a before_filter to set the Mongoid::MultiTenancy.current_tenant variable.
|
112
|
+
|
113
|
+
Mongoid Uniqueness validators
|
114
|
+
-------------------
|
115
|
+
|
116
|
+
mongoid-multitenancy will automatically add the tenant foreign key in the scope list for each of uniqueness validators in order
|
117
|
+
to avoid to redefine all your validators.
|
118
|
+
|
119
|
+
class Article
|
120
|
+
include Mongoid::Document
|
121
|
+
include Mongoid::Multitenancy::Document
|
122
|
+
|
123
|
+
tenant(:client)
|
124
|
+
|
125
|
+
field :slug
|
126
|
+
|
127
|
+
validates_uniqueness_of :slug # => :scope => client_id is added automatically
|
128
|
+
end
|
129
|
+
|
130
|
+
Mongoid indexes
|
131
|
+
-------------------
|
132
|
+
|
133
|
+
mongoid-multitenancy will automatically add the tenant foreign key in all your mongoid indexes to avoid to redefine all your validators.
|
134
|
+
|
135
|
+
class Article
|
136
|
+
include Mongoid::Document
|
137
|
+
include Mongoid::Multitenancy::Document
|
138
|
+
|
139
|
+
tenant(:client)
|
140
|
+
|
141
|
+
field :title
|
142
|
+
|
143
|
+
index({ :title => 1 }) # => create an index with { :client_id => 1, :title => 1 }
|
144
|
+
end
|
145
|
+
|
146
|
+
Author & Credits
|
147
|
+
----------------
|
148
|
+
mongoid-multitenancy is written by [Aymeric Brisse](https://github.com/abrisse/), from [Perfect Memory](http://www.perfect-memory.com).
|
149
|
+
|
150
|
+
## Contributing
|
151
|
+
|
152
|
+
1. Fork it
|
153
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
154
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
155
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
156
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'mongoid/multitenancy'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Multitenancy
|
3
|
+
require "mongoid"
|
4
|
+
|
5
|
+
require "mongoid/multitenancy/document"
|
6
|
+
require "mongoid/multitenancy/version"
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Set the current tenant. Make it Thread aware
|
11
|
+
def current_tenant=(tenant)
|
12
|
+
Thread.current[:current_tenant] = tenant
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the current tenant
|
16
|
+
def current_tenant
|
17
|
+
Thread.current[:current_tenant]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Affects a tenant temporary for a block execution
|
21
|
+
def with_tenant(tenant, &block)
|
22
|
+
if block.nil?
|
23
|
+
raise ArgumentError, "block required"
|
24
|
+
end
|
25
|
+
|
26
|
+
old_tenant = self.current_tenant
|
27
|
+
self.current_tenant = tenant
|
28
|
+
|
29
|
+
block.call
|
30
|
+
|
31
|
+
self.current_tenant = old_tenant
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Multitenancy
|
3
|
+
module Document
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
private
|
8
|
+
|
9
|
+
# Check that the tenant foreign key field has not been changed once the object has been persisted
|
10
|
+
def check_tenant_immutability
|
11
|
+
self.errors.add(self.class.tenant_field, 'is immutable and cannot be updated' ) if changed.include?(self.class.tenant_field)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
# Access to the tenant field
|
17
|
+
attr_reader :tenant_field
|
18
|
+
|
19
|
+
def tenant(association = :account)
|
20
|
+
# Setup the association between the class and the tenant class
|
21
|
+
# TODO: should index this association if no other indexes are defined => , index: true
|
22
|
+
belongs_to association
|
23
|
+
|
24
|
+
# Get the tenant model and its foreign key
|
25
|
+
fkey = reflect_on_association(association).foreign_key
|
26
|
+
@tenant_field = fkey
|
27
|
+
|
28
|
+
# Validates the presence of the association key
|
29
|
+
validates_presence_of fkey
|
30
|
+
|
31
|
+
# Set the current_tenant on newly created objects
|
32
|
+
after_initialize lambda { |m| m.send "#{association}=".to_sym, Multitenancy.current_tenant if Multitenancy.current_tenant ; true }
|
33
|
+
|
34
|
+
# Rewrite accessors to make tenant foreign_key/association immutable
|
35
|
+
validate :check_tenant_immutability, :unless => :new_record?
|
36
|
+
|
37
|
+
# Set the default_scope to scope to current tenant
|
38
|
+
default_scope lambda {
|
39
|
+
where(Multitenancy.current_tenant ? { self.tenant_field => Multitenancy.current_tenant.id } : nil)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Redefine 'validates_with' to add the tenant scope when using a UniquenessValidator
|
44
|
+
def validates_with(*args, &block)
|
45
|
+
if args.first == Validations::UniquenessValidator
|
46
|
+
args.last[:scope] = Array(args.last[:scope]) << self.tenant_field
|
47
|
+
end
|
48
|
+
super(*args, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Redefine 'index' to include the tenant field in first position
|
52
|
+
def index(spec, options = nil)
|
53
|
+
spec = { self.tenant_field => 1 }.merge(spec)
|
54
|
+
super(spec, options)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Redefine 'delete_all' to take in account the default scope
|
58
|
+
def delete_all(conditions = nil)
|
59
|
+
self.where(conditions).delete
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/mongoid/multitenancy/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Aymeric Brisse"]
|
6
|
+
gem.email = ["aymeric.brisse@mperfect-memory.com"]
|
7
|
+
gem.description = %q{MultiTenancy with Mongoid}
|
8
|
+
gem.summary = %q{Support of a multi-tenant database with Mongoid}
|
9
|
+
gem.homepage = "https://github.com/PerfectMemory/mongoid-multitenancy"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "mongoid-multitenancy"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Mongoid::Multitenancy::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency('mongoid', '~> 3')
|
19
|
+
|
20
|
+
gem.add_development_dependency('rake', '~> 10.0')
|
21
|
+
gem.add_development_dependency('rspec', '~> 2.12')
|
22
|
+
gem.add_development_dependency('yard', '~> 0.8')
|
23
|
+
gem.add_development_dependency('mongoid-rspec', '~> 1.5')
|
24
|
+
gem.add_development_dependency('database_cleaner', '~> 0.9')
|
25
|
+
gem.add_development_dependency('redcarpet', '~> 2.2')
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Article
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Multitenancy::Document
|
4
|
+
|
5
|
+
tenant(:client)
|
6
|
+
|
7
|
+
field :slug, :type => String
|
8
|
+
field :title, :type => String
|
9
|
+
|
10
|
+
validates_uniqueness_of :slug
|
11
|
+
validates_presence_of :slug
|
12
|
+
validates_presence_of :title
|
13
|
+
|
14
|
+
index({ :title => 1 })
|
15
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Multitenancy do
|
4
|
+
let(:client) { Client.create!(:name => "client") }
|
5
|
+
let(:another_client) { Client.create!(:name => "another client") }
|
6
|
+
|
7
|
+
before { Mongoid::Multitenancy.current_tenant = client }
|
8
|
+
after { Mongoid::Multitenancy.current_tenant = nil }
|
9
|
+
|
10
|
+
describe ".with_tenant" do
|
11
|
+
it "should change temporary the current tenant within the block" do
|
12
|
+
Mongoid::Multitenancy.with_tenant(another_client) do
|
13
|
+
Mongoid::Multitenancy.current_tenant.should == another_client
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should have restored the current tenant after the block" do
|
18
|
+
Mongoid::Multitenancy.with_tenant(another_client) do ; end
|
19
|
+
Mongoid::Multitenancy.current_tenant.should == client
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Article do
|
25
|
+
it { should belong_to(:client) }
|
26
|
+
it { should validate_presence_of(:client_id) }
|
27
|
+
it { should validate_uniqueness_of(:slug).scoped_to(:client_id) }
|
28
|
+
it { should have_index_for(:client_id => 1, :title => 1) }
|
29
|
+
|
30
|
+
let(:client) { Client.create!(:name => "client") }
|
31
|
+
let(:another_client) { Client.create!(:name => "another client") }
|
32
|
+
|
33
|
+
describe ".initialize" do
|
34
|
+
before { Mongoid::Multitenancy.current_tenant = client }
|
35
|
+
after { Mongoid::Multitenancy.current_tenant = nil }
|
36
|
+
|
37
|
+
it "should set the client field" do
|
38
|
+
Article.new.client.should eq client
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe ".default_scope" do
|
43
|
+
before {
|
44
|
+
Mongoid::Multitenancy.with_tenant(client) { @articleX = Article.create!(:title => "title X", :slug => "article-x") }
|
45
|
+
Mongoid::Multitenancy.with_tenant(another_client) { @articleY = Article.create!(:title => "title Y", :slug => "article-y") }
|
46
|
+
}
|
47
|
+
|
48
|
+
context "with a current tenant" do
|
49
|
+
before { Mongoid::Multitenancy.current_tenant = another_client }
|
50
|
+
after { Mongoid::Multitenancy.current_tenant = nil }
|
51
|
+
|
52
|
+
it "should filter on the current tenant" do
|
53
|
+
Article.all.to_a.should == [@articleY]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "without a current tenant" do
|
58
|
+
before { Mongoid::Multitenancy.current_tenant = nil }
|
59
|
+
|
60
|
+
it "should not filter on any tenant" do
|
61
|
+
Article.all.to_a.should == [@articleX, @articleY]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#valid?" do
|
67
|
+
before { Mongoid::Multitenancy.current_tenant = client }
|
68
|
+
after { Mongoid::Multitenancy.current_tenant = nil }
|
69
|
+
|
70
|
+
let(:article) { Article.create!(:title => "title X", :slug => "article-x") }
|
71
|
+
|
72
|
+
context "when the tenant has not changed" do
|
73
|
+
it 'should be valid' do
|
74
|
+
article.title = "title X (2)"
|
75
|
+
article.should be_valid
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when the tenant has changed" do
|
80
|
+
it 'should be invalid' do
|
81
|
+
article.title = "title X (2)"
|
82
|
+
article.client = another_client
|
83
|
+
article.should_not be_valid
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#delete_all" do
|
90
|
+
before {
|
91
|
+
Mongoid::Multitenancy.with_tenant(client) { @articleX = Article.create!(:title => "title X", :slug => "article-x") }
|
92
|
+
Mongoid::Multitenancy.with_tenant(another_client) { @articleY = Article.create!(:title => "title Y", :slug => "article-y") }
|
93
|
+
}
|
94
|
+
|
95
|
+
context "with a current tenant" do
|
96
|
+
it "should only delete the current tenant articles" do
|
97
|
+
Mongoid::Multitenancy.with_tenant(another_client) { Article.delete_all }
|
98
|
+
Article.all.to_a == [@articleX]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "without a current tenant" do
|
103
|
+
it "should delete all the articles" do
|
104
|
+
Article.delete_all
|
105
|
+
Article.all.to_a.should be_empty
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
3
|
+
MODELS = File.join(File.dirname(__FILE__), "models")
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'bundler/setup'
|
7
|
+
|
8
|
+
require 'rspec'
|
9
|
+
require 'mongoid'
|
10
|
+
require 'mongoid-multitenancy'
|
11
|
+
require 'database_cleaner'
|
12
|
+
require 'mongoid-rspec'
|
13
|
+
|
14
|
+
Dir["#{MODELS}/*.rb"].each { |f| require f }
|
15
|
+
|
16
|
+
Mongoid.configure do |config|
|
17
|
+
config.connect_to "mongoid_multitenancy"
|
18
|
+
end
|
19
|
+
|
20
|
+
Mongoid.logger = Logger.new($stdout)
|
21
|
+
|
22
|
+
DatabaseCleaner.orm = "mongoid"
|
23
|
+
|
24
|
+
RSpec.configure do |config|
|
25
|
+
config.include Mongoid::Matchers
|
26
|
+
|
27
|
+
config.before(:all) do
|
28
|
+
DatabaseCleaner.strategy = :truncation
|
29
|
+
end
|
30
|
+
|
31
|
+
config.before(:each) do
|
32
|
+
DatabaseCleaner.start
|
33
|
+
end
|
34
|
+
|
35
|
+
config.after(:each) do
|
36
|
+
DatabaseCleaner.clean
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongoid-multitenancy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Aymeric Brisse
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mongoid
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '10.0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '10.0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.12'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.12'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: yard
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.8'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0.8'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: mongoid-rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '1.5'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.5'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: database_cleaner
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.9'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.9'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: redcarpet
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.2'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '2.2'
|
126
|
+
description: MultiTenancy with Mongoid
|
127
|
+
email:
|
128
|
+
- aymeric.brisse@mperfect-memory.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- .rspec
|
135
|
+
- Gemfile
|
136
|
+
- Gemfile.lock
|
137
|
+
- LICENSE.TXT
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- lib/mongoid-multitenancy.rb
|
141
|
+
- lib/mongoid/multitenancy.rb
|
142
|
+
- lib/mongoid/multitenancy/document.rb
|
143
|
+
- lib/mongoid/multitenancy/version.rb
|
144
|
+
- mongoid-multitenancy.gemspec
|
145
|
+
- spec/models/article.rb
|
146
|
+
- spec/models/client.rb
|
147
|
+
- spec/mongoid-multitenancy_spec.rb
|
148
|
+
- spec/spec_helper.rb
|
149
|
+
homepage: https://github.com/PerfectMemory/mongoid-multitenancy
|
150
|
+
licenses: []
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
none: false
|
157
|
+
requirements:
|
158
|
+
- - ! '>='
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
none: false
|
163
|
+
requirements:
|
164
|
+
- - ! '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
requirements: []
|
168
|
+
rubyforge_project:
|
169
|
+
rubygems_version: 1.8.24
|
170
|
+
signing_key:
|
171
|
+
specification_version: 3
|
172
|
+
summary: Support of a multi-tenant database with Mongoid
|
173
|
+
test_files:
|
174
|
+
- spec/models/article.rb
|
175
|
+
- spec/models/client.rb
|
176
|
+
- spec/mongoid-multitenancy_spec.rb
|
177
|
+
- spec/spec_helper.rb
|
178
|
+
has_rdoc:
|