connection_manager 0.0.1 → 0.1.0
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/.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
|