connection_manager 0.2.0 → 0.2.1

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.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- connection_manager (0.2.0)
4
+ connection_manager (0.2.1)
5
5
  activerecord (~> 3.0)
6
6
 
7
7
  GEM
@@ -31,14 +31,15 @@ GEM
31
31
  mocha (0.10.0)
32
32
  metaclass (~> 0.0.1)
33
33
  multi_json (1.0.4)
34
- rspec (2.7.0)
35
- rspec-core (~> 2.7.0)
36
- rspec-expectations (~> 2.7.0)
37
- rspec-mocks (~> 2.7.0)
38
- rspec-core (2.7.1)
39
- rspec-expectations (2.7.0)
34
+ mysql2 (0.3.11)
35
+ rspec (2.8.0)
36
+ rspec-core (~> 2.8.0)
37
+ rspec-expectations (~> 2.8.0)
38
+ rspec-mocks (~> 2.8.0)
39
+ rspec-core (2.8.0)
40
+ rspec-expectations (2.8.0)
40
41
  diff-lcs (~> 1.1.2)
41
- rspec-mocks (2.7.0)
42
+ rspec-mocks (2.8.0)
42
43
  sqlite3 (1.3.5)
43
44
  tzinfo (0.3.31)
44
45
 
@@ -50,5 +51,6 @@ DEPENDENCIES
50
51
  connection_manager!
51
52
  factory_girl
52
53
  mocha
54
+ mysql2
53
55
  rspec
54
56
  sqlite3
@@ -23,4 +23,5 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency 'autotest'
24
24
  s.add_development_dependency 'mocha'
25
25
  s.add_development_dependency 'factory_girl'
26
+ s.add_development_dependency 'mysql2'
26
27
  end
@@ -15,6 +15,12 @@ module ConnectionManager
15
15
  @env = env
16
16
  end
17
17
 
18
+ def env_regex(with_underscore=true)
19
+ s = "#{env}$"
20
+ s.insert(0,"\_") if with_underscore
21
+ Regexp.new("(#{s})")
22
+ end
23
+
18
24
  # Get the current environment if defined
19
25
  # Check for Rails, check for RACK_ENV, default to 'development'
20
26
  def fetch_env
@@ -27,7 +33,7 @@ module ConnectionManager
27
33
  # is blank it grabs all the connection keys
28
34
  def connection_keys
29
35
  @connection_keys ||= ActiveRecord::Base.configurations.keys.
30
- select{|n| n.match(Regexp.new("(#{env}$)"))}
36
+ select{|n| n.match(env_regex(false))}
31
37
  end
32
38
 
33
39
  # Contains all the connection classes built
@@ -48,12 +54,12 @@ module ConnectionManager
48
54
  def clean_sqlite_db_name(name,remove_env=true)
49
55
  new_name = "#{name}".gsub(/(\.sqlite3$)/,'')
50
56
  new_name = new_name.split("/").last
51
- new_name.gsub!(Regexp.new("(\_#{env}$)"),'') if remove_env
57
+ new_name.gsub!(env_regex,'') if remove_env
52
58
  new_name
53
59
  end
54
60
 
55
61
  def clean_db_name(name)
56
- new_name = "#{name}".gsub(Regexp.new("#{env}$"),'')
62
+ new_name = "#{name}".gsub(env_regex(false),'')
57
63
  if new_name.blank?
58
64
  new_name = "#{database_name_from_yml(name)}"
59
65
  end
@@ -64,7 +70,7 @@ module ConnectionManager
64
70
  # Given an connection key name from the database.yml, returns the string
65
71
  # equivelent of the class name for that entry.
66
72
  def connection_class_name(name_from_yml)
67
- new_class_name = clean_db_name(name_from_yml)
73
+ new_class_name = clean_db_name(name_from_yml)
68
74
  new_class_name = new_class_name.gsub(/\_/,' ').titleize.gsub(/ /,'')
69
75
  new_class_name << "Connection"
70
76
  new_class_name
@@ -84,7 +90,7 @@ module ConnectionManager
84
90
  end
85
91
 
