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.
Files changed (45) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGE.md +12 -1
  3. data/README.md +99 -82
  4. data/connection_manager.gemspec +7 -11
  5. data/lib/connection_manager/builder.rb +56 -0
  6. data/lib/connection_manager/connection_adapters/abstract_adapter.rb +50 -0
  7. data/lib/connection_manager/connection_adapters/mysql_adapter.rb +39 -0
  8. data/lib/connection_manager/connection_handling.rb +91 -0
  9. data/lib/connection_manager/core.rb +24 -0
  10. data/lib/connection_manager/querying.rb +13 -0
  11. data/lib/connection_manager/railtie.rb +10 -0
  12. data/lib/connection_manager/relation.rb +21 -0
  13. data/lib/connection_manager/replication.rb +56 -85
  14. data/lib/connection_manager/shards.rb +2 -1
  15. data/lib/connection_manager/using.rb +30 -24
  16. data/lib/connection_manager/version.rb +1 -1
  17. data/lib/connection_manager.rb +26 -16
  18. data/spec/{mysql2_database.yml → database.yml} +30 -26
  19. data/spec/factories.rb +1 -1
  20. data/spec/helpers/database_spec_helper.rb +91 -62
  21. data/spec/helpers/models_spec_helper.rb +23 -12
  22. data/spec/lib/builder_spec.rb +31 -0
  23. data/spec/lib/connection_adapters/abstract_adapter_spec.rb +48 -0
  24. data/spec/lib/connection_adapters/mysql_adapter_spec.rb +13 -0
  25. data/spec/lib/connection_handling_spec.rb +65 -0
  26. data/spec/lib/core_spec.rb +10 -0
  27. data/spec/lib/integration/cross_schema_spec.rb +35 -0
  28. data/spec/lib/querying_spec.rb +19 -0
  29. data/spec/lib/relation_spec.rb +21 -0
  30. data/spec/lib/replication_spec.rb +19 -57
  31. data/spec/lib/shards_spec.rb +3 -3
  32. data/spec/lib/using_proxy_spec.rb +27 -0
  33. data/spec/lib/using_spec.rb +28 -15
  34. data/spec/spec_helper.rb +2 -10
  35. metadata +73 -35
  36. data/lib/connection_manager/connection_builder.rb +0 -82
  37. data/lib/connection_manager/connection_manager_railtie.rb +0 -8
  38. data/lib/connection_manager/helpers/abstract_adapter_helper.rb +0 -95
  39. data/lib/connection_manager/helpers/connection_helpers.rb +0 -119
  40. data/lib/connection_manager/patches/cross_schema_patch.rb +0 -67
  41. data/spec/jdbcmysql_database.yml +0 -50
  42. data/spec/lib/connection_builder_spec.rb +0 -28
  43. data/spec/lib/connection_helpers_spec.rb +0 -79
  44. data/spec/lib/patches/cross_schema_path_spec.rb +0 -74
  45. data/spec/sqlite_database.yml +0 -26
@@ -1,117 +1,88 @@
1
- require 'active_support/core_ext/hash/indifferent_access'
2
1
  module ConnectionManager
3
- module Replication
2
+ module Replication
3
+ attr_accessor :replication_connections
4
4
  # Replication methods (replication_method_name, which is the option[:name] for the
5
5
  # #replication method) and all their associated connections. The key is the
6
6
  # replication_method_name and the value is an array of all the replication_classes
7
7
  # the replication_method has access to.
8
- #
8
+ #
9
9
  # EX: replication_methods[:slaves] => ['Slave1Connection',Slave2Connection]
10
- def replication_methods
11
- @replication_methods ||= HashWithIndifferentAccess.new
10
+ def replication_connections
11
+ @replication_connections ||= {:slaves => [], :masters => []}
12
12
  end
13
-
13
+
14
+
14
15
  # Is this class replicated
15
16
  def replicated?
16
- (@replicated == true)
17
+ (@replication_connections && (!replication_connections[:slaves].empty? || !replication_connections[:masters].empty?))
17
18
  end
18
-
19
+
19
20
  # Builds a class method that returns an ActiveRecord::Relation for use with
20
21
  # in ActiveRecord method chaining.
21
- #
22
- # EX:
22
+ #
23
+ # EX:
23
24
  # class MyClass < ActiveRecord::Base
