connection_manager 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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){
|