hot-glue 0.4.5 → 0.4.9

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 +340 -251
  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 +292 -91
  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 +31 -21
  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 +6 -20
  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
@@ -69,7 +125,10 @@ module HotGlue
69
125
  class_option :smart_layout, type: :boolean, default: false
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
128
+ class_option :no_list_labels, type: :boolean, default: false
129
+ class_option :no_list_heading, type: :boolean, default: false
72
130
 
131
+ class_option :before_list_labels, type: :boolean, default: false
73
132
 
74
133
  def initialize(*meta_args)
75
134
  super
@@ -140,18 +199,45 @@ module HotGlue
140
199
  end
141
200
 
142
201
  args = meta_args[0]
202
+
203
+
143
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
+
144
211
  @plural = options['plural'] || @singular + "s" # supply to override; leave blank to use default
212
+ @namespace = options['namespace'] || nil
213
+
214
+
215
+ use_controller_name = plural.titleize.gsub(" ", "")
216
+
217
+ @controller_build_name = (( @namespace.titleize.gsub(" ","") + "::" if @namespace) || "") + use_controller_name + "Controller"
218
+ @controller_build_folder = use_controller_name.underscore
219
+ @controller_build_folder_singular = singular
220
+
221
+ if ! @controller_build_folder.ends_with?("s")
222
+ raise "can't build with controller name #{@controller_build_folder} because it doesn't end with an 's'"
223
+ end
224
+
145
225
  @auth = options['auth'] || "current_user"
146
226
  @auth_identifier = options['auth_identifier'] || (! @god && @auth.gsub("current_", "")) || nil
147
227
 
148
228
 
149
- @nest = (!options['nest'].empty? && options['nest']) || nil
150
- @namespace = options['namespace'] || nil
151
229
 
152
- @singular_class = @singular.titleize.gsub(" ", "")
153
- @exclude_fields = []
230
+ if options['nest']
231
+ raise "STOP: the flag --nest has been replaced with --nested; please re-run using the --nested flag"
232
+
233
+ end
234
+
235
+ @nested = (!options['nested'].empty? && options['nested']) || nil
154
236
 
237
+ @singular_class = args.first # note this is the full class name with a model namespace
238
+
239
+
240
+ @exclude_fields = []
155
241
  @exclude_fields += options['exclude'].split(",").collect(&:to_sym)
156
242
 
157
243
  if !options['include'].empty?
@@ -166,7 +252,6 @@ module HotGlue
166
252
  @show_only += options['show_only'].split(",").collect(&:to_sym)
167
253
  end
168
254
 
169
-
170
255
  @god = options['god'] || options['gd'] || false
171
256
  @specs_only = options['specs_only'] || false
172
257
 
@@ -179,41 +264,77 @@ module HotGlue
179
264
 
180
265
  @no_edit = options['no_edit'] || false
181
266
  @no_list = options['no_list'] || false
267
+ @no_list_labels = options['no_list_labels'] || false
268
+ @no_list_heading = options['no_list_heading'] || false
182
269
 
183
270
  @display_list_after_update = options['display_list_after_update'] || false
184
271
  @smart_layout = options['smart_layout']
185
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
186
276
 
187
- @container_name = @layout == "hotglue" ? "scaffold-container" : "container-fluid"
188
277
 
278
+ @container_name = @layout == "hotglue" ? "scaffold-container" : "container-fluid"
189
279
  @downnest = options['downnest'] || false
190
280
 
191
- @downnest_children = []
192
-
281
+ @downnest_children = [] # TODO: defactor @downnest_children in favor of downnest_object
282
+ @downnest_object = {}
193
283
  if @downnest
194
- @downnest_children = @downnest.split(",")
284
+ @downnest_children = @downnest.split(",").map{|child| child.gsub("+","")}
285
+ @downnest_object = HotGlue.construct_downnest_object(@downnest)
195
286
  end
196
287
 
197
-
198
288
  if @god
199
289
  @auth = nil
200
290
  end
201
291
 
202
292
  # when in self auth, the object is the same as the authenticated object
293
+
203
294
  if @auth && auth_identifier == @singular
204
295
  @self_auth = true
205
296
  end
206
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
207
303
  @nested_args = []
208
- if !@nest.nil?
209
- @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}"
210
331
  @nested_args_plural = {}
332
+
333
+
211
334
  @nested_args.each do |a|
212
335
  @nested_args_plural[a] = a + "s"
213
336
  end
214
337
  end
215
- @nestable = @nested_args.any?
216
-
217
338
 
218
339
  @magic_buttons = []
219
340
  if options['magic_buttons']
@@ -230,11 +351,14 @@ module HotGlue
230
351
  if @auth && ! @self_auth && @nested_args.none?