24
- # replicated :my_readonly_db, "FooConnection", :method_name => 'slaves'
25
+ # replicated :my_readonly_db, "FooConnection",
25
26
  # end
26
27
  # end
27
28
  #
28
29
  # Options:
29
30
  # * :name - name of class method to call to access replication, default to slaves
30
- # * :readonly - forces all results to readonly
31
- # * :type - the type of replication; :slave or :master, defaults to :slave
31
+ # * :type - the type of replication; :slaves or :masters, defaults to :slaves
32
32
  def replicated(*connections)
33
- @replicated = true
34
- options = {:name => "slaves"}.merge!(connections.extract_options!)
35
- options[:type] ||= :slaves
36
- options[:build_replicants] = true if (options[:build_replicants].blank? && options[:type] == :masters)
37
- use_database(current_database_name, :table_name => table_name) # make sure the base class has current_database_name set
38
- connections = connection.replication_keys(options[:type]) if connections.blank?
39
- set_replications_to_method(connections,options[:name])
40
- build_repliciation_class_method(options)
41
- build_query_method_alias_method(options[:name])
42
- build_repliciation_instance_method(options[:name])
43
- options[:name]
33
+ options = {:slaves => [], :masters => [], :type => :slaves}.merge(connections.extract_options!.symbolize_keys)
34
+ options[options[:type]] = connections unless connections.empty?
35
+ set_replications_connections(options)
44
36
  end
45
-
46
- # Get a connection class name from out replication_methods pool.
47
- def fetch_replication_method(method_name)
48
- available_connections = @replication_methods[method_name]
37
+
38
+ private
39
+
40
+ # Fetch a connection class name from out replication_connections pool.
41
+ # Since any numbers of threads could be attempting to access the replication
42
+ # connections we use sample to get a random connection instead of blocking
43
+ # to rotate the pool on every fetch.
44
+ def fetch_replication_connection(method_name)
45
+ set_replications_connections(self.replication_connections) unless self.replicated?
46
+ available_connections = self.replication_connections[method_name] || []
49
47
  raise ArgumentError, "No connections found for #{method_name}." if available_connections.blank?
50
- available_connections.rotate!
51
- available_connections[0]
48
+ available_connections.sample
52
49
  end
53
-
54
- private
50
+
51
+ def fetch_slave_connection
52
+ fetch_replication_connection(:slaves)
53
+ end
54
+
55
+ def fetch_master_connection
56
+ fetch_replication_connection(:masters)
57
+ end
58
+
55
59
  # Builds replication connection classes and methods
56
- def set_replications_to_method(connections,replication_method_name='slaves')
57
- raise ArgumentError, "connections could not be found for #{self.name}." if connections.blank?
58
- connections.each do |to_use|
59
- connection_class_name = fetch_connection_class_name(to_use)
60
- replication_methods[replication_method_name] ||= []
61
- replication_methods[replication_method_name] << connection_class_name
60
+ def set_replications_connections(options)
61
+ [:masters,:slaves].each do |type|
62
+ cons = (options[type].empty? ? connection.replications[type] : options[type])
63
+ unless cons.empty?
64
+ self.replication_connections[type] = []
65
+ cons.each do |to_use|
66
+ self.replication_connections[type] << fetch_connection_class_name(to_use)
67
+ end
68
+ end
62
69
  end
63
- true
70
+ raise ArgumentError, "Connections could not be found for #{self.name}." if self.replication_connections[:masters].empty? && self.replication_connections[:slaves].empty?
71
+ self.replication_connections
64
72
  end
65
-
66
- def fetch_connection_class_name(to_use)
67
- connection_class_name = to_use
68
- connection_class_name = fetch_connection_class_name_from_yml_key(connection_class_name) if connection_class_name.to_s.match(/_/)
69
- raise ArgumentError, "For #{self.name}, the class #{connection_class_name} could not be found." if connection_class_name.blank?
73
+
74
+ def fetch_connection_class_name(to_use)
75
+ connection_class_name = to_use
76
+ connection_class_name = fetch_connection_class_name_from_yml_key(connection_class_name) if connection_class_name.to_s.match(/_/)
77
+ raise ArgumentError, "For #{self.name}, the class #{connection_class_name} could not be found." if connection_class_name.blank?
70
78
  connection_class_name