86
92
  def available_secondary_connections(rep_collection_key)
87
- secondary_connections[(rep_collection_key.gsub(Regexp.new("(\_#{env}$)"),'')).to_sym]
93
+ secondary_connections[(rep_collection_key.gsub(env_regex,'')).to_sym]
88
94
  end
89
95
 
90
96
  # Sets class instance attributes, then builds connection classes, while populating
@@ -94,8 +100,8 @@ module ConnectionManager
94
100
  send("#{k.to_s}=",v)
95
101
  end
96
102
  connection_keys.each do |connection|
97
- new_connection = connection_class_name(connection)
98
- add_secondary_connection(connection,new_connection)
103
+ new_connection = connection_class_name(connection)
104
+ add_secondary_connection(connection,new_connection)
99
105
  build_connection_class(new_connection,connection)
100
106
  end
101
107
  all
@@ -109,7 +115,6 @@ module ConnectionManager
109
115
  end
110
116
  new_connection_class = Object.const_set(class_name, klass)
111
117
  new_connection_class.establish_connection(connection_key)
112
-
113
118
  (const_set class_name, new_connection_class)
114
119
  all << class_name
115
120
  end
@@ -49,37 +49,43 @@ module ConnectionManager
49
49
  build_secondary_connections(options)
50
50
  end
51
51
 
52
- def sharded(*settings)
52
+ def shard(*settings)
53
53
  options = {:name => "shard", :readonly => false, :shards => true}.merge(settings.extract_options!)
54
54
  build_secondary_connections(options)
55
55
  end
56
-
56
+
57
+ def child_connection_class?
58
+ false
59
+ end
57
60
  # Adds subclass with the class name of the type provided in the options, which
58
61
  # defaults to 'slave' if blank, that uses the connection from a connection class.
59
62
  # If :database option is blank?, replicated will assume the database.yml has
60
63
  # slave connections defined as: slave_database_name_test or slave_1_database_name_test,
61
64
  # where slave_1 is the secondary instance, 'database_name' is the actual
62
65
  # name of the database and '_test' is the Rails environment
63
- def build_secondary_connections(options={})
64
- connection_classes = secondary_connection_classes(options)
65
- if connection_classes.blank?
66
- raise ArgumentError, " a secondary connection was not found. Check your database.yml."
67
- else
68
- connection_methods = []
69
- connection_classes.each do |c|
70
- under_scored = c.underscore
71
- method_name = under_scored.split("_")[0]
72
- method_name = method_name.insert(method_name.index(/\d/),"_")
73
- class_name = method_name.classify
74
- connection_methods << method_name.to_sym
75
- build_secondary_class(class_name,c,options)
76
- build_single_secondary_method(method_name,class_name)
77
- set_table_name_for_joins
66
+ def build_secondary_connections(options={})
67
+ unless name.match(/\:\:/)
68
+ connection_classes = secondary_connection_classes(options)
69
+ sub_classes = []
70
+ if connection_classes.blank?
71
+ raise ArgumentError, " a secondary connection was not found. Check your database.yml."
72
+ else
73
+ connection_methods = []
74
+ connection_classes.each do |c|
75
+ under_scored = c.underscore
76
+ method_name = under_scored.split("_")[0]
77
+ method_name = method_name.insert(method_name.index(/\d/),"_")
78
+ class_name = method_name.classify
79
+ connection_methods << method_name.to_sym
80
+ build_secondary_class(class_name,c,options)
81
+ build_single_secondary_method(method_name,class_name)
82
+ #set_table_name_for_joins
83
+ sub_classes << "#{self.name}::#{class_name}".constantize if options[:shards]
84
+ end
78
85
  end
86
+ build_slaves_method(connection_methods) if options[:replication]
87
+ build_shards_method(sub_classes) if options[:shards]
79
88
  end
80
-
81
- build_slaves_method(connection_methods) if options[:replication]
82
- build_shards_method(connection_methods) if options[:shards]
83
89
  end
84
90
 
85
91
  # Creats a subclass that inherets from the model. The default model_name
