connection_manager 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/Gemfile.lock +8 -3
- data/README.md +26 -26
- data/connection_manager.gemspec +2 -0
- data/lib/connection_manager.rb +1 -0
- data/lib/connection_manager/connections.rb +34 -25
- data/lib/connection_manager/replication_builder.rb +11 -12
- data/lib/connection_manager/version.rb +1 -1
- data/spec/database.yml +20 -0
- data/spec/factories.rb +31 -0
- data/spec/helpers/database_spec_helper.rb +68 -0
- data/spec/helpers/models_spec_helper.rb +26 -0
- data/spec/integration/replication_builder_spec.rb +97 -0
- data/{test_app/spec/connection_manager → spec/lib}/associations_spec.rb +0 -0
- data/spec/lib/connections_spec.rb +93 -0
- data/{test_app/spec/connection_manager → spec/lib}/replication_builder_spec.rb +17 -1
- data/spec/spec_helper.rb +17 -5
- metadata +49 -60
- data/test_app/.gitignore +0 -15
- data/test_app/.rspec +0 -1
- data/test_app/Gemfile +0 -14
- data/test_app/Gemfile.lock +0 -140
- data/test_app/README +0 -261
- data/test_app/Rakefile +0 -7
- data/test_app/app/models/.gitkeep +0 -0
- data/test_app/app/models/basket.rb +0 -4
- data/test_app/app/models/fruit.rb +0 -6
- data/test_app/app/models/fruit_basket.rb +0 -4
- data/test_app/app/models/region.rb +0 -3
- data/test_app/app/models/type.rb +0 -2
- data/test_app/config.ru +0 -4
- data/test_app/config/application.rb +0 -52
- data/test_app/config/boot.rb +0 -6
- data/test_app/config/database.yml +0 -42
- data/test_app/config/environment.rb +0 -5
- data/test_app/config/environments/development.rb +0 -30
- data/test_app/config/environments/production.rb +0 -60
- data/test_app/config/environments/test.rb +0 -39
- data/test_app/config/initializers/backtrace_silencers.rb +0 -7
- data/test_app/config/initializers/inflections.rb +0 -10
- data/test_app/config/initializers/load_connection_manager.rb +0 -6
- data/test_app/config/initializers/mime_types.rb +0 -5
- data/test_app/config/initializers/secret_token.rb +0 -7
- data/test_app/config/initializers/session_store.rb +0 -8
- data/test_app/config/initializers/wrap_parameters.rb +0 -14
- data/test_app/config/locales/en.yml +0 -5
- data/test_app/config/routes.rb +0 -58
- data/test_app/db/migrate/20111127040654_create_fruits.rb +0 -9
- data/test_app/db/migrate/20111127040720_create_baskets.rb +0 -9
- data/test_app/db/migrate/20111127040846_create_fruit_baskets.rb +0 -9
- data/test_app/db/migrate/20111127040915_create_regions.rb +0 -9
- data/test_app/db/migrate/20111127060322_create_types.rb +0 -9
- data/test_app/db/schema.rb +0 -16
- data/test_app/db/seeds.rb +0 -7
- data/test_app/log/.gitkeep +0 -0
- data/test_app/script/rails +0 -6
- data/test_app/spec/connection_manager/connections_spec.rb +0 -51
- data/test_app/spec/factories/baskets.rb +0 -7
- data/test_app/spec/factories/fruit_baskets.rb +0 -8
- data/test_app/spec/factories/fruits.rb +0 -8
- data/test_app/spec/factories/regions.rb +0 -7
- data/test_app/spec/factories/types.rb +0 -7
- data/test_app/spec/models/type_spec.rb +0 -5
- data/test_app/spec/spec.opts +0 -4
- data/test_app/spec/spec_helper.rb +0 -42
- data/test_app/test_app +0 -0
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
|
4
|
+
connection_manager (0.1.0)
|
5
5
|
activerecord (~> 3.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -24,11 +24,13 @@ GEM
|
|
24
24
|
ZenTest (>= 4.4.1)
|
25
25
|
builder (3.0.0)
|
26
26
|
diff-lcs (1.1.3)
|
27
|
+
factory_girl (2.3.2)
|
28
|
+
activesupport
|
27
29
|
i18n (0.6.0)
|
28
30
|
metaclass (0.0.1)
|
29
31
|
mocha (0.10.0)
|
30
32
|
metaclass (~> 0.0.1)
|
31
|
-
multi_json (1.0.
|
33
|
+
multi_json (1.0.4)
|
32
34
|
rspec (2.7.0)
|
33
35
|
rspec-core (~> 2.7.0)
|
34
36
|
rspec-expectations (~> 2.7.0)
|
@@ -37,13 +39,16 @@ GEM
|
|
37
39
|
rspec-expectations (2.7.0)
|
38
40
|
diff-lcs (~> 1.1.2)
|
39
41
|
rspec-mocks (2.7.0)
|
42
|
+
sqlite3 (1.3.4)
|
40
43
|
tzinfo (0.3.31)
|
41
44
|
|
42
45
|
PLATFORMS
|
43
46
|
ruby
|
44
47
|
|
45
48
|
DEPENDENCIES
|
46
|
-
activerecord-connection_manager!
|
47
49
|
autotest
|
50
|
+
connection_manager!
|
51
|
+
factory_girl
|
48
52
|
mocha
|
49
53
|
rspec
|
54
|
+
sqlite3
|
data/README.md
CHANGED
@@ -1,23 +1,23 @@
|
|
1
|
-
#
|
1
|
+
# ConnectionManager
|
2
2
|
Replication and Multi-Database ActiveRecord add on.
|
3
3
|
|
4
4
|
## Goals
|
5
5
|
* Take the lib I've been using finally make something out of it ;)
|
6
|
-
* Use connection classes instead of establish_connection on every model to ensure connection pooling
|
7
|
-
*
|
6
|
+
* Use connection classes, instead of establish_connection on every model, to ensure connection pooling
|
7
|
+
* Use non-adapter specific code.
|
8
8
|
* Use the default database.yml as single point for all database configurations (no extra .yml files)
|
9
|
-
* When slave objects are used in html helpers like link_to and form_for the created urls
|
9
|
+
* When slave objects are used in html helpers like link_to and form_for the created urls match those created using a master object
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
13
|
-
|
13
|
+
ConnectionManager is available through [Rubygems](https://rubygems.org/gems/connection_manager) and can be installed via:
|
14
14
|
|
15
15
|
$ gem install connection_manager
|
16
16
|
|
17
17
|
## Rails 3 setup (Rails 2 untested at this time please let me know if it works for you )
|
18
18
|
|
19
|
-
|
20
|
-
models using the default connection this means the main
|
19
|
+
ConnectionManager assumes the primary connection for the model is the master. For standard
|
20
|
+
models using the default connection this means the main Rails database connection is the master.
|
21
21
|
|
22
22
|
Example database.yml
|
23
23
|
|
@@ -37,7 +37,7 @@ Example database.yml
|
|
37
37
|
|
38
38
|
slave_1_test_app_development:
|
39
39
|
<<: *common
|
40
|
-
database:
|
40
|
+
database: test_app
|
41
41
|
|
42
42
|
slave_2_test_app_development:
|
43
43
|
<<: *common
|
@@ -62,33 +62,32 @@ is the databases name and finally the "development" is the environment. (Of cour
|
|
62
62
|
each slave would have a different connection to is replication :)
|
63
63
|
|
64
64
|
|
65
|
-
|
65
|
+
## Multiple Databases
|
66
66
|
|
67
|
-
At startup
|
67
|
+
At startup ConnectionManager builds connection classes to ConnectionManager::Connections
|
68
68
|
using the connections described in your database.yml based on the current rails environment.
|
69
69
|
|
70
70
|
You can use a different master by having the model inherit from one of your ConnectionManager::Connections.
|
71
71
|
|
72
72
|
To view your ConnectionManager::Connections, at the Rails console type:
|
73
73
|
|
74
|
-
|
74
|
+
ConnectionManager::Connections.all => ["TestAppConnection", "Slave1TestAppConnection", "Slave2TestAppConnection"]
|
75
75
|
|
76
76
|
If your using the example database.yml your array would look like this:
|
77
77
|
["TestAppConnection", "Slave1TestAppConnection", "Slave2TestAppConnection",
|
78
78
|
"UserDataConnection", "Slave1UserDataConnection", "Slave2UserDataConnection"]
|
79
79
|
|
80
80
|
|
81
|
-
|
82
81
|
To use one of your ConnectionManager::Connections for your models default/master database
|
83
|
-
setup
|
82
|
+
setup your model like the following
|
84
83
|
|
85
84
|
class User < ConnectionManager::Connections::UserDataConnection
|
86
85
|
# model code ...
|
87
86
|
end
|
88
87
|
|
89
|
-
|
88
|
+
## Replication
|
90
89
|
|
91
|
-
|
90
|
+
Simply add 'replicated' to your model beneath any defined associations
|
92
91
|
|
93
92
|
class User < ConnectionManager::Connections::UserDataConnection
|
94
93
|
has_one :job
|
@@ -101,30 +100,31 @@ The replicated method addeds subclass whose names match the replication connecti
|
|
101
100
|
Based on the above example database.yml User class would now have User::Slave1 and User::Slave2.
|
102
101
|
|
103
102
|
You can treat your subclass like normal activerecord objects.
|
104
|
-
|
105
|
-
User::
|
103
|
+
|
104
|
+
User::Slave1.first => returns results from slave_1_user_data_development
|
105
|
+
User::Slave2.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from slave_2_user_data_development
|
106
106
|
|
107
|
-
For a more elegant implementation,
|
107
|
+
For a more elegant implementation, ConnectionManager also add class methods to your main model following the
|
108
108
|
same naming standard as the subclass creation.
|
109
|
-
|
110
|
-
User.
|
109
|
+
|
110
|
+
User.slave_1.first => returns results from slave_1_user_data_development
|
111
|
+
User.slave_2.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from slave_2_user_data_development
|
111
112
|
|
112
|
-
Finally
|
113
|
+
Finally, ConnectionManager creates an addional class method that shifts through your
|
113
114
|
available slave connections each time it is called using a different connection on each action.
|
115
|
+
|
114
116
|
User.slave.first => returns results from slave_1_use_data_development
|
115
117
|
User.slave.last => => returns results from slave_2_use_data_development
|
116
|
-
User.slave.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from
|
117
|
-
User.slave.where(['created_at BETWEEN ? and ?',Time.now - 5.days, Time.now]).all => returns results from
|
118
|
+
User.slave.where(['created_at BETWEEN ? and ?',Time.now - 3.hours, Time.now]).all => returns results from slave_1_user_data_development
|
119
|
+
User.slave.where(['created_at BETWEEN ? and ?',Time.now - 5.days, Time.now]).all => returns results from slave_2_user_data_development
|
118
120
|
|
119
121
|
## TODO's
|
120
|
-
* add more to readme
|
121
|
-
* more specs
|
122
122
|
* sharding
|
123
123
|
|
124
124
|
## Other activerecord Connection gems
|
125
125
|
* [Octopus](https://github.com/tchandy/octopus)
|
126
126
|
|
127
|
-
## Contributing to
|
127
|
+
## Contributing to ConnectionManager
|
128
128
|
|
129
129
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
130
130
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
data/connection_manager.gemspec
CHANGED
@@ -18,7 +18,9 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
s.add_runtime_dependency 'activerecord', '~> 3.0'
|
21
|
+
s.add_development_dependency 'sqlite3'
|
21
22
|
s.add_development_dependency 'rspec'
|
22
23
|
s.add_development_dependency 'autotest'
|
23
24
|
s.add_development_dependency 'mocha'
|
25
|
+
s.add_development_dependency 'factory_girl'
|
24
26
|
end
|
data/lib/connection_manager.rb
CHANGED
@@ -40,44 +40,49 @@ module ConnectionManager
|
|
40
40
|
|
41
41
|
# Returns the database value given a connection key from the database.yml
|
42
42
|
def database_name_from_yml(name_from_yml)
|
43
|
-
ActiveRecord::Base.configurations[name_from_yml]['database']
|
43
|
+
ActiveRecord::Base.configurations[name_from_yml]['database']
|
44
44
|
end
|
45
45
|
|
46
|
+
def clean_sqlite_db_name(name)
|
47
|
+
new_name = "#{name}".gsub(/(\.sqlite3$)/,'')
|
48
|
+
new_name = new_name.split("/").last
|
49
|
+
new_name.gsub!(Regexp.new("(\_#{env}$)"),'')
|
50
|
+
new_name
|
51
|
+
end
|
52
|
+
|
53
|
+
def clean_bd_name(name)
|
54
|
+
new_name = "#{name}".gsub(Regexp.new("#{env}$"),'')
|
55
|
+
if new_name.blank?
|
56
|
+
new_name = "#{database_name_from_yml(name)}"
|
57
|
+
end
|
58
|
+
new_name = clean_sqlite_db_name(new_name)
|
59
|
+
new_name.gsub(/\_$/,'')
|
60
|
+
end
|
61
|
+
|
46
62
|
# Given an connection key name from the database.yml, returns the string
|
47
63
|
# equivelent of the class name for that entry.
|
48
64
|
def connection_class_name(name_from_yml)
|
49
|
-
|
50
|
-
new_class_name = name_from_yml.gsub(Regexp.new("#{env}$"),'')
|
51
|
-
new_class_name = database_name_from_yml(name_from_yml) if new_class_name.blank?
|
52
|
-
|
53
|
-
#cleanup sqlite database names
|
54
|
-
if new_class_name.gsub!(/(^db\/)|(\.sqlite3$)/,'')
|
55
|
-
new_class_name.gsub!(Regexp.new("(\\_#{env}$)"),'')
|
56
|
-
end
|
57
|
-
|
65
|
+
new_class_name = clean_bd_name(name_from_yml)
|
58
66
|
new_class_name = new_class_name.gsub(/\_/,' ').titleize.gsub(/ /,'')
|
59
67
|
new_class_name << "Connection"
|
60
68
|
new_class_name
|
61
69
|
end
|
62
70
|
|
63
|
-
|
71
|
+
def replication_key(name_from_yml)
|
72
|
+
rep_name = clean_bd_name(name_from_yml)
|
73
|
+
rep_name.gsub!(/(\_)+(\d+)/,'')
|
74
|
+
rep_name.to_sym
|
75
|
+
end
|
64
76
|
|
65
77
|
def add_replication_connection(name_from_yml,new_connection)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
db_name.gsub!(Regexp.new("(\\_#{env}$)"),'')
|
70
|
-
end
|
71
|
-
rep_name << "_#{db_name}"
|
72
|
-
rep_name = rep_name.to_sym
|
73
|
-
replication_connections[rep_name] ||= []
|
74
|
-
replication_connections[rep_name] << new_connection
|
78
|
+
key = replication_key(name_from_yml)
|
79
|
+
replication_connections[key] ||= []
|
80
|
+
replication_connections[key] << new_connection
|
75
81
|
replication_connections
|
76
82
|
end
|
77
83
|
|
78
|
-
|
79
84
|
def connections_for_replication(rep_collection_key)
|
80
|
-
replication_connections[rep_collection_key.to_sym]
|
85
|
+
replication_connections[(rep_collection_key.gsub(Regexp.new("(\_#{env}$)"),'')).to_sym]
|
81
86
|
end
|
82
87
|
|
83
88
|
# Sets class instance attributes, then builds connection classes, while populating
|
@@ -87,11 +92,15 @@ module ConnectionManager
|
|
87
92
|
send("#{k.to_s}=",v)
|
88
93
|
end
|
89
94
|
connection_keys.each do |connection|
|
90
|
-
|
95
|
+
#puts ActiveRecord::Base.configurations["test"]
|
96
|
+
new_connection = connection_class_name(connection)
|
97
|
+
#puts ActiveRecord::Base.configurations["test"]
|
91
98
|
add_replication_connection(connection,new_connection)
|
92
|
-
|
99
|
+
#puts ActiveRecord::Base.configurations["test"]
|
100
|
+
build_connection_class(new_connection,connection)
|
101
|
+
#puts ActiveRecord::Base.configurations["test"]
|
93
102
|
end
|
94
|
-
|
103
|
+
all
|
95
104
|
end
|
96
105
|
|
97
106
|
# Addes a conneciton subclass to AvailableConnections using the supplied
|
@@ -1,11 +1,8 @@
|
|
1
1
|
module ConnectionManager
|
2
2
|
module ReplicationBuilder
|
3
3
|
|
4
|
-
def database_name
|
5
|
-
|
6
|
-
db_name.gsub!(/(\.sqlite3$)/,'')
|
7
|
-
db_name = db_name.split("/").last
|
8
|
-
db_name
|
4
|
+
def database_name
|
5
|
+
"#{connection.instance_variable_get(:@config)[:database].to_s}"
|
9
6
|
end
|
10
7
|
|
11
8
|
def replication_association_options(method,association,class_name,options={})
|
@@ -39,12 +36,14 @@ module ConnectionManager
|
|
39
36
|
|
40
37
|
def replication_connection_classes(options)
|
41
38
|
if options[:using] && options[:using].is_a?(Array)
|
42
|
-
connection_classes = options[:using].
|
39
|
+
connection_classes = options[:using].collect{|c| Connections.connection_class_name(c)}
|
43
40
|
else
|
44
|
-
|
41
|
+
rep_name = "#{options[:name].to_s}_#{Connections.clean_sqlite_db_name(database_name)}"
|
42
|
+
connection_classes = Connections.connections_for_replication(rep_name)
|
45
43
|
end
|
46
44
|
connection_classes
|
47
45
|
end
|
46
|
+
|
48
47
|
|
49
48
|
# Adds subclass with the class name of the type provided in the options, which
|
50
49
|
# defaults to 'slave' if blank, that uses the connection from a connection class.
|
@@ -80,8 +79,8 @@ module ConnectionManager
|
|
80
79
|
# overrides the rails "readonly?" method to ensure saves are prevented.
|
81
80
|
# Replication class can be called directly for operaitons.
|
82
81
|
# Usage:
|
83
|
-
#
|
84
|
-
#
|
82
|
+
# User::Slave1.where(:id => 1).first => returns results from slave_1 database
|
83
|
+
# User::Slave2.where(:id => 2).first => returns results from slave_1 database
|
85
84
|
def build_replication_class(class_name,connection_name,options)
|
86
85
|
class_eval <<-STR, __FILE__, __LINE__
|
87
86
|
class #{class_name} < #{self.name}
|
@@ -99,8 +98,8 @@ module ConnectionManager
|
|
99
98
|
|
100
99
|
# Adds as class method to call a specific replication conneciton.
|
101
100
|
# Usage:
|
102
|
-
#
|
103
|
-
#
|
101
|
+
# User.slave_1.where(:id => 2).first => returns results from slave_1 database
|
102
|
+
# User.slave_2.where(:id => 2).first => returns results from slave_2 database
|
104
103
|
def build_single_replication_method(method_name,class_name)
|
105
104
|
class_eval <<-STR, __FILE__, __LINE__
|
106
105
|
class << self
|
@@ -114,7 +113,7 @@ module ConnectionManager
|
|
114
113
|
# add a class method that shifts through available connections methods
|
115
114
|
# on each call.
|
116
115
|
# Usage:
|
117
|
-
#
|
116
|
+
# User.slave.where(:id => 2).first => can return results from slave_1 or slave_2
|
118
117
|
def build_full_replication_method(options,connection_methods)
|
119
118
|
class_eval <<-STR, __FILE__, __LINE__
|
120
119
|
@connection_methods = #{connection_methods}
|
data/spec/database.yml
ADDED
@@ -0,0 +1,20 @@
|
|
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
|
+
test:
|
5
|
+
adapter: sqlite3
|
6
|
+
database: spec/cm_test.sqlite3
|
7
|
+
pool: 5
|
8
|
+
timeout: 5000
|
9
|
+
|
10
|
+
slave_1_cm_test:
|
11
|
+
adapter: sqlite3
|
12
|
+
database: spec/cm_test.sqlite3
|
13
|
+
pool: 5
|
14
|
+
timeout: 5000
|
15
|
+
|
16
|
+
slave_2_cm_test:
|
17
|
+
adapter: sqlite3
|
18
|
+
database: spec/cm_test.sqlite3
|
19
|
+
pool: 5
|
20
|
+
timeout: 5000
|
data/spec/factories.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :basket do
|
3
|
+
name "MyString"
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
FactoryGirl.define do
|
8
|
+
factory :fruit_basket do
|
9
|
+
fruit
|
10
|
+
basket
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
FactoryGirl.define do
|
15
|
+
factory :fruit do
|
16
|
+
name "MyString"
|
17
|
+
region
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
FactoryGirl.define do
|
22
|
+
factory :region do
|
23
|
+
name "MyString"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
FactoryGirl.define do
|
28
|
+
factory :type do
|
29
|
+
name "MyString"
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class TestDB
|
2
|
+
def self.connect
|
3
|
+
ActiveRecord::Base.configurations = YAML::load(File.open(File.join(File.dirname(__FILE__),'..','database.yml')))
|
4
|
+
ActiveRecord::Base.establish_connection('test')
|
5
|
+
end
|
6
|
+
def self.clean
|
7
|
+
[:foos,:fruits,:baskets,:fruit_baskets,:regions,:types].each do |t|
|
8
|
+
DBSpecManagement.connection.execute("DELETE FROM #{t.to_s}")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
#Class to clean tables
|
12
|
+
class DBSpecManagement < ActiveRecord::Base
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
#Put all the test migrations here
|
18
|
+
class TestMigrations < ActiveRecord::Migration
|
19
|
+
|
20
|
+
# all the ups
|
21
|
+
def self.up
|
22
|
+
begin
|
23
|
+
create_table :foos do |t|
|
24
|
+
t.string :name
|
25
|
+
end
|
26
|
+
create_table :fruits do |t|
|
27
|
+
t.string :name
|
28
|
+
t.integer :region_id
|
29
|
+
t.timestamps
|
30
|
+
end
|
31
|
+
create_table :baskets do |t|
|
32
|
+
t.string :name
|
33
|
+
t.timestamps
|
34
|
+
end
|
35
|
+
create_table :fruit_baskets do |t|
|
36
|
+
t.integer :fruit_id
|
37
|
+
t.integer :basket_id
|
38
|
+
t.timestamps
|
39
|
+
end
|
40
|
+
create_table :regions do |t|
|
41
|
+
t.string :name
|
42
|
+
|
43
|
+
t.timestamps
|
44
|
+
end
|
45
|
+
create_table :types do |t|
|
46
|
+
t.string :name
|
47
|
+
t.timestamps
|
48
|
+
end
|
49
|
+
rescue => e
|
50
|
+
puts "tables failed to create: #{e}"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# all the downs
|
57
|
+
def self.down
|
58
|
+
begin
|
59
|
+
[:foos,:fruits,:baskets,:fruit_baskets,:regions,:types].each do |t|
|
60
|
+
drop_table t
|
61
|
+
end
|
62
|
+
rescue => e
|
63
|
+
puts "tables were not dropped: #{e}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
end
|