71
79
  end
72
80
 
73
81
  def fetch_connection_class_name_from_yml_key(yml_key)
74
82
  found = managed_connections[yml_key]
75
- connection_class_name = nil
76
- if found
77
- connection_class_name = found.first
78
- else
79
- raise ArgumentError, "For #{self.name}, a connection class for #{yml_key} could not be found."
80
- end
81
- connection_class_name
82
- end
83
-
84
- # Adds a class method, that calls #using with the correct connection class name
85
- # by calling fetch_replication_method with the method name. Adds readonly
86
- # query method class if replication is specified as readonly.
87
- def build_repliciation_class_method(options)
88
- class_eval <<-STR
89
- class << self
90
- def #{options[:name]}
91
- using(fetch_replication_method("#{options[:name]}"))#{options[:readonly] ? '.readonly' : ''}
92
- end
93
- end
94
- STR
95
- end
96
-
97
- # Build a query method with the name of our replication method. This method
98
- # uses the relation.klass to fetch the appropriate connection, ensuring the
99
- # correct connection is used even if the method is already defined by another class.
100
- # We want to make sure we don't override existing methods in ActiveRecord::QueryMethods
101
- def build_query_method_alias_method(replication_relation_name)
102
- unless ActiveRecord::QueryMethods.instance_methods.include?(replication_relation_name.to_sym)
103
- ActiveRecord::QueryMethods.module_eval do
104
- define_method replication_relation_name.to_sym do
105
- using(self.klass.fetch_replication_method(replication_relation_name))
106
- end
107
- end
108
- end
109
- end
110
-
111
- def build_repliciation_instance_method(replication_relation_name)
112
- define_method replication_relation_name.to_sym do
113
- using(self.class.fetch_replication_method(replication_relation_name))
114
- end
83
+ raise ArgumentError, "For #{self.name}, a connection class for #{yml_key} could not be found." unless found
84
+ found
115
85
  end
116
86
  end
117
- end
87
+ end
88
+ ActiveRecord::Base.extend(ConnectionManager::Replication)
@@ -22,4 +22,5 @@ module ConnectionManager
22
22
  end
23
23
  end
24
24
  end
25
- end
25
+ end
26
+ ActiveRecord::Base.extend(ConnectionManager::Shards)
@@ -1,23 +1,10 @@
1
- require 'active_support/core_ext/module/delegation'
2
1
  module ConnectionManager
3
2
  module Using
4
- module Relation
5
-
6
- # Specify connection class to used for query.For
7
- # example:
8
- #
9
- # users = User.using(MySlaveConnection).first
10
- def using(connection_class_name)
11
- @klass = ConnectionManager::Using::Proxy.new(@klass,connection_class_name)
12
- self
13
- end
14
- end
15
-
16
3
  class Proxy
17
4
  attr_accessor :klass, :connection_class
18
-
5
+
19
6
  def initialize(klass,connection_class)
20
- @klass = klass # the @klass insance from an ActiveRecord::Relation
7
+ @klass = klass # the @klass from an ActiveRecord::Relation
21
8
  @connection_class = (connection_class.is_a?(String) ? connection_class.constantize : connection_class)
22
9
  end
23
10
 
@@ -28,11 +15,38 @@ module ConnectionManager
28
15
  end
29
16
 
30
17
  # Make sure we return the @klass superclass,
31
- # which used through the query building code in AR
18
+ # which used throughout the query building code in AR
32
19
  def superclass
33
20
  @klass.superclass
34
21
  end
35
22
 
23
+ def >= compare
24
+ return @klass >= compare.klass if compare.is_a?(self.class)
25
+ @klass >= compare
26
+ end
27
+
28
+ def == compare
29
+ return @klass == compare.klass if compare.is_a?(self.class)
30
+ @klass == compare
31
+ end
32
+
33
+ def != compare
34
+ return @klass != compare.klass if compare.is_a?(self.class)
35
+ @klass != compare
36
+ end
37
+
38
+ def descendants
39
+ @klass.descendants
40
+ end
41
+
42
+ def subclasses
43
+ @klass.subclasses
44
+ end
45
+
46
+ def parent
47
+ @klass.parent
48
+ end
49
+
36
50
  # Pass all methods to @klass, this ensures objects
