connection_manager 1.0.4 → 1.1.0
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 +8 -8
- data/CHANGE.md +12 -1
- data/README.md +99 -82
- data/connection_manager.gemspec +7 -11
- data/lib/connection_manager/builder.rb +56 -0
- data/lib/connection_manager/connection_adapters/abstract_adapter.rb +50 -0
- data/lib/connection_manager/connection_adapters/mysql_adapter.rb +39 -0
- data/lib/connection_manager/connection_handling.rb +91 -0
- data/lib/connection_manager/core.rb +24 -0
- data/lib/connection_manager/querying.rb +13 -0
- data/lib/connection_manager/railtie.rb +10 -0
- data/lib/connection_manager/relation.rb +21 -0
- data/lib/connection_manager/replication.rb +56 -85
- data/lib/connection_manager/shards.rb +2 -1
- data/lib/connection_manager/using.rb +30 -24
- data/lib/connection_manager/version.rb +1 -1
- data/lib/connection_manager.rb +26 -16
- data/spec/{mysql2_database.yml → database.yml} +30 -26
- data/spec/factories.rb +1 -1
- data/spec/helpers/database_spec_helper.rb +91 -62
- data/spec/helpers/models_spec_helper.rb +23 -12
- data/spec/lib/builder_spec.rb +31 -0
- data/spec/lib/connection_adapters/abstract_adapter_spec.rb +48 -0
- data/spec/lib/connection_adapters/mysql_adapter_spec.rb +13 -0
- data/spec/lib/connection_handling_spec.rb +65 -0
- data/spec/lib/core_spec.rb +10 -0
- data/spec/lib/integration/cross_schema_spec.rb +35 -0
- data/spec/lib/querying_spec.rb +19 -0
- data/spec/lib/relation_spec.rb +21 -0
- data/spec/lib/replication_spec.rb +19 -57
- data/spec/lib/shards_spec.rb +3 -3
- data/spec/lib/using_proxy_spec.rb +27 -0
- data/spec/lib/using_spec.rb +28 -15
- data/spec/spec_helper.rb +2 -10
- metadata +73 -35
- data/lib/connection_manager/connection_builder.rb +0 -82
- data/lib/connection_manager/connection_manager_railtie.rb +0 -8
- data/lib/connection_manager/helpers/abstract_adapter_helper.rb +0 -95
- data/lib/connection_manager/helpers/connection_helpers.rb +0 -119
- data/lib/connection_manager/patches/cross_schema_patch.rb +0 -67
- data/spec/jdbcmysql_database.yml +0 -50
- data/spec/lib/connection_builder_spec.rb +0 -28
- data/spec/lib/connection_helpers_spec.rb +0 -79
- data/spec/lib/patches/cross_schema_path_spec.rb +0 -74
- data/spec/sqlite_database.yml +0 -26
@@ -1,52 +1,63 @@
|
|
1
1
|
class CmReplicationConnection < ActiveRecord::Base
|
2
|
-
|
2
|
+
establish_connection(:test_other)
|
3
3
|
end
|
4
4
|
|
5
|
-
class
|
6
|
-
|
5
|
+
class OtherConnection < ActiveRecord::Base
|
6
|
+
establish_connection(:test_other)
|
7
7
|
end
|
8
8
|
|
9
9
|
class Basket < ActiveRecord::Base
|
10
10
|
has_many :fruit_baskets
|
11
11
|
has_many :fruit, :through => :fruit_baskets
|
12
|
-
|
12
|
+
end
|
13
|
+
|
14
|
+
class PgFruit < OtherConnection
|
15
|
+
self.table_name = "cm_test.fruits"
|
13
16
|
end
|
14
17
|
|
15
18
|
class Fruit < ActiveRecord::Base
|
19
|
+
self.table_name_prefix = 'cm_test.'
|
16
20
|
belongs_to :region
|
17
21
|
has_many :fruit_baskets
|
18
22
|
has_many :baskets, :through => :fruit_baskets
|
19
|
-
#replicated
|
20
23
|
end
|
21
24
|
|
22
25
|
#Join table
|
23
26
|
class FruitBasket < ActiveRecord::Base
|
24
27
|
belongs_to :fruit
|
25
28
|
belongs_to :basket
|
26
|
-
#replicated
|
27
29
|
end
|
28
30
|
|
29
31
|
class Region < ActiveRecord::Base
|
30
32
|
has_one :fruit
|
31
|
-
#replicated
|
32
33
|
end
|
33
34
|
|
34
35
|
class Type < ActiveRecord::Base;end
|
35
36
|
|
36
|
-
class SouthernFruit < Fruit
|
37
|
-
self.table_name = 'fruits'
|
38
|
-
end
|
39
|
-
|
40
37
|
class CmUser < ActiveRecord::Base
|
38
|
+
self.table_name_prefix = 'cm_user_test.'
|
41
39
|
has_many :foos
|
42
40
|
end
|
43
41
|
|
42
|
+
class CmOtherUser < ActiveRecord::Base
|
43
|
+
self.table_name = 'cm_user_test.cm_users'
|
44
|
+
end
|
45
|
+
|
44
46
|
class Foo < ActiveRecord::Base
|
45
47
|
belongs_to :cm_user
|
46
48
|
end
|
47
49
|
|
50
|
+
# Subclassed
|
51
|
+
class SouthernFruit < Fruit
|
52
|
+
self.table_name = 'fruits'
|
53
|
+
end
|
54
|
+
|
55
|
+
class FruitCore < Fruit
|
56
|
+
self.table_name = 'fruits'
|
57
|
+
end
|
58
|
+
|
48
59
|
class ModelsHelper
|
49
60
|
def self.models
|
50
|
-
["Basket", "Fruit", "FruitBasket", "Region","SouthernFruit", "Type", "Foo", "CmUser"]
|
61
|
+
["Basket", "Fruit", "FruitBasket", "Region","SouthernFruit", "Type", "Foo", "CmUser", "FruitCore"]
|
51
62
|
end
|
52
63
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ConnectionManager::Builder do
|
3
|
+
|
4
|
+
describe '#connection_class_name' do
|
5
|
+
it "should return a string for a class name appended with 'Connection' " do
|
6
|
+
expect(ConnectionManager::Builder.send(:connection_class_name,"my_database")).to eql("MyDatabaseConnection")
|
7
|
+
end
|
8
|
+
it "should return remove the appended rails env" do
|
9
|
+
expect(ConnectionManager::Builder.send(:connection_class_name,"my_database_test")).to eql("MyDatabaseConnection")
|
10
|
+
end
|
11
|
+
it "should use the database name from the database.yml if supplied string is only is only the Rails.env" do
|
12
|
+
expect(ConnectionManager::Builder.send(:connection_class_name,"test")).to eql("BaseConnection")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#build_connection_class' do
|
17
|
+
before(:all) do
|
18
|
+
ConnectionManager::Builder.build_connection_class("MyConnectionClass", :test)
|
19
|
+
end
|
20
|
+
it "should add a class with supplied class name to ConnectionManager::Builder" do
|
21
|
+
expect(defined?(MyConnectionClass)).to be_true
|
22
|
+
expect(MyConnectionClass).to be_a(Class)
|
23
|
+
end
|
24
|
+
it "should have a super class of ActiveRecord::Base" do
|
25
|
+
expect(MyConnectionClass.superclass).to eql(ActiveRecord::Base)
|
26
|
+
end
|
27
|
+
it "should be an abstract class" do
|
28
|
+
expect(MyConnectionClass.abstract_class?).to be_true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ConnectionManager::AbstractAdapter do
|
3
|
+
before(:each) do
|
4
|
+
@con = ActiveRecord::ConnectionAdapters::AbstractAdapter.new(nil) # not testing connection so use nil it get an instance
|
5
|
+
end
|
6
|
+
|
7
|
+
describe '#config' do
|
8
|
+
it {expect(@con).to respond_to(:config)}
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#cross_schema_support?' do
|
12
|
+
it "should be true for Mysql" do
|
13
|
+
@con.stubs(:config).returns({:adapter => 'mysql'})
|
14
|
+
expect(@con.cross_schema_support?).to be_true
|
15
|
+
end
|
16
|
+
it "should be true for Postgres" do
|
17
|
+
@con.stubs(:config).returns({:adapter => 'postgresql'})
|
18
|
+
expect(@con.cross_schema_support?).to be_true
|
19
|
+
end
|
20
|
+
it "should be true for SQL server" do
|
21
|
+
@con.stubs(:config).returns({:adapter => 'sqlserver'})
|
22
|
+
expect(@con.cross_schema_support?).to be_true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#slave_keys' do
|
27
|
+
it "should return slaves from config symbolized" do
|
28
|
+
@con.stubs(:config).returns({:slaves => ['test','foo']})
|
29
|
+
expect(@con.slave_keys).to eql([:test,:foo])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#master_keys' do
|
34
|
+
it "should return slaves from config symbolized" do
|
35
|
+
@con.stubs(:config).returns({:masters => ['bar','baz']})
|
36
|
+
expect(@con.master_keys).to eql([:bar,:baz])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#replications' do
|
41
|
+
it "should return all slaves and master keys set in config" do
|
42
|
+
@con.stubs(:config).returns({:slaves => [:test,:foo],
|
43
|
+
:masters => [:bar,:baz]})
|
44
|
+
expect(@con.replications).to eql({:slaves => [:test,:foo],
|
45
|
+
:masters => [:bar,:baz]})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Really an integration/regression test will move once we drop support for <= 3.1
|
4
|
+
describe ActiveRecord::Base do
|
5
|
+
describe '#table_exists?' do
|
6
|
+
it "should return true for unquoted full_names" do
|
7
|
+
expect(Fruit.connection.table_exists?('cm_test.fruits')).to be_true
|
8
|
+
end
|
9
|
+
it "should return true for table only names" do
|
10
|
+
expect(Fruit.connection.table_exists?('fruits')).to be_true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ConnectionManager::ConnectionHandling do
|
3
|
+
before(:all) do
|
4
|
+
|
5
|
+
class MyConnectionClass < ActiveRecord::Base
|
6
|
+
self.abstract_class = true
|
7
|
+
establish_connection({
|
8
|
+
:database => "cm_test",
|
9
|
+
:adapter => "mysql2",
|
10
|
+
:username => TestDB.yml["test"]["username"],
|
11
|
+
:password => TestDB.yml["test"]["password"]
|
12
|
+
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
class MyManagedConnectionClass < ActiveRecord::Base
|
17
|
+
establish_managed_connection(:test, :schema_name => 'yep')
|
18
|
+
end
|
19
|
+
|
20
|
+
class MySchemaNameConnection < MyManagedConnectionClass
|
21
|
+
self.abstract_class = true
|
22
|
+
self.schema_name = "boo"
|
23
|
+
end
|
24
|
+
|
25
|
+
class Booed < MySchemaNameConnection;end
|
26
|
+
|
27
|
+
class MyFoo < MyManagedConnectionClass
|
28
|
+
self.table_name = 'foo'
|
29
|
+
self.schema_name = 'boo'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#schema_name=' do
|
34
|
+
it "should set the table_name_prefix for a table formatted as a schema" do
|
35
|
+
expect(MyFoo.table_name_prefix).to eql('boo.')
|
36
|
+
end
|
37
|
+
it "should set the table_name using schema" do
|
38
|
+
expect(MyFoo.table_name).to eql('boo.foo')
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be inherited" do
|
42
|
+
expect(Booed.schema_name).to eql(MySchemaNameConnection.schema_name)
|
43
|
+
expect(Booed.schema_name).to eql('boo')
|
44
|
+
expect(Booed.table_name_prefix).to eql(MySchemaNameConnection.table_name_prefix)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#establish_connection' do
|
49
|
+
it "should register class as connection class" do
|
50
|
+
expect(ActiveRecord::Base.managed_connection_classes.include?("MyConnectionClass")).to be_true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#establish_managed_connection' do
|
55
|
+
context 'the connection class' do
|
56
|
+
it "should create abstract class" do
|
57
|
+
expect(MyManagedConnectionClass.abstract_class).to be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should check in the connection" do
|
61
|
+
expect(ActiveRecord::Base.managed_connection_classes.include?("MyManagedConnectionClass")).to be_true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ConnectionManager::Core do
|
3
|
+
describe 'Arel::Table.name' do
|
4
|
+
it "should update as model's table_name update " do
|
5
|
+
expect(FruitCore.arel_table.name).to eql('fruits')
|
6
|
+
FruitCore.table_name = 'cm_test.fruits'
|
7
|
+
expect(FruitCore.arel_table.name).to eql('cm_test.fruits')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ActiveRecord::Base do
|
3
|
+
before :each do
|
4
|
+
@user = CmUser.new(:name => "Testing")
|
5
|
+
@user.save
|
6
|
+
@foo = Foo.new(:cm_user_id => @user.id)
|
7
|
+
@foo.save
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#joins' do
|
11
|
+
it "should work" do
|
12
|
+
@user.foos.blank?.should be_false
|
13
|
+
found = Foo.joins(:cm_user).select('cm_users.name AS user_name').where('cm_users.id = ?',@user.id).first
|
14
|
+
expect(found.user_name).to_not be_blank
|
15
|
+
end
|
16
|
+
end
|
17
|
+
describe '#includes' do
|
18
|
+
before(:each) do
|
19
|
+
@user.foos.blank?.should be_false
|
20
|
+
search = Foo.includes(:cm_user).where('cm_users.id = ?',@user.id)
|
21
|
+
search = search.references(:cm_user) if search.respond_to?(:references)
|
22
|
+
@found = search.first
|
23
|
+
end
|
24
|
+
it "should return a results" do
|
25
|
+
expect(@found).to be_a(Foo) # Make sure results are returns
|
26
|
+
end
|
27
|
+
it "should load associations" do
|
28
|
+
if @found.respond_to?(:association)
|
29
|
+
expect(@found.association(:cm_user)).to be_loaded
|
30
|
+
else
|
31
|
+
expect(@found.cm_user).to be_loaded
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ConnectionManager::Querying do
|
3
|
+
describe '#using' do
|
4
|
+
it "should be defined" do
|
5
|
+
expect(Fruit).to respond_to(:using)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
describe '#slaves' do
|
9
|
+
it "should be defined" do
|
10
|
+
expect(Fruit).to respond_to(:slaves)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#masters' do
|
15
|
+
it "should be defined" do
|
16
|
+
expect(Fruit).to respond_to(:masters)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ConnectionManager::Relation do
|
3
|
+
context 'ActiveRecord::Relation' do
|
4
|
+
describe '#using' do
|
5
|
+
it "should be defined" do
|
6
|
+
expect(Fruit.where(:id => 1)).to respond_to(:using)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
describe '#slaves' do
|
10
|
+
it "should be defined" do
|
11
|
+
expect(Fruit.where(:id => 1)).to respond_to(:slaves)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#masters' do
|
16
|
+
it "should be defined" do
|
17
|
+
expect(Fruit.where(:id => 1)).to respond_to(:masters)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,88 +1,50 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
describe ConnectionManager::Replication do
|
3
3
|
|
4
|
-
describe '#
|
4
|
+
describe '#arel_table' do
|
5
5
|
it "should return the name of the database the model is using" do
|
6
|
-
Fruit.
|
6
|
+
expect(Fruit.arel_table.name).to eql('cm_test.fruits')
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '#replicated' do
|
11
11
|
it "should raise an exception if no connections are empty, and connection.replication_keys are blank" do
|
12
|
-
|
13
|
-
|
12
|
+
ActiveRecord::Base.stubs(:replication_connections).returns({:masters => [], :slaves => []})
|
13
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.any_instance.stubs(:slave_keys).returns([])
|
14
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.any_instance.stubs(:master_keys).returns([])
|
15
|
+
expect(lambda { Fruit.replicated }).to raise_error
|
14
16
|
end
|
15
17
|
|
16
18
|
it "should not raise an exception if no connections are empty, but connection.replication_keys are not blank" do
|
17
19
|
Fruit.connection.stubs(:replication_keys).returns([:slave_1_cm_test])
|
18
|
-
lambda { Fruit.replicated }.
|
19
|
-
end
|
20
|
-
|
21
|
-
context "the methods created from #replicated" do
|
22
|
-
it "should create a method with the name given for the :name option" do
|
23
|
-
Fruit.replicated(:name => 'foozle')
|
24
|
-
Fruit.respond_to?(:foozle).should be_true
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should create a method in ActiveRecord::QueryMethods with the name given for the :name option" do
|
28
|
-
f = FactoryGirl.create(:fruit)
|
29
|
-
Fruit.replicated(:name => 'fizzle')
|
30
|
-
ActiveRecord::QueryMethods.instance_methods.include?(:fizzle).should be_true
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should return an ActiveRecord::Relation" do
|
34
|
-
Fruit.replicated(:name => 'slaves')
|
35
|
-
Fruit.slaves.should be_kind_of(ActiveRecord::Relation)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should have a different connection" do
|
39
|
-
Fruit.replicated
|
40
|
-
Fruit.slaves.connection.config.should_not eql(Fruit.connection.config)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should work" do
|
44
|
-
Fruit.replicated
|
45
|
-
Fruit.slaves.joins(:region).joins("LEFT OUTER JOIN `fruit_baskets` ON `fruit_baskets`.`fruit_id` = `cm_test`.`fruits`.`id`").to_sql.should eql(Fruit.joins(:region).joins("LEFT OUTER JOIN `fruit_baskets` ON `fruit_baskets`.`fruit_id` = `cm_test`.`fruits`.`id`").to_sql)
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should produce the same query string" do
|
49
|
-
Fruit.replicated
|
50
|
-
Fruit.slaves.joins(:region).to_sql.should eql(Fruit.joins(:region).to_sql)
|
51
|
-
Fruit.slaves.joins(:fruit_baskets).to_sql.should eql(Fruit.joins(:fruit_baskets).to_sql)
|
52
|
-
Fruit.slaves.includes(:fruit_baskets).to_sql.should eql(Fruit.includes(:fruit_baskets).to_sql)
|
53
|
-
Fruit.slaves.includes(:region).to_sql.should eql(Fruit.includes(:region).to_sql)
|
54
|
-
end
|
55
|
-
|
56
|
-
context '#slaves' do
|
57
|
-
it "should have the same quoted_table_name" do
|
58
|
-
Fruit.replicated
|
59
|
-
|
60
|
-
Fruit.slaves.quoted_table_name.should eql(Fruit.quoted_table_name)
|
61
|
-
end
|
62
|
-
it "should have the same table_name_prefix"do
|
63
|
-
Fruit.replicated
|
64
|
-
Fruit.slaves.table_name_prefix.should eql(Fruit.table_name_prefix)
|
65
|
-
end
|
66
|
-
end
|
20
|
+
expect(lambda { Fruit.replicated }).to_not raise_error
|
67
21
|
end
|
68
22
|
|
69
23
|
context "the objects return from a query" do
|
70
24
|
it "should not have the same connection as the master class" do
|
71
25
|
Fruit.replicated
|
72
26
|
FactoryGirl.create(:fruit)
|
73
|
-
Fruit.slaves.connection.config.
|
74
|
-
Fruit.slaves.first.
|
27
|
+
expect(Fruit.slaves.connection.config).to_not eql(Fruit.connection.config)
|
28
|
+
expect(Fruit.slaves.first).to_not be_nil
|
75
29
|
end
|
76
30
|
end
|
77
31
|
end
|
78
32
|
|
79
33
|
describe'#replicated?' do
|
80
34
|
it "should be false if not replicated" do
|
81
|
-
Fruit.
|
35
|
+
expect(Fruit).to_not be_replicated
|
82
36
|
end
|
83
37
|
it "should be true if replicated" do
|
84
38
|
Fruit.replicated
|
85
|
-
Fruit.
|
39
|
+
expect(Fruit).to be_replicated
|
86
40
|
end
|
87
41
|
end
|
42
|
+
|
43
|
+
it "should produce the same SQL string" do
|
44
|
+
Fruit.replicated
|
45
|
+
expect(Fruit.slaves.joins(:region).to_sql).to eql(Fruit.joins(:region).to_sql)
|
46
|
+
expect(Fruit.slaves.joins(:fruit_baskets).to_sql).to eql(Fruit.joins(:fruit_baskets).to_sql)
|
47
|
+
expect(Fruit.slaves.includes(:fruit_baskets).to_sql).to eql(Fruit.includes(:fruit_baskets).to_sql)
|
48
|
+
expect(Fruit.slaves.includes(:region).to_sql).to eql(Fruit.includes(:region).to_sql)
|
49
|
+
end
|
88
50
|
end
|
data/spec/lib/shards_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe ConnectionManager::Shards do
|
|
8
8
|
a = Fruit.shards do |shard|
|
9
9
|
shard.first
|
10
10
|
end
|
11
|
-
a.
|
11
|
+
expect(a).to be_a(Array)
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should execute the active record methods on the the provided models" do
|
@@ -17,7 +17,7 @@ describe ConnectionManager::Shards do
|
|
17
17
|
a = Fruit.shards do |shard|
|
18
18
|
shard.where(:id => fruit.id).first
|
19
19
|
end
|
20
|
-
klasses.include?(a[0].class.name).
|
20
|
+
expect(klasses.include?(a[0].class.name)).to be_true
|
21
21
|
end
|
22
22
|
|
23
23
|
|
@@ -34,7 +34,7 @@ describe ConnectionManager::Shards do
|
|
34
34
|
cfruit = Fruit.shards do |shard|
|
35
35
|
shard.where('id = ?', fruit.id).first
|
36
36
|
end
|
37
|
-
(afruit == bfruit && bfruit == cfruit).
|
37
|
+
expect((afruit == bfruit && bfruit == cfruit)).to be_true
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ConnectionManager::Using::Proxy do
|
3
|
+
before(:each) do
|
4
|
+
@proxy = ConnectionManager::Using::Proxy.new(Fruit, OtherConnection)
|
5
|
+
end
|
6
|
+
|
7
|
+
describe '#connection' do
|
8
|
+
it 'returns connection from connection_class' do
|
9
|
+
expect(@proxy.connection.config).to eql(OtherConnection.connection.config)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
describe '#superclass' do
|
13
|
+
it "should return the @klass's superclass" do
|
14
|
+
expect(@proxy.superclass).to eql(Fruit.superclass)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
describe '#method_missing' do
|
18
|
+
it "should direct to @klass" do
|
19
|
+
expect(@proxy.table_name).to eql(Fruit.table_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
describe '#responds_to?' do
|
23
|
+
it "should direct to @klass" do
|
24
|
+
expect(@proxy).to respond_to(:where)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/lib/using_spec.rb
CHANGED
@@ -1,37 +1,50 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
class CmFooSlaveConnection < ActiveRecord::Base
|
3
|
-
|
3
|
+
establish_connection(:slave_test)
|
4
4
|
end
|
5
5
|
|
6
6
|
describe ConnectionManager::Using do
|
7
|
-
|
8
7
|
describe '#using' do
|
9
8
|
it "should return an ActiveRecord::Relation" do
|
10
|
-
Fruit.using("CmFooSlaveConnection").
|
9
|
+
expect(Fruit.using("CmFooSlaveConnection")).to be_kind_of(ActiveRecord::Relation)
|
11
10
|
end
|
12
11
|
it "should change the connection" do
|
13
|
-
Fruit.using("CmFooSlaveConnection").connection.config.
|
12
|
+
expect(Fruit.using("CmFooSlaveConnection").connection.config).to_not eql(Fruit.connection.config)
|
14
13
|
end
|
15
14
|
|
16
15
|
it "should create the exact same sql if called from model or from relation" do
|
17
16
|
class_sql = Fruit.using("CmFooSlaveConnection").where(:name => "malarky").to_sql
|
18
17
|
relation_sql = Fruit.where(:name => "malarky").using("CmFooSlaveConnection").to_sql
|
19
|
-
class_sql.
|
18
|
+
expect(class_sql).to eql(relation_sql)
|
20
19
|
end
|
21
20
|
|
22
21
|
it "should have the same connection if called from model or from relation" do
|
23
|
-
Fruit.where(:name => "malarky").using("CmFooSlaveConnection").connection.
|
24
|
-
|
25
|
-
Fruit.using("CmFooSlaveConnection").where(:name => "malarky").connection.
|
26
|
-
|
27
|
-
Fruit.where(:name => "malarky").using("CmFooSlaveConnection").connection.
|
28
|
-
|
22
|
+
expect(Fruit.where(:name => "malarky").using("CmFooSlaveConnection").connection.
|
23
|
+
config).to eql(Fruit.using("CmFooSlaveConnection").where(:name => "malarky").connection.config)
|
24
|
+
expect(Fruit.using("CmFooSlaveConnection").where(:name => "malarky").connection.
|
25
|
+
config).to_not eql(Fruit.where(:name => "malarky").connection.config)
|
26
|
+
expect(Fruit.where(:name => "malarky").using("CmFooSlaveConnection").connection.
|
27
|
+
config).to_not eql(Fruit.where(:name => "malarky").connection.config)
|
29
28
|
end
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
context "A replication like connection" do
|
31
|
+
it "should return same record" do
|
32
|
+
fruit = FactoryGirl.create(:fruit)
|
33
|
+
expect(Fruit.using("CmFooSlaveConnection").where(:id => fruit.id).first).to eql(fruit)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should work" do
|
37
|
+
fb = FactoryGirl.create(:fruit_basket)
|
38
|
+
expect(lambda {FruitBasket.using("CmFooSlaveConnection").
|
39
|
+
joins(:fruit,:basket).includes(:fruit,:basket).where(:id => fb.id).first}).to_not raise_error
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'A shard like connection' do
|
44
|
+
it "should use other connection" do
|
45
|
+
fruit = FactoryGirl.create(:fruit)
|
46
|
+
expect(Fruit.using("OtherConnection").where(:name => fruit.name).exists?).to be_false
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
37
|
-
|
data/spec/spec_helper.rb
CHANGED
@@ -7,26 +7,18 @@ require 'active_support'
|
|
7
7
|
require 'logger'
|
8
8
|
require 'factory_girl'
|
9
9
|
require 'helpers/database_spec_helper'
|
10
|
-
if(defined? RUBY_ENGINE and 'jruby' == RUBY_ENGINE)
|
11
|
-
TestDB.connect('jdbcmysql')
|
12
|
-
else
|
13
|
-
TestDB.connect('mysql2')
|
14
|
-
end
|
15
10
|
|
11
|
+
TestDB.connect#(true)
|
16
12
|
TestMigrations.down
|
17
13
|
TestMigrations.up
|
18
14
|
FactoryGirl.find_definitions
|
19
|
-
# ActiveRecord::Base.logger = Logger.new(STDOUT)
|
20
15
|
RSpec.configure do |config|
|
21
16
|
config.mock_with :mocha
|
22
17
|
# Loads database.yml and establishes primary connection
|
23
18
|
# Create tables when tests are completed
|
24
19
|
config.before(:suite) {
|
25
20
|
require 'helpers/models_spec_helper.rb'
|
26
|
-
|
27
|
-
# Drops tables when tests are completed
|
28
|
-
config.after(:suite){
|
29
|
-
TestDB.clean
|
21
|
+
ConnectionManager::Builder.build_connection_classes(TestDB.yml.select{ |k,v| v['build_connection_class'] && k.match(ConnectionManager::Builder.env_regex)}.keys)
|
30
22
|
}
|
31
23
|
# Make sure every test is isolated.
|
32
24
|
config.before(:each){
|