hot-glue 0.4.6 → 0.4.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +71 -0
  3. data/.github/FUNDING.yml +2 -2
  4. data/.gitignore +4 -1
  5. data/Gemfile +5 -1
  6. data/Gemfile.lock +16 -16
  7. data/README.md +333 -314
  8. data/README2.md +79 -0
  9. data/config/database.yml +8 -83
  10. data/db/schema.rb +1 -0
  11. data/lib/generators/hot_glue/install_generator.rb +0 -1
  12. data/lib/generators/hot_glue/layout/builder.rb +51 -33
  13. data/lib/generators/hot_glue/markup_templates/erb.rb +97 -88
  14. data/lib/generators/hot_glue/scaffold_generator.rb +259 -95
  15. data/lib/generators/hot_glue/templates/controller.rb.erb +51 -47
  16. data/lib/generators/hot_glue/templates/erb/_form.erb +3 -2
  17. data/lib/generators/hot_glue/templates/erb/_line.erb +1 -1
  18. data/lib/generators/hot_glue/templates/erb/_list.erb +19 -12
  19. data/lib/generators/hot_glue/templates/erb/_new_button.erb +1 -1
  20. data/lib/generators/hot_glue/templates/erb/_new_form.erb +4 -3
  21. data/lib/generators/hot_glue/templates/erb/_show.erb +10 -6
  22. data/lib/generators/hot_glue/templates/erb/create.turbo_stream.erb +4 -4
  23. data/lib/generators/hot_glue/templates/erb/destroy.turbo_stream.erb +2 -2
  24. data/lib/generators/hot_glue/templates/erb/edit.erb +2 -2
  25. data/lib/generators/hot_glue/templates/erb/index.erb +1 -1
  26. data/lib/generators/hot_glue/templates/erb/new.erb +1 -1
  27. data/lib/generators/hot_glue/templates/erb/update.turbo_stream.erb +2 -2
  28. data/lib/hotglue/version.rb +3 -1
  29. metadata +5 -19
  30. data/db/schema.rb +0 -60
  31. data/lib/generators/hot_glue/markup_templates/haml.rb +0 -243
  32. data/lib/generators/hot_glue/markup_templates/slim.rb +0 -9
@@ -3,8 +3,8 @@ require 'ffaker'
3
3
 
4
4
  require_relative './markup_templates/base'
5
5
  require_relative './markup_templates/erb'
6
- require_relative './markup_templates/haml'
7
- require_relative './markup_templates/slim'
6
+ # require_relative './markup_templates/haml'
7
+ # require_relative './markup_templates/slim'
8
8
 
9
9
  require_relative './layout/builder'
10
10
 
@@ -12,6 +12,59 @@ module HotGlue
12
12
  class Error < StandardError
13
13
  end
14
14
 
15
+ def self.construct_downnest_object(input)
16
+ res = input.split(",").map { |child|
17
+ child_name = child.gsub("+","")
18
+ extra_size = child.count("+")
19
+ {child_name => 4+extra_size}
20
+ }
21
+ Hash[*res.collect{|hash| hash.collect{|key,value| [key,value].flatten}.flatten}.flatten]
22
+ end
23
+
24
+ def self.optionalized_ternary(params)
25
+ namespace = params[:namespace] || nil
26
+ target = params[:target]
27
+ nested_set = params[:nested_set]
28
+ modifier = params[:modifier] || ""
29
+ with_params = params[:with_params] || false
30
+ top_level = params[:top_level] || false
31
+
32
+ instance_sym = top_level ? "@" : ""
33
+
34
+ put_form = params[:put_form] || false
35
+
36
+ if nested_set.nil? || nested_set.empty?
37
+ return modifier + "#{(namespace + '_') if namespace}#{target}_path" + (("(#{instance_sym}#{target})" if put_form) || "")
38
+ elsif nested_set[0][:optional] == false
39
+ return modifier + ((namespace + "_" if namespace) || "") + nested_set.collect{|x|
40
+ x[:singular] + "_"
41
+ }.join() + target + "_path" + (("(#{nested_set.collect{
42
+ |x| instance_sym + x[:singular] }.join(",")
43
+ }#{ put_form ? ',' + instance_sym + target : '' })" if with_params) || "")
44
+
45
+ else
46
+ # copy the first item, make a ternery in this cycle, and recursively move to both the
47
+ # is present path and the is optional path
48
+
49
+ nonoptional = nested_set[0].dup
50
+ nonoptional[:optional] = false
51
+ rest_of_nest = nested_set[1..-1]
52
+
53
+ all_params = {namespace: namespace,
54
+ target: target,
55
+ modifier: modifier,
56
+ top_level: top_level,
57
+ with_params: with_params,
58
+ put_form: put_form}
59
+ is_present_path = HotGlue.optionalized_ternary(all_params.merge({ nested_set: [nonoptional, *rest_of_nest]}) )
60
+
61
+ is_missing_path = HotGlue.optionalized_ternary(all_params.merge({ nested_set: rest_of_nest}) )
62
+
63
+
64
+ return "defined?(#{instance_sym + nested_set[0][:singular]}) ? #{is_present_path} : #{is_missing_path}"
65
+ end
66
+ end
67
+
15
68
  def self.derrive_reference_name(thing_as_string)