231
352
  @object_owner_sym = @auth.gsub("current_", "").to_sym
232
353
  @object_owner_eval = @auth
354
+ @object_owner_optional = false
233
355
  else
234
356
 
235
357
  if @nested_args.any?
236
- @object_owner_sym = @nested_args.last.to_sym
237
- @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]
238
362
  else
239
363
  @object_owner_sym = ""
240
364
  @object_owner_eval = ""
@@ -243,20 +367,24 @@ module HotGlue
243
367
 
244
368
 
245
369
  @ujs_syntax = options['ujs_syntax']
370
+
246
371
  if !@ujs_syntax
247
372
  @ujs_syntax = !defined?(Turbo::Engine)
248
- puts "You did not specify ujs_syntax and so I default it to #{@ujs_syntax}"
249
373
  end
250
374
  @reference_name = HotGlue.derrive_reference_name(singular_class)
251
375
 
252
376
  identify_object_owner
253
377
  setup_fields
254
378
 
379
+ if (@columns - @show_only - (@object_owner_sym.empty? ? [] : [@ownership_field.to_sym])).empty?
380
+ @no_field_form = true
381
+ end
382
+
255
383
  buttons_width = ((!@no_edit && 1) || 0) + ((!@no_delete && 1) || 0) + @magic_buttons.count
256
384
 
257
385
  builder = HotGlue::Layout::Builder.new({
258
386
  include_setting: options['include'],
259
- downnest_children: @downnest_children,
387
+ downnest_object: @downnest_object,
260
388
  buttons_width: buttons_width,
261
389
  columns: @columns,
262
390
  smart_layout: @smart_layout
@@ -264,6 +392,7 @@ module HotGlue
264
392
  @layout_object = builder.construct
265
393
 
266
394
  @menu_file_exists = true if @nested_args.none? && File.exists?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
395
+
267
396
  end
268
397
 
269
398
  def identify_object_owner
@@ -271,25 +400,24 @@ module HotGlue
271
400
 
272
401
  if !@object_owner_sym.empty?
273
402
  auth_assoc_field = auth_assoc + "_id" unless @god
403
+
274
404
  assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
275
405
 
276
406
  if assoc
277
407
  @ownership_field = assoc.name.to_s + "_id"
278
- elsif !@nest
279
- 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?
409
+
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)
280
412
 
281
413
  else
282
- if @god
283
- exit_message= "*** Oops: Gd mode could not find the association(#{@object_owner_sym}). Something is wrong."
414
+
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?"
284
417
  else
285
- @auth_check = eval(@auth_identifier.titleize)
286
- @nested_args.each do |arg|
287
- if ! @auth_check.reflect_on_association("#{arg}s".to_sym)
288
- exit_message = "*** Oops: your nesting chain does not have a association for #{arg}s on #{@auth_check} something is wrong."
289
- end
290
- 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."
291
419
  end
292
- puts exit_message
420
+
293
421
  raise(HotGlue::Error, exit_message)
294
422
  end
295
423
  end
@@ -316,6 +444,7 @@ module HotGlue
316
444
  @columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) }
317
445
  end
318
446
 
447
+ @associations = []
319
448
  @columns.each do |col|
320
449
  if col.to_s.starts_with?("_")
321
450
  @show_only << col
@@ -325,11 +454,10 @@ module HotGlue
325
454
  if col.to_s.ends_with?("_id")
326
455
  # guess the association name label
327
456
  assoc_name = col.to_s.gsub("_id","")
328
- assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
329
457
 
330
458
 
331
459
  begin
332
- eval(assoc.class_name)
460
+ assoc_model = eval("#{singular_class}.reflect_on_association(:#{assoc_name}).active_record")
333
461
  rescue NameError => e
334
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."
335
463
  puts exit_message
@@ -337,20 +465,21 @@ module HotGlue
337
465
  end
338
466
 
339
467
 
340
- if assoc.nil?
468
+ if assoc_model.nil?
341
469
  exit_message = "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
342
470
  puts exit_message
343
471
  raise(HotGlue::Error,exit_message)
344
472
  end
345
473
 
346
- assoc_class = eval(assoc.class_name)
474
+ @associations << assoc_name.to_sym
475
+ assoc_class = eval(assoc_model.name)
347
476
  name_list = [:name, :to_label, :full_name, :display_name, :email]
348
477
  if name_list.collect{ |field|
349
478
  assoc_class.column_names.include?(field.to_s) || assoc_class.instance_methods.include?(field)
350
479
  }.any?
351
480
  # do nothing here
352
481
  else
353
- 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.)"
354
483
  raise(HotGlue::Error,exit_message)
355
484
  end
356
485
  end
@@ -369,7 +498,7 @@ module HotGlue
369
498
  def copy_controller_and_spec_files
370
499
  @default_colspan = @columns.size
371
500
  unless @specs_only
372
- template "controller.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}app/controllers#{namespace_with_dash}", "#{plural}_controller.rb")
501
+ template "controller.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}app/controllers#{namespace_with_dash}", "#{@controller_build_folder}_controller.rb")
373
502
  if @namespace
374
503
  begin
375
504
  eval(controller_descends_from)
@@ -406,16 +535,12 @@ module HotGlue
406
535
  end
407
536
 
408
537
  def list_column_headings
409
- 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"
410
542
  column_width = each_col * @columns.count
411
- else
412
- column_width = 0
413
- end
414
-
415
- if !@smart_layout
416
- col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-1"
417
- else
418
- col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-2"
543
+ col_identifier = "scaffold-cell"
419
544
  end
420
545
 
421
546
  @template_builder.list_column_headings(
@@ -473,16 +598,17 @@ module HotGlue
473
598
 
474
599
 
475
600
  def controller_class_name
476
- res = ""
477
- res << @namespace.titleize + "::" if @namespace
478
- res << plural.titleize.gsub(" ", "") + "Controller"
479
- res
601
+ @controller_build_name
480
602
  end
481
603
 
482
604
  def singular_name
483
605
  @singular
484
606
  end
485
607
 
608
+ def singular_class_name
609
+ @singular_class
610
+ end
611
+
486
612
  def plural_name
487
613
  plural
488
614
  end
@@ -492,7 +618,7 @@ module HotGlue
492
618
  end
493
619
 
494
620
  def path_helper_args
495
- if @nested_args.any? && @nest
621
+ if @nested_args.any? && @nested
496
622
  [(@nested_args).collect{|a| "#{a}"} , singular].join(",")
497
623
  else
498
624
  singular
@@ -500,49 +626,88 @@ module HotGlue
500
626
  end
501
627
 
502
628
  def path_helper_singular
503
- if @nest
504
- "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{singular}_path"
629
+ if @nested
630
+ "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{@controller_build_folder_singular}_path"
505
631
  else
506
- "#{@namespace+"_" if @namespace}#{singular}_path"
632
+ "#{@namespace+"_" if @namespace}#{@controller_build_folder_singular}_path"
507
633
  end
508
634
  end
509
635
 
510
636
  def path_helper_plural
511
- if ! @nest
512
- "#{@namespace+"_" if @namespace}#{plural}_path"
513
- else
514
- "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{plural}_path"
515
- 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)
516
675
  end
517
676
 
518
677
  def path_arity
519
678
  res = ""
520
- if @nested_args.any? && @nest
679
+ if @nested_args.any? && @nested
521
680
  res << nested_objects_arity + ", "
522
681
  end
523
682
  res << "@" + singular
524
683
  end
525
684
 
526
685
  def line_path_partial
527
- "#{@namespace+"/" if @namespace}#{plural}/line"
686
+ "#{@namespace+"/" if @namespace}#{@controller_build_folder}/line"
528
687
  end
529
688
 
530
689
  def show_path_partial
531
- "#{@namespace+"/" if @namespace}#{plural}/show"
690
+ "#{@namespace+"/" if @namespace}#{@controller_build_folder}/show"
532
691
  end
533
692
 
534
693
  def list_path_partial
535
- "#{@namespace+"/" if @namespace}#{plural}/list"
694
+ "#{@namespace+"/" if @namespace}#{@controller_build_folder}/list"
536
695
  end
537
696
 
538
697
  def new_path_name
539
- base = "new_#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_") if @nested_args.any?}#{singular}_path"
540
- if @nested_args.any?
541
- base += "(" + @nested_args.collect { |arg|
542
- "#{arg}.id"
543
- }.join(", ") + ")"
544
- end
545
- 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
546
711
  end
547
712
 
548
713
  def nested_assignments
@@ -557,7 +722,7 @@ module HotGlue
557
722
 
558
723
  def nest_assignments_operator(top_level = false, leading_comma = false)
559
724
  if @nested_args.any?
560
- "#{', ' + "\n " if leading_comma}#{top_level ? nested_assignments_top_level : nested_assignments }"
725
+ "#{", " if leading_comma}#{top_level ? nested_assignments_top_level : nested_assignments }"
561
726
  else
562
727
  ""
563
728
  end
@@ -626,8 +791,11 @@ module HotGlue
626
791
 
627
792
  def magic_button_output
628
793
  @template_builder.magic_button_output(
629
- path_helper_singular: path_helper_singular,
630
- 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),
631
799
  singular: singular,
632
800
  magic_buttons: @magic_buttons,
633
801
  small_buttons: @small_buttons
@@ -643,7 +811,7 @@ module HotGlue
643
811
 
