hot-glue 0.5.8 → 0.5.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/Gemfile +1 -1
- data/README.md +256 -146
- data/app/helpers/hot_glue/controller_helper.rb +9 -6
- data/lib/generators/hot_glue/direct_upload_install_generator.rb +47 -0
- data/lib/generators/hot_glue/dropzone_install_generator.rb +39 -0
- data/lib/generators/hot_glue/layout/builder.rb +15 -6
- data/lib/generators/hot_glue/layout_strategy/base.rb +2 -0
- data/lib/generators/hot_glue/layout_strategy/bootstrap.rb +4 -0
- data/lib/generators/hot_glue/markup_templates/erb.rb +173 -115
- data/lib/generators/hot_glue/scaffold_generator.rb +257 -134
- data/lib/generators/hot_glue/templates/controller.rb.erb +15 -9
- data/lib/generators/hot_glue/templates/erb/_list.erb +19 -6
- data/lib/generators/hot_glue/templates/erb/_show.erb +6 -4
- data/lib/generators/hot_glue/templates/javascript/dropzone_controller.js +191 -0
- data/lib/generators/hot_glue/templates/system_spec.rb.erb +17 -9
- data/lib/hotglue/version.rb +1 -1
- data/script/clean_generated_code +1 -1
- metadata +7 -4
@@ -70,7 +70,7 @@ module HotGlue
|
|
70
70
|
with_params: with_params,
|
71
71
|
put_form: put_form,
|
72
72
|
nested_set: rest_of_nest )
|
73
|
-
return "defined?(#{instance_sym + nested_set[0][:singular]}) ? #{is_present_path} : #{is_missing_path}"
|
73
|
+
return "defined?(#{instance_sym + nested_set[0][:singular]}2) ? #{is_present_path} : #{is_missing_path}"
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -150,8 +150,8 @@ module HotGlue
|
|
150
150
|
class_option :inline_list_labels, default: 'omit' # choices are before, after, omit
|
151
151
|
class_option :factory_creation, default: ''
|
152
152
|
class_option :alt_foreign_key_lookup, default: '' #
|
153
|
-
|
154
|
-
|
153
|
+
class_option :attachments, default: ''
|
154
|
+
class_option :stacked_downnesting, default: false
|
155
155
|
|
156
156
|
def initialize(*meta_args)
|
157
157
|
super
|
@@ -215,15 +215,6 @@ module HotGlue
|
|
215
215
|
LayoutStrategy::HotGlue.new(self)
|
216
216
|
end
|
217
217
|
|
218
|
-
|
219
|
-
if @markup == "erb"
|
220
|
-
@template_builder = HotGlue::ErbTemplate.new(layout_strategy: @layout_strategy)
|
221
|
-
elsif @markup == "slim"
|
222
|
-
raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
|
223
|
-
elsif @markup == "haml"
|
224
|
-
raise(HotGlue::Error, "HAML IS NOT IMPLEMENTED")
|
225
|
-
end
|
226
|
-
|
227
218
|
args = meta_args[0]
|
228
219
|
@singular = args.first.tableize.singularize # should be in form hello_world
|
229
220
|
|
@@ -233,32 +224,21 @@ module HotGlue
|
|
233
224
|
|
234
225
|
@plural = options['plural'] || @singular.pluralize # respects what you set in inflections.rb, to override, use plural option
|
235
226
|
@namespace = options['namespace'] || nil
|
236
|
-
|
237
|
-
|
238
227
|
use_controller_name = plural.titleize.gsub(" ", "")
|
239
|
-
|
240
228
|
@controller_build_name = (( @namespace.titleize.gsub(" ","") + "::" if @namespace) || "") + use_controller_name + "Controller"
|
241
229
|
@controller_build_folder = use_controller_name.underscore
|
242
230
|
@controller_build_folder_singular = singular
|
243
231
|
|
244
|
-
# if ! @controller_build_folder.ends_with?("s")
|
245
|
-
# raise HotGlue::Error, "can't build with controller name #{@controller_build_folder} because it doesn't end with an 's'"
|
246
|
-
# end
|
247
|
-
|
248
232
|
@auth = options['auth'] || "current_user"
|
249
233
|
@auth_identifier = options['auth_identifier'] || (! @god && @auth.gsub("current_", "")) || nil
|
250
234
|
|
251
|
-
|
252
|
-
|
253
235
|
if options['nest']
|
254
236
|
raise HotGlue::Error, "STOP: the flag --nest has been replaced with --nested; please re-run using the --nested flag"
|
255
|
-
|
256
237
|
end
|
257
|
-
|
258
238
|
@nested = (!options['nested'].empty? && options['nested']) || nil
|
259
|
-
|
260
239
|
@singular_class = args.first # note this is the full class name with a model namespace
|
261
240
|
|
241
|
+
setup_attachments
|
262
242
|
|
263
243
|
@exclude_fields = []
|
264
244
|
@exclude_fields += options['exclude'].split(",").collect(&:to_sym)
|
@@ -270,7 +250,6 @@ module HotGlue
|
|
270
250
|
@include_fields += options['include'].split(":").collect{|x|x.split(",")}.flatten.collect(&:to_sym)
|
271
251
|
end
|
272
252
|
|
273
|
-
|
274
253
|
@show_only = []
|
275
254
|
if !options['show_only'].empty?
|
276
255
|
@show_only += options['show_only'].split(",").collect(&:to_sym)
|
@@ -282,6 +261,76 @@ module HotGlue
|
|
282
261
|
end
|
283
262
|
|
284
263
|
|
264
|
+
# syntax should be xyz_id{xyz_email},abc_id{abc_email}
|
265
|
+
# instead of a drop-down for the foreign entity, a text field will be presented
|
266
|
+
# You must ALSO use a factory that contains a parameter of the same name as the 'value' (for example, `xyz_email`)
|
267
|
+
|
268
|
+
alt_lookups_entry = options['alt_foreign_key_lookup'].split(",")
|
269
|
+
@alt_lookups = {}
|
270
|
+
@alt_foreign_key_lookup = alt_lookups_entry.each do |setting|
|
271
|
+
setting =~ /(.*){(.*)}/
|
272
|
+
key, lookup_as = $1, $2
|
273
|
+
assoc = eval("#{class_name}.reflect_on_association(:#{key.to_s.gsub("_id","")}).class_name")
|
274
|
+
|
275
|
+
data = {lookup_as: lookup_as.gsub("+",""),
|
276
|
+
assoc: assoc,
|
277
|
+
with_create: lookup_as.include?("+")}
|
278
|
+
@alt_lookups[key] = data
|
279
|
+
end
|
280
|
+
|
281
|
+
puts "------ ALT LOOKUPS for #{@alt_lookups}"
|
282
|
+
|
283
|
+
@update_alt_lookups = @alt_lookups.collect{|key, value|
|
284
|
+
@update_show_only.include?(key) ?
|
285
|
+
{ key: value }
|
286
|
+
: nil}.compact
|
287
|
+
|
288
|
+
@label = options['label'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_singular)") ? eval("#{class_name}.class_variable_get(:@@table_label_singular)") : singular.gsub("_", " ").titleize )
|
289
|
+
@list_label_heading = options['list_label_heading'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_plural)") ? eval("#{class_name}.class_variable_get(:@@table_label_plural)") : plural.gsub("_", " ").upcase )
|
290
|
+
|
291
|
+
@new_button_label = options['new_button_label'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_singular)") ? "New " + eval("#{class_name}.class_variable_get(:@@table_label_singular)") : "New " + singular.gsub("_", " ").titleize )
|
292
|
+
@new_form_heading = options['new_form_heading'] || "New #{@label}"
|
293
|
+
|
294
|
+
|
295
|
+
|
296
|
+
setup_hawk_keys
|
297
|
+
@form_placeholder_labels = options['form_placeholder_labels'] # true or false
|
298
|
+
@inline_list_labels = options['inline_list_labels'] || 'omit' # 'before','after','omit'
|
299
|
+
|
300
|
+
|
301
|
+
@form_labels_position = options['form_labels_position']
|
302
|
+
if !['before','after','omit'].include?(@form_labels_position)
|
303
|
+
raise HotGlue::Error, "You passed '#{@form_labels_position}' as the setting for --form-labels-position but the only allowed options are before, after (default), and omit"
|
304
|
+
end
|
305
|
+
|
306
|
+
if !['before','after','omit'].include?(@inline_list_labels)
|
307
|
+
raise HotGlue::Error, "You passed '#{@inline_list_labels}' as the setting for --inline-list-labels but the only allowed options are before, after, and omit (default)"
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
|
312
|
+
if @markup == "erb"
|
313
|
+
@template_builder = HotGlue::ErbTemplate.new(
|
314
|
+
layout_strategy: @layout_strategy,
|
315
|
+
magic_buttons: @magic_buttons,
|
316
|
+
small_buttons: @small_buttons,
|
317
|
+
inline_list_labels: @inline_list_labels,
|
318
|
+
show_only: @show_only,
|
319
|
+
update_show_only: @update_show_only,
|
320
|
+
singular_class: singular_class,
|
321
|
+
singular: singular,
|
322
|
+
hawk_keys: @hawk_keys,
|
323
|
+
ownership_field: @ownership_field,
|
324
|
+
form_labels_position: @form_labels_position,
|
325
|
+
form_placeholder_labels: @form_placeholder_labels,
|
326
|
+
alt_lookups: @alt_lookups,
|
327
|
+
attachments: @attachments,
|
328
|
+
)
|
329
|
+
elsif @markup == "slim"
|
330
|
+
raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
|
331
|
+
elsif @markup == "haml"
|
332
|
+
raise(HotGlue::Error, "HAML IS NOT IMPLEMENTED")
|
333
|
+
end
|
285
334
|
|
286
335
|
@god = options['god'] || options['gd'] || false
|
287
336
|
@specs_only = options['specs_only'] || false
|
@@ -297,20 +346,8 @@ module HotGlue
|
|
297
346
|
@no_list = options['no_list'] || false
|
298
347
|
@no_list_label = options['no_list_label'] || false
|
299
348
|
@no_list_heading = options['no_list_heading'] || false
|
349
|
+
@stacked_downnesting = options['stacked_downnesting']
|
300
350
|
|
301
|
-
@form_labels_position = options['form_labels_position']
|
302
|
-
if !['before','after','omit'].include?(@form_labels_position)
|
303
|
-
|
304
|
-
raise HotGlue::Error, "You passed '#{@form_labels_position}' as the setting for --form-labels-position but the only allowed options are before, after (default), and omit"
|
305
|
-
end
|
306
|
-
|
307
|
-
@form_placeholder_labels = options['form_placeholder_labels'] # true or false
|
308
|
-
@inline_list_labels = options['inline_list_labels'] || 'omit' # 'before','after','omit'
|
309
|
-
|
310
|
-
|
311
|
-
if !['before','after','omit'].include?(@inline_list_labels)
|
312
|
-
raise HotGlue::Error, "You passed '#{@inline_list_labels}' as the setting for --inline-list-labels but the only allowed options are before, after, and omit (default)"
|
313
|
-
end
|
314
351
|
|
315
352
|
|
316
353
|
|
@@ -415,15 +452,16 @@ module HotGlue
|
|
415
452
|
end
|
416
453
|
end
|
417
454
|
|
418
|
-
identify_object_owner
|
419
|
-
setup_hawk_keys
|
420
455
|
|
421
456
|
@factory_creation = options['factory_creation'].gsub(";", "\n")
|
422
457
|
|
458
|
+
identify_object_owner
|
459
|
+
|
423
460
|
|
424
461
|
|
425
462
|
# SETUP FIELDS & LAYOUT
|
426
463
|
setup_fields
|
464
|
+
|
427
465
|
if (@columns - @show_only - (@ownership_field ? [@ownership_field.to_sym] : [])).empty?
|
428
466
|
@no_field_form = true
|
429
467
|
end
|
@@ -434,43 +472,21 @@ module HotGlue
|
|
434
472
|
downnest_object: @downnest_object,
|
435
473
|
buttons_width: buttons_width,
|
436
474
|
columns: @columns,
|
437
|
-
smart_layout: @smart_layout
|
475
|
+
smart_layout: @smart_layout,
|
476
|
+
stacked_downnesting: @stacked_downnesting)
|
438
477
|
@layout_object = builder.construct
|
439
478
|
|
440
|
-
@menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
|
441
479
|
|
442
|
-
@turbo_streams = !!options['with_turbo_streams']
|
443
480
|
|
481
|
+
@menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
|
444
482
|
|
445
|
-
|
446
|
-
# instead of a drop-down for the foreign entity, a text field will be presented
|
447
|
-
# You must ALSO use a factory that contains a parameter of the same name as the 'value' (for example, `xyz_email`)
|
483
|
+
@turbo_streams = !!options['with_turbo_streams']
|
448
484
|
|
449
|
-
alt_lookups_entry = options['alt_foreign_key_lookup'].split(",")
|
450
|
-
@alt_lookups = {}
|
451
|
-
@alt_foreign_key_lookup = alt_lookups_entry.each do |setting|
|
452
|
-
setting =~ /(.*){(.*)}/
|
453
|
-
key, lookup_as = $1, $2
|
454
|
-
assoc = eval("#{class_name}.reflect_on_association(:#{key.to_s.gsub("_id","")}).class_name")
|
455
485
|
|
456
|
-
data = {lookup_as: lookup_as.gsub("+",""),
|
457
|
-
assoc: assoc,
|
458
|
-
with_create: lookup_as.include?("+")}
|
459
|
-
@alt_lookups[key] = data
|
460
|
-
end
|
461
486
|
|
462
|
-
puts "------ ALT LOOKUPS for #{@alt_lookups}"
|
463
487
|
|
464
|
-
@update_alt_lookups = @alt_lookups.collect{|key, value|
|
465
|
-
@update_show_only.include?(key) ?
|
466
|
-
{ key: value }
|
467
|
-
: nil}.compact
|
468
488
|
|
469
|
-
@label = options['label'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_singular)") ? eval("#{class_name}.class_variable_get(:@@table_label_singular)") : singular.gsub("_", " ").titleize )
|
470
|
-
@list_label_heading = options['list_label_heading'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_plural)") ? eval("#{class_name}.class_variable_get(:@@table_label_plural)") : plural.gsub("_", " ").upcase )
|
471
489
|
|
472
|
-
@new_button_label = options['new_button_label'] || ( eval("#{class_name}.class_variable_defined?(:@@table_label_singular)") ? "New " + eval("#{class_name}.class_variable_get(:@@table_label_singular)") : "New " + singular.gsub("_", " ").titleize )
|
473
|
-
@new_form_heading = options['new_form_heading'] || "New #{@label}"
|
474
490
|
end
|
475
491
|
|
476
492
|
|
@@ -509,24 +525,115 @@ module HotGlue
|
|
509
525
|
end
|
510
526
|
|
511
527
|
hawk_scope = key.gsub("_id", "").pluralize
|
512
|
-
|
528
|
+
optional = eval(singular_class + ".reflect_on_association(:#{key.gsub('_id','')})").options[:optional]
|
529
|
+
|
530
|
+
@hawk_keys[key.to_sym] = {bind_to: [hawk_to], optional: optional}
|
513
531
|
use_shorthand = !options["hawk"].include?("{")
|
514
532
|
|
515
533
|
if use_shorthand # only include the hawk scope if using the shorthand
|
516
|
-
@hawk_keys[key.to_sym] << hawk_scope
|
534
|
+
@hawk_keys[key.to_sym][:bind_to] << hawk_scope
|
517
535
|
end
|
536
|
+
|
518
537
|
end
|
519
538
|
|
520
539
|
puts "HAWKING: #{@hawk_keys}"
|
521
540
|
end
|
522
541
|
end
|
523
542
|
|
543
|
+
|
544
|
+
def setup_attachments
|
545
|
+
@attachments = {}
|
546
|
+
|
547
|
+
if options["attachments"]
|
548
|
+
|
549
|
+
options['attachments'].split(",").each do |attachment_entry|
|
550
|
+
# format is: avatar{thumbnail|field_for_original_filename}
|
551
|
+
|
552
|
+
if attachment_entry.include?("{")
|
553
|
+
num_params = attachment_entry.split("|").count
|
554
|
+
if num_params == 1
|
555
|
+
attachment_entry =~ /(.*){(.*)}/
|
556
|
+
key, thumbnail = $1, $2
|
557
|
+
elsif num_params == 2
|
558
|
+
attachment_entry =~ /(.*){(.*)\|(.*)}/
|
559
|
+
key, thumbnail, field_for_original_filename = $1, $2, $3
|
560
|
+
elsif num_params > 2
|
561
|
+
if num_params == 3
|
562
|
+
attachment_entry =~ /(.*){(.*)\|(.*)\|(.*)}/
|
563
|
+
key, thumbnail, field_for_original_filename, direct_upload = $1, $2, $3, $4
|
564
|
+
elsif num_params > 3
|
565
|
+
attachment_entry =~ /(.*){(.*)\|(.*)\|(.*)\|(.*)}/
|
566
|
+
key, thumbnail, field_for_original_filename, direct_upload, dropzone = $1, $2, $3, $4, $5
|
567
|
+
end
|
568
|
+
|
569
|
+
field_for_original_filename = nil if field_for_original_filename == ""
|
570
|
+
|
571
|
+
if thumbnail == ''
|
572
|
+
thumbnail = nil
|
573
|
+
end
|
574
|
+
|
575
|
+
if !direct_upload.nil? && direct_upload != "direct"
|
576
|
+
raise HotGlue::Error, "received 3rd parameter in attachment long form specification that was not 'direct'; for direct uploads, just use 'direct' or leave off to disable"
|
577
|
+
end
|
578
|
+
|
579
|
+
if !dropzone.nil? && dropzone != "dropzone"
|
580
|
+
raise HotGlue::Error, "received 4th parameter in attachme long form specification that was not 'dropzone'; for dropzone, just use 'dropzone' or leave off to disable"
|
581
|
+
end
|
582
|
+
|
583
|
+
if dropzone && !direct_upload
|
584
|
+
raise HotGlue::Error, "dropzone requires direct_upload"
|
585
|
+
end
|
586
|
+
|
587
|
+
if field_for_original_filename && direct_upload
|
588
|
+
raise HotGlue::Error, "Unfortunately orig filename extraction doesn't work with direct upload; please set 2nd parameter to empty string to disable"
|
589
|
+
end
|
590
|
+
|
591
|
+
direct_upload = !!direct_upload
|
592
|
+
dropzone = !!dropzone
|
593
|
+
end
|
594
|
+
else
|
595
|
+
key = attachment_entry
|
596
|
+
|
597
|
+
if !(eval("#{singular_class}.reflect_on_attachment(:#{attachment_entry})"))
|
598
|
+
raise HotGlue::Error, "Could not find #{attachment_entry} attachment on #{singular_class}"
|
599
|
+
end
|
600
|
+
if eval("#{singular_class}.reflect_on_attachment(:#{attachment_entry}).variants.include?(:thumb)")
|
601
|
+
thumbnail = "thumb"
|
602
|
+
else
|
603
|
+
thumbnail = nil
|
604
|
+
end
|
605
|
+
|
606
|
+
direct_upload = nil
|
607
|
+
field_for_original_filename = nil
|
608
|
+
dropzone = nil
|
609
|
+
end
|
610
|
+
|
611
|
+
if thumbnail && !eval("#{singular_class}.reflect_on_attachment(:#{key}).variants.include?(:#{thumbnail})")
|
612
|
+
raise HotGlue::Error, "you specified to use #{thumbnail} as the thumbnail but could not find any such variant on the #{key} attachment; add to your #{singular}.rb file:
|
613
|
+
has_one_attached :#{key} do |attachable|
|
614
|
+
attachable.variant :#{thumbnail}, resize_to_limit: [100, 100]
|
615
|
+
end
|
616
|
+
"
|
617
|
+
end
|
618
|
+
|
619
|
+
|
620
|
+
@attachments[key.to_sym] = {thumbnail: thumbnail,
|
621
|
+
field_for_original_filename: field_for_original_filename,
|
622
|
+
direct_upload: direct_upload,
|
623
|
+
dropzone: dropzone}
|
624
|
+
end
|
625
|
+
|
626
|
+
puts "ATTACHMENTS: #{@attachments}"
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
524
630
|
def identify_object_owner
|
525
631
|
auth_assoc = @auth && @auth.gsub("current_","")
|
526
632
|
|
527
633
|
if @object_owner_sym && ! @self_auth
|
528
634
|
auth_assoc_field = auth_assoc + "_id" unless @god
|
529
635
|
assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
|
636
|
+
|
530
637
|
if assoc
|
531
638
|
@ownership_field = assoc.name.to_s + "_id"
|
532
639
|
elsif ! @nested_set.any?
|
@@ -561,54 +668,70 @@ module HotGlue
|
|
561
668
|
|
562
669
|
@columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| @exclude_fields.include?(field) }
|
563
670
|
|
671
|
+
|
564
672
|
else
|
565
673
|
@columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) }
|
566
674
|
end
|
567
675
|
|
676
|
+
if @attachments.any?
|
677
|
+
puts "adding attachments-as-columns: #{@attachments}"
|
678
|
+
@attachments.keys.each do |attachment|
|
679
|
+
@columns << attachment if !@columns.include?(attachment)
|
680
|
+
end
|
681
|
+
end
|
682
|
+
|
683
|
+
|
568
684
|
|
569
685
|
@associations = []
|
686
|
+
|
570
687
|
@columns.each do |col|
|
571
688
|
if col.to_s.starts_with?("_")
|
572
689
|
@show_only << col
|
573
690
|
end
|
574
691
|
|
575
|
-
if @the_object.columns_hash
|
576
|
-
if col.to_s.
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
assoc_class.
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
692
|
+
if @the_object.columns_hash.keys.include?(col.to_s)
|
693
|
+
if @the_object.columns_hash[col.to_s].type == :integer
|
694
|
+
if col.to_s.ends_with?("_id")
|
695
|
+
# guess the association name label
|
696
|
+
assoc_name = col.to_s.gsub("_id","")
|
697
|
+
|
698
|
+
|
699
|
+
assoc_model = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
|
700
|
+
|
701
|
+
if assoc_model.nil?
|
702
|
+
exit_message = "*** Oops: The model #{singular_class} is missing an association for :#{assoc_name} or the model #{assoc_name.titlecase} doesn't exist. TODO: Please implement a model for #{assoc_name.titlecase}; or add to #{singular_class} `belongs_to :#{assoc_name}`. To make a controller that can read all records, specify with --god."
|
703
|
+
puts exit_message
|
704
|
+
raise(HotGlue::Error, exit_message)
|
705
|
+
end
|
706
|
+
|
707
|
+
begin
|
708
|
+
assoc_class = eval(assoc_model.try(:class_name))
|
709
|
+
@associations << assoc_name.to_sym
|
710
|
+
name_list = [:name, :to_label, :full_name, :display_name, :email]
|
711
|
+
|
712
|
+
rescue
|
713
|
+
# unreachable(?)
|
714
|
+
# if eval("#{singular_class}.reflect_on_association(:#{assoc_name.singularize})")
|
715
|
+
# raise(HotGlue::Error,"*** Oops: #{singular_class} has no association for #{assoc_name.singularize}")
|
716
|
+
# else
|
717
|
+
# raise(HotGlue::Error,"*** Oops: Missing relationship from class #{singular_class} to :#{@object_owner_sym} maybe add `belongs_to :#{@object_owner_sym}` to #{singular_class}\n (If your user is called something else, pass with flag auth=current_X where X is the model for your auth object as lowercase. Also, be sure to implement current_X as a method on your controller. If you really don't want to implement a current_X on your controller and want me to check some other method for your current user, see the section in the docs for --auth-identifier flag). To make a controller that can read all records, specify with --god.")
|
718
|
+
# end
|
719
|
+
end
|
720
|
+
|
721
|
+
if assoc_class && name_list.collect{ |field|
|
722
|
+
assoc_class.respond_to?(field.to_s) || assoc_class.instance_methods.include?(field)
|
723
|
+
}.any?
|
724
|
+
# do nothing here
|
725
|
+
else
|
726
|
+
exit_message = "Oops: Missing a label for `#{assoc_class}`. Can't find any column to use as the display label for the #{assoc_name} association on the #{singular_class} model. TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name 5) email. You can implement any of these directly on your`#{assoc_class}` model (can be database fields or model methods) or alias them to field you want to use as your display label. Then RERUN THIS GENERATOR. (Field used will be chosen based on rank here.)"
|
727
|
+
raise(HotGlue::Error,exit_message)
|
728
|
+
end
|
610
729
|
end
|
611
730
|
end
|
731
|
+
elsif @attachments.keys.include?(col)
|
732
|
+
|
733
|
+
else
|
734
|
+
raise "couldn't find #{col} in either field list or attachments list"
|
612
735
|
end
|
613
736
|
end
|
614
737
|
end
|
@@ -671,7 +794,7 @@ module HotGlue
|
|
671
794
|
end
|
672
795
|
|
673
796
|
def spec_related_column_lets
|
674
|
-
(@columns - @show_only).map { |col|
|
797
|
+
(@columns - @show_only - @attachments.keys).map { |col|
|
675
798
|
type = eval("#{singular_class}.columns_hash['#{col}']").type
|
676
799
|
if (type == :integer && col.to_s.ends_with?("_id") || type == :uuid)
|
677
800
|
assoc = "#{col.to_s.gsub('_id','')}"
|
@@ -685,7 +808,7 @@ module HotGlue
|
|
685
808
|
|
686
809
|
def list_column_headings
|
687
810
|
@template_builder.list_column_headings(
|
688
|
-
|
811
|
+
layout_object: @layout_object,
|
689
812
|
col_identifier: @layout_strategy.column_classes_for_column_headings,
|
690
813
|
column_width: @layout_strategy.column_width,
|
691
814
|
singular: @singular
|
@@ -693,7 +816,7 @@ module HotGlue
|
|
693
816
|
end
|
694
817
|
|
695
818
|
def columns_spec_with_sample_data
|
696
|
-
@columns.map { |c|
|
819
|
+
(@columns - @attachments.keys).map { |c|
|
697
820
|
type = eval("#{singular_class}.columns_hash['#{c}']").type
|
698
821
|
random_data = case type
|
699
822
|
when :integer
|
@@ -715,23 +838,25 @@ module HotGlue
|
|
715
838
|
end
|
716
839
|
|
717
840
|
def object_parent_mapping_as_argument_for_specs
|
841
|
+
|
718
842
|
if @self_auth
|
719
843
|
""
|
720
|
-
elsif @nested_set.any?
|
844
|
+
elsif @nested_set.any? && ! @nested_set.last[:optional]
|
721
845
|
", " + @nested_set.last[:singular] + ": " + @nested_set.last[:singular]
|
722
|
-
elsif @auth
|
846
|
+
elsif @auth && !@god
|
723
847
|
", #{@auth_identifier}: #{@auth}"
|
724
848
|
end
|
725
849
|
end
|
726
850
|
|
727
851
|
def objest_nest_factory_setup
|
728
|
-
|
852
|
+
# TODO: figure out what this is for
|
853
|
+
res = ""
|
729
854
|
if @auth
|
730
855
|
last_parent = ", #{@auth_identifier}: #{@auth}"
|
731
856
|
end
|
732
857
|
|
733
858
|
@nested_set.each do |arg|
|
734
|
-
res << "let(:#{arg[:singular]}) {create(:#{arg[:singular]} #{last_parent} )}\n"
|
859
|
+
res << " let(:#{arg[:singular]}) {create(:#{arg[:singular]} #{last_parent} )}\n"
|
735
860
|
last_parent = ", #{arg[:singular]}: #{arg[:singular]}"
|
736
861
|
end
|
737
862
|
res
|
@@ -768,7 +893,7 @@ module HotGlue
|
|
768
893
|
end
|
769
894
|
|
770
895
|
def test_capybara_block(which_partial = :create)
|
771
|
-
(@columns - (which_partial == :create ? @show_only : (@update_show_only+@show_only))).map { |col|
|
896
|
+
((@columns - @attachments.keys) - (which_partial == :create ? @show_only : (@update_show_only+@show_only))).map { |col|
|
772
897
|
type = eval("#{singular_class}.columns_hash['#{col}']").type
|
773
898
|
case type
|
774
899
|
when :date
|
@@ -1154,19 +1279,8 @@ module HotGlue
|
|
1154
1279
|
end
|
1155
1280
|
|
1156
1281
|
def form_fields_html
|
1157
|
-
@template_builder.all_form_fields(
|
1158
|
-
|
1159
|
-
show_only: @show_only,
|
1160
|
-
update_show_only: @update_show_only,
|
1161
|
-
singular_class: singular_class,
|
1162
|
-
singular: singular,
|
1163
|
-
hawk_keys: @hawk_keys,
|
1164
|
-
col_identifier: @layout_strategy.column_classes_for_form_fields,
|
1165
|
-
ownership_field: @ownership_field,
|
1166
|
-
form_labels_position: @form_labels_position,
|
1167
|
-
form_placeholder_labels: @form_placeholder_labels,
|
1168
|
-
alt_lookups: @alt_lookups
|
1169
|
-
)
|
1282
|
+
@template_builder.all_form_fields(layout_strategy: @layout_strategy,
|
1283
|
+
layout_object: @layout_object)
|
1170
1284
|
end
|
1171
1285
|
|
1172
1286
|
def list_label
|
@@ -1179,13 +1293,15 @@ module HotGlue
|
|
1179
1293
|
|
1180
1294
|
def all_line_fields
|
1181
1295
|
@template_builder.all_line_fields(
|
1182
|
-
perc_width: @layout_strategy.each_col, #undefined method `each_col'
|
1183
|
-
columns: @layout_object[:columns][:container],
|
1184
|
-
show_only: @show_only,
|
1185
|
-
singular_class: singular_class,
|
1186
|
-
singular: singular,
|
1187
1296
|
col_identifier: @layout_strategy.column_classes_for_line_fields,
|
1188
|
-
|
1297
|
+
perc_width: @layout_strategy.each_col, #undefined method `each_col'
|
1298
|
+
layout_strategy: @layout_strategy,
|
1299
|
+
layout_object: @layout_object
|
1300
|
+
# columns: @layout_object[:columns][:container],
|
1301
|
+
# show_only: @show_only,
|
1302
|
+
# singular_class: singular_class,
|
1303
|
+
# singular: singular,
|
1304
|
+
# attachments: @attachments
|
1189
1305
|
)
|
1190
1306
|
end
|
1191
1307
|
|
@@ -1216,7 +1332,6 @@ module HotGlue
|
|
1216
1332
|
elsif me.column_names.include?("email") || me.instance_methods(false).include?(:email)
|
1217
1333
|
"email"
|
1218
1334
|
else
|
1219
|
-
# NOT UNREACHABLE BUT UNTESTED
|
1220
1335
|
exit_message = "*** Oops: Can't find any column to use as the display label on #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, 5) email, or 6) number directly on your #{singular_class} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
|
1221
1336
|
raise(HotGlue::Error, exit_message)
|
1222
1337
|
end
|
@@ -1282,8 +1397,8 @@ module HotGlue
|
|
1282
1397
|
end
|
1283
1398
|
|
1284
1399
|
def n_plus_one_includes
|
1285
|
-
if @associations.any?
|
1286
|
-
".includes(" + @associations.map{|x| ":#{x.to_s}"}.join(", ") + ")"
|
1400
|
+
if @associations.any? || @attachments.any?
|
1401
|
+
".includes(" + (@associations.map{|x| x} + @attachments.collect{|k,v| "#{k}_attachment"}).map{|x| ":#{x.to_s}"}.join(", ") + ")"
|
1287
1402
|
else
|
1288
1403
|
""
|
1289
1404
|
end
|
@@ -1319,9 +1434,17 @@ module HotGlue
|
|
1319
1434
|
|
1320
1435
|
def hawk_to_ruby
|
1321
1436
|
res = @hawk_keys.collect{ |k,v|
|
1322
|
-
"#{k}: [#{v[
|
1437
|
+
"#{k.to_s}: [#{v[:bind_to].join(".")}]"
|
1323
1438
|
}.join(", ")
|
1324
1439
|
res
|
1325
1440
|
end
|
1441
|
+
|
1442
|
+
def controller_attachment_orig_filename_pickup_syntax
|
1443
|
+
@attachments.collect{ |key, attachment| "\n" + " modified_params[:#{ attachment[:field_for_original_filename] }] = #{singular_name}_params['#{ key }'].original_filename" if attachment[:field_for_original_filename] }.compact.join("\n")
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
def any_datetime_fields?
|
1447
|
+
(@columns - @attachments.keys.collect(&:to_sym)).collect{|col| eval("#{singular_class}.columns_hash['#{col}']").type}.include?(:datetime)
|
1448
|
+
end
|
1326
1449
|
end
|
1327
1450
|
end
|
@@ -41,20 +41,25 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
41
41
|
<% else %>
|
42
42
|
@<%= @nested_set[0][:singular] %> ||= <%= root_object %>.find(params[:<%= @nested_set[0][:singular] %>_id])<%= " if params.include?(:#{@nested_set[0][:singular]}_id)" if @nested_set[0][:optional] %> <% end %>
|
43
43
|
end
|
44
|
-
<% end %><% if any_nested? %><% nest_chain = [@nested_set[0][:singular]];
|
45
|
-
<%
|
44
|
+
<% end %><% if any_nested? %><% nest_chain = [@nested_set[0][:singular]]; %>
|
45
|
+
<% for index in 1..(@nested_set.count - 1) do
|
46
46
|
arg = @nested_set[index]
|
47
|
+
|
47
48
|
last_arg = (index == 0 ? nil : @nested_set[index-1])
|
48
49
|
|
49
50
|
this_scope = "#{nest_chain.last}.#{arg[:plural]}"
|
50
|
-
nest_chain << arg %>
|
51
|
-
<% unless @nested_set[0][:singular] == arg[:singular] %>
|
51
|
+
nest_chain << arg[:singular] %>
|
52
52
|
def <%= arg[:singular] %>
|
53
|
-
@<%=
|
53
|
+
@<%= arg[:singular] %> ||= (<%= this_scope; %>.find(params[:<%= arg[:singular] %>_id]) <%= " if params.include?(:#{last_arg[:singular]}_id)" if last_arg && @god && last_arg[:optional] %>)
|
54
54
|
<% if @god && last_arg && (last_arg[:optional] ) %>@<%= arg[:singular] %> ||= (<%= collect_objects[index-1] %>.find(params[:<%= arg[:singular] %>_id]) if params.include?(:<%= arg[:singular] %>_id) ) <% end %>
|
55
|
-
end<% end %><% end
|
55
|
+
end<% end %><% end %>
|
56
|
+
<% if !@self_auth %>
|
56
57
|
def load_<%= singular_name %>
|
57
|
-
|
58
|
+
<% if @nested_set[0] && @nested_set[0][:optional] %>if params.include?(:<%= @nested_set.last[:singular] %>_id)
|
59
|
+
@<%= singular_name %> = <%= object_scope.gsub("@",'') %>.find(params[:id])
|
60
|
+
else
|
61
|
+
<% end %>@<%= singular_name %> = <%= object_scope %>.find(params[:id])<% if @nested_set[0] && @nested_set[0][:optional] %>
|
62
|
+
end<% end %>
|
58
63
|
end
|
59
64
|
<% else %>
|
60
65
|
def load_<%= singular_name %>
|
@@ -83,8 +88,9 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
83
88
|
" #{data[:assoc].downcase} = #{data[:assoc]}.#{data[:with_create] ? "find_or_create_by" : "find_by"}(#{data[:lookup_as]}: #{ singular_name }_params[:__lookup_#{data[:lookup_as]}])\n"
|
84
89
|
}.join("/n") %><% end %> <% merge_lookups = @alt_lookups.collect{|key, data| "#{key.gsub("_id", "")}: #{key.gsub("_id", "")}" }.join(",") %>
|
85
90
|
modified_params = modify_date_inputs_on_params(<%= singular_name %>_params.dup<%= controller_update_params_tap_away_alt_lookups %><% if @object_owner_sym && eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %>.merge!(<% if @object_owner_optional && any_nested? %><%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}<% else %><%= @object_owner_sym %>: <%= @object_owner_eval %><% end %>)<% end %>)<%= ".merge(#{merge_lookups})" if !merge_lookups.empty? %><% if @hawk_keys.any? %>
|
86
|
-
modified_params = hawk_params({<%= hawk_to_ruby %>}, modified_params)<% end %>
|
91
|
+
modified_params = hawk_params({<%= hawk_to_ruby %>}, modified_params)<% end %><%= controller_attachment_orig_filename_pickup_syntax %>
|
87
92
|
<%= creation_syntax %>
|
93
|
+
|
88
94
|
if @<%= singular_name %>.save
|
89
95
|
flash[:notice] = "Successfully created #{@<%= singular %>.<%= display_class %>}"
|
90
96
|
load_all_<%= plural %>
|
@@ -116,7 +122,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
116
122
|
}.join("/n") %><% end %><% if (@update_alt_lookups).any? %>
|
117
123
|
<%= @update_alt_lookups.collect{|key, data|
|
118
124
|
" @#{ singular_name }.#{key.gsub("_id", "")} = #{key.gsub("_id", "")}"
|
119
|
-
}.join("/n") %><% end %>
|
125
|
+
}.join("/n") %><% end %><%= controller_attachment_orig_filename_pickup_syntax %>
|
120
126
|
if @<%= singular_name %>.update(modified_params)
|
121
127
|
<% if @display_list_after_update %> load_all_<%= plural %><% end %>
|
122
128
|
flash[:notice] = (flash[:notice] || "") << "Saved #{@<%= singular %>.<%= display_class %>}"
|