config_scripts 0.4.1

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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.yardopts +1 -0
  5. data/CHANGELOG.md +17 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +124 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +55 -0
  10. data/Rakefile +1 -0
  11. data/TODO.md +8 -0
  12. data/config_scripts.gemspec +31 -0
  13. data/lib/config_scripts/generators/config_script.rb +24 -0
  14. data/lib/config_scripts/generators/migrations.rb +36 -0
  15. data/lib/config_scripts/generators.rb +2 -0
  16. data/lib/config_scripts/scripts/script.rb +135 -0
  17. data/lib/config_scripts/scripts/script_history.rb +39 -0
  18. data/lib/config_scripts/scripts.rb +9 -0
  19. data/lib/config_scripts/seeds/seed_set.rb +321 -0
  20. data/lib/config_scripts/seeds/seed_type.rb +361 -0
  21. data/lib/config_scripts/seeds.rb +8 -0
  22. data/lib/config_scripts/tasks/pending_migrations.rake +11 -0
  23. data/lib/config_scripts/tasks/seeds.rake +18 -0
  24. data/lib/config_scripts/tasks.rb +12 -0
  25. data/lib/config_scripts/version.rb +4 -0
  26. data/lib/config_scripts.rb +9 -0
  27. data/spec/dummy/README.rdoc +28 -0
  28. data/spec/dummy/Rakefile +6 -0
  29. data/spec/dummy/app/assets/images/.keep +0 -0
  30. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  31. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  32. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  33. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  34. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  35. data/spec/dummy/app/mailers/.keep +0 -0
  36. data/spec/dummy/app/models/.keep +0 -0
  37. data/spec/dummy/app/models/concerns/.keep +0 -0
  38. data/spec/dummy/app/models/hair_color.rb +2 -0
  39. data/spec/dummy/app/models/person.rb +4 -0
  40. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  41. data/spec/dummy/bin/bundle +3 -0
  42. data/spec/dummy/bin/rails +4 -0
  43. data/spec/dummy/bin/rake +4 -0
  44. data/spec/dummy/config/application.rb +23 -0
  45. data/spec/dummy/config/boot.rb +5 -0
  46. data/spec/dummy/config/database.yml +25 -0
  47. data/spec/dummy/config/environment.rb +5 -0
  48. data/spec/dummy/config/environments/development.rb +29 -0
  49. data/spec/dummy/config/environments/production.rb +80 -0
  50. data/spec/dummy/config/environments/test.rb +36 -0
  51. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  52. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  53. data/spec/dummy/config/initializers/inflections.rb +16 -0
  54. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  55. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  56. data/spec/dummy/config/initializers/session_store.rb +3 -0
  57. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  58. data/spec/dummy/config/locales/en.yml +23 -0
  59. data/spec/dummy/config/routes.rb +56 -0
  60. data/spec/dummy/config.ru +4 -0
  61. data/spec/dummy/db/migrate/20140208014550_create_config_scripts.rb +7 -0
  62. data/spec/dummy/db/migrate/20140208161829_create_people.rb +9 -0
  63. data/spec/dummy/db/migrate/20140208182050_create_hair_colors.rb +9 -0
  64. data/spec/dummy/db/migrate/20140208182101_add_hair_color_to_person.rb +6 -0
  65. data/spec/dummy/db/migrate/20140208225801_add_scope_to_people.rb +6 -0
  66. data/spec/dummy/db/migrate/20140209132911_add_hex_value_to_hair_color.rb +5 -0
  67. data/spec/dummy/db/schema.rb +38 -0
  68. data/spec/dummy/lib/assets/.keep +0 -0
  69. data/spec/dummy/log/.keep +0 -0
  70. data/spec/dummy/public/404.html +58 -0
  71. data/spec/dummy/public/422.html +58 -0
  72. data/spec/dummy/public/500.html +57 -0
  73. data/spec/dummy/public/favicon.ico +0 -0
  74. data/spec/generators/config_script_spec.rb +23 -0
  75. data/spec/generators/migrations_spec.rb +23 -0
  76. data/spec/scripts/script_history_spec.rb +53 -0
  77. data/spec/scripts/script_spec.rb +282 -0
  78. data/spec/seeds/seed_set_spec.rb +371 -0
  79. data/spec/seeds/seed_type_spec.rb +439 -0
  80. data/spec/spec_helper.rb +38 -0
  81. data/templates/config_script.rb +9 -0
  82. data/templates/create_config_scripts_migration.rb +7 -0
  83. metadata +321 -0