16
69
  assoc_class = eval(thing_as_string)
17
70
 
@@ -41,7 +94,10 @@ module HotGlue
41
94
  class_option :singular, type: :string, default: nil
42
95
  class_option :plural, type: :string, default: nil
43
96
  class_option :singular_class, type: :string, default: nil
44
- class_option :nest, type: :string, default: ""
97
+ class_option :nest, type: :string, default: nil # DEPRECATED —— DO NOT USE
98
+ class_option :nested, type: :string, default: ""
99
+
100
+
45
101
  class_option :namespace, type: :string, default: nil
46
102
  class_option :auth, type: :string, default: nil
47
103
  class_option :auth_identifier, type: :string, default: nil
@@ -70,7 +126,9 @@ module HotGlue
70
126
  class_option :markup, type: :string, default: nil # deprecated -- use in app config instead
71
127
  class_option :layout, type: :string, default: nil # if used here it will override what is in the config
72
128
  class_option :no_list_labels, type: :boolean, default: false
73
- class_option :alt_controller_name, type: :string, default: nil
129
+ class_option :no_list_heading, type: :boolean, default: false
130
+
131
+ class_option :before_list_labels, type: :boolean, default: false
74
132
 
75
133
  def initialize(*meta_args)
76
134
  super
@@ -144,35 +202,42 @@ module HotGlue
144
202
 
145
203
 
146
204
  @singular = args.first.tableize.singularize # should be in form hello_world
205
+
206
+
207
+ if @singular.include?("/")
208
+ @singular = @singular.split("/").last
209
+ end
210
+
147
211
  @plural = options['plural'] || @singular + "s" # supply to override; leave blank to use default
148
212
  @namespace = options['namespace'] || nil
149
213
 
150
214
 
151
- @alt_controller_name = options['alt_controller_name']
152
- use_controller_name = @alt_controller_name || plural.titleize.gsub(" ", "")
215
+ use_controller_name = plural.titleize.gsub(" ", "")
153
216
 
154
- @controller_build_name = (( @namespace.titleize + "::" if @namespace) || "") + use_controller_name + "Controller"
217
+ @controller_build_name = (( @namespace.titleize.gsub(" ","") + "::" if @namespace) || "") + use_controller_name + "Controller"
155
218
  @controller_build_folder = use_controller_name.underscore
219
+ @controller_build_folder_singular = singular
156
220
 
157
221
  if ! @controller_build_folder.ends_with?("s")
158
222
  raise "can't build with controller name #{@controller_build_folder} because it doesn't end with an 's'"
159
223
  end
160
224
 
161
- if @alt_controller_name
162
- @controller_build_folder_singular = @controller_build_folder.gsub(/s$/,'')
163
- else
164
- @controller_build_folder_singular = singular
165
- end
166
-
167
225
  @auth = options['auth'] || "current_user"
168
226
  @auth_identifier = options['auth_identifier'] || (! @god && @auth.gsub("current_", "")) || nil
169
227
 
170
228
 
171
- @nest = (!options['nest'].empty? && options['nest']) || nil
172
229
 
173
- @singular_class = @singular.titleize.gsub(" ", "")
174
- @exclude_fields = []
230
+ if options['nest']
231
+ raise "STOP: the flag --nest has been replaced with --nested; please re-run using the --nested flag"
175
232
 