37
51
  # build from the query are the correct class and
38
52
  # any settings in the model like table_name_prefix
@@ -47,11 +61,3 @@ module ConnectionManager
47
61
  end
48
62
  end
49
63
  end
50
- ActiveRecord::Relation.send(:include,ConnectionManager::Using::Relation)
51
- module ActiveRecord
52
- class Base
53
- class << self
54
- delegate :using, :to => (ActiveRecord::VERSION::MAJOR == 4 ? :all : :scoped)
55
- end
56
- end
57
- end
@@ -1,3 +1,3 @@
1
1
  module ConnectionManager
2
- VERSION = "1.0.4"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,29 +1,39 @@
1
1
  require "connection_manager/version"
2
2
 
3
3
  module ConnectionManager
4
+ require 'thread_safe'
4
5
  require 'active_record'
5
6
  require 'active_support'
6
- require 'connection_manager/helpers/abstract_adapter_helper'
7
- require 'connection_manager/connection_builder'
8
- require 'connection_manager/helpers/connection_helpers'
7
+ require 'connection_manager/connection_adapters/abstract_adapter'
8
+ require 'connection_manager/core'
9
+ require 'connection_manager/connection_handling'
10
+ require 'connection_manager/relation'
11
+ require 'connection_manager/querying'
12
+ require 'connection_manager/builder'
9
13
  require 'connection_manager/using'
10
- require 'connection_manager/shards'
11
14
  require 'connection_manager/replication'
12
- require 'connection_manager/patches/cross_schema_patch'
13
- require 'connection_manager/connection_manager_railtie' if defined?(Rails)
14
-
15
- ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include,(ConnectionManager::AbstractAdapterHelper))
16
- ActiveRecord::Base.extend(ConnectionManager::ConnectionHelpers)
17
- ActiveRecord::Base.extend(ConnectionManager::ConnectionBuilder)
18
- ActiveRecord::Base.extend(ConnectionManager::Replication)
19
- ActiveRecord::Base.extend(ConnectionManager::Shards)
20
-
21
- ActiveSupport.on_load(:active_record) do
22
- ActiveRecord::Base.build_connection_classes
15
+ require 'connection_manager/shards'
16
+ require 'connection_manager/railtie' if defined?(Rails)
17
+
18
+ # Get the current environment if defined
19
+ # Check for Rails, check for RACK_ENV, default to 'development'
20
+ def self.env
21
+ return @env if @env
22
+ return Rails.env if defined?(Rails)
23
+ return RACK_ENV if defined?(RACK_ENV)
24
+ return ENV["AR_ENV"] if ENV["AR_ENV"]
25
+ "development"
26
+ end
27
+
28
+ def self.env=env
29
+ @env=env
23
30
  end
24
31
 
25
32
  def self.logger
26
33
  @logger ||= ActiveRecord::Base.logger
27
34
  end
35
+
36
+ def self.logger=logger
37
+ @logger = logger
38
+ end
28
39
  end
29
-
@@ -2,49 +2,53 @@
2
2
  # re-generated from your development database when you run "rake".
3
3
  # Do not set this db to the same as development or production.
4
4
  common: &common
5
- adapter: mysql2
6
- username: root
7
- password: omegared
8
5
  pool: 100
9
6
  timeout: 5000
10
7
  build_connection_class: true
11
-
8
+
12
9
  master: &master
13
10
  username: root
14
11
  password: omegared
15
-
12
+
16
13
  readonly: &readonly
17
14
  username: root
18
15
  password: omegared
19
-
20
- test:
16
+
17
+ mysql_without_db:
21
18
  <<: *common
22
19
  <<: *master
23
- database: cm_test
24
- slaves: [slave_1_cm_test, slave_2_cm_test]
25
-
26
- cm_user_test:
20
+
21
+ test:
27
22
  <<: *common
28
23
  <<: *master
29
- database: cm_user_test
30
- slaves: [slave_1_cm_user_test]
31
-
32
- slave_1_cm_test:
33
- <<: *common
34
- <<: *readonly
24
+ adapter: mysql2
35
25
  database: cm_test
36
-
37
- slave_2_cm_test:
26
+ slaves: [slave_test]
27
+
28
+ slave_test:
38
29
  <<: *common