@@ -0,0 +1,371 @@
1
+ describe ConfigScripts::Seeds::SeedSet do
2
+ let(:klass) { ConfigScripts::Seeds::SeedSet }
3
+ describe "loading" do
4
+ describe "register_seed_set" do
5
+ before do
6
+ klass.clear_registered_sets
7
+ end
8
+
9
+ it "adds the seed set to the class list" do
10
+ seed_set = double(set_number: 1)
11
+ klass.register_seed_set(seed_set)
12
+ expect(klass.registered_sets).to eq 1 => seed_set
13
+ end
14
+
15
+ context "with a duplicate set number" do
16
+ it "increments the number until it has a unique one" do
17
+ seed_set_1 = klass.new 'set_1', 1
18
+ seed_set_2 = klass.new 'set_2', 1
19
+ expect(seed_set_2.set_number).to eq 2
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "load_seed_sets" do
25
+ it "requires all the files in the seed definitions folder" do
26
+ definitions_path = Rails.root.join('db', 'seeds', 'definitions', '*')
27
+ seed_files = ['/tmp/file1', '/tmp/file2']
28
+ Dir.stub(:[]).with(definitions_path).and_return(seed_files)
29
+ klass.stub :require
30
+ klass.load_seed_sets
31
+ expect(Dir).to have_received(:[]).with(definitions_path)
32
+ seed_files.each do |file|
33
+ expect(klass).to have_received(:require).with(file)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "batch operations" do
40
+ let(:seed_sets) { [double, double] }
41
+ before do
42
+ klass.clear_registered_sets
43
+ klass.stub :puts
44
+ seed_sets.each_with_index do |set, index|
45
+ set.stub(
46
+ write: true,
47
+ read: true,
48
+ set_number: (index + 1) * 2,
49
+ name: "Seed Set #{index + 1}",
50
+ reset_records: true
51
+ )
52
+ klass.register_seed_set(set)
53
+ end
54
+ end
55
+
56
+ describe "write" do
57
+ context "with no argument" do
58
+ it "calls the write method on each seed set" do
59
+ klass.write
60
+ seed_sets.each { |set| expect(set).to have_received(:write) }
61
+ end
62
+ end
63
+
64
+ context "with an argument" do
65
+ it "calls the write method on the set whose number is given" do
66
+ klass.write(2)
67
+ expect(seed_sets.first).to have_received(:write)
68
+ expect(seed_sets.last).not_to have_received(:write)
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "read" do
74
+ context "with no argument" do
75
+ it "calls the read method on each seed set, telling it not to reset" do
76
+ klass.read
77
+ seed_sets.each { |set| expect(set).to have_received(:read).with(false) }
78
+ end
79
+ end
80
+
81
+ context "with an argument" do
82
+ it "calls the read method on the set whose number is given, telling it to reset" do
83
+ klass.read(4)
84
+ expect(seed_sets.last).to have_received(:read).with(true)
85
+ expect(seed_sets.first).not_to have_received(:read)
86
+ end
87
+ end
88
+ end
89
+
90
+ describe "list" do
91
+ it "prints the set number and name for each seed set" do
92
+ klass.list
93
+ expect(klass).to have_received(:puts).with("2: Seed Set 1")
94
+ expect(klass).to have_received(:puts).with("4: Seed Set 2")
95
+ end
96
+ end
97
+ end
98
+
99
+ describe "instance reading and writing" do
100
+ let(:set) { klass.new('test_seeds', 1, 'my_seeds') }
101
+ let!(:seed_type) { double }
102
+ let(:seed_folder) { Rails.root.join('db', 'seeds', 'data', 'my_seeds') }
103
+
104
+ before do
105
+ FileUtils.stub :mkdir_p
106
+ set.stub :seed_types => {Person: seed_type}
107
+ seed_type.stub write_to_folder: nil, read_from_folder: true
108
+ set.stub :puts
109
+ end
110
+
111
+ describe "write" do
112
+ before do
113
+ set.write
114
+ end
115
+
116
+ it "creates the seed folder" do
117
+ expect(FileUtils).to have_received(:mkdir_p).with(seed_folder)
118
+ end
119
+
120
+ it "writes all of the seed types to the folder" do
121
+ expect(seed_type).to have_received(:write_to_folder).with(seed_folder)
122
+ end
123
+
124
+ it "says where it's writing the seeds to" do
125
+ expect(set).to have_received(:puts).with("Writing seeds for test_seeds to #{seed_folder}")
126
+ end
127
+ end
128
+
129
+ describe "read" do
130
+ before do
131
+ set.stub :reset_records
132
+ end
133
+
134
+ context do
135
+ before do
136
+ set.read
137
+ end
138
+
139
+ it "creates the seed folder" do
140
+ expect(FileUtils).to have_received(:mkdir_p).with(seed_folder)
141
+ end
142
+
143
+ it "says where it's reading the seeds from" do
144
+ expect(set).to have_received(:puts).with("Reading seeds for test_seeds from #{seed_folder}")
145
+ end
146
+
147
+ it "reads all of the seed types from the folder" do
148
+ expect(seed_type).to have_received(:read_from_folder).with(seed_folder)
149
+ end
150
+ end
151
+
152
+ context "when resetting" do
153
+ it "resets the records" do
154
+ set.read(true)
155
+ expect(set).to have_received(:reset_records)
156
+ end
157
+ end
158
+
159
+ context "when not resetting" do
160
+ it "does not reset the records" do
161
+ set.read(false)
162
+ expect(set).not_to have_received(:reset_records)
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ describe "DSL" do
169
+ describe "creation" do
170
+ before do
171
+ klass.clear_registered_sets
172
+ end
173
+
174
+ subject { klass.new('test_seeds', 5, 'my_seeds', setting: 'value') { @val = true } }
175
+
176
+ it "sets the name" do
177
+ expect(subject.name).to eq 'test_seeds'
178
+ end
179
+
180
+ it "sets the set number" do
181
+ expect(subject.set_number).to eq 5
182
+ end
183
+
184
+ it "sets the folder" do
185
+ expect(subject.folder).to eq 'my_seeds'
186
+ end
187
+
188
+ it "sets the options" do
189
+ expect(subject.options).to eq(setting: 'value')
190
+ end
191
+
192
+ it "runs the block on the instance" do
193
+ expect(subject.instance_eval{@val}).to eq true
194
+ end
195
+
196
+ it "gives it an empty hash of seed types" do
197
+ expect(subject.seed_types).to eq({})
198
+ end
199
+
200
+ it "registers the set with the klass" do
201
+ expect(klass.registered_sets[subject.set_number]).to eq subject
202
+ end
203
+ end
204
+
205
+ describe "seeds_for" do
206
+ let(:set) { ConfigScripts::Seeds::SeedSet.new('test_seeds', 1) }
207
+
208
+ subject { set.seeds_for(Person, 'people_seeds') { @val = true } }
209
+
210
+ it "constructs a seed type with the arguments" do
211
+ expect(subject).to be_a ConfigScripts::Seeds::SeedType
212
+ expect(subject.klass).to eq Person
213
+ expect(subject.filename).to eq 'people_seeds'
214
+ expect(subject.instance_eval {@val}).to eq true
215
+ end
216
+
217
+ it "maps the seed type to the class in the seed type list" do
218
+ subject
219
+ expect(set.seed_types[Person]).to eq subject
220
+ end
221
+
222
+ it "has a default filename based on the class name" do
223
+ seeds = set.seeds_for(Person)
224
+ expect(seeds.filename).to eq 'people'
225
+ end
226
+ end
227
+
228
+ describe "when_resetting" do
229
+ let(:set) { ConfigScripts::Seeds::SeedSet.new('test_seeds', 1) }
230
+
231
+ it "sets the reset_block value" do
232
+ value = 0
233
+ set.when_resetting do
234
+ value = 1
235
+ end
236
+ expect(value).to eq 0
237
+ set.reset_records
238
+ expect(value).to eq 1
239
+ end
240
+ end
241
+ end
242
+
243
+ describe "seed identifiers" do
244
+ let(:set) { ConfigScripts::Seeds::SeedSet.new('test_seeds', 1) }
245
+ let(:seed_type) { set.seeds_for(Person) }
246
+ let(:identifier) { double }
247
+
248
+ class AdultPerson < Person
249
+ end
250
+
251
+ describe "seed_identifier_for_record" do
252
+
253
+ subject { set.seed_identifier_for_record(record) }
254
+
255
+ before do
256
+ seed_type.stub :seed_identifier_for_record => identifier
257
+ end
258
+
259
+ context "with a record it has a seed type for" do
260
+ let(:record) { Person.new }
261
+
262
+ it "gets the identifier from the seed types" do
263
+ expect(subject).to eq identifier
264
+ expect(seed_type).to have_received(:seed_identifier_for_record).with(record)
265
+ end
266
+ end
267
+
268
+ context "with a record where it has a seed type for a superclass" do
269
+ let(:record) { AdultPerson.new }
270
+
271
+ it "gets the identifier from the seed types" do
272
+ expect(subject).to eq identifier
273
+ expect(seed_type).to have_received(:seed_identifier_for_record).with(record)
274
+ end
275
+ end
276
+
277
+ context "with a record it does not have a seed type for" do
278
+ let(:record) { ConfigScripts::Scripts::ScriptHistory.new(id: 5) }
279
+
280
+ it "is the record's id" do
281
+ expect(subject).to eq 5
282
+ end
283
+ end
284
+
285
+ context "with a record that is not a subclass of ActiveRecord" do
286
+ let(:record) { "Hello" }
287
+
288
+ it "is nil" do
289
+ expect(subject).to be_nil
290
+ end
291
+ end
292
+ end
293
+
294
+ describe "record_for_seed_identifier" do
295
+ let(:record) { Person.create }
296
+ let(:identifier) { ['red', 'John'] }
297
+ subject { set.record_for_seed_identifier(klass, identifier) }
298
+
299
+ before do
300
+ seed_type.stub :record_for_seed_identifier do |identifier|
301
+ identifier.shift
302
+ identifier.shift
303
+ record
304
+ end
305
+ seed_type.has_identifier_attributes :hair_color, :name
306
+ end
307
+
308
+ context "for a class it has seed types for" do
309
+ let(:klass) { Person }
310
+ it "gets the record from the seed type" do
311
+ expect(subject).to eq record
312
+ expect(seed_type).to have_received(:record_for_seed_identifier).with(identifier)
313
+ end
314
+
315
+ it "caches the result" do
316
+ identifier2 = identifier.dup
317
+ subject
318
+ set.record_for_seed_identifier(klass, identifier2)
319
+ expect(seed_type).to have_received(:record_for_seed_identifier).once
320
+ end
321
+ end
322
+
323
+ context "for a class where it has seed types for a parent class" do
324
+ let(:klass) { AdultPerson }
325
+ it "gets the record from the seed type" do
326
+ expect(subject).to eq record
327
+ expect(seed_type).to have_received(:record_for_seed_identifier).with(identifier)
328
+ end
329
+
330
+ it "caches the result" do
331
+ identifier2 = identifier.dup
332
+ subject
333
+ set.record_for_seed_identifier(klass, identifier2)
334
+ expect(seed_type).to have_received(:record_for_seed_identifier).once
335
+ end
336
+ end
337
+
338
+ context "with an identifier that has more keys than needed" do
339
+ let(:klass) { Person }
340
+ let(:identifier) { ['red', 'John', 'Smith'] }
341
+
342
+ it "only caches it with the keys needed" do
343
+ subject
344
+ set.record_for_seed_identifier(klass, ['red', 'John'])
345
+ expect(seed_type).to have_received(:record_for_seed_identifier).once
346
+ end
347
+
348
+ it "removes the keys it needs from the identifier" do
349
+ subject
350
+ expect(identifier).to eq ['Smith']
351
+ end
352
+
353
+ it "removes the keys it needs even on a cache hit" do
354
+ identifier2 = identifier.dup
355
+ subject
356
+ set.record_for_seed_identifier(klass, identifier2)
357
+ expect(seed_type).to have_received(:record_for_seed_identifier).once
358
+ expect(identifier2).to eq ['Smith']
359
+ end
360
+ end
361
+
362
+ context "for class where it does not have a seed type" do
363
+ let(:klass) { ConfigScripts::Scripts::ScriptHistory }
364
+
365
+ it "is nil" do
366
+ expect(subject).to be_nil
367
+ end
368
+ end
369
+ end
370
+ end
371
+ end