233
+ end
234
+
235
+ @nested = (!options['nested'].empty? && options['nested']) || nil
236
+
237
+ @singular_class = args.first # note this is the full class name with a model namespace
238
+
239
+
240
+ @exclude_fields = []
176
241
  @exclude_fields += options['exclude'].split(",").collect(&:to_sym)
177
242
 
178
243
  if !options['include'].empty?
@@ -200,40 +265,76 @@ module HotGlue
200
265
  @no_edit = options['no_edit'] || false
201
266
  @no_list = options['no_list'] || false
202
267
  @no_list_labels = options['no_list_labels'] || false
268
+ @no_list_heading = options['no_list_heading'] || false
269
+
203
270
  @display_list_after_update = options['display_list_after_update'] || false
204
271
  @smart_layout = options['smart_layout']
205
272
 
273
+ if options['include'].include?(":") && @smart_layout
274
+ raise "You specified both --smart-layout and also specified grouping mode (there is a : character in your field include list); you must remove the colon(s) from your --include tag or remove the --smart-layout option"
275
+ end
206
276
 
207
277
 
208
278
  @container_name = @layout == "hotglue" ? "scaffold-container" : "container-fluid"
209
279
  @downnest = options['downnest'] || false
210
280
 
211
- @downnest_children = []
212
-
281
+ @downnest_children = [] # TODO: defactor @downnest_children in favor of downnest_object
282
+ @downnest_object = {}
213
283
  if @downnest
214
- @downnest_children = @downnest.split(",")
284
+ @downnest_children = @downnest.split(",").map{|child| child.gsub("+","")}
285
+ @downnest_object = HotGlue.construct_downnest_object(@downnest)
215
286
  end
216
287
 
217
-
218
288
  if @god
219
289
  @auth = nil
220
290
  end
221
291
 
222
292
  # when in self auth, the object is the same as the authenticated object
293
+
223
294
  if @auth && auth_identifier == @singular
224
295
  @self_auth = true
225
296
  end
226
297
 
298
+ if @self_auth && !@no_create
299
+ raise "This controller appears to be the same as the authentication object but in this context you cannot build a new/create action; please re-run with --no-create flag"
300
+ end
301
+
302
+ # old syntax
227
303
  @nested_args = []
228
- if !@nest.nil?
229
- @nested_args = @nest.split("/")
304
+
305
+ # new syntax
306
+ # @nested_set = [
307
+ # {
308
+ # singular: ...,
309
+ # plural: ...,
310
+ # optional: false
311
+ # }]
312
+ @nested_set = []
313
+
314
+ if ! @nested.nil?
315
+
316
+
317
+ @nested_args = @nested.split("/").collect{|x| x.gsub("~","")}
318
+
319
+ @nested_set = @nested.split("/").collect { |arg|
320
+ is_optional = arg.start_with?("~")
321
+ arg.gsub!("~","")
322
+ {
323
+ singular: arg,
324
+ plural: arg.pluralize,
325
+ optional: is_optional
326
+ }
327
+
328
+ }
329
+
330
+ puts "@nested_set is #{@nested_set}"
230
331
  @nested_args_plural = {}
332
+
333
+
231
334
  @nested_args.each do |a|
232
335
  @nested_args_plural[a] = a + "s"
233
336
  end
234
337
  end
235
- @nestable = @nested_args.any?
236
-
237
338
 
238
339
  @magic_buttons = []
239
340
  if options['magic_buttons']
@@ -250,11 +351,14 @@ module HotGlue
250
351
  if @auth && ! @self_auth && @nested_args.none?
251
352
  @object_owner_sym = @auth.gsub("current_", "").to_sym
252
353
  @object_owner_eval = @auth
354
+ @object_owner_optional = false
253
355
  else
254
356
 
255
357
  if @nested_args.any?
256
- @object_owner_sym = @nested_args.last.to_sym
257
- @object_owner_eval = "@#{@nested_args.last}"
358
+ @object_owner_sym = @nested_set.last[:singular].to_sym
359
+ @object_owner_eval = "@#{@nested_set.last[:singular]}"
360
+ @object_owner_name = @nested_set.last[:singular]
361
+ @object_owner_optional = @nested_set.last[:optional]
258
362
  else
