molo 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +33 -0
- data/Molo.gemspec +57 -0
- data/README.markdown +92 -0
- data/Rakefile +21 -0
- data/VERSION +1 -0
- data/lib/tasks/molo.rb +279 -0
- data/spec/molo_spec.rb +268 -0
- data/vendor/migration_helpers/MIT-LICENSE +20 -0
- data/vendor/migration_helpers/README.markdown +92 -0
- data/vendor/migration_helpers/init.rb +3 -0
- data/vendor/migration_helpers/lib/migration_helper.rb +51 -0
- metadata +111 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
Molo (0.4.0)
|
5
|
+
activerecord (~> 3.0.3)
|
6
|
+
rake (~> 0.8)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activemodel (3.0.3)
|
12
|
+
activesupport (= 3.0.3)
|
13
|
+
builder (~> 2.1.2)
|
14
|
+
i18n (~> 0.4)
|
15
|
+
activerecord (3.0.3)
|
16
|
+
activemodel (= 3.0.3)
|
17
|
+
activesupport (= 3.0.3)
|
18
|
+
arel (~> 2.0.2)
|
19
|
+
tzinfo (~> 0.3.23)
|
20
|
+
activesupport (3.0.3)
|
21
|
+
arel (2.0.6)
|
22
|
+
builder (2.1.2)
|
23
|
+
i18n (0.5.0)
|
24
|
+
rake (0.8.7)
|
25
|
+
tzinfo (0.3.23)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
Molo!
|
32
|
+
activerecord (~> 3.0.3)
|
33
|
+
rake (~> 0.8)
|
data/Molo.gemspec
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{molo}
|
8
|
+
s.version = "0.5.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Joel Moss", "Todd Huss", "Michael Grosser"]
|
12
|
+
s.date = %q{2010-12-13}
|
13
|
+
s.email = %q{joel@developwithstyle.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"README.markdown"
|
16
|
+
]
|
17
|
+
s.files = [
|
18
|
+
".gitignore",
|
19
|
+
"Gemfile",
|
20
|
+
"Gemfile.lock",
|
21
|
+
"Molo.gemspec",
|
22
|
+
"README.markdown",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"lib/tasks/molo.rb",
|
26
|
+
"spec/molo_spec.rb",
|
27
|
+
"vendor/migration_helpers/MIT-LICENSE",
|
28
|
+
"vendor/migration_helpers/README.markdown",
|
29
|
+
"vendor/migration_helpers/init.rb",
|
30
|
+
"vendor/migration_helpers/lib/migration_helper.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://codaset.com/joelmoss/molo}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.7}
|
36
|
+
s.summary = %q{A thin wrapper to use Rails Migrations in non Rails projects}
|
37
|
+
s.test_files = [
|
38
|
+
"spec/molo_spec.rb"
|
39
|
+
]
|
40
|
+
|
41
|
+
if s.respond_to? :specification_version then
|
42
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
43
|
+
s.specification_version = 3
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
|
+
s.add_runtime_dependency(%q<activerecord>, ["~> 3.0.3"])
|
47
|
+
s.add_runtime_dependency(%q<rake>, ["~> 0.8"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<activerecord>, ["~> 3.0.3"])
|
50
|
+
s.add_dependency(%q<rake>, ["~> 0.8"])
|
51
|
+
end
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<activerecord>, ["~> 3.0.3"])
|
54
|
+
s.add_dependency(%q<rake>, ["~> 0.8"])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
data/README.markdown
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
Molo
|
2
|
+
====
|
3
|
+
|
4
|
+
Rails migrations in non-Rails (and non Ruby) projects.
|
5
|
+
|
6
|
+
Install Ruby, RubyGems and a ruby-database driver (e.g. `gem install mysql`) then:
|
7
|
+
|
8
|
+
sudo gem install molo
|
9
|
+
|
10
|
+
Add to `Rakefile` in your projects base directory:
|
11
|
+
|
12
|
+
begin
|
13
|
+
require 'tasks/molo'
|
14
|
+
MigratorTasks.new do |t|
|
15
|
+
# t.migrations = "db/migrations"
|
16
|
+
# t.config = "db/config.yml"
|
17
|
+
# t.schema = "db/schema.rb"
|
18
|
+
# t.env = "DB"
|
19
|
+
# t.default_env = "development"
|
20
|
+
# t.verbose = true
|
21
|
+
# t.log_level = Logger::ERROR
|
22
|
+
end
|
23
|
+
rescue LoadError => e
|
24
|
+
puts "gem install molo to get db:migrate:* tasks! (Error: #{e})"
|
25
|
+
end
|
26
|
+
|
27
|
+
Add database configuration to `db/config.yml` in your projects base directory e.g.:
|
28
|
+
|
29
|
+
development:
|
30
|
+
adapter: sqlite3
|
31
|
+
database: db/development.sqlite3
|
32
|
+
pool: 5
|
33
|
+
timeout: 5000
|
34
|
+
|
35
|
+
production:
|
36
|
+
adapter: mysql
|
37
|
+
encoding: utf8
|
38
|
+
reconnect: false
|
39
|
+
database: somedatabase_dev
|
40
|
+
pool: 5
|
41
|
+
username: root
|
42
|
+
password:
|
43
|
+
socket: /var/run/mysqld/mysqld.sock
|
44
|
+
|
45
|
+
test: &test
|
46
|
+
adapter: sqlite3
|
47
|
+
database: db/test.sqlite3
|
48
|
+
pool: 5
|
49
|
+
timeout: 5000
|
50
|
+
|
51
|
+
### To create a new database migration:
|
52
|
+
|
53
|
+
rake db:new_migration name=FooBarMigration
|
54
|
+
edit db/migrations/20081220234130_foo_bar_migration.rb
|
55
|
+
|
56
|
+
... and fill in the up and down migrations [Cheatsheet](http://dizzy.co.uk/ruby_on_rails/cheatsheets/rails-migrations).
|
57
|
+
|
58
|
+
If you're lazy and want to just execute raw SQL:
|
59
|
+
|
60
|
+
def self.up
|
61
|
+
execute "insert into foo values (123,'something');"
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.down
|
65
|
+
execute "delete from foo where field='something';"
|
66
|
+
end
|
67
|
+
|
68
|
+
### To apply your newest migration:
|
69
|
+
|
70
|
+
rake db:migrate
|
71
|
+
|
72
|
+
### To migrate to a specific version (for example to rollback)
|
73
|
+
|
74
|
+
rake db:migrate VERSION=20081220234130
|
75
|
+
|
76
|
+
### To migrate a specific database (for example your "testing" database)
|
77
|
+
|
78
|
+
rake db:migrate DB=test
|
79
|
+
|
80
|
+
### To execute a specific up/down of one single migration
|
81
|
+
|
82
|
+
rake db:migrate:up VERSION=20081220234130
|
83
|
+
|
84
|
+
Contributors
|
85
|
+
============
|
86
|
+
This work is based on [Lincoln Stoll's blog post](http://lstoll.net/2008/04/stand-alone-activerecord-migrations/) and [David Welton's post](http://journal.dedasys.com/2007/01/28/using-migrations-outside-of-rails).
|
87
|
+
|
88
|
+
- [Joel Moss](http://developwithstyle.com/)
|
89
|
+
- [Todd Huss](http://gabrito.com/)
|
90
|
+
- [Michael Grosser](http://pragmatig.wordpress.com)
|
91
|
+
- [Eric Lindvall](http://bitmonkey.net)
|
92
|
+
- [Steve Hodgkiss](http://stevehodgkiss.com/)
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
task :default => :spec
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
Spec::Rake::SpecTask.new {|t| t.spec_opts = ['--color']}
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = 'molo'
|
9
|
+
gem.summary = "A thin wrapper to use Rails Migrations in non Rails projects"
|
10
|
+
gem.email = "joel@developwithstyle.com"
|
11
|
+
gem.homepage = "http://codaset.com/joelmoss/molo"
|
12
|
+
gem.authors = ["Joel Moss","Todd Huss", "Michael Grosser"]
|
13
|
+
gem.files += ["lib/tasks/*"]
|
14
|
+
gem.add_dependency "activerecord", "~> 3.0.3"
|
15
|
+
gem.add_dependency "rake", "~> 0.8"
|
16
|
+
end
|
17
|
+
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0
|
data/lib/tasks/molo.rb
ADDED
@@ -0,0 +1,279 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
class MigratorTasks < ::Rake::TaskLib
|
6
|
+
attr_accessor :name, :base, :vendor, :config, :schema, :env, :default_env, :verbose, :log_level, :logger
|
7
|
+
attr_reader :migrations
|
8
|
+
|
9
|
+
def initialize(name = :migrator)
|
10
|
+
@name = name
|
11
|
+
base = File.expand_path('.')
|
12
|
+
here = File.expand_path(File.dirname(File.dirname(File.dirname((__FILE__)))))
|
13
|
+
@base = base
|
14
|
+
@vendor = "#{here}/vendor"
|
15
|
+
@migrations = ["#{base}/db/migrations"]
|
16
|
+
@config = "#{base}/db/config.yml"
|
17
|
+
@schema = "#{base}/db/schema.rb"
|
18
|
+
@env = 'DB'
|
19
|
+
@default_env = 'development'
|
20
|
+
@verbose = true
|
21
|
+
@log_level = Logger::ERROR
|
22
|
+
yield self if block_given?
|
23
|
+
# Add to load_path every "lib/" directory in vendor
|
24
|
+
Dir["#{vendor}/**/lib"].each{|p| $LOAD_PATH << p }
|
25
|
+
define
|
26
|
+
end
|
27
|
+
|
28
|
+
def migrations=(*value)
|
29
|
+
@migrations = value.flatten
|
30
|
+
end
|
31
|
+
|
32
|
+
def define
|
33
|
+
namespace :db do
|
34
|
+
task :ar_init do
|
35
|
+
require 'active_record'
|
36
|
+
ENV[@env] ||= @default_env
|
37
|
+
|
38
|
+
require 'erb'
|
39
|
+
|
40
|
+
if @config.is_a?(Hash)
|
41
|
+
ActiveRecord::Base.configurations = @config
|
42
|
+
else
|
43
|
+
ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(@config)).result)
|
44
|
+
end
|
45
|
+
ActiveRecord::Base.establish_connection(ENV[@env])
|
46
|
+
if @logger
|
47
|
+
logger = @logger
|
48
|
+
else
|
49
|
+
logger = Logger.new($stderr)
|
50
|
+
logger.level = @log_level
|
51
|
+
end
|
52
|
+
ActiveRecord::Base.logger = logger
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Migrate the database using the scripts in the migrations directory. Target specific version with VERSION=x. Turn off output with VERBOSE=false."
|
56
|
+
task :migrate => :ar_init do
|
57
|
+
require "#{@vendor}/migration_helpers/init"
|
58
|
+
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
59
|
+
@migrations.each do |path|
|
60
|
+
ActiveRecord::Migrator.migrate(path, ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
61
|
+
end
|
62
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
63
|
+
end
|
64
|
+
|
65
|
+
namespace :migrate do
|
66
|
+
desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
|
67
|
+
task :redo => :ar_init do
|
68
|
+
if ENV["VERSION"]
|
69
|
+
Rake::Task["db:migrate:down"].invoke
|
70
|
+
Rake::Task["db:migrate:up"].invoke
|
71
|
+
else
|
72
|
+
Rake::Task["db:rollback"].invoke
|
73
|
+
Rake::Task["db:migrate"].invoke
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'Runs the "up" for a given migration VERSION.'
|
78
|
+
task :up => :ar_init do
|
79
|
+
ActiveRecord::Migration.verbose = @verbose
|
80
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
81
|
+
raise "VERSION is required" unless version
|
82
|
+
|
83
|
+
migration_path = nil
|
84
|
+
if @migrations.length == 1
|
85
|
+
migration_path = @migrations.first
|
86
|
+
else
|
87
|
+
@migrations.each do |path|
|
88
|
+
Dir[File.join(path, '*.rb')].each do |file|
|
89
|
+
if File.basename(file).match(/^\d+/)[0] == version.to_s
|
90
|
+
migration_path = path
|
91
|
+
break
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
raise "Migration #{version} wasn't found on paths #{@migrations.join(', ')}" if migration_path.nil?
|
96
|
+
end
|
97
|
+
|
98
|
+
ActiveRecord::Migrator.run(:up, migration_path, version)
|
99
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
100
|
+
end
|
101
|
+
|
102
|
+
desc 'Runs the "down" for a given migration VERSION.'
|
103
|
+
task :down => :ar_init do
|
104
|
+
ActiveRecord::Migration.verbose = @verbose
|
105
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
106
|
+
raise "VERSION is required" unless version
|
107
|
+
|
108
|
+
migration_path = nil
|
109
|
+
if @migrations.length == 1
|
110
|
+
migration_path = @migrations.first
|
111
|
+
else
|
112
|
+
@migrations.each do |path|
|
113
|
+
Dir[File.join(path, '*.rb')].each do |file|
|
114
|
+
if File.basename(file).match(/^\d+/)[0] == version.to_s
|
115
|
+
migration_path = path
|
116
|
+
break
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
raise "Migration #{version} wasn't found on paths #{@migrations.join(', ')}" if migration_path.nil?
|
121
|
+
end
|
122
|
+
|
123
|
+
ActiveRecord::Migrator.run(:down, migration_path, version)
|
124
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
125
|
+
end
|
126
|
+
|
127
|
+
desc "Display status of migrations"
|
128
|
+
task :status => :ar_init do
|
129
|
+
config = ActiveRecord::Base.configurations[ENV[@env]]
|
130
|
+
ActiveRecord::Base.establish_connection(config)
|
131
|
+
unless ActiveRecord::Base.connection.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
|
132
|
+
puts 'Schema migrations table does not exist yet.'
|
133
|
+
next # means "return" for rake task
|
134
|
+
end
|
135
|
+
db_list = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}")
|
136
|
+
file_list = []
|
137
|
+
@migrations.each do |dir|
|
138
|
+
Dir.foreach(dir) do |file|
|
139
|
+
# only files matching "20091231235959_some_name.rb" pattern
|
140
|
+
if match_data = /(\d{14})_(.+)\.rb/.match(file)
|
141
|
+
status = db_list.delete(match_data[1]) ? 'up' : 'down'
|
142
|
+
file_list << [status, match_data[1], match_data[2]]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
# output
|
147
|
+
puts "\ndatabase: #{config['database']}\n\n"
|
148
|
+
puts "#{"Status".center(8)} #{"Migration ID".ljust(14)} Migration Name"
|
149
|
+
puts "-" * 50
|
150
|
+
file_list.each do |file|
|
151
|
+
puts "#{file[0].center(8)} #{file[1].ljust(14)} #{file[2].humanize}"
|
152
|
+
end
|
153
|
+
db_list.each do |version|
|
154
|
+
puts "#{'up'.center(8)} #{version.ljust(14)} *** NO FILE ***"
|
155
|
+
end
|
156
|
+
puts
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
|
161
|
+
task :rollback => :ar_init do
|
162
|
+
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
|
163
|
+
@migrations.each do |path|
|
164
|
+
ActiveRecord::Migrator.rollback(path, step)
|
165
|
+
end
|
166
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
167
|
+
end
|
168
|
+
|
169
|
+
desc "Retrieves the current schema version number"
|
170
|
+
task :version => :ar_init do
|
171
|
+
puts "Current version: #{ActiveRecord::Migrator.current_version}"
|
172
|
+
end
|
173
|
+
|
174
|
+
desc "Raises an error if there are pending migrations"
|
175
|
+
task :abort_if_pending_migrations => :ar_init do
|
176
|
+
@migrations.each do |path|
|
177
|
+
pending_migrations = ActiveRecord::Migrator.new(:up, path).pending_migrations
|
178
|
+
|
179
|
+
if pending_migrations.any?
|
180
|
+
puts "You have #{pending_migrations.size} pending migrations:"
|
181
|
+
pending_migrations.each do |pending_migration|
|
182
|
+
puts ' %4d %s' % [pending_migration.version, pending_migration.name]
|
183
|
+
end
|
184
|
+
abort %{Run "rake db:migrate" to update your database then try again.}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
namespace :schema do
|
190
|
+
desc "Create schema.rb file that can be portably used against any DB supported by AR"
|
191
|
+
task :dump => :ar_init do
|
192
|
+
if schema_file = ENV['SCHEMA'] || @schema
|
193
|
+
require 'active_record/schema_dumper'
|
194
|
+
File.open(schema_file, "w") do |file|
|
195
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
desc "Load a ar_schema.rb file into the database"
|
201
|
+
task :load => :ar_init do
|
202
|
+
file = ENV['SCHEMA'] || @schema
|
203
|
+
load(file)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
namespace :test do
|
208
|
+
desc "Recreate the test database from the current schema.rb"
|
209
|
+
task :load => ['db:ar_init', 'db:test:purge'] do
|
210
|
+
ActiveRecord::Base.establish_connection(:test)
|
211
|
+
ActiveRecord::Schema.verbose = false
|
212
|
+
Rake::Task["db:schema:load"].invoke
|
213
|
+
end
|
214
|
+
|
215
|
+
desc "Empty the test database"
|
216
|
+
task :purge => 'db:ar_init' do
|
217
|
+
config = ActiveRecord::Base.configurations['test']
|
218
|
+
case config["adapter"]
|
219
|
+
when "mysql"
|
220
|
+
ActiveRecord::Base.establish_connection(:test)
|
221
|
+
ActiveRecord::Base.connection.recreate_database(config["database"], config)
|
222
|
+
when "postgresql" #TODO i doubt this will work <-> methods are not defined
|
223
|
+
ActiveRecord::Base.clear_active_connections!
|
224
|
+
drop_database(config)
|
225
|
+
create_database(config)
|
226
|
+
when "sqlite", "sqlite3"
|
227
|
+
db_file = config["database"] || config["dbfile"]
|
228
|
+
File.delete(db_file) if File.exist?(db_file)
|
229
|
+
when "sqlserver"
|
230
|
+
drop_script = "#{config["host"]}.#{config["database"]}.DP1".gsub(/\\/,'-')
|
231
|
+
`osql -E -S #{config["host"]} -d #{config["database"]} -i db\\#{drop_script}`
|
232
|
+
`osql -E -S #{config["host"]} -d #{config["database"]} -i db\\test_structure.sql`
|
233
|
+
when "oci", "oracle"
|
234
|
+
ActiveRecord::Base.establish_connection(:test)
|
235
|
+
ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
|
236
|
+
ActiveRecord::Base.connection.execute(ddl)
|
237
|
+
end
|
238
|
+
when "firebird"
|
239
|
+
ActiveRecord::Base.establish_connection(:test)
|
240
|
+
ActiveRecord::Base.connection.recreate_database!
|
241
|
+
else
|
242
|
+
raise "Task not supported by #{config["adapter"].inspect}"
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
desc 'Check for pending migrations and load the test schema'
|
247
|
+
task :prepare => ['db:abort_if_pending_migrations', 'db:test:load']
|
248
|
+
end
|
249
|
+
|
250
|
+
desc "Create a new migration"
|
251
|
+
task :new_migration do |t|
|
252
|
+
unless migration = ENV['name']
|
253
|
+
puts "Error: must provide name of migration to generate."
|
254
|
+
puts "For example: rake #{t.name} name=add_field_to_form"
|
255
|
+
abort
|
256
|
+
end
|
257
|
+
|
258
|
+
class_name = migration.split('_').map{|s| s.capitalize }.join
|
259
|
+
file_contents = <<eof
|
260
|
+
class #{class_name} < ActiveRecord::Migration
|
261
|
+
def self.up
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.down
|
265
|
+
raise ActiveRecord::IrreversibleMigration
|
266
|
+
end
|
267
|
+
end
|
268
|
+
eof
|
269
|
+
migration_path = @migrations.first
|
270
|
+
FileUtils.mkdir_p(migration_path) unless File.exist?(migration_path)
|
271
|
+
file_name = "#{migration_path}/#{Time.now.utc.strftime('%Y%m%d%H%M%S')}_#{migration}.rb"
|
272
|
+
|
273
|
+
File.open(file_name, 'w'){|f| f.write file_contents }
|
274
|
+
|
275
|
+
puts "Created migration #{file_name}"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
data/spec/molo_spec.rb
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
describe 'Molo' do
|
2
|
+
def write(file, content)
|
3
|
+
raise "cannot write nil" unless file
|
4
|
+
file = tmp_file(file)
|
5
|
+
folder = File.dirname(file)
|
6
|
+
`mkdir -p #{folder}` unless File.exist?(folder)
|
7
|
+
File.open(file,'w'){|f| f.write content}
|
8
|
+
end
|
9
|
+
|
10
|
+
def read(file)
|
11
|
+
File.read(tmp_file(file))
|
12
|
+
end
|
13
|
+
|
14
|
+
def migration(name)
|
15
|
+
m = `cd spec/tmp/db/migrations && ls`.split("\n").detect{|m| m =~ name}
|
16
|
+
m ? "db/migrations/#{m}" : m
|
17
|
+
end
|
18
|
+
|
19
|
+
def tmp_file(file)
|
20
|
+
"spec/tmp/#{file}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def run(cmd)
|
24
|
+
`cd spec/tmp && #{cmd} 2>&1 && echo SUCCESS`
|
25
|
+
end
|
26
|
+
|
27
|
+
def make_migration(name)
|
28
|
+
migration = run("rake db:new_migration name=#{name}").match(%r{db/migrations/\d+.*.rb})[0]
|
29
|
+
content = read(migration)
|
30
|
+
content.sub!(/def self.down.*?\send/m, "def self.down;puts 'DOWN-#{name}';end")
|
31
|
+
content.sub!(/def self.up.*?\send/m, "def self.up;puts 'UP-#{name}';end")
|
32
|
+
write(migration, content)
|
33
|
+
migration.match(/\d{14}/)[0]
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_rakefile(config=nil)
|
37
|
+
write 'Rakefile', <<-TXT
|
38
|
+
$LOAD_PATH.unshift '#{File.expand_path('lib')}'
|
39
|
+
begin
|
40
|
+
require 'tasks/molo'
|
41
|
+
MigratorTasks.new do |t|
|
42
|
+
t.log_level = Logger::INFO
|
43
|
+
#{config}
|
44
|
+
end
|
45
|
+
rescue LoadError => e
|
46
|
+
puts "gem install molo to get db:migrate:* tasks! (Error: \#{e})"
|
47
|
+
end
|
48
|
+
TXT
|
49
|
+
end
|
50
|
+
|
51
|
+
def write_multiple_migrations
|
52
|
+
write_rakefile %{t.migrations = "db/migrations", "db/migrations2"}
|
53
|
+
write "db/migrations/20100509095815_create_tests.rb", <<-TXT
|
54
|
+
class CreateTests < ActiveRecord::Migration
|
55
|
+
def self.up
|
56
|
+
puts "UP-CreateTests"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.down
|
60
|
+
puts "DOWN-CreateTests"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
TXT
|
64
|
+
write "db/migrations2/20100509095816_create_tests2.rb", <<-TXT
|
65
|
+
class CreateTests2 < ActiveRecord::Migration
|
66
|
+
def self.up
|
67
|
+
puts "UP-CreateTests2"
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.down
|
71
|
+
puts "DOWN-CreateTests2"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
TXT
|
75
|
+
end
|
76
|
+
|
77
|
+
before do
|
78
|
+
`rm -rf spec/tmp` if File.exist?('spec/tmp')
|
79
|
+
`mkdir spec/tmp`
|
80
|
+
write_rakefile
|
81
|
+
write 'db/config.yml', <<-TXT
|
82
|
+
development:
|
83
|
+
adapter: sqlite3
|
84
|
+
database: db/development.sql
|
85
|
+
test:
|
86
|
+
adapter: sqlite3
|
87
|
+
database: db/test.sql
|
88
|
+
TXT
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'db:new_migration' do
|
92
|
+
context "single migration path" do
|
93
|
+
it "fails if i do not add a name" do
|
94
|
+
run("rake db:new_migration").should_not =~ /SUCCESS/
|
95
|
+
end
|
96
|
+
|
97
|
+
it "generates a new migration with this name and timestamp" do
|
98
|
+
run("rake db:new_migration name=test_abc").should =~ %r{Created migration .*spec/tmp/db/migrations/\d+_test_abc\.rb}
|
99
|
+
run("ls db/migrations").should =~ /^\d+_test_abc.rb$/
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "multiple migration paths" do
|
104
|
+
before do
|
105
|
+
write_rakefile %{t.migrations = "db/migrations", "db/migrations2"}
|
106
|
+
end
|
107
|
+
it "chooses the first path" do
|
108
|
+
run("rake db:new_migration name=test_abc").should =~ %r{Created migration .*db/migrations/\d+_test_abc\.rb}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'db:migrate' do
|
114
|
+
context "single migration path" do
|
115
|
+
it "does nothing when no migrations are present" do
|
116
|
+
run("rake db:migrate").should =~ /SUCCESS/
|
117
|
+
end
|
118
|
+
|
119
|
+
it "migrates if i add a migration" do
|
120
|
+
run("rake db:new_migration name=xxx")
|
121
|
+
result = run("rake db:migrate")
|
122
|
+
result.should =~ /SUCCESS/
|
123
|
+
result.should =~ /Migrating to Xxx \(#{Time.now.year}/
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "multiple migration paths" do
|
128
|
+
before do
|
129
|
+
write_multiple_migrations
|
130
|
+
end
|
131
|
+
it "runs the migrator on each migration path" do
|
132
|
+
result = run("rake db:migrate")
|
133
|
+
result.should =~ /Migrating to CreateTests \(#{Time.now.year}/
|
134
|
+
result.should =~ /Migrating to CreateTests2 \(#{Time.now.year}/
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'db:migrate:down' do
|
140
|
+
context "single migration path" do
|
141
|
+
it "migrates down" do
|
142
|
+
make_migration('xxx')
|
143
|
+
sleep 1
|
144
|
+
version = make_migration('yyy')
|
145
|
+
run 'rake db:migrate'
|
146
|
+
|
147
|
+
result = run("rake db:migrate:down VERSION=#{version}")
|
148
|
+
result.should =~ /SUCCESS/
|
149
|
+
result.should_not =~ /DOWN-xxx/
|
150
|
+
result.should =~ /DOWN-yyy/
|
151
|
+
end
|
152
|
+
|
153
|
+
it "fails without version" do
|
154
|
+
make_migration('yyy')
|
155
|
+
result = run("rake db:migrate:down")
|
156
|
+
result.should_not =~ /SUCCESS/
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "multiple migration paths" do
|
161
|
+
before do
|
162
|
+
write_multiple_migrations
|
163
|
+
end
|
164
|
+
|
165
|
+
it "runs down on the correct path" do
|
166
|
+
run 'rake db:migrate'
|
167
|
+
result = run 'rake db:migrate:down VERSION=20100509095815'
|
168
|
+
result.should =~ /DOWN-CreateTests/
|
169
|
+
result.should_not =~ /DOWN-CreateTests2/
|
170
|
+
end
|
171
|
+
|
172
|
+
it "fails if migration number isn't found" do
|
173
|
+
run 'rake db:migrate'
|
174
|
+
result = run 'rake db:migrate:down VERSION=20100509095820'
|
175
|
+
result.should_not =~ /SUCCESS/
|
176
|
+
result.should =~ /wasn't found on path/
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe 'db:migrate:up' do
|
182
|
+
context "single migration path" do
|
183
|
+
it "migrates up" do
|
184
|
+
make_migration('xxx')
|
185
|
+
run 'rake db:migrate'
|
186
|
+
sleep 1
|
187
|
+
version = make_migration('yyy')
|
188
|
+
result = run("rake db:migrate:up VERSION=#{version}")
|
189
|
+
result.should =~ /SUCCESS/
|
190
|
+
result.should_not =~ /UP-xxx/
|
191
|
+
result.should =~ /UP-yyy/
|
192
|
+
end
|
193
|
+
|
194
|
+
it "fails without version" do
|
195
|
+
make_migration('yyy')
|
196
|
+
result = run("rake db:migrate:up")
|
197
|
+
result.should_not =~ /SUCCESS/
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context "multiple migration paths" do
|
202
|
+
before do
|
203
|
+
write_multiple_migrations
|
204
|
+
end
|
205
|
+
|
206
|
+
it "runs down on the correct path" do
|
207
|
+
result = run 'rake db:migrate:up VERSION=20100509095815'
|
208
|
+
result.should =~ /UP-CreateTests/
|
209
|
+
result.should_not =~ /UP-CreateTests2/
|
210
|
+
end
|
211
|
+
|
212
|
+
it "fails if migration number isn't found" do
|
213
|
+
result = run 'rake db:migrate:up VERSION=20100509095820'
|
214
|
+
result.should_not =~ /SUCCESS/
|
215
|
+
result.should =~ /wasn't found on path/
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe 'schema:dump' do
|
221
|
+
it "dumps the schema" do
|
222
|
+
result = run('rake db:schema:dump')
|
223
|
+
result.should =~ /SUCCESS/
|
224
|
+
read('db/schema.rb').should =~ /ActiveRecord/
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe 'db:schema:load' do
|
229
|
+
it "loads the schema" do
|
230
|
+
run('rake db:schema:dump')
|
231
|
+
schema = "db/schema.rb"
|
232
|
+
write(schema, read(schema)+"\nputs 'LOADEDDD'")
|
233
|
+
result = run('rake db:schema:load')
|
234
|
+
result.should =~ /SUCCESS/
|
235
|
+
result.should =~ /LOADEDDD/
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe 'db:abort_if_pending_migrations' do
|
240
|
+
it "passes when no migrations are pending" do
|
241
|
+
run("rake db:abort_if_pending_migrations").should_not =~ /try again/
|
242
|
+
end
|
243
|
+
|
244
|
+
it "fails when migrations are pending" do
|
245
|
+
make_migration('yyy')
|
246
|
+
result = run("rake db:abort_if_pending_migrations")
|
247
|
+
result.should =~ /try again/
|
248
|
+
result.should =~ /1 pending migration/
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe 'db:test:load' do
|
253
|
+
it 'loads' do
|
254
|
+
write("db/schema.rb", "puts 'LOADEDDD'")
|
255
|
+
run("rake db:test:load").should =~ /LOADEDDD.*SUCCESS/m
|
256
|
+
end
|
257
|
+
|
258
|
+
it "fails without schema" do
|
259
|
+
run("rake db:test:load").should =~ /no such file to load/
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe 'db:test:purge' do
|
264
|
+
it "runs" do
|
265
|
+
run('rake db:test:purge').should =~ /SUCCESS/
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Jesús García Sáez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
DESCRIPTION
|
3
|
+
===========
|
4
|
+
|
5
|
+
Helpers for migrations of ActiveRecord for dealing with foreign keys and primary keys.
|
6
|
+
|
7
|
+
FEATURES
|
8
|
+
========
|
9
|
+
|
10
|
+
* **foreign keys**
|
11
|
+
* foreign_key(table, field, referenced_table, referenced_field, on_cascade)
|
12
|
+
* drop_foreign_key(table, field)
|
13
|
+
* **primary keys**
|
14
|
+
* primary_key(table, field)
|
15
|
+
|
16
|
+
Examples
|
17
|
+
========
|
18
|
+
|
19
|
+
Typical use:
|
20
|
+
|
21
|
+
def self.up
|
22
|
+
create_table :profiles do |t|
|
23
|
+
t.string :first_name
|
24
|
+
t.string :last_name
|
25
|
+
t.string :email
|
26
|
+
t.boolean :is_disabled
|
27
|
+
end
|
28
|
+
create_table :users do |t|
|
29
|
+
t.string :login
|
30
|
+
t.string :crypted_password
|
31
|
+
t.string :salt
|
32
|
+
t.integer :profile_id
|
33
|
+
end
|
34
|
+
|
35
|
+
foreign_key :users, :profile_id, :profiles
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.down
|
39
|
+
drop_foreign_key :users, :profile_id
|
40
|
+
drop_table :users
|
41
|
+
drop_table :profiles
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
Also, if we don't defined a common :id (exactly it's rails who define it), we should create a primary key:
|
46
|
+
|
47
|
+
def self.up
|
48
|
+
create_table :foo, :id => false do |t|
|
49
|
+
t.string :foo, :bar
|
50
|
+
end
|
51
|
+
|
52
|
+
primary_key :foo, [ :foo, :bar ]
|
53
|
+
end
|
54
|
+
|
55
|
+
In the parameter where a field is required (like the second parameter in *primary_key*) you can specified and symbol (or string) or an array of symbols (or strings).
|
56
|
+
|
57
|
+
|
58
|
+
REQUIREMENTS
|
59
|
+
============
|
60
|
+
|
61
|
+
* It's been tested with Mysql adapter and Jdbcmysql adapter
|
62
|
+
|
63
|
+
INSTALL
|
64
|
+
=======
|
65
|
+
|
66
|
+
* script/plugin install git://github.com/blaxter/migration_helpers.git
|
67
|
+
|
68
|
+
LICENSE
|
69
|
+
=======
|
70
|
+
|
71
|
+
(The MIT License)
|
72
|
+
|
73
|
+
Copyright (c) 2008 Jesús García Sáez <jgarcia@warp.es>
|
74
|
+
|
75
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
76
|
+
a copy of this software and associated documentation files (the
|
77
|
+
'Software'), to deal in the Software without restriction, including
|
78
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
79
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
80
|
+
permit persons to whom the Software is furnished to do so, subject to
|
81
|
+
the following conditions:
|
82
|
+
|
83
|
+
The above copyright notice and this permission notice shall be
|
84
|
+
included in all copies or substantial portions of the Software.
|
85
|
+
|
86
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
87
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
88
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
89
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
90
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
91
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
92
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MigrationConstraintHelpers
|
2
|
+
|
3
|
+
# Creates a foreign key from +table+.+field+ against referenced_table.referenced_field
|
4
|
+
#
|
5
|
+
# table: The tablename
|
6
|
+
# field: A field of the table
|
7
|
+
# referenced_table: The table which contains the field referenced
|
8
|
+
# referenced_field: The field (which should be part of the primary key) of the referenced table
|
9
|
+
# cascade: delete & update on cascade?
|
10
|
+
def foreign_key(table, field, referenced_table, referenced_field = :id, cascade = true)
|
11
|
+
execute "ALTER TABLE #{table} ADD CONSTRAINT #{constraint_name(table, field)}
|
12
|
+
FOREIGN KEY #{constraint_name(table, field)} (#{field_list(field)})
|
13
|
+
REFERENCES #{referenced_table}(#{field_list(referenced_field)})
|
14
|
+
#{(cascade ? 'ON DELETE CASCADE ON UPDATE CASCADE' : '')}"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Drops a foreign key from +table+.+field+ that has been created before with
|
18
|
+
# foreign_key method
|
19
|
+
#
|
20
|
+
# table: The table name
|
21
|
+
# field: A field (or array of fields) of the table
|
22
|
+
def drop_foreign_key(table, field)
|
23
|
+
execute "ALTER TABLE #{table} DROP FOREIGN KEY #{constraint_name(table, field)}"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates a primary key for +table+, which right now HAS NOT primary key defined
|
27
|
+
#
|
28
|
+
# table: The table name
|
29
|
+
# field: A field (or array of fields) of the table that will be part of the primary key
|
30
|
+
def primary_key(table, field)
|
31
|
+
execute "ALTER TABLE #{table} ADD PRIMARY KEY(#{field_list(field)})"
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Creates a constraint name for table and field given as parameters
|
37
|
+
#
|
38
|
+
# table: The table name
|
39
|
+
# field: A field of the table
|
40
|
+
def constraint_name(table, field)
|
41
|
+
"fk_#{table}_#{field_list_name(field)}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def field_list(fields)
|
45
|
+
fields.is_a?(Array) ? fields.join(',') : fields
|
46
|
+
end
|
47
|
+
|
48
|
+
def field_list_name(fields)
|
49
|
+
fields.is_a?(Array) ? fields.join('_') : fields
|
50
|
+
end
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: molo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Joel Moss
|
14
|
+
- Todd Huss
|
15
|
+
- Michael Grosser
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2010-12-13 00:00:00 +00:00
|
21
|
+
default_executable:
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
24
|
+
name: activerecord
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ~>
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 1
|
32
|
+
segments:
|
33
|
+
- 3
|
34
|
+
- 0
|
35
|
+
- 3
|
36
|
+
version: 3.0.3
|
37
|
+
type: :runtime
|
38
|
+
version_requirements: *id001
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: rake
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 27
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
- 8
|
51
|
+
version: "0.8"
|
52
|
+
type: :runtime
|
53
|
+
version_requirements: *id002
|
54
|
+
description:
|
55
|
+
email: joel@developwithstyle.com
|
56
|
+
executables: []
|
57
|
+
|
58
|
+
extensions: []
|
59
|
+
|
60
|
+
extra_rdoc_files:
|
61
|
+
- README.markdown
|
62
|
+
files:
|
63
|
+
- .gitignore
|
64
|
+
- Gemfile
|
65
|
+
- Gemfile.lock
|
66
|
+
- Molo.gemspec
|
67
|
+
- README.markdown
|
68
|
+
- Rakefile
|
69
|
+
- VERSION
|
70
|
+
- lib/tasks/molo.rb
|
71
|
+
- spec/molo_spec.rb
|
72
|
+
- vendor/migration_helpers/MIT-LICENSE
|
73
|
+
- vendor/migration_helpers/README.markdown
|
74
|
+
- vendor/migration_helpers/init.rb
|
75
|
+
- vendor/migration_helpers/lib/migration_helper.rb
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: http://codaset.com/joelmoss/molo
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options:
|
82
|
+
- --charset=UTF-8
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
hash: 3
|
100
|
+
segments:
|
101
|
+
- 0
|
102
|
+
version: "0"
|
103
|
+
requirements: []
|
104
|
+
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 1.3.7
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: A thin wrapper to use Rails Migrations in non Rails projects
|
110
|
+
test_files:
|
111
|
+
- spec/molo_spec.rb
|