sbf-dm-migrations 1.3.0.beta
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/.gitignore +38 -0
- data/.rspec +1 -0
- data/.rubocop.yml +468 -0
- data/.travis.yml +52 -0
- data/Gemfile +61 -0
- data/LICENSE +20 -0
- data/README.rdoc +39 -0
- data/Rakefile +4 -0
- data/db/migrations/1_create_people_table.rb +12 -0
- data/db/migrations/2_add_dob_to_people.rb +13 -0
- data/db/migrations/config.rb +4 -0
- data/dm-migrations.gemspec +20 -0
- data/examples/Rakefile +149 -0
- data/examples/sample_migration.rb +58 -0
- data/examples/sample_migration_spec.rb +46 -0
- data/lib/dm-migrations/adapters/dm-do-adapter.rb +304 -0
- data/lib/dm-migrations/adapters/dm-mysql-adapter.rb +306 -0
- data/lib/dm-migrations/adapters/dm-oracle-adapter.rb +339 -0
- data/lib/dm-migrations/adapters/dm-postgres-adapter.rb +152 -0
- data/lib/dm-migrations/adapters/dm-sqlite-adapter.rb +88 -0
- data/lib/dm-migrations/adapters/dm-sqlserver-adapter.rb +184 -0
- data/lib/dm-migrations/adapters/dm-yaml-adapter.rb +21 -0
- data/lib/dm-migrations/auto_migration.rb +227 -0
- data/lib/dm-migrations/exceptions/duplicate_migration.rb +6 -0
- data/lib/dm-migrations/migration.rb +323 -0
- data/lib/dm-migrations/migration_runner.rb +76 -0
- data/lib/dm-migrations/sql/column.rb +5 -0
- data/lib/dm-migrations/sql/mysql.rb +84 -0
- data/lib/dm-migrations/sql/oracle.rb +9 -0
- data/lib/dm-migrations/sql/postgres.rb +89 -0
- data/lib/dm-migrations/sql/sqlite.rb +59 -0
- data/lib/dm-migrations/sql/sqlserver.rb +9 -0
- data/lib/dm-migrations/sql/table.rb +15 -0
- data/lib/dm-migrations/sql/table_creator.rb +105 -0
- data/lib/dm-migrations/sql/table_modifier.rb +57 -0
- data/lib/dm-migrations/sql.rb +7 -0
- data/lib/dm-migrations/version.rb +5 -0
- data/lib/dm-migrations.rb +3 -0
- data/lib/spec/example/migration_example_group.rb +69 -0
- data/lib/spec/matchers/migration_matchers.rb +96 -0
- data/spec/integration/auto_migration_spec.rb +590 -0
- data/spec/integration/auto_upgrade_spec.rb +41 -0
- data/spec/integration/migration_runner_spec.rb +84 -0
- data/spec/integration/migration_spec.rb +156 -0
- data/spec/integration/sql_spec.rb +290 -0
- data/spec/isolated/require_after_setup_spec.rb +24 -0
- data/spec/isolated/require_before_setup_spec.rb +24 -0
- data/spec/isolated/require_spec.rb +23 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/unit/migration_spec.rb +501 -0
- data/spec/unit/sql/column_spec.rb +14 -0
- data/spec/unit/sql/postgres_spec.rb +90 -0
- data/spec/unit/sql/sqlite_extensions_spec.rb +103 -0
- data/spec/unit/sql/table_creator_spec.rb +91 -0
- data/spec/unit/sql/table_modifier_spec.rb +47 -0
- data/spec/unit/sql/table_spec.rb +26 -0
- data/spec/unit/sql_spec.rb +7 -0
- data/tasks/spec.rake +21 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +120 -0
@@ -0,0 +1,501 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe 'Migration' do
|
4
|
+
|
5
|
+
describe 'repository_execute' do
|
6
|
+
before(:each) do
|
7
|
+
class DefaultKlass
|
8
|
+
include DataMapper::Resource
|
9
|
+
property :required_property, String, key: true
|
10
|
+
end
|
11
|
+
|
12
|
+
class ContextKlass
|
13
|
+
include DataMapper::Resource
|
14
|
+
property :required_property, String, key: true
|
15
|
+
def self.repository_name
|
16
|
+
:not_default_repository
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'sends the method to all models by default' do
|
22
|
+
DataMapper.finalize
|
23
|
+
expect(DefaultKlass).to receive(:auto_migrate!).with(:default)
|
24
|
+
expect(ContextKlass).to receive(:auto_migrate!).with(:not_default_repository)
|
25
|
+
DataMapper.auto_migrate!
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'sends the method to only repository models if a repository_name is given' do
|
29
|
+
DataMapper.finalize
|
30
|
+
expect(DefaultKlass).not_to receive(:auto_migrate!)
|
31
|
+
expect(ContextKlass).to receive(:auto_migrate!).with(:not_default_repository)
|
32
|
+
DataMapper.auto_migrate!(:not_default_repository)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
supported_by :postgres, :mysql, :sqlite do
|
37
|
+
before do
|
38
|
+
@adapter = double('adapter', :class => DataMapper::Spec.adapter.class)
|
39
|
+
@repo = double('DataMapper.repository', :adapter => @adapter)
|
40
|
+
DataMapper.stub!(:repository).and_return(@repo)
|
41
|
+
@m = DataMapper::Migration.new(1, :do_nothing, {}) {}
|
42
|
+
@m.stub!(:write) # silence any output
|
43
|
+
end
|
44
|
+
|
45
|
+
[:position, :name, :database, :adapter].each do |meth|
|
46
|
+
it "responds to ##{meth}" do
|
47
|
+
expect(@m).to respond_to(meth)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'initialization' do
|
52
|
+
it 'sets @position from the given position' do
|
53
|
+
expect(@m.instance_variable_get(:@position)).to eq 1
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'sets @name from the given name' do
|
57
|
+
expect(@m.instance_variable_get(:@name)).to eq :do_nothing
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'sets @options from the options hash' do
|
61
|
+
expect(@m.instance_variable_get(:@options)).to eq({})
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'sets @repository from the default repository if no :repository option is given' do
|
65
|
+
m = DataMapper::Migration.new(1, :do_nothing, {}) {}
|
66
|
+
|
67
|
+
expect(m.instance_variable_get(:@repository)).to eq :default
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'sets @repository to the specified :repository option' do
|
71
|
+
m = DataMapper::Migration.new(1, :do_nothing, :repository => :foobar) {}
|
72
|
+
|
73
|
+
expect(m.instance_variable_get(:@repository)).to eq :foobar
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'sets @verbose from the options hash' do
|
77
|
+
m = DataMapper::Migration.new(1, :do_nothing, :verbose => false) {}
|
78
|
+
expect(m.instance_variable_get(:@verbose)).to be(false)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'sets @verbose to true by default' do
|
82
|
+
expect(@m.instance_variable_get(:@verbose)).to be(true)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'sets the @up_action to nil' do
|
86
|
+
expect(@m.instance_variable_get(:@up_action)).to be_nil
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'sets the @down_action to nil' do
|
90
|
+
expect(@m.instance_variable_get(:@down_action)).to be_nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'evaluates the given block'
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'sets the @up_action when #up is called with a block' do
|
98
|
+
action = lambda {}
|
99
|
+
@m.up(&action)
|
100
|
+
expect(@m.instance_variable_get(:@up_action)).to eq action
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'sets the @up_action when #up is called with a block' do
|
104
|
+
action = lambda {}
|
105
|
+
@m.down(&action)
|
106
|
+
expect(@m.instance_variable_get(:@down_action)).to eq action
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'adapter' do
|
110
|
+
before(:each) do
|
111
|
+
@m.instance_variable_set(:@adapter, nil)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'determines the class of the adapter to be extended' do
|
115
|
+
expect(@adapter).to receive(:class).and_return(DataMapper::Spec.adapter.class)
|
116
|
+
|
117
|
+
@m.adapter
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'extends the adapter with the right module' do
|
121
|
+
expect(@adapter).to receive(:extend).with(SQL.const_get(DataMapper::Spec.adapter_name.capitalize))
|
122
|
+
|
123
|
+
@m.adapter
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'raises "Unsupported adapter" on an unknown adapter' do
|
127
|
+
expect(@adapter).to receive(:class).any_number_of_times.and_return("InvalidAdapter")
|
128
|
+
|
129
|
+
expect { @m.adapter }.to raise_error
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe 'perform_up' do
|
134
|
+
before do
|
135
|
+
@up_action = mock('proc', :call => true)
|
136
|
+
@m.instance_variable_set(:@up_action, @up_action)
|
137
|
+
@m.stub!(:needs_up?).and_return(true)
|
138
|
+
@m.stub!(:update_migration_info)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'calls the action assigned to @up_action and return the result' do
|
142
|
+
expect(@up_action).to receive(:call).and_return(:result)
|
143
|
+
expect(@m.perform_up).to eq :result
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'outputs a status message with the position and name of the migration' do
|
147
|
+
expect(@m).to receive(:write).with(/Performing Up Migration #1: do_nothing/)
|
148
|
+
@m.perform_up
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'does not run if it doesnt need to be' do
|
152
|
+
expect(@m).to receive(:needs_up?).and_return(false)
|
153
|
+
expect(@up_action).not_to receive(:call)
|
154
|
+
@m.perform_up
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'updates the migration info table' do
|
158
|
+
expect(@m).to receive(:update_migration_info).with(:up)
|
159
|
+
@m.perform_up
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'does not update the migration info table if the migration does not need run' do
|
163
|
+
expect(@m).to receive(:needs_up?).and_return(false)
|
164
|
+
expect(@m).not_to receive(:update_migration_info)
|
165
|
+
@m.perform_up
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
describe 'perform_down' do
|
171
|
+
before do
|
172
|
+
@down_action = mock('proc', :call => true)
|
173
|
+
@m.instance_variable_set(:@down_action, @down_action)
|
174
|
+
@m.stub!(:needs_down?).and_return(true)
|
175
|
+
@m.stub!(:update_migration_info)
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'calls the action assigned to @down_action and return the result' do
|
179
|
+
expect(@down_action).to receive(:call).and_return(:result)
|
180
|
+
expect(@m.perform_down).to eq :result
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'outputs a status message with the position and name of the migration' do
|
184
|
+
expect(@m).to receive(:write).with(/Performing Down Migration #1: do_nothing/)
|
185
|
+
@m.perform_down
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'does not run if it doesnt need to be' do
|
189
|
+
expect(@m).to receive(:needs_down?).and_return(false)
|
190
|
+
expect(@down_action).not_to receive(:call)
|
191
|
+
@m.perform_down
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'updates the migration info table' do
|
195
|
+
expect(@m).to receive(:update_migration_info).with(:down)
|
196
|
+
@m.perform_down
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'does not update the migration info table if the migration does not need run' do
|
200
|
+
expect(@m).to receive(:needs_down?).and_return(false)
|
201
|
+
expect(@m).not_to receive(:update_migration_info)
|
202
|
+
@m.perform_down
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
describe 'methods used in the action blocks' do
|
208
|
+
|
209
|
+
describe '#execute' do
|
210
|
+
before do
|
211
|
+
@adapter.stub!(:execute)
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'sends the SQL it its executing to the adapter execute method' do
|
215
|
+
expect(@adapter).to receive(:execute).with('SELECT SOME SQL')
|
216
|
+
@m.execute('SELECT SOME SQL')
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'outputs the SQL it is executing' do
|
220
|
+
expect(@m).to receive(:write).with(/SELECT SOME SQL/)
|
221
|
+
@m.execute('SELECT SOME SQL')
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe '#execute' do
|
226
|
+
before do
|
227
|
+
@adapter.stub!(:select)
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'sends the SQL it its executing to the adapter execute method' do
|
231
|
+
expect(@adapter).to receive(:select).with('SELECT SOME SQL')
|
232
|
+
@m.select('SELECT SOME SQL')
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'outputs the SQL it is executing' do
|
236
|
+
expect(@m).to receive(:write).with(/SELECT SOME SQL/)
|
237
|
+
@m.select('SELECT SOME SQL')
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe 'helpers' do
|
242
|
+
before do
|
243
|
+
@m.stub!(:execute) # don't actually run anything
|
244
|
+
end
|
245
|
+
|
246
|
+
describe '#create_table' do
|
247
|
+
before do
|
248
|
+
@tc = mock('TableCreator', :to_sql => 'CREATE TABLE')
|
249
|
+
SQL::TableCreator.stub!(:new).and_return(@tc)
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'creates a new TableCreator object' do
|
253
|
+
expect(SQL::TableCreator).to receive(:new).with(@adapter, :users, {}).and_return(@tc)
|
254
|
+
@m.create_table(:users) { }
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'converts the TableCreator object to an sql statement' do
|
258
|
+
expect(@tc).to receive(:to_sql).and_return('CREATE TABLE')
|
259
|
+
@m.create_table(:users) { }
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'executes the create table sql' do
|
263
|
+
expect(@m).to receive(:execute).with('CREATE TABLE')
|
264
|
+
@m.create_table(:users) { }
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
describe '#drop_table' do
|
270
|
+
it 'quotes the table name' do
|
271
|
+
expect(@adapter).to receive(:quote_name).with('users')
|
272
|
+
@m.drop_table :users
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'executes the DROP TABLE sql for the table' do
|
276
|
+
@adapter.stub!(:quote_name).and_return("'users'")
|
277
|
+
expect(@m).to receive(:execute).with(%{DROP TABLE 'users'})
|
278
|
+
@m.drop_table :users
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
282
|
+
|
283
|
+
describe '#modify_table' do
|
284
|
+
before do
|
285
|
+
@tm = mock('TableModifier', :statements => [])
|
286
|
+
SQL::TableModifier.stub!(:new).and_return(@tm)
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'creates a new TableModifier object' do
|
290
|
+
expect(SQL::TableModifier).to receive(:new).with(@adapter, :users, {}).and_return(@tm)
|
291
|
+
@m.modify_table(:users){ }
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'gets the statements from the TableModifier object' do
|
295
|
+
expect(@tm).to receive(:statements).and_return([])
|
296
|
+
@m.modify_table(:users){ }
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'iterates over the statements and execute each one' do
|
300
|
+
expect(@tm).to receive(:statements).and_return(['SELECT 1', 'SELECT 2'])
|
301
|
+
expect(@m).to receive(:execute).with('SELECT 1')
|
302
|
+
expect(@m).to receive(:execute).with('SELECT 2')
|
303
|
+
@m.modify_table(:users){ }
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
describe 'sorting' do
|
309
|
+
it 'orders things by position' do
|
310
|
+
m1 = DataMapper::Migration.new(1, :do_nothing){}
|
311
|
+
m2 = DataMapper::Migration.new(2, :do_nothing_else){}
|
312
|
+
|
313
|
+
expect(m1 <=> m2).to eq -1
|
314
|
+
end
|
315
|
+
|
316
|
+
it 'orders things by name when they have the same position' do
|
317
|
+
m1 = DataMapper::Migration.new(1, :do_nothing_a){}
|
318
|
+
m2 = DataMapper::Migration.new(1, :do_nothing_b){}
|
319
|
+
|
320
|
+
expect(m1 <=> m2).to eq -1
|
321
|
+
end
|
322
|
+
|
323
|
+
end
|
324
|
+
|
325
|
+
describe 'formatting output' do
|
326
|
+
describe '#say' do
|
327
|
+
it 'outputs the message' do
|
328
|
+
expect(@m).to receive(:write).with(/Paul/)
|
329
|
+
@m.say("Paul")
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'indents the message with 4 spaces by default' do
|
333
|
+
expect(@m).to receive(:write).with(/^\s{4}/)
|
334
|
+
@m.say("Paul")
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'indents the message with a given number of spaces' do
|
338
|
+
expect(@m).to receive(:write).with(/^\s{3}/)
|
339
|
+
@m.say("Paul", 3)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
describe '#say_with_time' do
|
344
|
+
before do
|
345
|
+
@m.stub!(:say)
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'says the message with an indent of 2' do
|
349
|
+
expect(@m).to receive(:say).with("Paul", 2)
|
350
|
+
@m.say_with_time("Paul"){}
|
351
|
+
end
|
352
|
+
|
353
|
+
it 'outputs the time it took' do
|
354
|
+
expect(@m).to receive(:say).with(/\d+/, 2)
|
355
|
+
@m.say_with_time("Paul"){}
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
describe '#write' do
|
360
|
+
before do
|
361
|
+
# need a new migration object, because the main one had #write stubbed to silence output
|
362
|
+
@m = DataMapper::Migration.new(1, :do_nothing) {}
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'puts the message' do
|
366
|
+
expect(@m).to receive(:puts).with("Paul")
|
367
|
+
@m.write("Paul")
|
368
|
+
end
|
369
|
+
|
370
|
+
it 'does not puts the message if @verbose is false' do
|
371
|
+
@m.instance_variable_set(:@verbose, false)
|
372
|
+
expect(@m).not_to receive(:puts)
|
373
|
+
@m.write("Paul")
|
374
|
+
end
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
describe 'working with the migration_info table' do
|
381
|
+
before do
|
382
|
+
@adapter.stub!(:storage_exists?).and_return(true)
|
383
|
+
# --- Please remove stubs ---
|
384
|
+
@adapter.stub!(:quote_name).and_return { |name| "'#{name}'" }
|
385
|
+
end
|
386
|
+
|
387
|
+
describe '#update_migration_info' do
|
388
|
+
it 'adds a record of the migration' do
|
389
|
+
expect(@m).to receive(:execute).with(
|
390
|
+
%Q{INSERT INTO 'migration_info' ('migration_name') VALUES ('do_nothing')}
|
391
|
+
)
|
392
|
+
@m.update_migration_info(:up)
|
393
|
+
end
|
394
|
+
|
395
|
+
it 'removes the record of the migration' do
|
396
|
+
expect(@m).to receive(:execute).with(
|
397
|
+
%Q{DELETE FROM 'migration_info' WHERE 'migration_name' = 'do_nothing'}
|
398
|
+
)
|
399
|
+
@m.update_migration_info(:down)
|
400
|
+
end
|
401
|
+
|
402
|
+
it 'tries to create the migration_info table' do
|
403
|
+
expect(@m).to receive(:create_migration_info_table_if_needed)
|
404
|
+
@m.update_migration_info(:up)
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
describe '#create_migration_info_table_if_needed' do
|
409
|
+
it 'creates the migration info table' do
|
410
|
+
expect(@m).to receive(:migration_info_table_exists?).and_return(false)
|
411
|
+
expect(@m).to receive(:execute).with(
|
412
|
+
%Q{CREATE TABLE 'migration_info' ('migration_name' VARCHAR(255) UNIQUE)}
|
413
|
+
)
|
414
|
+
@m.create_migration_info_table_if_needed
|
415
|
+
end
|
416
|
+
|
417
|
+
it 'does not try to create the migration info table if it already exists' do
|
418
|
+
expect(@m).to receive(:migration_info_table_exists?).and_return(true)
|
419
|
+
expect(@m).not_to receive(:execute)
|
420
|
+
@m.create_migration_info_table_if_needed
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'quotes the name of the migration for use in sql' do
|
425
|
+
expect(@m.quoted_name).to eq %{'do_nothing'}
|
426
|
+
end
|
427
|
+
|
428
|
+
it 'queries the adapter to see if the migration_info table exists' do
|
429
|
+
expect(@adapter).to receive(:storage_exists?).with('migration_info').and_return(true)
|
430
|
+
expect(@m.migration_info_table_exists?).to eq true
|
431
|
+
end
|
432
|
+
|
433
|
+
describe '#migration_record' do
|
434
|
+
it 'queries for the migration' do
|
435
|
+
expect(@adapter).to receive(:select).with(
|
436
|
+
%Q{SELECT 'migration_name' FROM 'migration_info' WHERE 'migration_name' = 'do_nothing'}
|
437
|
+
)
|
438
|
+
@m.migration_record
|
439
|
+
end
|
440
|
+
|
441
|
+
it 'does not try to query if the table does not exist' do
|
442
|
+
@m.stub!(:migration_info_table_exists?).and_return(false)
|
443
|
+
expect(@adapter).not_to receive(:select)
|
444
|
+
@m.migration_record
|
445
|
+
end
|
446
|
+
|
447
|
+
end
|
448
|
+
|
449
|
+
describe '#needs_up?' do
|
450
|
+
it 'is true if there is no record' do
|
451
|
+
expect(@m).to receive(:migration_record).and_return([])
|
452
|
+
expect(@m.needs_up?).to eq true
|
453
|
+
end
|
454
|
+
|
455
|
+
it 'is false if the record exists' do
|
456
|
+
expect(@m).to receive(:migration_record).and_return([:not_empty])
|
457
|
+
expect(@m.needs_up?).to eq false
|
458
|
+
end
|
459
|
+
|
460
|
+
it 'is true if there is no migration_info table' do
|
461
|
+
expect(@m).to receive(:migration_info_table_exists?).and_return(false)
|
462
|
+
expect(@m.needs_up?).to eq true
|
463
|
+
end
|
464
|
+
|
465
|
+
end
|
466
|
+
|
467
|
+
describe '#needs_down?' do
|
468
|
+
it 'is false if there is no record' do
|
469
|
+
expect(@m).to receive(:migration_record).and_return([])
|
470
|
+
expect(@m.needs_down?).to eq false
|
471
|
+
end
|
472
|
+
|
473
|
+
it 'is true if the record exists' do
|
474
|
+
expect(@m).to receive(:migration_record).and_return([:not_empty])
|
475
|
+
expect(@m.needs_down?).to eq true
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'is false if there is no migration_info table' do
|
479
|
+
expect(@m).to receive(:migration_info_table_exists?).and_return(false)
|
480
|
+
expect(@m.needs_down?).to eq false
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|
484
|
+
|
485
|
+
it 'has the adapter quote the migration_info table' do
|
486
|
+
expect(@adapter).to receive(:quote_name).with('migration_info').and_return("'migration_info'")
|
487
|
+
expect(@m.migration_info_table).to eq "'migration_info'"
|
488
|
+
end
|
489
|
+
|
490
|
+
it 'has a quoted migration_name_column' do
|
491
|
+
expect(@adapter).to receive(:quote_name).with('migration_name').and_return("'migration_name'")
|
492
|
+
expect(@m.migration_name_column).to eq "'migration_name'"
|
493
|
+
end
|
494
|
+
|
495
|
+
end
|
496
|
+
|
497
|
+
end
|
498
|
+
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
describe SQL::Column do
|
4
|
+
before do
|
5
|
+
@column = SQL::Column.new
|
6
|
+
end
|
7
|
+
|
8
|
+
%w{name type not_null default_value primary_key unique}.each do |meth|
|
9
|
+
it "has a ##{meth} attribute" do
|
10
|
+
expect(@column).to respond_to(meth.intern)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
# a dummy class to include the module into
|
4
|
+
class PostgresExtension
|
5
|
+
include SQL::Postgres
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "Postgres Extensions" do
|
9
|
+
before do
|
10
|
+
@pe = PostgresExtension.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'supports schema-level transactions' do
|
14
|
+
expect(@pe.supports_schema_transactions?).to be(true)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'supports the serial column attribute' do
|
18
|
+
expect(@pe.supports_serial?).to be(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'creates a table object from the name' do
|
22
|
+
table = instance_double('Postgres Table')
|
23
|
+
expect(SQL::Postgres::Table).to receive(:new).with(@pe, 'users').and_return(table)
|
24
|
+
|
25
|
+
expect(@pe.table('users')).to eq table
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'recreating the database'
|
29
|
+
|
30
|
+
describe 'Table' do
|
31
|
+
before do
|
32
|
+
@cs1 = instance_double('Column Struct')
|
33
|
+
@cs2 = instance_double('Column Struct')
|
34
|
+
@adapter = instance_double('adapter', select: [])
|
35
|
+
allow(@adapter).to receive(:query_table).with('users').and_return([@cs1, @cs2])
|
36
|
+
|
37
|
+
@col1 = instance_double('Postgres Column')
|
38
|
+
@col2 = instance_double('Postgres Column')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'initializes columns by querying the table' do
|
42
|
+
expect(SQL::Postgres::Column).to receive(:new).with(@cs1).and_return(@col1)
|
43
|
+
expect(SQL::Postgres::Column).to receive(:new).with(@cs2).and_return(@col2)
|
44
|
+
expect(@adapter).to receive(:query_table).with('users').and_return([@cs1,@cs2])
|
45
|
+
SQL::Postgres::Table.new(@adapter, 'users')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'creates Postgres Column objects from the returned column structs' do
|
49
|
+
expect(SQL::Postgres::Column).to receive(:new).with(@cs1).and_return(@col1)
|
50
|
+
expect(SQL::Postgres::Column).to receive(:new).with(@cs2).and_return(@col2)
|
51
|
+
SQL::Postgres::Table.new(@adapter, 'users')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'sets the @columns to the looked-up columns' do
|
55
|
+
expect(SQL::Postgres::Column).to receive(:new).with(@cs1).and_return(@col1)
|
56
|
+
expect(SQL::Postgres::Column).to receive(:new).with(@cs2).and_return(@col2)
|
57
|
+
t = SQL::Postgres::Table.new(@adapter, 'users')
|
58
|
+
expect(t.columns).to eq [@col1, @col2]
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#query_column_constraints'
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'Column' do
|
65
|
+
before do
|
66
|
+
@cs = instance_double('Struct',
|
67
|
+
column_name: 'id',
|
68
|
+
data_type: 'integer',
|
69
|
+
column_default: 123,
|
70
|
+
is_nullable: 'NO')
|
71
|
+
@c = SQL::Postgres::Column.new(@cs)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'sets the name from the column_name value' do
|
75
|
+
expect(@c.name).to eq 'id'
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'sets the type from the data_type value' do
|
79
|
+
expect(@c.type).to eq 'integer'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'sets the default_value from the column_default value' do
|
83
|
+
expect(@c.default_value).to eq 123
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'sets not_null based on the is_nullable value' do
|
87
|
+
expect(@c.not_null).to eq true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
# a dummy class to include the module into
|
4
|
+
class SqliteExtension
|
5
|
+
include SQL::Sqlite
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "SQLite3 Extensions" do
|
9
|
+
before do
|
10
|
+
@se = SqliteExtension.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'supports schema-level transactions' do
|
14
|
+
expect(@se.supports_schema_transactions?).to be(true)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'supports the serial column attribute' do
|
18
|
+
expect(@se.supports_serial?).to be(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'creates a table object from the name' do
|
22
|
+
table = instance_double('SQLite3 Table')
|
23
|
+
expect(SQL::Sqlite::Table).to receive(:new).with(@se, 'users').and_return(table)
|
24
|
+
|
25
|
+
expect(@se.table('users')).to eq table
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'recreating the database' do
|
29
|
+
before do
|
30
|
+
uri = instance_double('URI', path: '/foo/bar.db')
|
31
|
+
@se.instance_variable_set('@uri', uri)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "rm's the db file" do
|
35
|
+
expect(FileUtils).to receive(:rm_f).with('/foo/bar.db')
|
36
|
+
@se.recreate_database
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'Table' do
|
41
|
+
before do
|
42
|
+
@cs1 = double('Column Struct')
|
43
|
+
@cs2 = double('Column Struct')
|
44
|
+
@adapter = double('adapter')
|
45
|
+
allow(@adapter).to receive(:table_info).with('users').and_return([@cs1, @cs2])
|
46
|
+
|
47
|
+
@col1 = double('SQLite3 Column')
|
48
|
+
@col2 = double('SQLite3 Column')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'initializes columns by querying the table' do
|
52
|
+
expect(SQL::Sqlite::Column).to receive(:new).with(@cs1).and_return(@col1)
|
53
|
+
expect(SQL::Sqlite::Column).to receive(:new).with(@cs2).and_return(@col2)
|
54
|
+
expect(@adapter).to receive(:table_info).with('users').and_return([@cs1,@cs2])
|
55
|
+
SQL::Sqlite::Table.new(@adapter, 'users')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'creates SQLite3 Column objects from the returned column structs' do
|
59
|
+
expect(SQL::Sqlite::Column).to receive(:new).with(@cs1).and_return(@col1)
|
60
|
+
expect(SQL::Sqlite::Column).to receive(:new).with(@cs2).and_return(@col2)
|
61
|
+
SQL::Sqlite::Table.new(@adapter, 'users')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'sets the @columns to the looked-up columns' do
|
65
|
+
expect(SQL::Sqlite::Column).to receive(:new).with(@cs1).and_return(@col1)
|
66
|
+
expect(SQL::Sqlite::Column).to receive(:new).with(@cs2).and_return(@col2)
|
67
|
+
t = SQL::Sqlite::Table.new(@adapter, 'users')
|
68
|
+
expect(t.columns).to eq [ @col1, @col2 ]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'Column' do
|
73
|
+
before do
|
74
|
+
@cs = instance_double('Struct',
|
75
|
+
name: 'id',
|
76
|
+
type: 'integer',
|
77
|
+
dflt_value: 123,
|
78
|
+
pk: true,
|
79
|
+
notnull: 0)
|
80
|
+
@c = SQL::Sqlite::Column.new(@cs)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'sets the name from the name value' do
|
84
|
+
expect(@c.name).to eq 'id'
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'sets the type from the type value' do
|
88
|
+
expect(@c.type).to eq 'integer'
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'sets the default_value from the dflt_value value' do
|
92
|
+
expect(@c.default_value).to eq 123
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'sets the primary_key from the pk value' do
|
96
|
+
expect(@c.primary_key).to eq true
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'sets not_null based on the notnull value' do
|
100
|
+
expect(@c.not_null).to eq true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|