mongoid-tenant 0.0.5 → 0.0.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d98d3fcee576f2aa4fd6d1c72225b0491b614694
4
- data.tar.gz: 600205308c2e42bc4c4b8ea8c855b89af2402797
3
+ metadata.gz: 13200e42649305b163500529ef5cf49d9f72b6af
4
+ data.tar.gz: 3d7df78088d6668b12b1e1f371ff2dd283c2f1fe
5
5
  SHA512:
6
- metadata.gz: a04ab62aa4848479701228f93b75f2fad985c489284ac95d5c0922d0b697baccfb974424678374d030a9274e80a344b6c19e35b94fd5e78a4bde30124870f3a4
7
- data.tar.gz: 4c44fd1d7bc9b70dc58cad1720ea93e094574903656ecdb1e6eda79590b18f3fb3ca97c391d62bad61c734949612c743fe8a74a17b1331fbae9b4d5d2aeac645
6
+ metadata.gz: 890d1639ca4a5b59fe6a49c72ba53942c223c25f766ad84d2ffc1bd15f40a42bb8127810c5af0f6ce69b1bc48efa0f29f5ade830e302ae3c25af2e5ee4a31b6e
7
+ data.tar.gz: b3784c0a6748cc5380bec1bafab4cd1f317f3d92193d732bc3c5fd1852223a579781a6d2471f8d23a344414e9d4a617d660e9b406d7454ccea4b89fc857a8f2f
data/.travis.yml CHANGED
@@ -24,3 +24,5 @@ services:
24
24
  env: CI="travis"
25
25
 
26
26
  script: "bundle exec rspec"
27
+
28
+ sudo: false
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source 'http://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'mongoid', '5.0.0.beta'
6
+
5
7
  group :test do
6
8
  gem 'guard'
7
9
  gem 'guard-rspec'
@@ -9,5 +11,5 @@ group :test do
9
11
  gem 'rspec', '>= 3.2.0'
10
12
  gem 'coveralls', require: false
11
13
  gem 'codeclimate-test-reporter', require: nil
12
- gem 'mongoid-rspec', git: 'https://github.com/nofxx/mongoid-rspec'
14
+ gem 'mongoid-rspec'
13
15
  end
data/Guardfile CHANGED
@@ -9,14 +9,14 @@
9
9
 
10
10
  # guard :rubocop do
11
11
  guard :rubocop, all_on_start: false, keep_failed: false, cli: ['-D'] do
12
- watch(%r{.+\.rb$})
12
+ watch(/.+\.rb$/)
13
13
  watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
14
14
  end
15
15
 
16
16
  guard :rspec, cmd: 'bundle exec rspec' do
17
17
  watch(%r{^spec/.+_spec\.rb$})
18
18
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
19
- watch(/^generators\/(.+)\.rb$/) { |_m| 'spec/schemaless/worker_spec' }
19
+ watch(%r{^generators/(.+)\.rb$}) { |_m| 'spec/schemaless/worker_spec' }
20
20
 
21
21
  watch('spec/spec_helper.rb') { 'spec' }
22
22
  end
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  Mongoid::Tenant
2
2
  ===============
3
3
 
4
- [![Gem Version](https://badge.fury.io/rb/mongoid-tenant.png)](http://badge.fury.io/rb/mongoid-tenant)
4
+ [![Gem Version](https://badge.fury.io/rb/mongoid-tenant.svg)](http://badge.fury.io/rb/mongoid-tenant)
5
5
  [![Dependency Status](https://gemnasium.com/nofxx/mongoid-tenant.svg)](https://gemnasium.com/nofxx/mongoid-tenant)
6
- [![Build Status](https://secure.travis-ci.org/nofxx/mongoid-tenant.png)](http://travis-ci.org/nofxx/mongoid-tenant)
6
+ [![Build Status](https://secure.travis-ci.org/nofxx/mongoid-tenant.svg)](http://travis-ci.org/nofxx/mongoid-tenant)
7
7
 
8
8
  ## Mongoid::Tenant
9
9
 
@@ -35,6 +35,8 @@ And that's all. But we need a tenancy:
35
35
  class Shop
36
36
  include Mongoid::Document
37
37
  include Mongoid::Tenancy
38
+
39
+ tenant_key :url
38
40
  end
39
41
  ```
40
42
 
@@ -54,10 +56,20 @@ Shop.first.tenancy!
54
56
 
55
57
  ### Tenancy.tenants
56
58
 
57
- Helper to execute something on each tenant namespace. Eg:
59
+ Helper to execute something on each tenant namespace.
60
+ has_many substitute. Eg:
58
61
 
59
62
  ```
60
- Shop.tenants { |t| puts "#{t} has #{Bike.count}" }
63
+ class Shop
64
+ ...
65
+ has_tenant :bikes
66
+ end
67
+ ```
68
+
69
+ Or raw:
70
+
71
+ ```
72
+ Shop.tenants { |tenant| puts "#{tenant} have #{Bike.count} bike(s)" }
61
73
  ```
62
74
 
63
75
 
@@ -69,3 +81,20 @@ You'll need to provide which Tenancy to scope. In our example:
69
81
  ```
70
82
  TENANCY=Shop bundle exec rails db:mongoid:create_indexes
71
83
  ```
84
+
85
+ ## ApplicationController
86
+
87
+ Write your logic:
88
+
89
+ ```
90
+ def app_domain
91
+ @domain ||= Shop.find_by(uri: /^#{request.env["SERVER_NAME"]}/)
92
+ @domain.tenancy!
93
+ end
94
+ ```
95
+
96
+
97
+ ## Issues
98
+
99
+
100
+ http://github.com/nofxx/mongoid-tenant
@@ -1,3 +1,3 @@
1
- $: << File.expand_path("../../lib", __FILE__)
1
+ $LOAD_PATH << File.expand_path('../../lib', __FILE__)
2
2
 
3
3
  # Maybe benchmark stringex vs babosa just for fun...
@@ -1,24 +1,49 @@
1
1
  module Mongoid
2
+ #
3
+ # Tenancy Module
4
+ #
5
+ # Provides #tenant_key and #tenancy!
6
+ #
2
7
  module Tenancy
3
8
  extend ActiveSupport::Concern
9
+ #
10
+ # Model instance
11
+ module ClassMethods
12
+ def tenant_key(key, options = {})
13
+ field key, type: Symbol
14
+ options[:validates] ||= { presence: true }
15
+ options[:index] ||= {}
4
16
 
5
- included do
6
- field :uri, type: String
17
+ validates key, { uniqueness: true }.merge(options[:validates])
7
18
 
8
- validates :uri, uniqueness: true
19
+ index({ key => 1 }, { unique: true }.merge(options[:index]))
9
20
 
10
- index({ uri: 1 }, unique: true)
21
+ define_method(:tenant_key) do
22
+ send(key).to_s
23
+ end
24
+
25
+ define_singleton_method(:clear_tenancy!) do
26
+ Thread.current[:tenancy] = nil
27
+ end
28
+
29
+ define_singleton_method(:with_tenants) do |&block|
30
+ all.each do |t|
31
+ t.tenancy!
32
+ block.call(t)
33
+ end
34
+ clear_tenancy!
35
+ end
36
+ end
11
37
 
12
- def self.tenants
13
- all.each do |t|
14
- t.tenancy!
15
- yield t
38
+ def has_tenant(relative)
39
+ define_method(relative) do
40
+ tenancy! && relative.to_s.classify.constantize
16
41
  end
17
42
  end
18
43
  end
19
44
 
20
45
  def tenancy!
21
- Thread.current[:mongodb] = _id.to_s
46
+ Thread.current[:tenancy] = tenant_key
22
47
  end
23
48
  end # Tenancy
24
49
  end # Mongoid
@@ -1,10 +1,13 @@
1
1
  module Rails
2
- module Mongoid::Tenant
3
- class Railtie < Rails::Railtie
4
- rake_tasks do
5
- load "mongoid/tenant/tasks/tenant.rake"
2
+ module Mongoid
3
+ module Tenant
4
+ # Load rake tasks
5
+ # MongoDB Indexes
6
+ class Railtie < Rails::Railtie
7
+ rake_tasks do
8
+ load 'mongoid/tenant/tasks/tenant.rake'
9
+ end
6
10
  end
7
-
8
- end
9
- end
10
- end
11
+ end # Tenant
12
+ end # Mongoid
13
+ end # Rails
@@ -1,25 +1,26 @@
1
- Rake::Task["db:mongoid:create_indexes"].clear
2
- Rake::Task["db:mongoid:remove_undefined_indexes"].clear
1
+ Rake::Task['db:mongoid:create_indexes'].clear
2
+ Rake::Task['db:mongoid:remove_undefined_indexes'].clear
3
3
 
4
4
  namespace :db do
5
5
  namespace :mongoid do
6
-
7
- def get_tenancy
6
+ def tenancy_env
8
7
  ENV['TENANCY'] ||
9
8
  fail("Provide a tenancy model: `TENANCY=Foo #{ARGV.join}`")
10
9
  end
11
10
 
12
- task :create_indexes => [:environment, :load_models] do
13
- Rake::Task["db:mongoid:create_indexes"].clear
14
- Object.const_get(get_tenancy).all.each do |t|
11
+ desc 'Create Mongoid indexes, tenant aware'
12
+ task create_indexes: [:environment, :load_models] do
13
+ Rake::Task['db:mongoid:create_indexes'].clear
14
+ Object.const_get(tenancy_env).all.each do |t|
15
15
  puts "Tenant #{t}"
16
16
  t.tenancy!
17
17
  ::Mongoid::Tasks::Database.create_indexes
18
18
  end
19
19
  end
20
20
 
21
- task :remove_undefined_indexes => [:environment, :load_models] do
22
- Object.const_get(get_tenancy).all.each do |t|
21
+ desc 'Removes undefined Mongoid indexes, tenant aware'
22
+ task remove_undefined_indexes: [:environment, :load_models] do
23
+ Object.const_get(tenancy_env).all.each do |t|
23
24
  puts "Tenant #{t}"
24
25
  t.tenancy!
25
26
  ::Mongoid::Tasks::Database.remove_undefined_indexes
@@ -1,6 +1,6 @@
1
1
  module Mongoid
2
2
  # Mongoid::Tenant::VERSION
3
3
  module Tenant
4
- VERSION = '0.0.5'
4
+ VERSION = '0.0.7'
5
5
  end
6
6
  end
@@ -1,14 +1,17 @@
1
1
  require 'mongoid'
2
- require_relative 'tenancy'
2
+ require 'mongoid/tenancy'
3
3
 
4
4
  require 'mongoid/tenant/railtie' if defined?(Rails)
5
5
 
6
6
  module Mongoid
7
+ #
8
+ # The tenant
9
+ #
7
10
  module Tenant
8
11
  extend ActiveSupport::Concern
9
12
 
10
13
  included do
11
- store_in database: -> { Thread.current[:mongodb] }
14
+ store_in database: -> { Thread.current[:tenancy] }
12
15
  end
13
16
  end # Tenant
14
17
  end # Mongoid
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
3
  require 'mongoid/tenant/version'
4
4
 
5
5
  Gem::Specification.new do |s|
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ['Marcos Piccinini']
10
10
  s.homepage = 'http://github.com/nofxx/mongoid-tenant'
11
- s.summary = 'Multi Database/Tenants models for Mongoid documents.'
12
- s.description = 'Mongoid Tenant with multiple database per client.'
11
+ s.summary = 'Multiple databases Models for Mongoid documents.'
12
+ s.description = 'Multiple databases Mongoid Models. Good for SaaS Apps.'
13
13
  s.license = 'MIT'
14
14
 
15
15
  s.rubyforge_project = 'mongoid-tenant'
@@ -17,6 +17,5 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.files = `git ls-files`.split("\n")
19
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
21
20
  s.require_paths = ['lib']
22
21
  end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Tenancy do
4
+ def clear_tenancy!
5
+ Thread.current[:tenancy] = nil
6
+ end
7
+
8
+ describe 'A Journal' do
9
+ let(:journal) { Journal.create!(url: 'a_casseta_test', name: 'A Casseta') }
10
+ let(:other) { Journal.create!(url: 'a_planeta_test', name: 'O Planeta') }
11
+
12
+ it 'should work' do
13
+ journal.tenancy!
14
+ expect { Article.create!(title: 'Nice Coffeeshop') }.to_not raise_error
15
+ expect(Article.count).to eq 1
16
+ end
17
+
18
+ it 'should not interfer with mongoid' do
19
+ journal.tenancy!
20
+ expect(Journal.count).to eq 1
21
+ expect(Journal.all.to_a).to eq [journal]
22
+ end
23
+
24
+ it 'should switch from tenant to tenant' do
25
+ journal.tenancy!
26
+ expect { Article.create!(title: 'Nice Coffeeshop') }.to_not raise_error
27
+ expect(Article.count).to eq 1
28
+ other.tenancy!
29
+ expect(Article.count).to eq 0
30
+ end
31
+
32
+ it 'should switch back from tenant' do
33
+ other.tenancy!
34
+ expect { Article.create!(title: 'Nice Coffeeshop') }.to_not raise_error
35
+ expect(Article.count).to eq 1
36
+ journal.tenancy!
37
+ expect(Article.count).to eq 0
38
+ end
39
+
40
+ it 'should switch another test' do
41
+ journal.tenancy!
42
+ expect { Article.create!(title: 'Nice Coffeeshop 1') }.to_not raise_error
43
+ other.tenancy!
44
+ expect { Article.create!(title: 'Nice Coffeeshop 2') }.to_not raise_error
45
+ expect(Article.count).to eq 1
46
+ journal.tenancy!
47
+ expect(Article.count).to eq 1
48
+ end
49
+
50
+ it 'should have a multiple helper' do
51
+ journal.tenancy!
52
+ Article.create!(title: 'Nice Coffeeshop')
53
+ clear_tenancy!
54
+ expect(journal.articles.count).to eq 1
55
+ end
56
+
57
+ it 'should have a multiple helper' do
58
+ journal.tenancy!
59
+ article = Article.create!(title: 'Nice Coffeeshop')
60
+ clear_tenancy!
61
+ expect(journal.articles.first).to eq article
62
+ end
63
+
64
+ it 'should not leak tenancy key' do
65
+ journal && other
66
+ Journal.with_tenants { Article.create!(title: 'Hello') }
67
+ expect(Thread.current[:tenancy]).to be nil
68
+ end
69
+
70
+ it 'should have a multiple helper' do
71
+ journal && other
72
+ Journal.with_tenants { Article.create!(title: 'Hello') }
73
+ Journal.with_tenants { Article.create!(title: 'Hello') }
74
+ journal.tenancy!
75
+ expect(Article.count).to eq 2
76
+ end
77
+ end
78
+
79
+ describe 'A Blog' do
80
+ let(:blog) { Blog.create!(url: 'b_casseta_test', name: 'A Casseta') }
81
+ let(:other) { Blog.create!(url: 'b_planeta_test', name: 'O Planeta') }
82
+
83
+ it 'should not validate key' do
84
+ expect(Blog.create!(name: 'Monty News')).to be_valid
85
+ expect(Blog.count).to eq 1
86
+ end
87
+
88
+ it 'should work fine w/o key' do
89
+ Blog.create!(name: 'Monty News')
90
+ expect(Blog.first.name).to eq 'Monty News'
91
+ end
92
+
93
+ it 'should not create database if it`s sparse' do
94
+ expect { Blog.create!(name: 'Monty News') }
95
+ .to_not change(self, :fetch_dbs)
96
+ end
97
+
98
+ it 'should create database if it`s sparse' do
99
+ expect { blog && blog.tenancy! && Article.create! }
100
+ .to change(self, :fetch_dbs)
101
+ end
102
+
103
+ end
104
+ end
@@ -1,4 +1,35 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mongoid::Tenant do
4
+ it 'should have a tenancy' do
5
+ expect(Journal).to include(Mongoid::Tenancy)
6
+ end
7
+
8
+ it 'should not have both modules' do
9
+ expect(Journal).to_not include(Mongoid::Tenant)
10
+ end
11
+
12
+ it 'should have a tenant' do
13
+ expect(Article).to include(Mongoid::Tenant)
14
+ end
15
+
16
+ it 'should not have both modules' do
17
+ expect(Article).to_not include(Mongoid::Tenancy)
18
+ end
19
+
20
+ it 'should not interfer with tenancy' do
21
+ expect do
22
+ Journal.create!(url: 'a_planeta_test', name: 'Planeta Diário')
23
+ end.to_not raise_error
24
+ expect(Journal.count).to eq 1
25
+ end
26
+
27
+ it 'should not interfer other models' do
28
+ expect { City.create!(name: 'Sin City') }.to_not raise_error
29
+ end
30
+
31
+ it 'should interfer with tenant w/o tenancy' do
32
+ expect { Article.create!(title: 'A Very Nice Coffeeshop') }
33
+ .to raise_error(NoMethodError)
34
+ end
4
35
  end
data/spec/spec_helper.rb CHANGED
@@ -16,7 +16,7 @@ require 'mongoid/tenant'
16
16
 
17
17
  ENV['MONGOID_ENV'] = 'test'
18
18
 
19
- db_config = {
19
+ DB_CONFIG = {
20
20
  default: {
21
21
  database: 'mongoid_tenant_test',
22
22
  hosts: ["localhost: #{ENV['MONGODB_PORT'] || 27_017}"],
@@ -24,12 +24,28 @@ db_config = {
24
24
  }
25
25
  }
26
26
 
27
+ def new_conn(db = '')
28
+ Mongo::Client.new(DB_CONFIG[:default][:hosts], database: db)
29
+ end
30
+
31
+ def fetch_dbs
32
+ new_conn.database_names.to_a # each { |n| START_DBS << n }
33
+ end
34
+
35
+ def drop_shared
36
+ %w( a_casseta_test a_planeta_test b_casseta_test b_planeta_test ).each do |db|
37
+ new_conn(db).database.drop
38
+ end
39
+ end
40
+
41
+ START_DBS = fetch_dbs
42
+
27
43
  Mongoid.configure do |config|
28
44
  config.load_configuration(
29
45
  if Mongoid::VERSION >= '5'
30
- { clients: db_config }
46
+ { clients: DB_CONFIG }
31
47
  else
32
- { sessions: db_config }
48
+ { sessions: DB_CONFIG }
33
49
  end
34
50
  )
35
51
  end
@@ -42,10 +58,19 @@ RSpec.configure do |config|
42
58
  config.include Mongoid::Matchers
43
59
 
44
60
  config.before(:each) do
45
- Mongoid.purge!
61
+ Thread.current[:tenancy] = nil
62
+ drop_shared
63
+ # HACK: Mongoid.purge!
64
+ [Journal, Blog, City].each(&:delete_all)
65
+ end
66
+
67
+ config.after(:each) do
68
+ drop_shared
46
69
  end
47
70
 
48
71
  config.after(:suite) do
72
+ extra_dbs = fetch_dbs - START_DBS
73
+ fail "Extra DBs: #{extra_dbs.inspect}" unless extra_dbs.empty?
49
74
  puts "\n# With Mongoid v#{Mongoid::VERSION}"
50
75
  end
51
76
  end
@@ -1,14 +1,42 @@
1
- # A nice model for a blog!
1
+ # A nice model for jornalistic SaaS!
2
2
  class Journal
3
3
  include Mongoid::Document
4
4
  include Mongoid::Tenancy
5
5
 
6
6
  field :name
7
+ tenant_key :url
8
+
9
+ has_tenant :articles
7
10
  end
8
11
 
12
+ # Reporter -> Journal tenant
13
+ class Reporter
14
+ include Mongoid::Document
15
+ include Mongoid::Tenant
16
+
17
+ field :name
18
+ end
19
+
20
+ # Article -> Journal tenant
9
21
  class Article
10
22
  include Mongoid::Document
11
23
  include Mongoid::Tenant
24
+
12
25
  field :title
13
26
  field :body
14
27
  end
28
+
29
+ # City normal model
30
+ class City
31
+ include Mongoid::Document
32
+ field :name
33
+ end
34
+
35
+ class Blog
36
+ include Mongoid::Document
37
+ include Mongoid::Tenancy
38
+ field :name
39
+ tenant_key :url, validates: { allow_nil: true }, index: { sparse: true }
40
+
41
+ has_tenant :articles
42
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-tenant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcos Piccinini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-18 00:00:00.000000000 Z
11
+ date: 2015-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mongoid
@@ -24,7 +24,7 @@ dependencies:
24
24
  - - ">"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 4.0.0
27
- description: Mongoid Tenant with multiple database per client.
27
+ description: Multiple databases Mongoid Models. Good for SaaS Apps.
28
28
  email:
29
29
  executables: []
30
30
  extensions: []
@@ -45,6 +45,7 @@ files:
45
45
  - lib/mongoid/tenant/tasks/tenant.rake
46
46
  - lib/mongoid/tenant/version.rb
47
47
  - mongoid-tenant.gemspec
48
+ - spec/mongoid/tenancy_spec.rb
48
49
  - spec/mongoid/tenant_spec.rb
49
50
  - spec/spec_helper.rb
50
51
  - spec/support/models.rb
@@ -68,11 +69,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
69
  version: '0'
69
70
  requirements: []
70
71
  rubyforge_project: mongoid-tenant
71
- rubygems_version: 2.4.7
72
+ rubygems_version: 2.4.8
72
73
  signing_key:
73
74
  specification_version: 4
74
- summary: Multi Database/Tenants models for Mongoid documents.
75
+ summary: Multiple databases Models for Mongoid documents.
75
76
  test_files:
77
+ - spec/mongoid/tenancy_spec.rb
76
78
  - spec/mongoid/tenant_spec.rb
77
79
  - spec/spec_helper.rb
78
80
  - spec/support/models.rb
81
+ has_rdoc: