mongoid-tenant 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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: