apartment 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +5 -8
  4. data/Gemfile +1 -0
  5. data/README.md +79 -4
  6. data/apartment.gemspec +2 -2
  7. data/gemfiles/rails_3_2.gemfile +2 -0
  8. data/lib/apartment.rb +22 -2
  9. data/lib/apartment/adapters/abstract_adapter.rb +70 -16
  10. data/lib/apartment/adapters/abstract_jdbc_adapter.rb +4 -9
  11. data/lib/apartment/adapters/jdbc_mysql_adapter.rb +2 -13
  12. data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +5 -16
  13. data/lib/apartment/adapters/mysql2_adapter.rb +8 -19
  14. data/lib/apartment/adapters/postgresql_adapter.rb +16 -41
  15. data/lib/apartment/adapters/sqlite3_adapter.rb +6 -3
  16. data/lib/apartment/elevators/first_subdomain.rb +1 -1
  17. data/lib/apartment/elevators/generic.rb +5 -3
  18. data/lib/apartment/version.rb +1 -1
  19. data/lib/generators/apartment/install/templates/apartment.rb +26 -1
  20. data/lib/tasks/apartment.rake +0 -1
  21. data/spec/adapters/jdbc_mysql_adapter_spec.rb +1 -1
  22. data/spec/adapters/jdbc_postgresql_adapter_spec.rb +1 -1
  23. data/spec/adapters/mysql2_adapter_spec.rb +2 -1
  24. data/spec/adapters/postgresql_adapter_spec.rb +1 -0
  25. data/spec/adapters/sqlite3_adapter_spec.rb +56 -0
  26. data/spec/apartment_spec.rb +2 -2
  27. data/spec/examples/connection_adapter_examples.rb +1 -1
  28. data/spec/examples/generic_adapter_custom_configuration_example.rb +90 -0
  29. data/spec/examples/generic_adapter_examples.rb +15 -15
  30. data/spec/examples/schema_adapter_examples.rb +25 -25
  31. data/spec/integration/apartment_rake_integration_spec.rb +4 -4
  32. data/spec/integration/query_caching_spec.rb +2 -2
  33. data/spec/spec_helper.rb +11 -0
  34. data/spec/support/apartment_helpers.rb +8 -2
  35. data/spec/support/setup.rb +3 -3
  36. data/spec/tasks/apartment_rake_spec.rb +11 -11
  37. data/spec/tenant_spec.rb +12 -12
  38. data/spec/unit/config_spec.rb +53 -23
  39. data/spec/unit/elevators/domain_spec.rb +4 -4
  40. data/spec/unit/elevators/first_subdomain_spec.rb +7 -2
  41. data/spec/unit/elevators/generic_spec.rb +19 -2
  42. data/spec/unit/elevators/host_hash_spec.rb +2 -2
  43. data/spec/unit/elevators/subdomain_spec.rb +6 -6
  44. data/spec/unit/migrator_spec.rb +1 -1
  45. data/spec/unit/reloader_spec.rb +2 -2
  46. metadata +11 -9
@@ -60,7 +60,7 @@ describe Apartment::Tenant do
60
60
  describe "#adapter" do
61
61
  it "should load postgresql adapter" do
62
62
  subject.adapter
63
- Apartment::Adapters::PostgresqlAdapter.should be_a(Class)
63
+ expect(Apartment::Adapters::PostgresqlAdapter).to be_a(Class)
64
64
  end
65
65
 
66
66
  it "raises exception with invalid adapter specified" do
@@ -77,9 +77,9 @@ describe Apartment::Tenant do
77
77
 
78
78
  it 'has a threadsafe adapter' do
79
79
  subject.switch!(db1)
80
- thread = Thread.new { subject.current.should == Apartment.default_tenant }
80
+ thread = Thread.new { expect(subject.current).to eq(Apartment.default_tenant) }
81
81
  thread.join
82
- subject.current.should == db1
82
+ expect(subject.current).to eq(db1)
83
83
  end
84
84
  end
85
85
  end
@@ -100,7 +100,7 @@ describe Apartment::Tenant do
100
100
  describe "#create" do
101
101
  it "should seed data" do
102
102
  subject.switch! db1
103
- User.count.should be > 0
103
+ expect(User.count).to be > 0
104
104
  end
105
105
  end
106
106
 
@@ -121,10 +121,10 @@ describe Apartment::Tenant do
121
121
  db_count = User.count + x.times{ User.create }
122
122
 
123
123
  subject.switch! db2
124
- User.count.should == db2_count
124
+ expect(User.count).to eq(db2_count)
125
125
 
126
126
  subject.switch! db1
127
- User.count.should == db_count
127
+ expect(User.count).to eq(db_count)
128
128
  end
129
129
  end
130
130
 
@@ -143,9 +143,9 @@ describe Apartment::Tenant do
143
143
 
144
144
  subject.switch! db1
145
145
  x.times{ Company.create }
146
- Company.count.should == count + x
146
+ expect(Company.count).to eq(count + x)
147
147
  subject.reset
148
- Company.count.should == count + x
148
+ expect(Company.count).to eq(count + x)
149
149
  end
150
150
  end
151
151
  end
@@ -165,8 +165,8 @@ describe Apartment::Tenant do
165
165
  it 'should seed from default path' do
166
166
  subject.create db1
167
167
  subject.switch! db1
168
- User.count.should eq(3)
169
- User.first.name.should eq('Some User 0')
168
+ expect(User.count).to eq(3)
169
+ expect(User.first.name).to eq('Some User 0')
170
170
  end
171
171
 
172
172
  it 'should seed from custom path' do
@@ -175,8 +175,8 @@ describe Apartment::Tenant do
175
175
  end
176
176
  subject.create db1
177
177
  subject.switch! db1
178
- User.count.should eq(6)
179
- User.first.name.should eq('Different User 0')
178
+ expect(User.count).to eq(6)
179
+ expect(User.first.name).to eq('Different User 0')
180
180
  end
181
181
  end
182
182
  end
@@ -7,10 +7,16 @@ describe Apartment do
7
7
  let(:excluded_models){ ["Company"] }
8
8
  let(:seed_data_file_path){ "#{Rails.root}/db/seeds/import.rb" }
9
9
 
10
+ def tenant_names_from_array(names)
11
+ names.each_with_object({}) do |tenant, hash|
12
+ hash[tenant] = Apartment.connection_config
13
+ end.with_indifferent_access
14
+ end
15
+
10
16
  it "should yield the Apartment object" do
11
17
  Apartment.configure do |config|
12
18
  config.excluded_models = []
13
- config.should == Apartment
19
+ expect(config).to eq(Apartment)
14
20
  end
15
21
  end
16
22
 
@@ -18,7 +24,7 @@ describe Apartment do
18
24
  Apartment.configure do |config|
19
25
  config.excluded_models = excluded_models
20
26
  end
21
- Apartment.excluded_models.should == excluded_models
27
+ expect(Apartment.excluded_models).to eq(excluded_models)
22
28
  end
23
29
 
24
30
  it "should set use_schemas" do
@@ -26,14 +32,14 @@ describe Apartment do
26
32
  config.excluded_models = []
27
33
  config.use_schemas = false
28
34
  end
29
- Apartment.use_schemas.should be false
35
+ expect(Apartment.use_schemas).to be false
30
36
  end
31
37
 
32
38
  it "should set seed_data_file" do
33
39
  Apartment.configure do |config|
34
40
  config.seed_data_file = seed_data_file_path
35
41
  end
36
- Apartment.seed_data_file.should eq(seed_data_file_path)
42
+ expect(Apartment.seed_data_file).to eq(seed_data_file_path)
37
43
  end
38
44
 
39
45
  it "should set seed_after_create" do
@@ -41,47 +47,71 @@ describe Apartment do
41
47
  config.excluded_models = []
42
48
  config.seed_after_create = true
43
49
  end
44
- Apartment.seed_after_create.should be true
50
+ expect(Apartment.seed_after_create).to be true
45
51
  end
46
52
 
47
53
  it "should set tld_length" do
48
54
  Apartment.configure do |config|
49
55
  config.tld_length = 2
50
56
  end
51
- Apartment.tld_length.should == 2
57
+ expect(Apartment.tld_length).to eq(2)
52
58
  end
53
59
 
54
60
  context "databases" do
55
- it "should return object if it doesnt respond_to call" do
56
- tenant_names = ['users', 'companies']
61
+ let(:users_conf_hash) { { port: 5444 } }
57
62
 
63
+ before do
58
64
  Apartment.configure do |config|
59
- config.excluded_models = []
60
65
  config.tenant_names = tenant_names
61
66
  end
62
- Apartment.tenant_names.should == tenant_names
63
67
  end
