connection_manager 0.3.11 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,3 +1,2 @@
1
1
  source "http://rubygems.org"
2
-
3
2
  gemspec
data/README.md CHANGED
@@ -24,7 +24,7 @@ ConnectionManager is available through [Rubygems](https://rubygems.org/gems/conn
24
24
 
25
25
  $ gem install connection_manager
26
26
 
27
- ## Rails 3 setup (No Rails 2 at this time)
27
+ ## Rails 3/4 setup (No Rails 2 at this time)
28
28
 
29
29
  Add connection_manager to you gemfile:
30
30
 
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["Joshua Mckinney"]
9
9
  s.email = ["joshmckin@gmail.com"]
10
10
  s.homepage = ""
11
- s.summary = %q{Simplifies connecting to Muliple and Replication databases with rails and active_record}
12
- s.description = %q{Simplifies connecting to Muliple and Replication databases with rails and active_record}
11
+ s.summary = %q{Simplifies connecting to Multiple and Replication databases with rails and active_record}
12
+ s.description = %q{Simplifies connecting to Multiple and Replication databases with rails and active_record}
13
13
 
14
14
  s.rubyforge_project = "connection_manager"
15
15
 
@@ -17,12 +17,12 @@ Gem::Specification.new do |s|
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
- s.add_runtime_dependency 'activerecord', '~> 3.0'
20
+ s.add_runtime_dependency 'activerecord', '>= 3.0', '<= 4.0'
21
21
  s.add_development_dependency 'rspec'
22
22
  s.add_development_dependency 'autotest'
23
23
  s.add_development_dependency 'mocha'
24
24
  s.add_development_dependency 'factory_girl'
25
- s.add_development_dependency 'activesupport', '~> 3.0'
25
+ s.add_development_dependency 'activesupport', '>= 3.0', '<= 4.0'
26
26
 
27
27
  if(defined? RUBY_ENGINE and 'jruby' == RUBY_ENGINE)
28
28
  s.add_development_dependency 'jruby-openssl'
@@ -10,6 +10,8 @@ module ConnectionManager
10
10
  require 'connection_manager/shards'
11
11
  require 'connection_manager/replication'
12
12
  require 'connection_manager/patches/cross_schema_patch'
13
+ require 'connection_manager/patches/reflections_patch'
14
+ require 'connection_manager/patches/query_methods_patch'
13
15
  require 'connection_manager/connection_manager_railtie' if defined?(Rails)
14
16
 
15
17
  ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include,(ConnectionManager::AbstractAdapterHelper))
@@ -5,12 +5,12 @@ if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR <= 2
5
5
  module ActiveRecord
6
6
  module ConnectionAdapters
7
7
  class Mysql2Adapter < ((ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 2) ? AbstractMysqlAdapter : AbstractAdapter)
8
-
8
+
9
9
  # Force all tables to be cached for the life connection
10
10
  def cached_tables
11
11
  @cached_tables ||= {}
12
12
  end
13
-
13
+
14
14
  def tables(name = nil, database = nil, like =nil)
15
15
  return cached_tables[database] if cached_tables[database] && like.nil?
16
16
  cached_tables[database] ||= []
@@ -21,9 +21,9 @@ if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR <= 2
21
21
  result = execute(sql, 'SCHEMA')
22
22
  cached_tables[database] = (cached_tables[database] | result.collect { |field| field[0] }).compact
23
23
  end
24
-
24
+
25
25
  alias :new_tables :tables
26
-
26
+
27
27
  def table_exists?(name)
28
28
  return false unless name
29
29
  name = name.to_s
@@ -37,4 +37,4 @@ if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR <= 2
37
37
  end
38
38
  end
39
39
  end
40
- end
40
+ end
@@ -0,0 +1,15 @@
1
+ module ActiveRecord
2
+ module QueryMethods
3
+ private
4
+ # For some reason on .include or a custom join
5
+ # Arel drops the table name prefix on slave classes
6
+ def build_select(arel, selects)
7
+ unless selects.empty?
8
+ @implicit_readonly = false
9
+ arel.project(*selects)
10
+ else
11
+ arel.project("#{quoted_table_name}.*")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ if ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR <= 0
2
+ # Sometimes for some reason the quoted_table_name instance methods
3
+ # drops the schema. If the quoted table name does not include a '.'
4
+ # want to retrieve the quoted_table_name from the class and reset
5
+ module ActiveRecord
6
+ # = Active Record Reflection
7
+ module Reflection # :nodoc:
8
+ class AssociationReflection < MacroReflection
9
+ def table_name
10
+ @table_name = klass.table_name
11
+ end
12
+
13
+ def quoted_table_name
14
+ @quoted_table_name = klass.quoted_table_name
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -25,7 +25,8 @@ module ConnectionManager
25
25
 
