hot-glue 0.5.7 → 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/.github/FUNDING.yml +1 -1
- data/.gitignore +2 -1
- data/Gemfile +1 -1
- data/LICENSE +12 -5
- data/README.md +323 -143
- 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 -7
- data/lib/generators/hot_glue/layout_strategy/base.rb +2 -0
- data/lib/generators/hot_glue/layout_strategy/bootstrap.rb +16 -3
- data/lib/generators/hot_glue/markup_templates/erb.rb +186 -127
- data/lib/generators/hot_glue/scaffold_generator.rb +269 -142
- data/lib/generators/hot_glue/templates/controller.rb.erb +19 -11
- 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 +31 -13
- 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
|
|
479
|
+
|
480
|
+
|
440
481
|
@menu_file_exists = true if @nested_set.none? && File.exist?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
|
441
482
|
|
442
483
|
@turbo_streams = !!options['with_turbo_streams']
|
443
484
|
|
444
485
|
|
445
|
-
# syntax should be xyz_id{xyz_email},abc_id{abc_email}
|
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`)
|
448
486
|
|
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
487
|
|
456
|
-
data = {lookup_as: lookup_as.gsub("+",""),
|
457
|
-
assoc: assoc,
|
458
|
-
with_create: lookup_as.include?("+")}
|
459
|
-
@alt_lookups[key] = data
|
460
|
-
end
|
461
488
|
|
462
|
-
puts "------ ALT LOOKUPS for #{@alt_lookups}"
|
463
489
|
|
464
|
-
@update_alt_lookups = @alt_lookups.collect{|key, value|
|
465
|
-
@update_show_only.include?(key) ?
|
466
|
-
{ key: value }
|
467
|
-
: nil}.compact
|
468
|
-
|
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
|
-
|
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
|
|
@@ -480,16 +496,19 @@ module HotGlue
|
|
480
496
|
|
481
497
|
|
482
498
|
def creation_syntax
|
499
|
+
|
500
|
+
merge_with = @alt_lookups.collect{ |key, data|
|
501
|
+
"#{data[:assoc].downcase}: #{data[:assoc].downcase}_factory.#{data[:assoc].downcase}"
|
502
|
+
}.join(", ")
|
503
|
+
|
483
504
|
if @factory_creation == ''
|
484
505
|
"@#{singular_name } = #{ class_name }.create(modified_params)"
|
485
506
|
else
|
486
507
|
"#{@factory_creation}\n" +
|
487
|
-
" @#{singular_name } = #{ class_name }.create(modified_params)"
|
508
|
+
" @#{singular_name } = #{ class_name }.create(modified_params#{'.merge(' + merge_with + ')' if !merge_with.empty?})"
|
488
509
|
end
|
489
510
|
end
|
490
|
-
|
491
|
-
|
492
|
-
|
511
|
+
|
493
512
|
def setup_hawk_keys
|
494
513
|
@hawk_keys = {}
|
495
514
|
|
@@ -506,24 +525,115 @@ module HotGlue
|
|
506
525
|
end
|
507
526
|
|
508
527
|
hawk_scope = key.gsub("_id", "").pluralize
|
509
|
-
|
510
|
-
|
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}
|
531
|
+
use_shorthand = !options["hawk"].include?("{")
|
511
532
|
|
512
533
|
if use_shorthand # only include the hawk scope if using the shorthand
|
513
|
-
@hawk_keys[key.to_sym] << hawk_scope
|
534
|
+
@hawk_keys[key.to_sym][:bind_to] << hawk_scope
|
514
535
|
end
|
536
|
+
|
515
537
|
end
|
516
538
|
|
517
539
|
puts "HAWKING: #{@hawk_keys}"
|
518
540
|
end
|
519
541
|
end
|
520
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
|
+
|
521
630
|
def identify_object_owner
|
522
631
|
auth_assoc = @auth && @auth.gsub("current_","")
|
523
632
|
|
524
633
|
if @object_owner_sym && ! @self_auth
|
525
634
|
auth_assoc_field = auth_assoc + "_id" unless @god
|
526
635
|
assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
|
636
|
+
|
527
637
|
if assoc
|
528
638
|
@ownership_field = assoc.name.to_s + "_id"
|
529
639
|
elsif ! @nested_set.any?
|
@@ -558,54 +668,70 @@ module HotGlue
|
|
558
668
|
|
559
669
|
@columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| @exclude_fields.include?(field) }
|
560
670
|
|
671
|
+
|
561
672
|
else
|
562
673
|
@columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) }
|
563
674
|
end
|
564
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
|
+
|
565
684
|
|
566
685
|
@associations = []
|
686
|
+
|
567
687
|
@columns.each do |col|
|
568
688
|
if col.to_s.starts_with?("_")
|
569
689
|
@show_only << col
|
570
690
|
end
|
571
691
|
|
572
|
-
if @the_object.columns_hash
|
573
|
-
if col.to_s.
|
574
|
-
|
575
|
-
|
576
|
-
|
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
|
-
assoc_class.
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
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
|
607
729
|
end
|
608
730
|
end
|
731
|
+
elsif @attachments.keys.include?(col)
|
732
|
+
|
733
|
+
else
|
734
|
+
raise "couldn't find #{col} in either field list or attachments list"
|
609
735
|
end
|
610
736
|
end
|
611
737
|
end
|
@@ -638,7 +764,7 @@ module HotGlue
|
|
638
764
|
end
|
639
765
|
|
640
766
|
unless @no_specs
|
641
|
-
dest_file = File.join("#{'spec/dummy/' if Rails.env.test?}spec/
|
767
|
+
dest_file = File.join("#{'spec/dummy/' if Rails.env.test?}spec/features#{namespace_with_dash}", "#{plural}_behavior_spec.rb")
|
642
768
|
|
643
769
|
if File.exist?(dest_file)
|
644
770
|
existing_file = File.open(dest_file)
|
@@ -668,7 +794,7 @@ module HotGlue
|
|
668
794
|
end
|
669
795
|
|
670
796
|
def spec_related_column_lets
|
671
|
-
(@columns - @show_only).map { |col|
|
797
|
+
(@columns - @show_only - @attachments.keys).map { |col|
|
672
798
|
type = eval("#{singular_class}.columns_hash['#{col}']").type
|
673
799
|
if (type == :integer && col.to_s.ends_with?("_id") || type == :uuid)
|
674
800
|
assoc = "#{col.to_s.gsub('_id','')}"
|
@@ -682,14 +808,15 @@ module HotGlue
|
|
682
808
|
|
683
809
|
def list_column_headings
|
684
810
|
@template_builder.list_column_headings(
|
685
|
-
|
811
|
+
layout_object: @layout_object,
|
686
812
|
col_identifier: @layout_strategy.column_classes_for_column_headings,
|
687
|
-
column_width: @layout_strategy.column_width
|
813
|
+
column_width: @layout_strategy.column_width,
|
814
|
+
singular: @singular
|
688
815
|
)
|
689
816
|
end
|
690
817
|
|
691
818
|
def columns_spec_with_sample_data
|
692
|
-
@columns.map { |c|
|
819
|
+
(@columns - @attachments.keys).map { |c|
|
693
820
|
type = eval("#{singular_class}.columns_hash['#{c}']").type
|
694
821
|
random_data = case type
|
695
822
|
when :integer
|
@@ -711,23 +838,25 @@ module HotGlue
|
|
711
838
|
end
|
712
839
|
|
713
840
|
def object_parent_mapping_as_argument_for_specs
|
841
|
+
|
714
842
|
if @self_auth
|
715
843
|
""
|
716
|
-
elsif @nested_set.any?
|
844
|
+
elsif @nested_set.any? && ! @nested_set.last[:optional]
|
717
845
|
", " + @nested_set.last[:singular] + ": " + @nested_set.last[:singular]
|
718
|
-
elsif @auth
|
846
|
+
elsif @auth && !@god
|
719
847
|
", #{@auth_identifier}: #{@auth}"
|
720
848
|
end
|
721
849
|
end
|
722
850
|
|
723
851
|
def objest_nest_factory_setup
|
724
|
-
|
852
|
+
# TODO: figure out what this is for
|
853
|
+
res = ""
|
725
854
|
if @auth
|
726
855
|
last_parent = ", #{@auth_identifier}: #{@auth}"
|
727
856
|
end
|
728
857
|
|
729
858
|
@nested_set.each do |arg|
|
730
|
-
res << "let(:#{arg[:singular]}) {create(:#{arg[:singular]} #{last_parent} )}\n"
|
859
|
+
res << " let(:#{arg[:singular]}) {create(:#{arg[:singular]} #{last_parent} )}\n"
|
731
860
|
last_parent = ", #{arg[:singular]}: #{arg[:singular]}"
|
732
861
|
end
|
733
862
|
res
|
@@ -764,7 +893,7 @@ module HotGlue
|
|
764
893
|
end
|
765
894
|
|
766
895
|
def test_capybara_block(which_partial = :create)
|
767
|
-
(@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|
|
768
897
|
type = eval("#{singular_class}.columns_hash['#{col}']").type
|
769
898
|
case type
|
770
899
|
when :date
|
@@ -1150,19 +1279,8 @@ module HotGlue
|
|
1150
1279
|
end
|
1151
1280
|
|
1152
1281
|
def form_fields_html
|
1153
|
-
@template_builder.all_form_fields(
|
1154
|
-
|
1155
|
-
show_only: @show_only,
|
1156
|
-
update_show_only: @update_show_only,
|
1157
|
-
singular_class: singular_class,
|
1158
|
-
singular: singular,
|
1159
|
-
hawk_keys: @hawk_keys,
|
1160
|
-
col_identifier: @layout_strategy.column_classes_for_form_fields,
|
1161
|
-
ownership_field: @ownership_field,
|
1162
|
-
form_labels_position: @form_labels_position,
|
1163
|
-
form_placeholder_labels: @form_placeholder_labels,
|
1164
|
-
alt_lookups: @alt_lookups
|
1165
|
-
)
|
1282
|
+
@template_builder.all_form_fields(layout_strategy: @layout_strategy,
|
1283
|
+
layout_object: @layout_object)
|
1166
1284
|
end
|
1167
1285
|
|
1168
1286
|
def list_label
|
@@ -1175,13 +1293,15 @@ module HotGlue
|
|
1175
1293
|
|
1176
1294
|
def all_line_fields
|
1177
1295
|
@template_builder.all_line_fields(
|
1178
|
-
perc_width: @layout_strategy.each_col, #undefined method `each_col'
|
1179
|
-
columns: @layout_object[:columns][:container],
|
1180
|
-
show_only: @show_only,
|
1181
|
-
singular_class: singular_class,
|
1182
|
-
singular: singular,
|
1183
1296
|
col_identifier: @layout_strategy.column_classes_for_line_fields,
|
1184
|
-
|
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
|
1185
1305
|
)
|
1186
1306
|
end
|
1187
1307
|
|
@@ -1212,7 +1332,6 @@ module HotGlue
|
|
1212
1332
|
elsif me.column_names.include?("email") || me.instance_methods(false).include?(:email)
|
1213
1333
|
"email"
|
1214
1334
|
else
|
1215
|
-
# NOT UNREACHABLE BUT UNTESTED
|
1216
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)"
|
1217
1336
|
raise(HotGlue::Error, exit_message)
|
1218
1337
|
end
|
@@ -1259,7 +1378,7 @@ module HotGlue
|
|
1259
1378
|
|
1260
1379
|
def controller_update_params_tap_away_magic_buttons
|
1261
1380
|
@magic_buttons.collect{ |magic_button|
|
1262
|
-
".tap{ |ary| ary.delete('#{magic_button}') }"
|
1381
|
+
".tap{ |ary| ary.delete('__#{magic_button}') }"
|
1263
1382
|
}.join("")
|
1264
1383
|
end
|
1265
1384
|
|
@@ -1278,8 +1397,8 @@ module HotGlue
|
|
1278
1397
|
end
|
1279
1398
|
|
1280
1399
|
def n_plus_one_includes
|
1281
|
-
if @associations.any?
|
1282
|
-
".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(", ") + ")"
|
1283
1402
|
else
|
1284
1403
|
""
|
1285
1404
|
end
|
@@ -1315,9 +1434,17 @@ module HotGlue
|
|
1315
1434
|
|
1316
1435
|
def hawk_to_ruby
|
1317
1436
|
res = @hawk_keys.collect{ |k,v|
|
1318
|
-
"#{k}: [#{v[
|
1437
|
+
"#{k.to_s}: [#{v[:bind_to].join(".")}]"
|
1319
1438
|
}.join(", ")
|
1320
1439
|
res
|
1321
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
|
1322
1449
|
end
|
1323
1450
|
end
|