259
363
  @object_owner_sym = ""
260
364
  @object_owner_eval = ""
@@ -266,18 +370,21 @@ module HotGlue
266
370
 
267
371
  if !@ujs_syntax
268
372
  @ujs_syntax = !defined?(Turbo::Engine)
269
- puts "You did not specify ujs_syntax and so I default it to #{@ujs_syntax}"
270
373
  end
271
374
  @reference_name = HotGlue.derrive_reference_name(singular_class)
272
375
 
273
376
  identify_object_owner
274
377
  setup_fields
275
378
 
379
+ if (@columns - @show_only - (@object_owner_sym.empty? ? [] : [@ownership_field.to_sym])).empty?
380
+ @no_field_form = true
381
+ end
382
+
276
383
  buttons_width = ((!@no_edit && 1) || 0) + ((!@no_delete && 1) || 0) + @magic_buttons.count
277
384
 
278
385
  builder = HotGlue::Layout::Builder.new({
279
386
  include_setting: options['include'],
280
- downnest_children: @downnest_children,
387
+ downnest_object: @downnest_object,
281
388
  buttons_width: buttons_width,
282
389
  columns: @columns,
283
390
  smart_layout: @smart_layout
@@ -285,6 +392,7 @@ module HotGlue
285
392
  @layout_object = builder.construct
286
393
 
287
394
  @menu_file_exists = true if @nested_args.none? && File.exists?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
395
+
288
396
  end
289
397
 
290
398
  def identify_object_owner
@@ -292,35 +400,24 @@ module HotGlue
292
400
 
293
401
  if !@object_owner_sym.empty?
294
402
  auth_assoc_field = auth_assoc + "_id" unless @god
295
- assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
296
403
 
404
+ assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
297
405
 
298
406
  if assoc
299
407
  @ownership_field = assoc.name.to_s + "_id"
300
- elsif !@nest
301
- exit_message = "*** Oops: It looks like is no association from current_#{@object_owner_sym} to a class called #{@singular_class}. If your user is called something else, pass with flag auth=current_X where X is the model for your users 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.) To make a controller that can read all records, specify with --god."
408
+ elsif ! @nested_args.any?
302
409
 
303
- else
304
- exit_message = "*** Oops: Missing relationship from class #{singular_class} to :#{@object_owner_sym} \n
305
- maybe add `belongs_to :#{@object_owner_sym}` to #{singular_class}\n
306
- (If your user is called something else, pass with flag auth=current_X where X is the model for your auth object as lowercase.
307
- 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)
410
+ exit_message = "*** Oops: It looks like is no association from class called #{@singular_class} to the current_#{@object_owner_sym}. If your user is called something else, pass with flag auth=current_X where X is the model for your users 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.) To make a controller that can read all records, specify with --god."
411
+ raise(HotGlue::Error, exit_message)
308
412
 
309
- To make a controller that can read all records, specify with --god."
413
+ else
310
414
 
311
- if @god
312
- exit_message << "does #{singular_class} have a relOops: Gd mode could not find the association(#{@object_owner_sym}). Something is wrong."
415
+ if eval(singular_class + ".reflect_on_association(:#{@object_owner_sym.to_s})").nil? && !eval(singular_class + ".reflect_on_association(:#{@object_owner_sym.to_s.singularize})").nil?
416
+ exit_message = "*** Oops: you tried to nest #{singular_class} within a route for `#{@object_owner_sym}` but I can't find an association for this relationship. Did you mean `#{@object_owner_sym.to_s.singularize}` (singular) instead?"
313
417
  else
314
-
315
- @auth_check = eval(@auth_identifier.titleize)
316
- @nested_args.each do |arg|
317
-
318
- if ! @auth_check.reflect_on_association("#{arg}s".to_sym)
319
- exit_message << "... your nesting chain does not have a association for #{arg}s on #{@auth_check} something is wrong."
320
- end
321
- end
418
+ exit_message = "*** 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."
322
419
  end
323
- puts "\n" + exit_message
420
+
324
421
  raise(HotGlue::Error, exit_message)
325
422
  end
326
423
  end
@@ -347,6 +444,7 @@ To make a controller that can read all records, specify with --god."
347
444
  @columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) }
