Skip to content

Commit 0e20cb8

Browse files
committed
* Update db:migrate:up & db:migrate:down to act more like active record one
1 parent a94425a commit 0e20cb8

File tree

4 files changed

+223
-5
lines changed

4 files changed

+223
-5
lines changed

lib/sequel_rails/migrations.rb

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
module SequelRails
44
class Migrations
55
class << self
6-
def migrate(version = nil)
7-
opts = {}
6+
def migrate(version = nil, migrator_class = ::Sequel::Migrator, opts = {})
87
opts[:target] = version.to_i if version
98
opts[:allow_missing_migration_files] = !!SequelRails.configuration.allow_missing_migration_files
109

1110
if migrations_dir.directory?
12-
::Sequel::Migrator.run(::Sequel::Model.db, migrations_dir, opts)
11+
migrator_class.run(::Sequel::Model.db, migrations_dir, opts)
1312
else
1413
relative_path_name = migrations_dir.relative_path_from(Rails.root).to_s
1514
raise "The #{relative_path_name} directory doesn't exist, you need to create it."
@@ -18,6 +17,14 @@ def migrate(version = nil)
1817
alias_method :migrate_up!, :migrate
1918
alias_method :migrate_down!, :migrate
2019

20+
def migrate_up_one_version!(version)
21+
migrate(version, SequelRails::OneTimestampVersionMigrator, { direction: :up })
22+
end
23+
24+
def migrate_down_one_version!(version)
25+
migrate(version, SequelRails::OneTimestampVersionMigrator, { direction: :down })
26+
end
27+
2128
def pending_migrations?
2229
return false unless available_migrations?
2330
!::Sequel::Migrator.is_current?(::Sequel::Model.db, migrations_dir)
@@ -78,4 +85,47 @@ def init_migrator
7885
end
7986
end
8087
end
88+
89+
class OneTimestampVersionMigrator < ::Sequel::TimestampMigrator
90+
Error = ::Sequel::Migrator::Error
91+
92+
# The direction of the migrator, either :up or :down
93+
attr_reader :direction
94+
95+
# Set up all state for the migrator instance
96+
def initialize(db, directory, opts = OPTS)
97+
@direction = opts[:direction]
98+
super
99+
100+
raise(Error, 'target (version) is absent') if target.nil?
101+
raise(Error, "Invalid direction: #{direction}") unless [:up, :down].include?(direction)
102+
# `allow_missing_migration_files` ignored, as version is from user input
103+
raise(Error, "Migration with version #{target} not found") if migration_tuples.empty?
104+
end
105+
106+
private
107+
108+
def get_migration_tuples
109+
up_mts = []
110+
down_mts = []
111+
files.each do |path|
112+
f = File.basename(path)
113+
fi = f.downcase
114+
next unless migration_version_from_file(f) == target
115+
116+
case [direction, applied_migrations.include?(fi)]
117+
when [:up, false]
118+
# Normal migrate up
119+
up_mts << [load_migration_file(path), f, :up]
120+
when [:down, true]
121+
# Normal migrate down
122+
down_mts << [load_migration_file(path), f, :down]
123+
else
124+
# Already run, don't re-run
125+
raise(Error, "Migration with version #{target} is already migrated/rollback")
126+
end
127+
end
128+
up_mts + down_mts.reverse
129+
end
130+
end
81131
end

lib/sequel_rails/railties/database.rake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,15 @@ namespace sequel_rails_namespace do
154154
task :up => :load do
155155
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
156156
raise 'VERSION is required' unless version
157-
SequelRails::Migrations.migrate_up!(version)
157+
SequelRails::Migrations.migrate_up_one_version!(version)
158158
Rake::Task["#{sequel_rails_namespace}:dump"].invoke if SequelRails.configuration.schema_dump
159159
end
160160

161161
desc 'Runs the "down" for a given migration VERSION.'
162162
task :down => :load do
163163
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
164164
raise 'VERSION is required' unless version
165-
SequelRails::Migrations.migrate_down!(version)
165+
SequelRails::Migrations.migrate_down_one_version!(version)
166166
Rake::Task["#{sequel_rails_namespace}:dump"].invoke if SequelRails.configuration.schema_dump
167167
end
168168
end

spec/lib/sequel_rails/railties/database_rake_spec.rb

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,172 @@
8181
end
8282
end
8383

84+
describe 'db:migrate:up' do
85+
let(:version) { nil }
86+
around do |example|
87+
env_value_before = ENV['VERSION']
88+
ENV['VERSION'] = version
89+
example.run
90+
ENV['VERSION'] = env_value_before
91+
end
92+
let(:rake_task_call) do
93+
proc { Rake::Task['db:migrate:up'].execute }
94+
end
95+
96+
context 'when no version supplied' do
97+
it 'raises error' do
98+
Dir.chdir app_root do
99+
begin
100+
expect do
101+
rake_task_call.call
102+
end.to raise_error('VERSION is required')
103+
ensure
104+
SequelRails::Migrations.migrate_up!
105+
end
106+
end
107+
end
108+
end
109+
110+
context 'when version with no matching migration supplied' do
111+
let(:version) { '1273253848' }
112+
113+
it 'raises error' do
114+
Dir.chdir app_root do
115+
begin
116+
expect do
117+
rake_task_call.call
118+
end.to raise_error("Migration with version #{version} not found")
119+
ensure
120+
SequelRails::Migrations.migrate_up!
121+
end
122+
end
123+
end
124+
end
125+
126+
context 'when version with matching migration supplied' do
127+
let(:version) { '1273253849' }
128+
129+
context 'and migration already run' do
130+
it 'raises error' do
131+
Dir.chdir app_root do
132+
begin
133+
expect do
134+
rake_task_call.call
135+
end.to raise_error("Migration with version #{version} is already migrated/rollback")
136+
ensure
137+
SequelRails::Migrations.migrate_up!
138+
end
139+
end
140+
end
141+
end
142+
143+
context 'and migration NOT already run' do
144+
before do
145+
Dir.chdir app_root do
146+
SequelRails::Migrations.migrate_down!(0)
147+
end
148+
end
149+
150+
it 'runs the matching migration ONLY' do
151+
Dir.chdir app_root do
152+
begin
153+
expect do
154+
rake_task_call.call
155+
end.to change { SequelRails::Migrations.current_migration }
156+
.from(nil)
157+
.to('1273253849_add_twitter_handle_to_users.rb')
158+
ensure
159+
SequelRails::Migrations.migrate_up!
160+
end
161+
end
162+
end
163+
end
164+
end
165+
end
166+
167+
describe 'db:migrate:down' do
168+
let(:version) { nil }
169+
around do |example|
170+
env_value_before = ENV['VERSION']
171+
ENV['VERSION'] = version
172+
example.run
173+
ENV['VERSION'] = env_value_before
174+
end
175+
let(:rake_task_call) do
176+
proc { Rake::Task['db:migrate:down'].execute }
177+
end
178+
179+
context 'when no version supplied' do
180+
it 'raises error' do
181+
Dir.chdir app_root do
182+
begin
183+
expect do
184+
rake_task_call.call
185+
end.to raise_error('VERSION is required')
186+
ensure
187+
SequelRails::Migrations.migrate_up!
188+
end
189+
end
190+
end
191+
end
192+
193+
context 'when version with no matching migration supplied' do
194+
let(:version) { '1273253848' }
195+
196+
it 'raises error' do
197+
Dir.chdir app_root do
198+
begin
199+
expect do
200+
rake_task_call.call
201+
end.to raise_error("Migration with version #{version} not found")
202+
ensure
203+
SequelRails::Migrations.migrate_up!
204+
end
205+
end
206+
end
207+
end
208+
209+
context 'when version with matching migration supplied' do
210+
let(:version) { '1365762738' }
211+
212+
context 'and migration already run' do
213+
it 'reverts the matching migration ONLY' do
214+
Dir.chdir app_root do
215+
begin
216+
expect do
217+
rake_task_call.call
218+
end.to change { SequelRails::Migrations.previous_migration }
219+
.from('1365762738_add_display_name_to_users.rb')
220+
.to('1273253849_add_twitter_handle_to_users.rb')
221+
ensure
222+
SequelRails::Migrations.migrate_up!
223+
end
224+
end
225+
end
226+
end
227+
228+
context 'and migration NOT already run' do
229+
before do
230+
Dir.chdir app_root do
231+
SequelRails::Migrations.migrate_down!(0)
232+
end
233+
end
234+
235+
it 'raises error' do
236+
Dir.chdir app_root do
237+
begin
238+
expect do
239+
rake_task_call.call
240+
end.to raise_error("Migration with version #{version} is already migrated/rollback")
241+
ensure
242+
SequelRails::Migrations.migrate_up!
243+
end
244+
end
245+
end
246+
end
247+
end
248+
end
249+
84250
describe 'db:rollback' do
85251
let(:version) { nil }
86252
let(:rake_task_call) do

spec/spec_helper.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
# Combustion initialization has to happen before loading rspec/rails
77
Combustion.initialize! :sequel_rails
8+
# Load rake tasks
9+
Combustion::Application.load_tasks
810

911
require 'rspec/rails'
1012
require 'ammeter/init'

0 commit comments

Comments
 (0)