standalone_migrations_new 7.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.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/.travis.yml +29 -0
- data/Gemfile +11 -0
- data/LICENSE +20 -0
- data/README.markdown +273 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/example/.gitignore +5 -0
- data/example/Rakefile +9 -0
- data/example/db/config.yml +15 -0
- data/example/db/migrate/20120930053225_create_table_awesome_migration.rb +7 -0
- data/lib/standalone_migrations_new/callbacks.rb +13 -0
- data/lib/standalone_migrations_new/configurator.rb +103 -0
- data/lib/standalone_migrations_new/generator.rb +22 -0
- data/lib/standalone_migrations_new/minimal_railtie_config.rb +10 -0
- data/lib/standalone_migrations_new/tasks/connection.rake +8 -0
- data/lib/standalone_migrations_new/tasks/db/new_migration.rake +19 -0
- data/lib/standalone_migrations_new/tasks/environment.rake +3 -0
- data/lib/standalone_migrations_new/tasks.rb +34 -0
- data/lib/standalone_migrations_new.rb +20 -0
- data/lib/tasks/standalone_migrations_new.rb +10 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/standalone_migrations_new/callbacks_spec.rb +48 -0
- data/spec/standalone_migrations_new/configurator_spec.rb +261 -0
- data/spec/standalone_migrations_new_spec.rb +371 -0
- data/standalone_migrations-7.1.1.gem +0 -0
- data/standalone_migrations_new-7.1.1.gem +0 -0
- data/standalone_migrations_new.gemspec +73 -0
- data/vendor/migration_helpers/MIT-LICENSE +20 -0
- data/vendor/migration_helpers/README.markdown +92 -0
- data/vendor/migration_helpers/init.rb +4 -0
- data/vendor/migration_helpers/lib/migration_helper.rb +51 -0
- metadata +136 -0
@@ -0,0 +1,371 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe 'Standalone migrations' do
|
3
|
+
|
4
|
+
def write(file, content)
|
5
|
+
raise "cannot write nil" unless file
|
6
|
+
file = tmp_file(file)
|
7
|
+
folder = File.dirname(file)
|
8
|
+
`mkdir -p #{folder}` unless File.exist?(folder)
|
9
|
+
File.open(file, 'w') { |f| f.write content }
|
10
|
+
end
|
11
|
+
|
12
|
+
def read(file)
|
13
|
+
File.read(tmp_file(file))
|
14
|
+
end
|
15
|
+
|
16
|
+
def migration(name)
|
17
|
+
m = `cd spec/tmp/db/migrate && ls`.split("\n").detect { |m| m =~ /#{name}/ }
|
18
|
+
m ? "db/migrate/#{m}" : m
|
19
|
+
end
|
20
|
+
|
21
|
+
def tmp_file(file)
|
22
|
+
"spec/tmp/#{file}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def schema
|
26
|
+
ENV['SCHEMA']
|
27
|
+
end
|
28
|
+
|
29
|
+
def run(cmd)
|
30
|
+
result = `cd spec/tmp && #{cmd} 2>&1`
|
31
|
+
raise result unless $?.success?
|
32
|
+
result
|
33
|
+
end
|
34
|
+
|
35
|
+
def make_migration(name, options={})
|
36
|
+
task_name = options[:task_name] || 'db:new_migration'
|
37
|
+
migration = run("rake #{task_name} name=#{name}").match(%r{db/migrate/\d+.*.rb})[0]
|
38
|
+
content = read(migration)
|
39
|
+
content.sub!(/def down.*?\send/m, "def down;puts 'DOWN-#{name}';end")
|
40
|
+
content.sub!(/def up.*?\send/m, "def up;puts 'UP-#{name}';end")
|
41
|
+
write(migration, content)
|
42
|
+
migration.match(/\d{14}/)[0]
|
43
|
+
end
|
44
|
+
|
45
|
+
def write_rakefile(config=nil)
|
46
|
+
write 'Rakefile', <<-TXT
|
47
|
+
$LOAD_PATH.unshift '#{File.expand_path('lib')}'
|
48
|
+
begin
|
49
|
+
require "standalone_migrations_new"
|
50
|
+
StandaloneMigrationsNew::Tasks.load_tasks
|
51
|
+
rescue LoadError => e
|
52
|
+
puts "gem install standalone_migrations_new to get db:migrate:* tasks! (Error: \#{e})"
|
53
|
+
end
|
54
|
+
TXT
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_multiple_migrations
|
58
|
+
migration_superclass = if Rails::VERSION::MAJOR >= 5
|
59
|
+
"ActiveRecord::Migration[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
60
|
+
else
|
61
|
+
"ActiveRecord::Migration"
|
62
|
+
end
|
63
|
+
|
64
|
+
write_rakefile %{t.migrations = "db/migrations", "db/migrations2"}
|
65
|
+
write "db/migrate/20100509095815_create_tests.rb", <<-TXT
|
66
|
+
class CreateTests < #{migration_superclass}
|
67
|
+
def up
|
68
|
+
puts "UP-CreateTests"
|
69
|
+
end
|
70
|
+
|
71
|
+
def down
|
72
|
+
puts "DOWN-CreateTests"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
TXT
|
76
|
+
write "db/migrate/20100509095816_create_tests2.rb", <<-TXT
|
77
|
+
class CreateTests2 < #{migration_superclass}
|
78
|
+
def up
|
79
|
+
puts "UP-CreateTests2"
|
80
|
+
end
|
81
|
+
|
82
|
+
def down
|
83
|
+
puts "DOWN-CreateTests2"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
TXT
|
87
|
+
end
|
88
|
+
|
89
|
+
before do
|
90
|
+
StandaloneMigrationsNew::Configurator.instance_variable_set(:@env_config, nil)
|
91
|
+
`rm -rf spec/tmp` if File.exist?('spec/tmp')
|
92
|
+
`mkdir spec/tmp`
|
93
|
+
write_rakefile
|
94
|
+
write(schema, '')
|
95
|
+
write 'db/config.yml', <<-TXT
|
96
|
+
development:
|
97
|
+
adapter: sqlite3
|
98
|
+
database: db/development.sql
|
99
|
+
test:
|
100
|
+
adapter: sqlite3
|
101
|
+
database: db/test.sql
|
102
|
+
production:
|
103
|
+
adapter: sqlite3
|
104
|
+
database: db/production.sql
|
105
|
+
TXT
|
106
|
+
end
|
107
|
+
|
108
|
+
after(:all) do
|
109
|
+
`rm -rf spec/tmp` if File.exist?('spec/tmp')
|
110
|
+
end
|
111
|
+
|
112
|
+
it "warns of deprecated folder structure" do
|
113
|
+
warning = /DEPRECATED.* db\/migrate/
|
114
|
+
expect(run("rake db:create")).not_to match(warning)
|
115
|
+
write('db/migrations/fooo.rb', 'xxx')
|
116
|
+
expect(run("rake db:create --trace")).to match(warning)
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'db:create and drop' do
|
120
|
+
it "should create the database and drop the database that was created" do
|
121
|
+
run "rake db:create"
|
122
|
+
run "rake db:drop"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe 'callbacks' do
|
127
|
+
it 'runs the callbacks' do
|
128
|
+
expect(StandaloneMigrationsNew::Tasks).to receive(:configure).and_call_original
|
129
|
+
|
130
|
+
connection_established = false
|
131
|
+
expect(ActiveRecord::Base).to receive(:establish_connection) do
|
132
|
+
connection_established = true
|
133
|
+
end
|
134
|
+
expect(StandaloneMigrationsNew).to receive(:run_on_load_callbacks) do
|
135
|
+
expect(connection_established).to be true
|
136
|
+
end
|
137
|
+
|
138
|
+
Dir.chdir(File.join(File.dirname(__FILE__), "tmp")) do
|
139
|
+
load "Rakefile"
|
140
|
+
Rake::Task['standalone:connection'].invoke
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe 'db:new_migration' do
|
146
|
+
it "fails if i do not add a name" do
|
147
|
+
expect(lambda{ run("rake db:new_migration") }).to raise_error(/name=/)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "generates a new migration with this name from ENV and timestamp" do
|
151
|
+
expect(run("rake db:new_migration name=test_abc_env")).to match(%r{create(.*)db/migrate/\d+_test_abc_env\.rb})
|
152
|
+
expect(run("ls db/migrate")).to match(/^\d+_test_abc_env.rb$/)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "generates a new migration with this name from args and timestamp" do
|
156
|
+
expect(run("rake db:new_migration[test_abc_args]")).to match(%r{create(.*)db/migrate/\d+_test_abc_args\.rb})
|
157
|
+
expect(run("ls db/migrate")).to match(/^\d+_test_abc_args.rb$/)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "generates a new migration with the name converted to the Rails migration format" do
|
161
|
+
expect(run("rake db:new_migration name=MyNiceModel")).to match(%r{create(.*)db/migrate/\d+_my_nice_model\.rb})
|
162
|
+
expect(read(migration('my_nice_model'))).to match(/class MyNiceModel/)
|
163
|
+
expect(run("ls db/migrate")).to match(/^\d+_my_nice_model.rb$/)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "generates a new migration with name and options from ENV" do
|
167
|
+
run("rake db:new_migration name=add_name_and_email_to_users options='name:string email:string'")
|
168
|
+
expect(read(migration('add_name_and_email_to_users'))).to match(/add_column :users, :name, :string\n\s*add_column :users, :email, :string/)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "generates a new migration with name and options from args" do
|
172
|
+
run("rake db:new_migration[add_website_and_username_to_users,website:string/username:string]")
|
173
|
+
expect(read(migration('add_website_and_username_to_users'))).to match(/add_column :users, :website, :string\n\s*add_column :users, :username, :string/)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe 'db:version' do
|
178
|
+
it "should start with a new database version" do
|
179
|
+
expect(run("rake db:version")).to match(/Current version: 0/)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should display the current version" do
|
183
|
+
run("rake db:new_migration name=test_abc")
|
184
|
+
run("rake --trace db:migrate")
|
185
|
+
expect(run("rake db:version")).to match(/Current version: #{Time.now.year}/)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe 'db:migrate' do
|
190
|
+
it "does nothing when no migrations are present" do
|
191
|
+
expect(run("rake db:migrate")).not_to match(/Migrating/)
|
192
|
+
end
|
193
|
+
|
194
|
+
it "migrates if i add a migration" do
|
195
|
+
run("rake db:new_migration name=xxx")
|
196
|
+
expect(run("rake db:migrate")).to match(/Xxx: Migrating/i)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe 'db:migrate:down' do
|
201
|
+
it "migrates down" do
|
202
|
+
make_migration('xxx')
|
203
|
+
sleep 1
|
204
|
+
version = make_migration('yyy')
|
205
|
+
run 'rake db:migrate'
|
206
|
+
|
207
|
+
result = run("rake db:migrate:down VERSION=#{version}")
|
208
|
+
expect(result).not_to match(/Xxx: reverting/)
|
209
|
+
expect(result).to match(/Yyy: reverting/)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "fails without version" do
|
213
|
+
make_migration('yyy')
|
214
|
+
# Rails has a bug where it's sending a bad failure exception
|
215
|
+
# https://github.com/rails/rails/issues/28905
|
216
|
+
expect(lambda{ run("rake db:migrate:down") }).to raise_error(/VERSION|version/)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe 'db:migrate:up' do
|
221
|
+
it "migrates up" do
|
222
|
+
make_migration('xxx')
|
223
|
+
run 'rake db:migrate'
|
224
|
+
sleep 1
|
225
|
+
version = make_migration('yyy')
|
226
|
+
result = run("rake db:migrate:up VERSION=#{version}")
|
227
|
+
expect(result).not_to match(/Xxx: migrating/)
|
228
|
+
expect(result).to match(/Yyy: migrating/)
|
229
|
+
end
|
230
|
+
|
231
|
+
it "fails without version" do
|
232
|
+
make_migration('yyy')
|
233
|
+
# Rails has a bug where it's sending a bad failure exception
|
234
|
+
# https://github.com/rails/rails/issues/28905
|
235
|
+
expect(lambda{ run("rake db:migrate:up") }).to raise_error(/VERSION|version/)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe 'db:rollback' do
|
240
|
+
it "does nothing when no migrations have been run" do
|
241
|
+
expect(run("rake db:version")).to match(/version: 0/)
|
242
|
+
expect(run("rake db:rollback")).to eq('')
|
243
|
+
expect(run("rake db:version")).to match(/version: 0/)
|
244
|
+
end
|
245
|
+
|
246
|
+
it "rolls back the last migration if one has been applied" do
|
247
|
+
write_multiple_migrations
|
248
|
+
run("rake db:migrate")
|
249
|
+
expect(run("rake db:version")).to match(/version: 20100509095816/)
|
250
|
+
expect(run("rake db:rollback")).to match(/revert/)
|
251
|
+
expect(run("rake db:version")).to match(/version: 20100509095815/)
|
252
|
+
end
|
253
|
+
|
254
|
+
it "rolls back multiple migrations if the STEP argument is given" do
|
255
|
+
write_multiple_migrations
|
256
|
+
run("rake db:migrate")
|
257
|
+
expect(run("rake db:version")).to match(/version: 20100509095816/)
|
258
|
+
run("rake db:rollback STEP=2") =~ /revert/
|
259
|
+
expect(run("rake db:version")).to match(/version: 0/)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe 'schema:dump' do
|
264
|
+
it "dumps the schema" do
|
265
|
+
write(schema, '')
|
266
|
+
run('rake db:schema:dump')
|
267
|
+
expect(read(schema)).to match(/ActiveRecord/)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe 'db:schema:load' do
|
272
|
+
it "loads the schema" do
|
273
|
+
run('rake db:schema:dump')
|
274
|
+
write(schema, read(schema)+"\nputs 'LOADEDDD'")
|
275
|
+
result = run('rake db:schema:load')
|
276
|
+
expect(result).to match(/LOADEDDD/)
|
277
|
+
end
|
278
|
+
|
279
|
+
it "loads all migrations" do
|
280
|
+
make_migration('yyy')
|
281
|
+
run "rake db:migrate"
|
282
|
+
run "rake db:drop"
|
283
|
+
run "rake db:create"
|
284
|
+
run "rake db:schema:load"
|
285
|
+
expect(run( "rake db:migrate").strip).to eq('')
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe 'db:abort_if_pending_migrations' do
|
290
|
+
it "passes when no migrations are pending" do
|
291
|
+
expect(run("rake db:abort_if_pending_migrations").strip).to eq('')
|
292
|
+
end
|
293
|
+
|
294
|
+
it "fails when migrations are pending" do
|
295
|
+
make_migration('yyy')
|
296
|
+
expect(lambda{ run("rake db:abort_if_pending_migrations") }).to raise_error(/1 pending migration/)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
describe 'db:test:load' do
|
301
|
+
it 'loads' do
|
302
|
+
write(schema, "puts 'LOADEDDD'")
|
303
|
+
expect(run("rake db:test:load")).to match(/LOADEDDD/)
|
304
|
+
end
|
305
|
+
|
306
|
+
it "fails without schema" do
|
307
|
+
schema_path = "spec/tmp/#{schema}"
|
308
|
+
`rm -rf #{schema_path}` if File.exist?(schema_path)
|
309
|
+
expect(lambda{ run("rake db:test:load") }).to raise_error(/try again/)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe 'db:test:purge' do
|
314
|
+
it "runs" do
|
315
|
+
run('rake db:test:purge')
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
describe "db:seed" do
|
320
|
+
it "loads" do
|
321
|
+
write("db/seeds.rb", "puts 'LOADEDDD'")
|
322
|
+
expect(run("rake db:seed")).to match(/LOADEDDD/)
|
323
|
+
end
|
324
|
+
|
325
|
+
describe 'with non-default seed file' do
|
326
|
+
let(:yaml_hash) do
|
327
|
+
{
|
328
|
+
"db" => {
|
329
|
+
"seeds" => "db/seeds2.rb",
|
330
|
+
}
|
331
|
+
}
|
332
|
+
end
|
333
|
+
|
334
|
+
before do
|
335
|
+
write(".standalone_migrations_new", yaml_hash.to_yaml)
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
it "loads" do
|
340
|
+
write("db/seeds2.rb", "puts 'LOADEDDD'")
|
341
|
+
expect(run("rake db:seed")).to match(/LOADEDDD/)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
|
346
|
+
it "does nothing without seeds" do
|
347
|
+
expect(run("rake db:seed").length).to eq(0)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe "db:reset" do
|
352
|
+
it "should not error when a seeds file does not exist" do
|
353
|
+
make_migration('yyy')
|
354
|
+
run('rake db:migrate DB=test')
|
355
|
+
expect(lambda{ run("rake db:reset") }).not_to raise_error
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
describe 'db:migrate when environment is specified' do
|
360
|
+
it "runs when using the DB environment variable", :travis_error => true do
|
361
|
+
make_migration('yyy')
|
362
|
+
run('rake db:migrate RAILS_ENV=test')
|
363
|
+
expect(run('rake db:version RAILS_ENV=test')).not_to match(/version: 0/)
|
364
|
+
expect(run('rake db:version')).to match(/version: 0/)
|
365
|
+
end
|
366
|
+
|
367
|
+
it "should error on an invalid database", :travis_error => true do
|
368
|
+
expect(lambda{ run("rake db:create RAILS_ENV=nonexistent")}).to raise_error(/rake aborted/)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: standalone_migrations_new 7.1.0 ruby lib
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "standalone_migrations_new".freeze
|
9
|
+
s.version = "7.1.0"
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib".freeze]
|
13
|
+
s.authors = ["Serhii Hiba".freeze]
|
14
|
+
s.date = "2022-05-02"
|
15
|
+
s.email = "enotikalt@gmail.com".freeze
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE",
|
18
|
+
"README.markdown"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".rspec",
|
22
|
+
".travis.yml",
|
23
|
+
"Gemfile",
|
24
|
+
"LICENSE",
|
25
|
+
"README.markdown",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"example/.gitignore",
|
29
|
+
"example/Rakefile",
|
30
|
+
"example/db/config.yml",
|
31
|
+
"example/db/migrate/20120930053225_create_table_awesome_migration.rb",
|
32
|
+
"lib/standalone_migrations_new.rb",
|
33
|
+
"lib/standalone_migrations_new/callbacks.rb",
|
34
|
+
"lib/standalone_migrations_new/configurator.rb",
|
35
|
+
"lib/standalone_migrations_new/generator.rb",
|
36
|
+
"lib/standalone_migrations_new/minimal_railtie_config.rb",
|
37
|
+
"lib/standalone_migrations_new/tasks.rb",
|
38
|
+
"lib/standalone_migrations_new/tasks/connection.rake",
|
39
|
+
"lib/standalone_migrations_new/tasks/db/new_migration.rake",
|
40
|
+
"lib/standalone_migrations_new/tasks/environment.rake",
|
41
|
+
"lib/tasks/standalone_migrations_new.rb",
|
42
|
+
"spec/spec_helper.rb",
|
43
|
+
"spec/standalone_migrations_new/callbacks_spec.rb",
|
44
|
+
"spec/standalone_migrations_new/configurator_spec.rb",
|
45
|
+
"spec/standalone_migrations_new_spec.rb",
|
46
|
+
"standalone_migrations-7.1.1.gem",
|
47
|
+
"standalone_migrations_new-7.1.1.gem",
|
48
|
+
"standalone_migrations_new.gemspec",
|
49
|
+
"vendor/migration_helpers/MIT-LICENSE",
|
50
|
+
"vendor/migration_helpers/README.markdown",
|
51
|
+
"vendor/migration_helpers/init.rb",
|
52
|
+
"vendor/migration_helpers/lib/migration_helper.rb"
|
53
|
+
]
|
54
|
+
s.homepage = "https://github.com/enotikalt/standalone-migrations".freeze
|
55
|
+
s.licenses = ["MIT".freeze]
|
56
|
+
s.rubygems_version = "3.3.7".freeze
|
57
|
+
s.summary = "A thin wrapper to use Rails Migrations in non Rails projects".freeze
|
58
|
+
|
59
|
+
if s.respond_to? :specification_version then
|
60
|
+
s.specification_version = 4
|
61
|
+
end
|
62
|
+
|
63
|
+
if s.respond_to? :add_runtime_dependency then
|
64
|
+
s.add_runtime_dependency(%q<rake>.freeze, ["~> 13.0", ">= 13.0.6"])
|
65
|
+
s.add_runtime_dependency(%q<activerecord>.freeze, ["~> 7.0", ">= 7.0.2.4"])
|
66
|
+
s.add_runtime_dependency(%q<railties>.freeze, ["~> 7.0", ">= 7.0.2.4"])
|
67
|
+
else
|
68
|
+
s.add_dependency(%q<rake>.freeze, ["~> 13.0", ">= 13.0.6"])
|
69
|
+
s.add_dependency(%q<activerecord>.freeze, ["~> 7.0", ">= 7.0.2.4"])
|
70
|
+
s.add_dependency(%q<railties>.freeze, ["~> 7.0", ">= 7.0.2.4"])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
@@ -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
|