348
445
  end
349
446
 
447
+ @associations = []
350
448
  @columns.each do |col|
351
449
  if col.to_s.starts_with?("_")
352
450
  @show_only << col
@@ -356,11 +454,10 @@ To make a controller that can read all records, specify with --god."
356
454
  if col.to_s.ends_with?("_id")
357
455
  # guess the association name label
358
456
  assoc_name = col.to_s.gsub("_id","")
359
- assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
360
457
 
361
458
 
362
459
  begin
363
- eval(assoc.class_name)
460
+ assoc_model = eval("#{singular_class}.reflect_on_association(:#{assoc_name}).active_record")
364
461
  rescue NameError => e
365
462
  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}; your model #{singular_class.titlecase} should belong_to :#{assoc_name}. To make a controller that can read all records, specify with --god."
366
463
  puts exit_message
@@ -368,20 +465,21 @@ To make a controller that can read all records, specify with --god."
368
465
  end
369
466
 
370
467
 
371
- if assoc.nil?
468
+ if assoc_model.nil?
372
469
  exit_message = "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
373
470
  puts exit_message
374
471
  raise(HotGlue::Error,exit_message)
375
472
  end
376
473
 
377
- assoc_class = eval(assoc.class_name)
474
+ @associations << assoc_name.to_sym
475
+ assoc_class = eval(assoc_model.name)
378
476
  name_list = [:name, :to_label, :full_name, :display_name, :email]
379
477
  if name_list.collect{ |field|
380
478
  assoc_class.column_names.include?(field.to_s) || assoc_class.instance_methods.include?(field)
381
479
  }.any?
382
480
  # do nothing here
383
481
  else
384
- exit_message = "*** Oops: Missing a label for #{assoc.class_name.upcase}. Can't find any column to use as the display label for the #{assoc.name.to_s} association on the #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, or 5) email directly on your #{assoc.class_name.upcase} 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)"
482
+ exit_message = "\n*** 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: \n1) name, \n2) to_label, \n3) full_name, \n4) display_name \n5) email \nYou 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.)"
385
483
  raise(HotGlue::Error,exit_message)
386
484
  end
387
485
  end
@@ -437,16 +535,12 @@ To make a controller that can read all records, specify with --god."
437
535
  end
438
536
 
439
537
  def list_column_headings
440
- if @nested_args.any?
538
+ if @layout == "bootstrap"
539
+ column_width = @layout_object[:columns][:size_each]
540
+ col_identifier = "col-md-#{column_width}"
541
+ elsif @layout == "hotglue"
441
542
  column_width = each_col * @columns.count
442
- else
443
- column_width = 0
444
- end
445
-
446
- if !@smart_layout
447
- col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-1"
448
- else
449
- col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-2"
543
+ col_identifier = "scaffold-cell"
450
544
  end
451
545
 