64
68
 
65
- it "should invoke the proc if appropriate" do
66
- tenant_names = lambda{ ['users', 'users'] }
67
- tenant_names.should_receive(:call)
69
+ context "tenant_names as string array" do
70
+ let(:tenant_names) { ['users', 'companies'] }
68
71
 
69
- Apartment.configure do |config|
70
- config.excluded_models = []
71
- config.tenant_names = tenant_names
72
+ it "should return object if it doesnt respond_to call" do
73
+ expect(Apartment.tenant_names).to eq(tenant_names_from_array(tenant_names).keys)
74
+ end
75
+
76
+ it "should set tenants_with_config" do
77
+ expect(Apartment.tenants_with_config).to eq(tenant_names_from_array(tenant_names))
72
78
  end
73
- Apartment.tenant_names
74
79
  end
75
80
 
76
- it "should return the invoked proc if appropriate" do
77
- dbs = lambda{ Company.all }
81
+ context "tenant_names as proc returning an array" do
82
+ let(:tenant_names) { lambda { ['users', 'companies'] } }
78
83
 
79
- Apartment.configure do |config|
80
- config.excluded_models = []
81
- config.tenant_names = dbs
84
+ it "should return object if it doesnt respond_to call" do
85
+ expect(Apartment.tenant_names).to eq(tenant_names_from_array(tenant_names.call).keys)
86
+ end
87
+
88
+ it "should set tenants_with_config" do
89
+ expect(Apartment.tenants_with_config).to eq(tenant_names_from_array(tenant_names.call))
90
+ end
91
+ end
92
+
93
+ context "tenant_names as Hash" do
94
+ let(:tenant_names) { { users: users_conf_hash }.with_indifferent_access }
95
+
96
+ it "should return object if it doesnt respond_to call" do
97
+ expect(Apartment.tenant_names).to eq(tenant_names.keys)
98
+ end
99
+
100
+ it "should set tenants_with_config" do
101
+ expect(Apartment.tenants_with_config).to eq(tenant_names)
82
102
  end
103
+ end
104
+
105
+ context "tenant_names as proc returning a Hash" do
106
+ let(:tenant_names) { lambda { { users: users_conf_hash }.with_indifferent_access } }
83
107
 
84
- Apartment.tenant_names.should == Company.all
108
+ it "should return object if it doesnt respond_to call" do
109
+ expect(Apartment.tenant_names).to eq(tenant_names.call.keys)
110
+ end
111
+
112
+ it "should set tenants_with_config" do
113
+ expect(Apartment.tenants_with_config).to eq(tenant_names.call)
114
+ end
85
115
  end
86
116
  end
87
117
 
@@ -8,23 +8,23 @@ describe Apartment::Elevators::Domain do
8
8
  describe "#parse_tenant_name" do
9
9
  it "parses the host for a domain name" do
10
10
  request = ActionDispatch::Request.new('HTTP_HOST' => 'example.com')
11
- elevator.parse_tenant_name(request).should == 'example'
11
+ expect(elevator.parse_tenant_name(request)).to eq('example')
12
12
  end
13
13
 
14
14
  it "ignores a www prefix and domain suffix" do
15
15
  request = ActionDispatch::Request.new('HTTP_HOST' => 'www.example.bc.ca')
16
- elevator.parse_tenant_name(request).should == 'example'
16
+ expect(elevator.parse_tenant_name(request)).to eq('example')
17
17
  end
18
18
 
19
19
  it "returns nil if there is no host" do
20
20
  request = ActionDispatch::Request.new('HTTP_HOST' => '')
21
- elevator.parse_tenant_name(request).should be_nil
21
+ expect(elevator.parse_tenant_name(request)).to be_nil
22
22
  end
23
23
  end
24
24
 
25
25
  describe "#call" do
26
26
  it "switches to the proper tenant" do
27
- Apartment::Tenant.should_receive(:switch!).with('example')
27
+ expect(Apartment::Tenant).to receive(:switch).with('example')
28
28
 
29
29
  elevator.call('HTTP_HOST' => 'www.example.com')
30
30
  end
@@ -8,12 +8,17 @@ describe Apartment::Elevators::FirstSubdomain do
8
8
 
9
9
  context "one subdomain" do
10
10
  let(:subdomain) { "test" }
11
- it { should == "test" }
11
+ it { is_expected.to eq("test") }
12
12
  end
13
13
 
14
14
  context "nested subdomains" do
15
15
  let(:subdomain) { "test1.test2" }
16
- it { should == "test1" }
16
+ it { is_expected.to eq("test1") }
17
+ end
18
+
19
+ context "no subdomain" do
20
+ let(:subdomain) { nil }
21
+ it { is_expected.to eq(nil) }
17
22
  end
18
23
  end
19
24
  end
@@ -15,7 +15,7 @@ describe Apartment::Elevators::Generic do
15
15
  it "calls the processor if given" do
16
16
  elevator = described_class.new(Proc.new{}, Proc.new{'tenant1'})
17
17
 
18
- Apartment::Tenant.should_receive(:switch!).with('tenant1')
18
+ expect(Apartment::Tenant).to receive(:switch).with('tenant1')
19
19
 
20
20
  elevator.call('HTTP_HOST' => 'foo.bar.com')
21
21
  end
@@ -29,7 +29,24 @@ describe Apartment::Elevators::Generic do
29
29
  it "switches to the parsed db_name" do
30
30
  elevator = MyElevator.new(Proc.new{})
31
31
 
32
- Apartment::Tenant.should_receive(:switch!).with('tenant2')
32
+ expect(Apartment::Tenant).to receive(:switch).with('tenant2')
33
+
34
+ elevator.call('HTTP_HOST' => 'foo.bar.com')
35
+ end
36
+
37
+ it "calls the block implementation of `switch`" do
38
+ elevator = MyElevator.new(Proc.new{}, Proc.new{'tenant2'})
39
+
40
+ expect(Apartment::Tenant).to receive(:switch).with('tenant2').and_yield
41
+ elevator.call('HTTP_HOST' => 'foo.bar.com')
42
+ end
43
+
44
+ it "does not call `switch` if no database given" do
45
+ app = Proc.new{}
46
+ elevator = MyElevator.new(app, Proc.new{})
47
+
48
+ expect(Apartment::Tenant).not_to receive(:switch)
49
+ expect(app).to receive :call
33
50
 
34
51
  elevator.call('HTTP_HOST' => 'foo.bar.com')
35
52
  end
@@ -8,7 +8,7 @@ describe Apartment::Elevators::HostHash do
8
8
  describe "#parse_tenant_name" do
9
9
  it "parses the host for a domain name" do
10
10
  request = ActionDispatch::Request.new('HTTP_HOST' => 'example.com')
11
- elevator.parse_tenant_name(request).should == 'example_tenant'
11
+ expect(elevator.parse_tenant_name(request)).to eq('example_tenant')
12
12
  end
13
13
 
14
14
  it "raises TenantNotFound exception if there is no host" do
@@ -24,7 +24,7 @@ describe Apartment::Elevators::HostHash do
24
24
 
25
25
  describe "#call" do
26
26
  it "switches to the proper tenant" do
27
- Apartment::Tenant.should_receive(:switch!).with('example_tenant')
27
+ expect(Apartment::Tenant).to receive(:switch).with('example_tenant')
28
28
 
29
29
  elevator.call('HTTP_HOST' => 'example.com')
30
30
  end
@@ -9,12 +9,12 @@ describe Apartment::Elevators::Subdomain do
9
9
  context "assuming tld_length of 1" do
10
10
  it "should parse subdomain" do
11
11
  request = ActionDispatch::Request.new('HTTP_HOST' => 'foo.bar.com')
12
- elevator.parse_tenant_name(request).should == 'foo'
12
+ expect(elevator.parse_tenant_name(request)).to eq('foo')
13
13
  end
14
14
 
15
15
  it "should return nil when no subdomain" do
16
16
  request = ActionDispatch::Request.new('HTTP_HOST' => 'bar.com')
17
- elevator.parse_tenant_name(request).should be_nil
17
+ expect(elevator.parse_tenant_name(request)).to be_nil
18
18
  end
19
19
  end
20
20
 
@@ -27,26 +27,26 @@ describe Apartment::Elevators::Subdomain do
27
27
 
28
28
  it "should parse subdomain in the third level domain" do
29
29
  request = ActionDispatch::Request.new('HTTP_HOST' => 'foo.bar.co.uk')
30
- elevator.parse_tenant_name(request).should == "foo"
30
+ expect(elevator.parse_tenant_name(request)).to eq("foo")
31
31
  end
32
32
 