@@ -93,38 +99,50 @@ module ConnectionManager
93
99
  # User::Slave2.where(:id => 2).first => returns results from slave_2 database
94
100
  # User::Shard1.where(:id => 2).first => returns results from slave_1 database
95
101
  def build_secondary_class(class_name,connection_name,options)
96
- class_eval <<-STR, __FILE__, __LINE__
97
- class #{class_name} < self
98
- #{build_secondary_associations(class_name)}
102
+ klass = Class.new(self) do
103
+ class << self
104
+ def model_name
105
+ ActiveModel::Name.new(superclass)
106
+ end
107
+ def child_connection_class?
108
+ true
109
+ end
110
+ end
111
+
112
+ if (options[:name] == "readonly" || options[:readonly])
113
+ def readonly?
114
+ true
115
+ end
116
+ end
117
+ end
118
+
119
+ sub_class = const_set(class_name, klass)
120
+ sub_class.build_secondary_associations(class_name)
121
+ sub_class.class_eval <<-STR, __FILE__, __LINE__
99
122
  class << self
100
123
  def connection
101
124
  Connections::#{connection_name}.connection
102
125
  end
103
- def model_name
104
- ActiveModel::Name.new(#{name})
105
- end
106
126
  end
107
- #{'def readonly?; true; end;' if (options[:name] == "readonly" || options[:readonly])}
108
- end
109
127
  STR
128
+
129
+ sub_class
110
130
  end
111
131
 
112
- def set_table_name_for_joins
113
- self.table_name_prefix = "#{database_name}." unless database_name.match(/\.sqlite3$/)
114
- end
132
+ # def set_table_name_for_joins
133
+ # self.table_name_prefix = "#{database_name}." unless database_name.match(/\.sqlite3$/)
134
+ # end
115
135
 
116
136
  # Adds as class method to call a specific secondary conneciton.
117
137
  # Usage:
118
138
  # User.slave_1.where(:id => 2).first => returns results from slave_1 database
119
139
  # User.slave_2.where(:id => 2).first => returns results from slave_2 database
120
140
  def build_single_secondary_method(method_name,class_name)
121
- class_eval <<-STR, __FILE__, __LINE__
122
- class << self
123
- def #{method_name}
124
- self::#{class_name}
125
- end
126
- end
127
- STR
141
+ self.class.instance_eval do
142
+ define_method method_name.to_s do
143
+ "#{name}::#{class_name}".constantize
144
+ end
145
+ end
128
146
  end
129
147
 
130
148
  # add a class method that shifts through available connections methods
@@ -132,35 +150,27 @@ module ConnectionManager
132
150
  # Usage:
133
151
  # User.slave.where(:id => 2).first => can return results from slave_1 or slave_2
134
152
  def build_slaves_method(connection_methods)
135
- class_eval <<-STR, __FILE__, __LINE__
136
- @connection_methods = #{connection_methods}
137
- class << self
138
- def slaves
153
+ @connection_methods = connection_methods
154
+ self.class.instance_eval do
155
+ define_method 'slaves' do
139
156
  current = @connection_methods.shift
140
157
  @connection_methods << current
141
158
  send(current)
142
159
  end
143
- alias :slave :slaves
144
- def connection_methods
145
- @connection_methods
146
- end
147
- end
148
- STR
160
+ alias_method :slave, :slaves
161
+ end
149
162
  end
150
163
 
151
164
  # add a class method that shifts through available connections methods
152
165
  # on each call.
153
166
  # Usage:
154
167
  # User.shards.where(:id => 2).first => can return results from slave_1 or slave_2
155
- def build_shards_method(connection_methods)
156
- class_eval <<-STR, __FILE__, __LINE__
157
- @shard_connection_methods = #{connection_methods}
158
- class << self
159
- def shards
160
- ConnectionManager::MethodRecorder.new(@shard_connection_methods)
168
+ def build_shards_method(connection_classes)
169
+ self.class.instance_eval do
170
+ define_method 'shards' do
171
+ ConnectionManager::MethodRecorder.new(connection_classes)
161
172
  end
162
- end
163
- STR
173
+ end
164
174
  end
165
175
  end
166
176
  end
@@ -1,4 +1,4 @@
1
1
  module ConnectionManager
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
4
4
 
@@ -1,6 +1,6 @@
1
1
  class TestDB
2
- def self.connect
3
- ActiveRecord::Base.configurations = YAML::load(File.open(File.join(File.dirname(__FILE__),'..','database.yml')))
2
+ def self.connect(driver='sqlite')
3
+ ActiveRecord::Base.configurations = YAML::load(File.open(File.join(File.dirname(__FILE__),'..',"#{driver}_database.yml")))
4
4
  ActiveRecord::Base.establish_connection('test')
5
5
  end
6
6
  def self.clean
@@ -18,7 +18,8 @@ end
18
18
  class TestMigrations < ActiveRecord::Migration
19
19
 
20
20
  # all the ups
21
- def self.up
21
+ def self.up(connection_name='test')
22
+ ActiveRecord::Base.establish_connection(connection_name)
22
23
  begin
23
24
  create_table :foos do |t|
24
25
  t.string :name
@@ -54,7 +55,8 @@ class TestMigrations < ActiveRecord::Migration
54
55
 
55
56
 
56
57
  # all the downs
57
- def self.down
58
+ def self.down(connection_name='test')
59
+ ActiveRecord::Base.establish_connection(connection_name)
58
60
  begin
59
61
  [:foos,:fruits,:baskets,:fruit_baskets,:regions,:types].each do |t|
60
62
  drop_table t
@@ -33,6 +33,7 @@ describe ConnectionManager::SecondaryConnectionBuilder do
33
33
 
34
34
  context "subclasses" do
35
35
  it "should have a superclass of the parent class" do
36
+
36
37
  Fruit::Slave1.superclass.should eql(Fruit)
37
38
  end
38
39
  end
@@ -94,7 +95,7 @@ describe ConnectionManager::SecondaryConnectionBuilder do
94
95
  end
95
96
  context "model_name for slave" do
96
97
  it "should return the supers model_name" do
97
- Fruit.slave.model_name.should eql(Fruit.model_name)
98
+ Fruit.slave_1.model_name.should eql(Fruit.model_name)
98
99
  end
99
100
 
100
101
  it "should not interfear with inheritance" do
@@ -102,7 +103,6 @@ describe ConnectionManager::SecondaryConnectionBuilder do
102
103
  class MyFruit < Fruit
103
104
  replicated
104
105
  end
105
-
106
106
  Fruit.model_name.should_not eql(MyFruit.model_name)
107
107
  MyFruit.model_name.should eql("MyFruit")
108
108
  MyFruit.model_name.respond_to?(:plural).should be_true
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ConnectionManager::MethodRecorder do
4
- before(:each) do
4
+ before(:all) do
5
+ TestMigrations.up('shard_1_cm_test')
6
+ ConnectionManager::Connections.initialize(:env => 'test')
5
7
  class Fruit < ActiveRecord::Base
6
- #include ConnectionManager::MethodRecorder
7
- def self.shards
8
- ConnectionManager::MethodRecorder.new([self])
9
- end
8
+ shard(:using => ["shard_1_cm_test"])
10
9
  end
10
+
11
11
  end
12
12
  context 'shards'do
13
13
  it "it should record methods" do
@@ -36,4 +36,8 @@ describe ConnectionManager::MethodRecorder do
36
36
  end
37
37
  end
38
38
  end
39
+ after(:all) do
40
+ TestMigrations.down('shard_1_cm_test')
41
+ ActiveRecord::Base.establish_connection('test')
42
+ end
39
43
  end
@@ -4,7 +4,7 @@ describe ConnectionManager::SecondaryConnectionBuilder do
4
4
 
5
5
  context '#database_name' do
6
6
  it "should return the name of the database the model is using" do
7
- Fruit.database_name.should eql('spec/cm_test.sqlite3')
7
+ Fruit.database_name.should eql('cm_test')
8
8
  end
9
9
  end
10
10
 
@@ -0,0 +1,25 @@
1
+ # Warning: The database defined as "test" will be erased and
2
+ # re-generated from your development database when you run "rake".
3
+ # Do not set this db to the same as development or production.
4
+ common: &common
5
+ adapter: mysql2
6
+ username: root
7
+ password: some_password
8
+ pool: 100
9
+ timeout: 5000
10
+
11
+ test:
12
+ <<: *common
13
+ database: cm_test
14
+
15
+ slave_1_cm_test:
16
+ <<: *common
17
+ database: cm_test
18
+
19
+ slave_2_cm_test:
20
+ <<: *common
21
+ database: cm_test
22
+
23
+ shard_1_cm_test:
24
+ <<: *common
25
+ database: legacy_cm_test
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,7 @@ require 'active_record'
5
5
  require 'factory_girl'
6
6
  require 'helpers/database_spec_helper'
7
7
 
8
- TestDB.connect
8
+ TestDB.connect('mysql2')
9
9
  TestMigrations.up
10
10
  FactoryGirl.find_definitions
11
11
 
File without changes
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.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-27 00:00:00.000000000Z
12
+ date: 2012-01-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
- requirement: &70148774706040 !ruby/object:Gem::Requirement
16
+ requirement: &70350833047080 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70148774706040
24
+ version_requirements: *70350833047080
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sqlite3
27
- requirement: &70148774705620 !ruby/object:Gem::Requirement
27
+ requirement: &70350833046660 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70148774705620
35
+ version_requirements: *70350833046660
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70148774705160 !ruby/object:Gem::Requirement
38
+ requirement: &70350833046200 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70148774705160
46
+ version_requirements: *70350833046200
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: autotest
49
- requirement: &70148774704740 !ruby/object:Gem::Requirement
49
+ requirement: &70350833045780 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70148774704740
57
+ version_requirements: *70350833045780
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: mocha
60
- requirement: &70148774704320 !ruby/object:Gem::Requirement
60
+ requirement: &70350833045360 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70148774704320
68
+ version_requirements: *70350833045360
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: factory_girl
71
- requirement: &70148774703900 !ruby/object:Gem::Requirement
71
+ requirement: &70350833044940 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,18 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70148774703900
79
+ version_requirements: *70350833044940
80
+ - !ruby/object:Gem::Dependency
81
+ name: mysql2
82
+ requirement: &70350833044520 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70350833044520
80
91
  description: Simplifies connecting to Muliple and Replication databases with rails
81
92
  and active_record
82
93
  email:
@@ -100,7 +111,6 @@ files:
100
111
  - lib/connection_manager/method_recorder.rb
101
112
  - lib/connection_manager/secondary_connection_builder.rb
102
113
  - lib/connection_manager/version.rb
103
- - spec/database.yml
104
114
  - spec/factories.rb
105
115
  - spec/helpers/database_spec_helper.rb
106
116
  - spec/helpers/models_spec_helper.rb
@@ -109,8 +119,10 @@ files:
109
119
  - spec/lib/connections_spec.rb
110
120
  - spec/lib/method_recorder_spec.rb
111
121
  - spec/lib/secondary_connection_builder_spec.rb
122
+ - spec/mysql2_database.yml
112
123
  - spec/spec.opts
113
124
  - spec/spec_helper.rb
125
+ - spec/sqlite_database.yml
114
126
  homepage: ''
115
127
  licenses: []
116
128
  post_install_message:
@@ -137,7 +149,6 @@ specification_version: 3
137
149
  summary: Simplifies connecting to Muliple and Replication databases with rails and
138
150
  active_record
139
151
  test_files:
140
- - spec/database.yml
141
152
  - spec/factories.rb
142
153
  - spec/helpers/database_spec_helper.rb
143
154
  - spec/helpers/models_spec_helper.rb
@@ -146,5 +157,7 @@ test_files:
146
157
  - spec/lib/connections_spec.rb
147
158
  - spec/lib/method_recorder_spec.rb
148
159
  - spec/lib/secondary_connection_builder_spec.rb
160
+ - spec/mysql2_database.yml
149
161
  - spec/spec.opts
150
162
  - spec/spec_helper.rb
163
+ - spec/sqlite_database.yml