452
546
  @template_builder.list_column_headings(
@@ -511,6 +605,10 @@ To make a controller that can read all records, specify with --god."
511
605
  @singular
512
606
  end
513
607
 
608
+ def singular_class_name
609
+ @singular_class
610
+ end
611
+
514
612
  def plural_name
515
613
  plural
516
614
  end
@@ -520,7 +618,7 @@ To make a controller that can read all records, specify with --god."
520
618
  end
521
619
 
522
620
  def path_helper_args
523
- if @nested_args.any? && @nest
621
+ if @nested_args.any? && @nested
524
622
  [(@nested_args).collect{|a| "#{a}"} , singular].join(",")
525
623
  else
526
624
  singular
@@ -528,7 +626,7 @@ To make a controller that can read all records, specify with --god."
528
626
  end
529
627
 
530
628
  def path_helper_singular
531
- if @nest
629
+ if @nested
532
630
  "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{@controller_build_folder_singular}_path"
533
631
  else
534
632
  "#{@namespace+"_" if @namespace}#{@controller_build_folder_singular}_path"
@@ -536,16 +634,49 @@ To make a controller that can read all records, specify with --god."
536
634
  end
537
635
 
538
636
  def path_helper_plural
539
- if ! @nest
540
- "#{@namespace+"_" if @namespace}#{@controller_build_folder}_path"
541
- else
542
- "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{plural}_path"
543
- end
637
+ HotGlue.optionalized_ternary(namespace: @namespace,
638
+ target: @controller_build_folder,
639
+ nested_set: @nested_set)
640
+ end
641
+
642
+ def form_path_new_helper
643
+ HotGlue.optionalized_ternary(namespace: @namespace,
644
+ target: @controller_build_folder,
645
+ nested_set: @nested_set,
646
+ with_params: true,
647
+ top_level: false)
648
+ end
649
+
650
+ def form_path_edit_helper
651
+ HotGlue.optionalized_ternary(namespace: @namespace,
652
+ target: @singular,
653
+ nested_set: @nested_set,
654
+ with_params: true,
655
+ put_form: true,
656
+ top_level: true)
657
+ end
658
+
659
+
660
+ def delete_path_helper
661
+ HotGlue.optionalized_ternary(namespace: @namespace,
662
+ target: @singular,
663
+ nested_set: @nested_set,
664
+ with_params: true,
665
+ put_form: true)
666
+ end
667
+
668
+ def edit_path_helper
669
+ HotGlue.optionalized_ternary(namespace: @namespace,
670
+ target: @singular,
671
+ nested_set: @nested_set,
672
+ modifier: "edit_",
673
+ with_params: true,
674
+ put_form: true)
544
675
  end
545
676
 
546
677
  def path_arity
547
678
  res = ""
548
- if @nested_args.any? && @nest
679
+ if @nested_args.any? && @nested
549
680
  res << nested_objects_arity + ", "
550
681
  end
551
682
  res << "@" + singular
@@ -564,13 +695,19 @@ To make a controller that can read all records, specify with --god."
564
695
  end
565
696
 
566
697
  def new_path_name
567
- base = "new_#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_") if @nested_args.any?}#{@controller_build_folder_singular}_path"
568
- if @nested_args.any?
569
- base += "(" + @nested_args.collect { |arg|
570
- "#{arg}.id"
571
- }.join(", ") + ")"
572
- end
573
- base
698
+
699
+ HotGlue.optionalized_ternary(namespace: @namespace,
700
+ target: singular,
701
+ nested_set: @nested_set,
702
+ modifier: "new_",
703
+ with_params: true)
704
+ # base = "new_#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_") if @nested_args.any?}#{@controller_build_folder_singular}_path"
705
+ # if @nested_args.any?
706
+ # base += "(" + @nested_args.collect { |arg|
707
+ # "#{arg}.id"
708
+ # }.join(", ") + ")"
709
+ # end
710
+ # base
574
711
  end
575
712
 
576
713
  def nested_assignments
@@ -585,7 +722,7 @@ To make a controller that can read all records, specify with --god."
585
722
 
586
723
  def nest_assignments_operator(top_level = false, leading_comma = false)
587
724
  if @nested_args.any?
588
- "#{', ' + "\n " if leading_comma}#{top_level ? nested_assignments_top_level : nested_assignments }"
725
+ "#{", " if leading_comma}#{top_level ? nested_assignments_top_level : nested_assignments }"
589
726
  else
590
727
  ""
591
728
  end
@@ -654,8 +791,11 @@ To make a controller that can read all records, specify with --god."
654
791
 
655
792
  def magic_button_output