26
26
  # Modifies the dup class to use the connection class connection.
27
27
  # We want to use the current class table name, but the connection
28
- # class database as the prefix. We also want the superclass method to
28
+ # class database as the prefix, useful when shards but normally
29
+ # should be the same. We also want the superclass method to
29
30
  # return the connection class as AR sometimes uses the the superclass
30
31
  # connection
31
32
  def build_dup_class(connection_class_name)
@@ -1,3 +1,3 @@
1
1
  module ConnectionManager
2
- VERSION = "0.3.11"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
  describe ConnectionManager::Replication do
3
-
3
+
4
4
  describe '#database_name' do
5
5
  it "should return the name of the database the model is using" do
6
6
  Fruit.current_database_name.should eql('cm_test')
@@ -12,45 +12,61 @@ describe ConnectionManager::Replication do
12
12
  Fruit.connection.stubs(:replication_keys).returns([])
13
13
  lambda { Fruit.replicated }.should raise_error
14
14
  end
15
-
15
+
16
16
  it "should not raise an exception if no connections are empty, but connection.replication_keys are not blank" do
17
- Fruit.connection.stubs(:replication_keys).returns([:slave_1_cm_test])
17
+ Fruit.connection.stubs(:replication_keys).returns([:slave_1_cm_test])
18
18
  lambda { Fruit.replicated }.should_not raise_error
19
19
  end
20
-
20
+
21
21
  context "the methods created from #replicated" do
22
22
  it "should create a method with the name given for the :name option" do
23
23
  Fruit.replicated(:name => 'foozle')
24
24
  Fruit.respond_to?(:foozle).should be_true
25
25
  end
26
-
26
+
27
27
  it "should create a method in ActiveRecord::QueryMethods with the name given for the :name option" do
28
28
  f = FactoryGirl.create(:fruit)
29
29
  Fruit.replicated(:name => 'fizzle')
30
30
  ActiveRecord::QueryMethods.instance_methods.include?(:fizzle).should be_true
31
31
  Fruit.where(:id => f.id).fizzle.first.should_not eql(Fruit.where(:id => f.id).first)
32
32
  end
33
-
33
+
34
34
  it "should return an ActiveRecord::Relation" do
35
35
  Fruit.replicated(:name => 'slaves')
36
36
  Fruit.slaves.should be_kind_of(ActiveRecord::Relation)
37
37
  end
38
-
38
+
39
39
  it "should have a different connection" do
40
40
  Fruit.replicated
41
41
  Fruit.slaves.connection.config.should_not eql(Fruit.connection.config)
42
42
  end
43
-
43
+
44
+ it "should work" do
45
+ Fruit.replicated
46
+ 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)
47
+ end
48
+
44
49
  it "should produce the same query string" do
45
50
  Fruit.replicated
46
51
  Fruit.slaves.joins(:region).to_sql.should eql(Fruit.joins(:region).to_sql)
47
52
  Fruit.slaves.joins(:fruit_baskets).to_sql.should eql(Fruit.joins(:fruit_baskets).to_sql)
48
- 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)
49
53
  Fruit.slaves.includes(:fruit_baskets).to_sql.should eql(Fruit.includes(:fruit_baskets).to_sql)
50
54
  Fruit.slaves.includes(:region).to_sql.should eql(Fruit.includes(:region).to_sql)
51
55
  end
56
+
57
+ context '#slaves' do
58
+ it "should have the same quoted_table_name" do
59
+ Fruit.replicated
60
+
61
+ Fruit.slaves.quoted_table_name.should eql(Fruit.quoted_table_name)
62
+ end
63
+ it "should have the same table_name_prefix"do
64
+ Fruit.replicated
65
+ Fruit.slaves.table_name_prefix.should eql(Fruit.table_name_prefix)
66
+ end
67
+ end
52
68
  end
53
-
69
+
54
70
  context "the objects return from a query" do
55
71
  # The default connection is the original connection for the model
56
72
  it "should have the connection as the replication" do
@@ -58,10 +74,10 @@ describe ConnectionManager::Replication do
58
74
  FactoryGirl.create(:fruit)