39
- <<: *readonly
30
+ <<: *master
31
+ adapter: mysql2
40
32
  database: cm_test
33
+ masters: [test]
41
34
 
42
- shard_1_cm_test:
43
- <<: *common
44
- <<: *master
45
- database: legacy_cm_test
35
+ mysql_without_db:
36
+ <<: *common
37
+ <<: *master
38
+ adapter: mysql2
46
39
 
47
- slave_1_cm_user_test:
40
+ cm_user_test:
48
41
  <<: *common
49
- <<: *readonly
42
+ <<: *master
43
+ adapter: mysql2
50
44
  database: cm_user_test
45
+
46
+ postgres_without_db:
47
+ <<: *common
48
+ adapter: postgresql
49
+ database: postgres
50
+
51
+ test_other:
52
+ <<: *common
53
+ adapter: postgresql
54
+ database: cm_test
data/spec/factories.rb CHANGED
@@ -13,7 +13,7 @@ FactoryGirl.define do
13
13
  end
14
14
 
15
15
  factory :fruit do
16
- name "MyString"
16
+ name {FactoryGirl.generate(:rand_name)}
17
17
  region
18
18
  end
19
19
 
@@ -1,11 +1,11 @@
1
1
  class TestDB
2
- def self.yml(driver='sqlite')
3
- YAML::load(File.open(File.join(File.dirname(__FILE__),'..',"#{driver}_database.yml")))
2
+ def self.yml
3
+ YAML::load(File.open(File.join(File.dirname(__FILE__),'..',"database.yml")))
4
4
  end
5
5
 
6
- def self.connect(driver='sqlite',logging=false)
7
- ActiveRecord::Base.configurations = yml(driver)
8
- ActiveRecord::Base.establish_connection('test')
6
+ def self.connect(logging=false)
7
+ ActiveRecord::Base.configurations = yml
8
+ ActiveRecord::Base.establish_connection(:test)
9
9
  ActiveRecord::Base.logger = Logger.new(STDOUT) if logging
10
10
  end
11
11
 
@@ -23,62 +23,90 @@ end
23
23
  class TestMigrations < ActiveRecord::Migration
24
24
  # all the ups
25
25
  def self.up
26
- ActiveRecord::Base.establish_connection(:test)
27
- begin
28
- create_table "#{ActiveRecord::Base.schema_name}.foos" do |t|
29
- t.string :name
30
- t.integer :cm_user_id
26
+ {:mysql_without_db => :test,:postgres_without_db => :test_other}.each do |build,key|
27
+ ActiveRecord::Base.establish_connection(build)
28
+
29
+ if build == :mysql_without_db
30
+ begin
31
+ ActiveRecord::Base.connection.execute("CREATE DATABASE IF NOT EXISTS cm_test;")
32
+ rescue => e
33
+ puts "Error creating database: #{e}"
34
+ end
35
+ begin
36
+ ActiveRecord::Base.connection.execute("CREATE DATABASE IF NOT EXISTS cm_user_test;")
37
+ rescue => e
38
+ puts "Error creating database: #{e}"
39
+ end
40
+ ActiveRecord::Base.establish_connection(key)
41
+ else
42
+ begin
43
+ ActiveRecord::Base.connection.execute("CREATE DATABASE cm_test;")
44
+ rescue => e
45
+ puts "Error creating database: #{e}"
46
+ end
47
+ ActiveRecord::Base.establish_connection(key)
48
+ begin
49
+ ActiveRecord::Base.connection.execute("CREATE SCHEMA cm_test;")
50
+ rescue => e
51
+ puts "Error creating schema: #{e}"
52
+ end
31
53
  end
32
- rescue => e
33
- puts "tables failed to create: #{e}"
34
- end
35
- begin
36
- create_table "#{ActiveRecord::Base.schema_name}.fruits" do |t|
37
- t.string :name
38
- t.integer :region_id
39
- t.timestamps
54
+
55
+ begin
56
+ create_table "cm_test.foos" do |t|
57
+ t.string :name
58
+ t.integer :cm_user_id
59
+ end
60
+ rescue => e
61
+ puts "tables failed to create: #{e}"
40
62
  end