656
793
  @template_builder.magic_button_output(
657
- path_helper_singular: path_helper_singular,
658
- path_helper_args: path_helper_args,
794
+ path: HotGlue.optionalized_ternary(namespace: @namespace,
795
+ target: @singular,
796
+ nested_set: @nested_set,
797
+ with_params: true,
798
+ put_form: true),
659
799
  singular: singular,
660
800
  magic_buttons: @magic_buttons,
661
801
  small_buttons: @small_buttons
@@ -767,19 +907,15 @@ To make a controller that can read all records, specify with --god."
767
907
  end
768
908
 
769
909
  def all_form_fields
770
- # TODO: DRY THIS
771
- if !@smart_layout
772
- col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-1"
773
- else
774
- col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-2"
775
- end
910
+ col_identifier = (@layout == "hotglue") ? "scaffold-cell" : "col-md-#{@layout_object[:columns][:size_each]}"
776
911
 
777
912
  @template_builder.all_form_fields(
778
913
  columns: @layout_object[:columns][:container],
779
914
  show_only: @show_only,
780
915
  singular_class: singular_class,
781
916
  singular: singular,
782
- col_identifier: col_identifier
917
+ col_identifier: col_identifier,
918
+ ownership_field: @ownership_field
783
919
  )
784
920
  end
785
921
 
@@ -787,6 +923,22 @@ To make a controller that can read all records, specify with --god."
787
923
  @each_col ||= each_col
788
924
  end
789
925
 
926
+ def list_label
927
+ if(eval("#{class_name}.class_variable_defined?(:@@table_label_plural)"))
928
+ eval("#{class_name}.class_variable_get(:@@table_label_plural)")
929
+ else
930
+ plural.gsub("_", " ").upcase
931
+ end
932
+ end
933
+
934
+ def thing_label
935
+ if(eval("#{class_name}.class_variable_defined?(:@@table_label_singular)"))
936
+ eval("#{class_name}.class_variable_get(:@@table_label_singular)")
937
+ else
938
+ singular.gsub("_", " ").upcase
939
+ end
940
+ end
941
+
790
942
  def each_col
791
943
  return col_width if @columns.count == 0
792
944
  (col_width/(@columns.count)).to_i
@@ -808,6 +960,7 @@ To make a controller that can read all records, specify with --god."
808
960
  end
809
961
 
810
962
  def all_line_fields
963
+ col_identifier = (@layout == "hotglue") ? "scaffold-cell" : "col-md-#{@layout_object[:columns][:size_each]}"
811
964
 
812
965
  @template_builder.all_line_fields(
813
966
  perc_width: column_width,
@@ -815,13 +968,14 @@ To make a controller that can read all records, specify with --god."
815
968
  show_only: @show_only,
816
969
  singular_class: singular_class,
817
970
  singular: singular,
818
- layout: @layout
971
+ layout: @layout,
972
+ col_identifier: col_identifier
819
973
  )
820
974
  end
821
975
 
822
976
  def controller_descends_from
823
- if defined?(@namespace.titlecase + "::BaseController")
824
- @namespace.titlecase + "::BaseController"
977
+ if defined?(@namespace.titlecase.gsub(" ", "") + "::BaseController")
978
+ @namespace.titlecase.gsub(" ", "") + "::BaseController"
825
979
  else
826
980
  "ApplicationController"
827
981
  end
@@ -908,10 +1062,19 @@ To make a controller that can read all records, specify with --god."
908
1062
 
909
1063
 
910
1064
  def nested_for_turbo_id_list_constructor
911
- if @nested_args.none?
1065
+ if @nested_set.any?
1066
+ '+ (((\'__\' + nested_for) if defined?(nested_for)) || "")'
1067
+ else
912
1068
  ""
1069
+ end
1070
+ end
1071
+
1072
+
1073
+ def n_plus_one_includes
1074
+ if @associations.any?
1075
+ ".includes(" + @associations.map{|x| ":#{x.to_s}"}.join(", ") + ")"
913
1076
  else
914
- "+ ('__' + nested_for)"
1077
+ ""
915
1078
  end
916
1079
  end
917
1080
 
@@ -919,9 +1082,11 @@ To make a controller that can read all records, specify with --god."
919
1082
  instance_symbol = "@" if top_level
920
1083
  instance_symbol = "" if !top_level
921
1084
  if @nested_args.none?
922
- ""
1085
+ "\"\""
923
1086
  else
924
- "__" + @nested_args.collect{|a| "#{a}-" + '#{' + instance_symbol + a + '.id}'}.join("__")
1087
+ @nested_set.collect{|arg|
1088
+ "(((\"__#{arg[:singular]}-\#{" + "@" + arg[:singular] + ".id}\") if @" + arg[:singular] + ") || \"\")"
1089
+ }.join(" + ")
925
1090
  end
926
1091
  end
927
1092
 
@@ -935,7 +1100,6 @@ To make a controller that can read all records, specify with --god."
935
1100
  end
936
1101
  end
937
1102
 
938
-
939
1103
  private # thor does something fancy like sending the class all of its own methods during some strange run sequence
940
1104
  # does not like public methods
941
1105
  def cc_filename_with_extensions(name, file_format = format)