59
75
  Fruit.slaves.first.connection.config.should eql(Fruit.slaves.connection.config)
60
76
  Fruit.slaves.first.should_not be_nil
61
- end
77
+ end
62
78
  end
63
79
  end
64
-
80
+
65
81
  describe'#replicated?' do
66
82
  it "should be false if not replicated" do
67
83
  Fruit.replicated?.should be_false
@@ -71,34 +87,34 @@ describe ConnectionManager::Replication do
71
87
  Fruit.replicated?.should be_true
72
88
  end
73
89
  end
74
-
75
-
90
+
91
+
76
92
 
77
93
  #ConnectionManager::Connections.build_connection_classes(:env => 'test')
78
94
  class CmFooSlaveConnection < ActiveRecord::Base
79
95
  establish_managed_connection(:slave_1_cm_test)
80
96
  end
81
-
97
+
82
98
  class CmUserConnection < ActiveRecord::Base
83
99
  establish_managed_connection(:cm_user_test)
84
100
  end
85
-
101
+
86
102
  class SlaveCmUserConnection < ActiveRecord::Base
87
103
  establish_managed_connection(:slave_1_cm_user_test)
88
104
  end
89
-
105
+
90
106
  class User < CmUserConnection
91
107
  has_many :foos
92
108
  has_many(:foo_slaves, :class_name => "Foo::Slaves")
93
109
  replicated('SlaveCmUserConnection')
94
-
110
+
95
111
  end
96
-
112
+
97
113
  class Foo < ActiveRecord::Base
98
114
  belongs_to :user
99
115
  replicated("CmFooSlaveConnection")
100
116
  end
101
-
117
+
102
118
  context "eager loading (#includes)" do
103
119
  before :each do
104
120
  @user = User.new(:name => "Testing")
@@ -106,38 +122,37 @@ describe ConnectionManager::Replication do
106
122
  @foo = Foo.new(:user_id => @user.id)
107
123
  @foo.save
108
124
  end
109
-
125
+
110
126
  # We'd like this to happen magically some day. Possible in 3.2
111
127
  it "should eager load with replication instances" #do
112
- # user = User.slaves.includes(:foos).where(:id => @user.id).first
113
- # user.foos.first.should_not be_kind_of(Foo)
114
- # end
115
-
128
+ # user = User.slaves.includes(:foos).where(:id => @user.id).first
129
+ # user.foos.first.should_not be_kind_of(Foo)
130
+ # end
131
+
116
132
  context "specifically defined replication association" do
117
133
  it "should eager load with replication instances" do
118
134
  user = User.slaves.includes(:foo_slaves).where(:id => @user.id).first
119
135
  user.foo_slaves.first.should_not be_kind_of(Foo)
120
136
  end
121
- end
137
+ end
122
138
  end
123
- context "cross database joins" do
139
+ context "cross database joins" do
124
140
  before :each do
125
141
  @user = User.new(:name => "Testing")
126
142
  @user.save
127
143
  @foo = Foo.new(:user_id => @user.id)
128
144
  @foo.save
129
145
  end
130
-
146
+
131
147
  it "should work" do
132
- @user.foos.blank?.should be_false
148
+ @user.foos.blank?.should be_false
133
149
  found = Foo.select('users.name AS user_name').joins(:user).where(:id => @foo.id).first
134
150
  found.user_name.blank?.should be_false
135
151
  end
136
-
152
+
137
153
  it "should work with replication" do
138
154
  found = Foo.slaves.select('foos.*, users.name AS user_name').joins(:user).where(:id => @foo.id).first
139
155
  found.user.blank?.should be_false
140
156
  end
141
- end
157
+ end
142
158
  end
143
-
@@ -23,18 +23,18 @@ describe ConnectionManager::Shards do
23
23
 
24
24
  it "should not matter how the where statement is formated" do
25
25
  fruit = FactoryGirl.create(:fruit)
26
- a = Fruit.shards do |shard|
26
+ afruit = Fruit.shards do |shard|
27
27
  shard.where(:id => fruit.id).first
28
28
  end
29
- b = Fruit.shards do |shard|
29
+
30
+ bfruit = Fruit.shards do |shard|
30
31
  shard.where(['id = ?', fruit.id]).first
31
32
  end
32
33
 
33
- c = Fruit.shards do |shard|
34
+ cfruit = Fruit.shards do |shard|
34
35
  shard.where('id = ?', fruit.id).first