41
- rescue => e
42
- puts "tables failed to create: #{e}"
43
- end
44
- begin
45
- create_table "#{ActiveRecord::Base.schema_name}.baskets" do |t|
46
- t.string :name
47
- t.timestamps
63
+ begin
64
+ create_table "cm_test.fruits" do |t|
65
+ t.string :name
66
+ t.integer :region_id
67
+ t.timestamps
68
+ end
69
+ rescue => e
70
+ puts "tables failed to create: #{e}"
48
71
  end
49
- rescue => e
50
- puts "tables failed to create: #{e}"
51
- end
52
- begin
53
- create_table "#{ActiveRecord::Base.schema_name}.fruit_baskets" do |t|
54
- t.integer :fruit_id
55
- t.integer :basket_id
56
- t.timestamps
72
+ begin
73
+ create_table "cm_test.baskets" do |t|
74
+ t.string :name
75
+ t.timestamps
76
+ end
77
+ rescue => e
78
+ puts "tables failed to create: #{e}"
57
79
  end
58
- rescue => e
59
- puts "tables failed to create: #{e}"
60
- end
61
- begin
62
- create_table "#{ActiveRecord::Base.schema_name}.regions" do |t|
63
- t.string :name
64
- t.integer :type_id
65
- t.timestamps
80
+ begin
81
+ create_table "cm_test.fruit_baskets" do |t|
82
+ t.integer :fruit_id
83
+ t.integer :basket_id
84
+ t.timestamps
85
+ end
86
+ rescue => e
87
+ puts "tables failed to create: #{e}"
66
88
  end
67
- rescue => e
68
- puts "tables failed to create: #{e}"
69
- end
70
- begin
71
- create_table "#{ActiveRecord::Base.schema_name}.types" do |t|
72
- t.string :name
73
- t.timestamps
89
+ begin
90
+ create_table "cm_test.regions" do |t|
91
+ t.string :name
92
+ t.integer :type_id
93
+ t.timestamps
94
+ end
95
+ rescue => e
96
+ puts "tables failed to create: #{e}"
97
+ end
98
+ begin
99
+ create_table "cm_test.types" do |t|
100
+ t.string :name
101
+ t.timestamps
102
+ end
103
+ rescue => e
104
+ puts "tables failed to create: #{e}"
74
105
  end
75
- rescue => e
76
- puts "tables failed to create: #{e}"
77
106
  end
78
-
79
107
  ActiveRecord::Base.establish_connection(:cm_user_test)
80
108
  begin
81
- create_table :cm_users do |t|
109
+ create_table 'cm_user_test.cm_users' do |t|
82
110
  t.string :name
83
111
  end
84
112
  rescue => e
@@ -87,31 +115,32 @@ class TestMigrations < ActiveRecord::Migration
87
115
 
88
116
  # Table is in more than 1 schema
89
117
  begin
90
- create_table "#{ActiveRecord::Base.schema_name}.types" do |t|
118
+ create_table "cm_user_test.types" do |t|
91
119
  t.string :name
92
120
  t.timestamps
93
121
  end
94
122
  rescue => e
95
123
  puts "tables failed to create: #{e}"
96
124
  end
97
-
98
125
  ActiveRecord::Base.establish_connection(:test)
99
126
  end
100
127
 
101
128
  # all the downs
102
- def self.down(connection_name='test',user_connection_name='cm_user_test')
103
- ActiveRecord::Base.establish_connection(:test)
104
- [:foos,:fruits,:baskets,:fruit_baskets,:regions,:types].each do |t|
105
- begin
106
- drop_table t
107
- rescue => e
108
- puts "tables were not dropped: #{e}"
129
+ def self.down
130
+ [:test, :test_other].each do |key|
131
+ ActiveRecord::Base.establish_connection(key)
132
+ [:foos,:fruits,:baskets,:fruit_baskets,:regions,:types].each do |t|
133
+ begin
134
+ drop_table "cm_test.#{t.to_s}"
135
+ rescue => e
136
+ puts "tables were not dropped: #{e}"
137
+ end
109
138
  end
110
139
  end
111
140
  ActiveRecord::Base.establish_connection(:cm_user_test)
112
141
  [ :cm_users, :types].each do |t|
113
142
  begin
114
- drop_table t
143
+ puts drop_table "cm_user_test.#{t.to_s}"
115
144
  rescue => e
116
145
  puts "tables were not dropped: #{e}"
117
146
  end