644
812
 
645
813
  dest_filepath = File.join("#{'spec/dummy/' if Rails.env.test?}app/views#{namespace_with_dash}",
646
- plural, dest_filename)
814
+ @controller_build_folder, dest_filename)
647
815
 
648
816
 
649
817
  template source_filename, dest_filepath
@@ -657,7 +825,7 @@ module HotGlue
657
825
  source_filename = cc_filename_with_extensions( "#{@markup}/#{view}.turbo_stream.#{@markup}")
658
826
  dest_filename = cc_filename_with_extensions("#{view}", "turbo_stream.#{@markup}")
659
827
  dest_filepath = File.join("#{'spec/dummy/' if Rails.env.test?}app/views#{namespace_with_dash}",
660
- plural, dest_filename)
828
+ @controller_build_folder, dest_filename)
661
829
 
662
830
 
663
831
  template source_filename, dest_filepath
@@ -665,6 +833,15 @@ module HotGlue
665
833
 
666
834
  end
667
835
  end
836
+
837
+ # menu_file = "app/views#{namespace_with_dash}/menu.erb"
838
+ #
839
+ # if File.exists?(menu_file)
840
+ # # TODO: can I insert the new menu item into the menu programatically here?
841
+ # # not sure how i would acheive this without nokogiri
842
+ #
843
+ # end
844
+
668
845
  end
669
846
 
670
847
  def namespace_with_dash
@@ -730,19 +907,15 @@ module HotGlue
730
907
  end
731
908
 
732
909
  def all_form_fields
733
- # TODO: DRY THIS
734
- if !@smart_layout
735
- col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-1"
736
- else
737
- col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-2"
738
- end
910
+ col_identifier = (@layout == "hotglue") ? "scaffold-cell" : "col-md-#{@layout_object[:columns][:size_each]}"
739
911
 
740
912
  @template_builder.all_form_fields(
741
913
  columns: @layout_object[:columns][:container],
742
914
  show_only: @show_only,
743
915
  singular_class: singular_class,
744
916
  singular: singular,
745
- col_identifier: col_identifier
917
+ col_identifier: col_identifier,
918
+ ownership_field: @ownership_field
746
919
  )
747
920
  end
748
921
 
@@ -750,6 +923,22 @@ module HotGlue
750
923
  @each_col ||= each_col
751
924
  end
752
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
+
753
942
  def each_col
754
943
  return col_width if @columns.count == 0
755
944
  (col_width/(@columns.count)).to_i
@@ -771,6 +960,7 @@ module HotGlue
771
960
  end
772
961
 
773
962
  def all_line_fields
963
+ col_identifier = (@layout == "hotglue") ? "scaffold-cell" : "col-md-#{@layout_object[:columns][:size_each]}"
774
964
 
775
965
  @template_builder.all_line_fields(
776
966
  perc_width: column_width,
@@ -778,13 +968,14 @@ module HotGlue
778
968
  show_only: @show_only,
779
969
  singular_class: singular_class,
780
970
  singular: singular,
781
- layout: @layout
971
+ layout: @layout,
972
+ col_identifier: col_identifier
782
973
  )
783
974
  end
784
975
 
785
976
  def controller_descends_from
786
- if defined?(@namespace.titlecase + "::BaseController")
787
- @namespace.titlecase + "::BaseController"
977
+ if defined?(@namespace.titlecase.gsub(" ", "") + "::BaseController")
978
+ @namespace.titlecase.gsub(" ", "") + "::BaseController"
788
979
  else
789
980
  "ApplicationController"
790
981
  end
@@ -871,10 +1062,19 @@ module HotGlue
871
1062
 
872
1063
 
873
1064
  def nested_for_turbo_id_list_constructor
874
- if @nested_args.none?
1065
+ if @nested_set.any?
1066
+ '+ (((\'__\' + nested_for) if defined?(nested_for)) || "")'
1067
+ else
875
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(", ") + ")"
876
1076
  else
877
- "+ ('__' + nested_for)"
1077
+ ""
878
1078
  end
879
1079
  end
880
1080
 
@@ -882,9 +1082,11 @@ module HotGlue
882
1082
  instance_symbol = "@" if top_level
883
1083
  instance_symbol = "" if !top_level
884
1084
  if @nested_args.none?
885
- ""
1085
+ "\"\""
886
1086
  else
887
- "__" + @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(" + ")
888
1090
  end
889
1091
  end
890
1092
 
@@ -898,7 +1100,6 @@ module HotGlue
898
1100
  end
899
1101
  end
900
1102
 
901
-
902
1103
  private # thor does something fancy like sending the class all of its own methods during some strange run sequence
903
1104
  # does not like public methods
904
1105
  def cc_filename_with_extensions(name, file_format = format)