35
36
  end
36
-
37
- (a == b && b == c).should be_true
37
+ (afruit == bfruit && bfruit == cfruit).should be_true
38
38
  end
39
39
  end
40
40
  end
@@ -10,7 +10,7 @@ describe ConnectionManager::Using do
10
10
 
11
11
  it "should add sub class to current class with the name of the connection" do
12
12
  Fruit.send(:fetch_duplicate_class,"CmFooSlaveConnection")
13
- lambda { "Fruit::CmFooSlaveConnectionDup".constantize}.should_not raise_error(NameError)
13
+ lambda { "Fruit::CmFooSlaveConnectionDup".constantize}.should_not raise_error
14
14
  end
15
15
 
16
16
  describe '#using' do
@@ -20,11 +20,11 @@ RSpec.configure do |config|
20
20
  config.mock_with :mocha
21
21
  # Loads database.yml and establishes primary connection
22
22
  # Create tables when tests are completed
23
- config.before(:all) {
23
+ config.before(:suite) {
24
24
  require 'helpers/models_spec_helper.rb'
25
25
  }
26
26
  # Drops tables when tests are completed
27
- config.after(:all){
27
+ config.after(:suite){
28
28
  TestDB.clean
29
29
  }
30
30
  # Make sure every test is isolated.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: connection_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.11
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,30 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-04 00:00:00.000000000 Z
12
+ date: 2013-10-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '3.0'
22
+ - - <=
23
+ - !ruby/object:Gem::Version
24
+ version: '4.0'
22
25
  type: :runtime
23
26
  prerelease: false
24
27
  version_requirements: !ruby/object:Gem::Requirement
25
28
  none: false
26
29
  requirements:
27
- - - ~>
30
+ - - ! '>='
28
31
  - !ruby/object:Gem::Version
29
32
  version: '3.0'
33
+ - - <=
34
+ - !ruby/object:Gem::Version
35
+ version: '4.0'
30
36
  - !ruby/object:Gem::Dependency
31
37
  name: rspec
32
38
  requirement: !ruby/object:Gem::Requirement
@@ -96,17 +102,23 @@ dependencies:
96
102
  requirement: !ruby/object:Gem::Requirement
97
103
  none: false
98
104
  requirements:
99
- - - ~>
105
+ - - ! '>='
100
106
  - !ruby/object:Gem::Version
101
107
  version: '3.0'
108
+ - - <=
109
+ - !ruby/object:Gem::Version
110
+ version: '4.0'
102
111
  type: :development
103
112
  prerelease: false
104
113
  version_requirements: !ruby/object:Gem::Requirement
105
114
  none: false
106
115
  requirements:
107
- - - ~>
116
+ - - ! '>='
108
117
  - !ruby/object:Gem::Version
109
118
  version: '3.0'
119
+ - - <=
120
+ - !ruby/object:Gem::Version
121
+ version: '4.0'
110
122
  - !ruby/object:Gem::Dependency
111
123
  name: mysql2
112
124
  requirement: !ruby/object:Gem::Requirement
@@ -123,7 +135,7 @@ dependencies:
123
135
  - - ! '>='
124
136
  - !ruby/object:Gem::Version
125
137
  version: '0'
126
- description: Simplifies connecting to Muliple and Replication databases with rails
138
+ description: Simplifies connecting to Multiple and Replication databases with rails
127
139
  and active_record
128
140
  email:
129
141
  - joshmckin@gmail.com
@@ -144,6 +156,8 @@ files:
144
156
  - lib/connection_manager/helpers/abstract_adapter_helper.rb
145
157
  - lib/connection_manager/helpers/connection_helpers.rb
146
158
  - lib/connection_manager/patches/cross_schema_patch.rb
159
+ - lib/connection_manager/patches/query_methods_patch.rb
160
+ - lib/connection_manager/patches/reflections_patch.rb
147
161
  - lib/connection_manager/replication.rb
148
162
  - lib/connection_manager/shards.rb
149
163
  - lib/connection_manager/using.rb
@@ -184,7 +198,7 @@ rubyforge_project: connection_manager
184
198
  rubygems_version: 1.8.25
185
199
  signing_key:
186
200
  specification_version: 3
187
- summary: Simplifies connecting to Muliple and Replication databases with rails and
201
+ summary: Simplifies connecting to Multiple and Replication databases with rails and
188
202
  active_record
189
203
  test_files:
190
204
  - spec/factories.rb