33
33
  it "should return nil when no subdomain in the third level domain" do
34
34
  request = ActionDispatch::Request.new('HTTP_HOST' => 'bar.co.uk')
35
- elevator.parse_tenant_name(request).should be_nil
35
+ expect(elevator.parse_tenant_name(request)).to be_nil
36
36
  end
37
37
  end
38
38
  end
39
39
 
40
40
  describe "#call" do
41
41
  it "switches to the proper tenant" do
42
- Apartment::Tenant.should_receive(:switch!).with('tenant1')
42
+ expect(Apartment::Tenant).to receive(:switch).with('tenant1')
43
43
  elevator.call('HTTP_HOST' => 'tenant1.example.com')
44
44
  end
45
45
 
46
46
  it "ignores excluded subdomains" do
47
47
  described_class.excluded_subdomains = %w{foo}
48
48
 
49
- Apartment::Tenant.should_not_receive(:switch!)
49
+ expect(Apartment::Tenant).not_to receive(:switch)
50
50
 
51
51
  elevator.call('HTTP_HOST' => 'foo.bar.com')
52
52
 
@@ -6,7 +6,7 @@ describe Apartment::Migrator do
6
6
  let(:tenant){ Apartment::Test.next_db }
7
7
 
8
8
  # Don't need a real switch here, just testing behaviour
9
- before { Apartment::Tenant.adapter.stub(:connect_to_new) }
9
+ before { allow(Apartment::Tenant.adapter).to receive(:connect_to_new) }
10
10
 
11
11
  describe "::migrate" do
12
12
  it "switches and migrates" do
@@ -16,9 +16,9 @@ describe Apartment::Reloader do
16
16
  subject{ Apartment::Reloader.new(double("Rack::Application", :call => nil)) }
17
17
 
18
18
  it "should initialize apartment when called" do
19
- Company.table_name.should_not include('public.')
19
+ expect(Company.table_name).not_to include('public.')
20
20
  subject.call(double('env'))
21
- Company.table_name.should include('public.')
21
+ expect(Company.table_name).to include('public.')
22
22
  end
23
23
  end
24
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apartment
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Brunner
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-02 00:00:00.000000000 Z
12
+ date: 2016-05-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -74,33 +74,33 @@ dependencies:
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0.9'
76
76
  - !ruby/object:Gem::Dependency
77
- name: rspec-rails
77
+ name: rspec
78
78
  requirement: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '2.14'
82
+ version: '3.4'
83
83
  type: :development
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '2.14'
89
+ version: '3.4'
90
90
  - !ruby/object:Gem::Dependency
91
- name: guard-rspec
91
+ name: rspec-rails
92
92
  requirement: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '4.2'
96
+ version: '3.4'
97
97
  type: :development
98
98
  prerelease: false
99
99
  version_requirements: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '4.2'
103
+ version: '3.4'
104
104
  - !ruby/object:Gem::Dependency
105
105
  name: capybara
106
106
  requirement: !ruby/object:Gem::Requirement
@@ -282,6 +282,7 @@ files:
282
282
  - spec/dummy_engine/test/dummy/config/routes.rb
283
283
  - spec/dummy_engine/test/dummy/config/secrets.yml
284
284
  - spec/examples/connection_adapter_examples.rb
285
+ - spec/examples/generic_adapter_custom_configuration_example.rb
285
286
  - spec/examples/generic_adapter_examples.rb
286
287
  - spec/examples/schema_adapter_examples.rb
287
288
  - spec/integration/apartment_rake_integration_spec.rb
@@ -340,7 +341,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
340
341
  version: '0'
341
342
  requirements: []
342
343
  rubyforge_project:
343
- rubygems_version: 2.4.5
344
+ rubygems_version: 2.5.1
344
345
  signing_key:
345
346
  specification_version: 4
346
347
  summary: A Ruby gem for managing database multitenancy
@@ -417,6 +418,7 @@ test_files:
417
418
  - spec/dummy_engine/test/dummy/config/routes.rb
418
419
  - spec/dummy_engine/test/dummy/config/secrets.yml
419
420
  - spec/examples/connection_adapter_examples.rb
421
+ - spec/examples/generic_adapter_custom_configuration_example.rb
420
422
  - spec/examples/generic_adapter_examples.rb
421
423
  - spec/examples/schema_adapter_examples.rb
422
424
  - spec/integration/apartment_rake_integration_spec.rb