-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathresource_generator.rb
More file actions
365 lines (305 loc) · 12 KB
/
resource_generator.rb
File metadata and controls
365 lines (305 loc) · 12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
module Draft
class ResourceGenerator < Rails::Generators::NamedBase
source_root File.expand_path("../templates", __FILE__)
argument :attributes, type: :array, default: [], banner: "field:type field:type"
class_option :skip_model, type: :boolean, default: false, desc: "Skip model, migration, and specs"
class_option :skip_controller, type: :boolean, default: false, desc: "Skip controller and routes"
class_option :read_only, type: :boolean, default: false, desc: "Only generates the index and show actions"
class_option :skip_validation_alerts, type: :boolean, default: false, desc: "Skip validation failure alerts"
class_option :skip_post, type: :boolean, default: false, desc: "Skip HTTP POST verb"
class_option :skip_redirect, type: :boolean, default: false, desc: "Skip redirecting after create, update, and destroy"
class_option :buggy, type: :boolean, default: false, desc: "Creates buggy resources for RCAV and Golden Seven practice"
def generate_controller
return if skip_controller?
if read_only?
template "controllers/read_only_controller.rb", "app/controllers/#{plural_table_name.underscore}_controller.rb"
else
template "controllers/controller.rb", "app/controllers/#{plural_table_name.underscore}_controller.rb"
end
end
def generate_model
return if skip_model?
invoke "draft:model", ARGV
end
def generate_view_files
available_views.each do |view|
filename = view_filename_with_extensions(view)
template filename, File.join("app/views", "#{singular_table_name}_templates", File.basename(filename))
end
end
def generate_routes
return if skip_controller?
if read_only?
buggy? ? buggy_read_only_routes : read_only_routes
else
buggy? ? buggy_golden_seven_routes : golden_seven_routes
end
end
def generate_specs
return if read_only? || skip_controller? || skip_model?
template "specs/crud_spec.rb", "spec/features/crud_#{plural_table_name.underscore}_spec.rb"
template "specs/factories.rb", "spec/factories/#{plural_table_name.underscore}.rb"
end
private
def golden_seven_routes
log :route, "RESTful routes"
route <<-RUBY.gsub(/^ /, "")
# Routes for the #{singular_table_name.humanize} resource:
# CREATE
get("/#{plural_table_name}/new", { :controller => "#{plural_table_name}", :action => "new_form" })
#{skip_post? ? "get" : "post"}("/create_#{singular_table_name}", { :controller => "#{plural_table_name}", :action => "create_row" })
# READ
get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "index" })
get("/#{plural_table_name}/:id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
# UPDATE
get("/#{plural_table_name}/:prefill_with_id/edit", { :controller => "#{plural_table_name}", :action => "edit_form" })
#{skip_post? ? "get" : "post"}("/update_#{singular_table_name}/:id_to_modify", { :controller => "#{plural_table_name}", :action => "update_row" })
# DELETE
get("/delete_#{singular_table_name}/:id_to_remove", { :controller => "#{plural_table_name}", :action => "destroy_row" })
#------------------------------
RUBY
end
def buggy_golden_seven_routes
log :route, "Buggy Golden Seven routes"
max_route_bugs = rand(2) + 4
bug_count = 0
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
new_form_route = buggy_new_form_route
bug_count += 1
else
new_form_route = <<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}/new", { :controller => "#{plural_table_name}", :action => "new_form" })
RUBY
end
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
create_row_route = buggy_create_row_route
bug_count += 1
else
create_row_route = <<-RUBY.gsub(/^ /, "")
#{skip_post? ? "get" : "post"}("/create_#{singular_table_name}", { :controller => "#{plural_table_name}", :action => "create_row" })
RUBY
end
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
index_route = buggy_index_route
bug_count += 1
else
index_route = <<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "index" })
RUBY
end
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
show_route = buggy_show_route
bug_count += 1
else
show_route = <<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}/:id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
RUBY
end
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
edit_form_route = buggy_edit_form_route
bug_count += 1
else
edit_form_route = <<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}/:prefill_with_id/edit", { :controller => "#{plural_table_name}", :action => "edit_form" })
RUBY
end
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
update_route = buggy_update_route
bug_count += 1
else
update_route = <<-RUBY.gsub(/^ /, "")
#{skip_post? ? "get" : "post"}("/update_#{singular_table_name}/:id_to_modify", { :controller => "#{plural_table_name}", :action => "update_row" })
RUBY
end
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
destroy_row_route = buggy_destroy_row_route
bug_count += 1
else
destroy_row_route = <<-RUBY.gsub(/^ /, "")
get("/delete_#{singular_table_name}/:id_to_remove", { :controller => "#{plural_table_name}", :action => "destroy_row" })
RUBY
end
route <<-RUBY.gsub(/^ /, "")
# Routes for the #{singular_table_name.humanize} resource:
# CREATE
#{new_form_route} #{create_row_route}
# READ
#{index_route} #{show_route}
# UPDATE
#{edit_form_route} #{update_route}
# DELETE
#{destroy_row_route}
RUBY
puts "#{bug_count} route bugs created"
end
def buggy_read_only_routes
log :route, "Buggy index and show routes"
max_route_bugs = 2
bug_count = 0
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
index_route = buggy_index_route
bug_count += 1
else
index_route = <<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "index" })
RUBY
end
if create_bug?(likelihood: :high) && bug_count < max_route_bugs
show_route = buggy_show_route
bug_count += 1
else
show_route = <<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}/:id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
RUBY
end
route <<-RUBY.gsub(/^ /, "")
# Routes for the #{singular_table_name.humanize} resource:
# READ
#{index_route} #{show_route}
#------------------------------
RUBY
end
def buggy_new_form_route
bug_option = rand(2) + 1
if bug_option == 1
<<-RUBY.gsub(/^ /, "")
get("/new_#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "new_form" })
RUBY
elsif bug_option == 2
<<-RUBY.gsub(/^ /, "")
get("/new_#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "new" })
RUBY
end
end
def buggy_create_row_route
<<-RUBY.gsub(/^ /, "")
#{skip_post? ? "get" : "post"}("/create_#{singular_table_name}", { controller => "#{plural_table_name}", action => "create_row" })
RUBY
end
def buggy_index_route
bug_option = rand(2) + 1
if bug_option == 1
<<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "#{plural_table_name}" })
RUBY
elsif bug_option == 2
<<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}", { :controller => #{plural_table_name}, :action => index })
RUBY
end
end
def buggy_show_route
bug_option = rand(2) + 1
if bug_option == 1
<<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}/id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
RUBY
elsif bug_option == 2
<<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}/:id_to_display", { controller => "#{plural_table_name}", :action => "show" })
RUBY
end
end
def buggy_edit_form_route
bug_option = rand(2) + 1
if bug_option == 1
<<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}/prefill_with_id/edit", { :controller => "#{plural_table_name}", :action => "edit_form" })
RUBY
elsif bug_option == 2
<<-RUBY.gsub(/^ /, "")
get("/#{plural_table_name}/:prefill_with_id/edit", { :controller => #{plural_table_name}, :action => "edit" })
RUBY
end
end
def buggy_update_route
bug_option = rand(2) + 1
if bug_option == 1
<<-RUBY.gsub(/^ /, "")
#{skip_post? ? "get" : "post"}("/update_#{singular_table_name}/id_to_modify", { :controller => "#{plural_table_name}", :action => "update_row" })
RUBY
elsif bug_option == 2
<<-RUBY.gsub(/^ /, "")
#{skip_post? ? "get" : "post"}("/update_#{singular_table_name}/id_to_modify", { controller => "#{plural_table_name}", action => "update_row" })
RUBY
end
end
def buggy_destroy_row_route
bug_option = rand(2) + 1
if bug_option == 1
<<-RUBY.gsub(/^ /, "")
get("/delete_#{singular_table_name}/id_to_remove", { :controller => "#{plural_table_name}", :action => "destroy_row" })
RUBY
elsif bug_option == 2
<<-RUBY.gsub(/^ /, "")
get("/delete_#{singular_table_name}/:id_to_remove", { controller => "#{plural_table_name}", action => "destroy" })
RUBY
end
end
def read_only_routes
log :route, "Index and show routes"
route <<-RUBY.gsub(/^ /, "")
# Routes for the #{singular_table_name.humanize} resource:
# READ
get("/#{plural_table_name}", { :controller => "#{plural_table_name}", :action => "index" })
get("/#{plural_table_name}/:id_to_display", { :controller => "#{plural_table_name}", :action => "show" })
#------------------------------
RUBY
end
def skip_controller?
options[:skip_controller]
end
def skip_model?
options[:skip_model]
end
def read_only?
options[:read_only]
end
def skip_validation_alerts?
options[:skip_validation_alerts] || options[:skip_redirect]
end
def skip_post?
options[:skip_post]
end
def skip_redirect?
options[:skip_redirect]
end
def buggy?
options[:buggy]
end
def route(routing_code)
sentinel = /\.routes\.draw do(?:\s*\|map\|)?\s*$/
inside "config" do
insert_into_file "routes.rb", routing_code, after: sentinel
end
end
def available_views
if read_only?
%w(index show)
elsif skip_redirect?
%w(index show new_form create_row edit_form update_row destroy_row)
else
%w(index new_form edit_form show)
end
end
def view_filename_with_extensions(name)
filename = [name, :html, :erb].compact.join(".")
folders = ["views"]
filename = File.join(folders, filename) if folders.any?
filename
end
def create_bug?(likelihood_hash)
if likelihood_hash.fetch(:likelihood) == :high
return rand(10) > 3
elsif likelihood_hash.fetch(:likelihood) == :low
return rand(10) > 7
elsif likelihood_hash.fetch(:likelihood) == :none
return false
elsif likelihood_hash.fetch(:likelihood) == :total
return true
else
return rand(10) > 5
end
end
end
end