hot-glue 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/.github/FUNDING.yml +2 -0
  3. data/.gitignore +16 -0
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +196 -0
  6. data/LICENCE +13 -0
  7. data/README.md +262 -0
  8. data/Rakefile +32 -0
  9. data/app/helpers/hot_glue/controller_helper.rb +105 -0
  10. data/app/helpers/hot_glue_helper.rb +4 -0
  11. data/bin/rails +14 -0
  12. data/lib/generators/hot_glue/install_generator.rb +21 -0
  13. data/lib/generators/hot_glue/scaffold_generator.rb +674 -0
  14. data/lib/generators/hot_glue/templates/_errors.haml +5 -0
  15. data/lib/generators/hot_glue/templates/_flash_notices.haml +7 -0
  16. data/lib/generators/hot_glue/templates/_form.haml +4 -0
  17. data/lib/generators/hot_glue/templates/_line.haml +6 -0
  18. data/lib/generators/hot_glue/templates/_list.haml +9 -0
  19. data/lib/generators/hot_glue/templates/_new_button.haml +2 -0
  20. data/lib/generators/hot_glue/templates/_show.haml +7 -0
  21. data/lib/generators/hot_glue/templates/base_controller.rb +3 -0
  22. data/lib/generators/hot_glue/templates/controller.rb +125 -0
  23. data/lib/generators/hot_glue/templates/controller_spec.rb +110 -0
  24. data/lib/generators/hot_glue/templates/create.turbo_stream.haml +5 -0
  25. data/lib/generators/hot_glue/templates/destroy.turbo_stream.haml +2 -0
  26. data/lib/generators/hot_glue/templates/edit.haml +19 -0
  27. data/lib/generators/hot_glue/templates/edit.turbo_stream.haml +4 -0
  28. data/lib/generators/hot_glue/templates/index.haml +9 -0
  29. data/lib/generators/hot_glue/templates/new.haml +10 -0
  30. data/lib/generators/hot_glue/templates/update.turbo_stream.haml +5 -0
  31. data/lib/hot-glue.rb +28 -0
  32. data/lib/hotglue/engine.rb +6 -0
  33. data/lib/hotglue/version.rb +3 -0
  34. metadata +178 -0
@@ -0,0 +1,21 @@
1
+ require 'rails/generators/erb/scaffold/scaffold_generator'
2
+ require 'ffaker'
3
+
4
+ module HotGlue
5
+ class InstallGenerator < Rails::Generators::Base
6
+ hook_for :form_builder, :as => :scaffold
7
+
8
+ source_root File.expand_path('templates', __dir__)
9
+
10
+
11
+ def initialize(*args) #:nodoc:
12
+ super
13
+ # copy_file "common_core.js", "app/javascript/common_core.js"
14
+ # copy_file "common_core.scss", "app/assets/stylesheets/common_core.scss"
15
+ copy_file "_flash_notices.haml", "app/views/layouts/_flash_notices.haml"
16
+ end
17
+ end
18
+ end
19
+
20
+
21
+
@@ -0,0 +1,674 @@
1
+ require 'rails/generators/erb/scaffold/scaffold_generator'
2
+ require 'ffaker'
3
+
4
+
5
+ module HotGlue
6
+ module GeneratorHelper
7
+ def text_area_output(col, field_length, col_identifier )
8
+ lines = field_length % 40
9
+ if lines > 5
10
+ lines = 5
11
+ end
12
+
13
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
14
+ = f.text_area :#{col.to_s}, class: 'form-control', cols: 40, rows: '#{lines}'
15
+ %label.form-text
16
+ #{col.to_s.humanize}\n"
17
+ end
18
+
19
+
20
+
21
+ def field_output(col, type = nil, width, col_identifier )
22
+
23
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
24
+ = f.text_field :#{col.to_s}, value: @#{singular}.#{col.to_s}, size: #{width}, class: 'form-control', type: '#{type}'
25
+ %label.form-text
26
+ #{col.to_s.humanize}\n"
27
+ end
28
+ end
29
+
30
+
31
+ class ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
32
+ hook_for :form_builder, :as => :scaffold
33
+
34
+ source_root File.expand_path('templates', __dir__)
35
+ attr_accessor :path, :singular, :plural, :singular_class, :nest_with
36
+
37
+
38
+ include GeneratorHelper
39
+
40
+
41
+ def initialize(*meta_args) #:nodoc:
42
+ super
43
+
44
+ begin
45
+ object = eval(class_name)
46
+ rescue StandardError => e
47
+ puts "*** Oops: It looks like there is no object for #{class_name}. Please define the object + database table first."
48
+ exit
49
+ end
50
+
51
+
52
+
53
+ args = meta_args[0]
54
+ @singular = args[0].tableize.singularize # should be in form hello_world
55
+
56
+
57
+ @plural = @singular + "s" # supply to override; leave blank to use default
58
+ @singular_class = @singular.titleize.gsub(" ", "")
59
+ @nest = nil
60
+ @namespace = nil
61
+ @nested_args = []
62
+
63
+ @auth = "current_user"
64
+ @auth_identifier = nil
65
+
66
+ args[1..-1].each do |a|
67
+ var_name, var_value = a.split("=")
68
+ case (var_name)
69
+
70
+ when "plural"
71
+ @plural = var_value
72
+ when "nest"
73
+ @nest = var_value
74
+ when "namespace"
75
+ @namespace = var_value
76
+ when "auth"
77
+ @auth = var_value
78
+ when "auth_identifier"
79
+ @auth_identifier = var_value || ""
80
+ end
81
+ end
82
+
83
+ auth_assoc = @auth.gsub("current_","")
84
+
85
+ @no_delete = false
86
+ @no_create = false
87
+
88
+ flags = meta_args[1]
89
+ flags.each do |f|
90
+ case (f)
91
+ when "--god"
92
+ @auth = nil
93
+ # when "--with-index"
94
+ # @with_index = true
95
+ when "--specs-only"
96
+ @specs_only = true
97
+ when "--no-specs"
98
+ @no_specs = true
99
+ when "--no-delete"
100
+ @no_delete = true
101
+ when "--no-create"
102
+ @no_create = true
103
+ end
104
+ end
105
+
106
+ if @specs_only && @no_specs
107
+ puts "*** Oops: You seem to have specified both the --specs-only flag and --no-specs flags. this doesn't make any sense, so I am aborting. sorry."
108
+ exit
109
+ end
110
+
111
+
112
+ # only used for the before_action
113
+ if @auth_identifier.nil? && !@auth.nil?
114
+ @auth_identifier = @auth.gsub("current_", "")
115
+ end
116
+
117
+ # when in self auth, the object is the same as the authenticated object
118
+ if @auth && auth_identifier == @singular
119
+ @self_auth = true
120
+ end
121
+
122
+ if !@nest.nil?
123
+ @nested_args = @nest.split("/")
124
+ @nested_args_plural = {}
125
+ @nested_args.each do |a|
126
+ @nested_args_plural[a] = a + "s"
127
+ end
128
+ end
129
+
130
+ # the @object_owner will always be object that will 'own' the object
131
+ # for new and create
132
+
133
+ if @auth && ! @self_auth && @nested_args.none?
134
+ @object_owner_sym = @auth.gsub("current_", "").to_sym
135
+ @object_owner_eval = @auth
136
+ else
137
+
138
+ if @nested_args.any?
139
+ @object_owner_sym = @nested_args.last.to_sym
140
+ @object_owner_eval = "@#{@nested_args.last}"
141
+ else
142
+ @object_owner_sym = ""
143
+ @object_owner_eval = ""
144
+ end
145
+ end
146
+
147
+
148
+
149
+ # create the columns
150
+ if !@object_owner_sym.empty?
151
+ auth_assoc_field = auth_assoc + "_id"
152
+ assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
153
+ if assoc
154
+ ownership_field = assoc.name.to_s + "_id"
155
+ else
156
+ if @auth
157
+ puts "*** 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."
158
+ else
159
+ puts "*** Oops: god mode could not find the association(?). something is wrong."
160
+ end
161
+ exit
162
+ end
163
+ end
164
+
165
+ exclude_fields = [ :id, :created_at, :updated_at, :encrypted_password, :reset_password_token,
166
+ :reset_password_sent_at, :remember_created_at, :confirmation_token, :confirmed_at,
167
+ :confirmation_sent_at, :unconfirmed_email]
168
+
169
+ exclude_fields << auth_assoc_field.to_sym if !auth_assoc_field.nil?
170
+ exclude_fields << ownership_field.to_sym if !ownership_field.nil?
171
+
172
+
173
+ begin
174
+ @columns = object.columns.map(&:name).map(&:to_sym).reject{|field| exclude_fields.include?(field) }
175
+ rescue StandardError => e
176
+ puts "Ooops... it looks like is an object for #{class_name}. Please create the database table with fields first. "
177
+ exit
178
+ end
179
+
180
+
181
+
182
+ end
183
+
184
+ def formats
185
+ [format]
186
+ end
187
+
188
+ def format
189
+ nil
190
+ end
191
+
192
+ def copy_controller_and_spec_files
193
+ @default_colspan = @columns.size
194
+
195
+ unless @specs_only
196
+ template "controller.rb", File.join("app/controllers#{namespace_with_dash}", "#{plural}_controller.rb")
197
+ if @namespace && defined?(controller_descends_from) == nil
198
+ template "base_controller.rb", File.join("app/controllers#{namespace_with_dash}", "base_controller.rb")
199
+ end
200
+ end
201
+
202
+ unless @no_specs
203
+ template "controller_spec.rb", File.join("spec/controllers#{namespace_with_dash}", "#{plural}_controller_spec.rb")
204
+ end
205
+
206
+ template "_errors.haml", File.join("app/views#{namespace_with_dash}", "_errors.haml")
207
+ end
208
+
209
+ def list_column_headings
210
+ @columns.map(&:to_s).map{|col_name| ' .col ' + col_name.humanize}.join("\n")
211
+ end
212
+
213
+ def columns_spec_with_sample_data
214
+ @columns.map { |c|
215
+ if eval("#{singular_class}.columns_hash['#{c}']").nil?
216
+ byebug
217
+ end
218
+ type = eval("#{singular_class}.columns_hash['#{c}']").type
219
+ random_data = case type
220
+ when :integer
221
+ rand(1...1000)
222
+ when :string
223
+ FFaker::AnimalUS.common_name
224
+ when :text
225
+ FFaker::AnimalUS.common_name
226
+ when :datetime
227
+ Time.now + rand(1..5).days
228
+ end
229
+ c.to_s + ": '" + random_data.to_s + "'"
230
+ }.join(", ")
231
+ end
232
+
233
+ def object_parent_mapping_as_argument_for_specs
234
+ if @nested_args.any?
235
+ ", " + @nested_args.last + ": " + @nested_args.last
236
+ elsif @auth
237
+ ", #{@auth_identifier}: #{@auth}"
238
+ end
239
+ end
240
+
241
+ def objest_nest_factory_setup
242
+ res = ""
243
+ if @auth
244
+ last_parent = ", #{@auth_identifier}: #{@auth}"
245
+ end
246
+
247
+ @nested_args.each do |arg|
248
+ res << " let(:#{arg}) {create(:#{arg} #{last_parent} )}\n"
249
+ last_parent = ", #{arg}: #{arg}"
250
+ end
251
+ res
252
+ end
253
+
254
+
255
+ def objest_nest_params_by_id_for_specs
256
+ @nested_args.map{|arg|
257
+ "#{arg}_id: #{arg}.id"
258
+ }.join(",\n ")
259
+ end
260
+
261
+
262
+ def controller_class_name
263
+ res = ""
264
+ res << @namespace.titleize + "::" if @namespace
265
+ res << plural.titleize.gsub(" ", "") + "Controller"
266
+ res
267
+ end
268
+
269
+ def singular_name
270
+ @singular
271
+ end
272
+
273
+ def plural_name
274
+ plural
275
+ end
276
+
277
+ def auth_identifier
278
+ @auth_identifier
279
+ end
280
+
281
+
282
+ def path_helper_full
283
+ "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{singular}_path"
284
+ end
285
+
286
+ def path_helper_args
287
+ if @nested_args.any?
288
+ [(@nested_args).collect{|a| "@#{a}"} , singular].join(",")
289
+ else
290
+ singular
291
+ end
292
+ end
293
+
294
+ def path_helper_singular
295
+ "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{singular}_path"
296
+ end
297
+
298
+ def path_helper_plural
299
+ "#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_" if @nested_args.any?)}#{plural}_path"
300
+ end
301
+
302
+ def path_arity
303
+ res = ""
304
+ if @nested_args.any?
305
+ res << nested_objects_arity + ", "
306
+ end
307
+ res << "@" + singular
308
+ end
309
+
310
+ def line_path_partial
311
+ "#{@namespace+"/" if @namespace}#{plural}/line"
312
+ end
313
+
314
+ def nested_assignments
315
+ @nested_args.map{|a| "#{a}: @#{a}"}.join(", ") #metaprgramming into Ruby hash
316
+ end
317
+
318
+ def nested_assignments_with_leading_comma
319
+ if @nested_args.any?
320
+ ", #{nested_assignments}"
321
+ else
322
+ ""
323
+ end
324
+ end
325
+
326
+ def nested_objects_arity
327
+ @nested_args.map{|a| "@#{a}"}.join(", ")
328
+ end
329
+
330
+ def nested_arity_for_path
331
+ [@nested_args[0..-1].collect{|a| "@#{a}"}].join(", ") #metaprgramming into arity for the Rails path helper
332
+ end
333
+
334
+ def object_scope
335
+ if @auth
336
+ if @nested_args.none?
337
+ @auth + ".#{plural}"
338
+ else
339
+ "@" + @nested_args.last + ".#{plural}"
340
+ end
341
+ else
342
+ @singular_class
343
+ end
344
+ end
345
+
346
+
347
+ def all_objects_root
348
+ if @auth
349
+ if @self_auth
350
+ @singular_class + ".where(id: #{@auth}.id)"
351
+ elsif @nested_args.none?
352
+ @auth + ".#{plural}"
353
+ else
354
+ "@" + @nested_args.last + ".#{plural}"
355
+ end
356
+ else
357
+ @singular_class + ".all"
358
+ end
359
+ end
360
+
361
+ def any_nested?
362
+ @nested_args.any?
363
+ end
364
+
365
+ def all_objects_variable
366
+
367
+ # needs the authenticated root user
368
+ # "#{@auth}.#{ @nested_args.map{|a| "#{@nested_args_plural[a]}.find(@#{a})"}.join('.') + "." if @nested_args.any?}#{plural}"
369
+
370
+ all_objects_root + ".page(params[:page])"
371
+
372
+ end
373
+
374
+ def auth_object
375
+ @auth
376
+ end
377
+
378
+
379
+ def no_devise_installed
380
+ !Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.group_by{ |g| g.name }['devise']
381
+ end
382
+
383
+
384
+ def copy_view_files
385
+ return if @specs_only
386
+ haml_views.each do |view|
387
+ formats.each do |format|
388
+ filename = cc_filename_with_extensions(view, "haml")
389
+ template filename, File.join("app/views#{namespace_with_dash}", controller_file_path, filename)
390
+ end
391
+ end
392
+
393
+ turbo_stream_views.each do |view|
394
+ formats.each do |format|
395
+ filename = cc_filename_with_extensions(view, 'turbo_stream.haml')
396
+ template filename, File.join("app/views#{namespace_with_dash}", controller_file_path, filename)
397
+ end
398
+ end
399
+ end
400
+
401
+ def namespace_with_dash
402
+ if @namespace
403
+ "/#{@namespace}"
404
+ else
405
+ ""
406
+ end
407
+ end
408
+
409
+ def namespace_with_trailing_dash
410
+ if @namespace
411
+ "#{@namespace}/"
412
+ else
413
+ ""
414
+ end
415
+ end
416
+
417
+ def haml_views
418
+ res = %w(index edit new _form _line _list _new_button _show)
419
+
420
+ res
421
+ end
422
+
423
+ def turbo_stream_views
424
+ res = %w(create destroy edit update)
425
+ end
426
+
427
+ def handler
428
+ :erb
429
+ end
430
+
431
+ def model_has_strings?
432
+ false
433
+ end
434
+
435
+
436
+ def model_search_fields # an array of fields we can search on
437
+ []
438
+ end
439
+
440
+ def all_form_fields
441
+ col_identifier = " .col"
442
+ col_spaces_prepend = " "
443
+
444
+ res = @columns.map { |col|
445
+ type = eval("#{singular_class}.columns_hash['#{col}']").type
446
+ limit = eval("#{singular_class}.columns_hash['#{col}']").limit
447
+ sql_type = eval("#{singular_class}.columns_hash['#{col}']").sql_type
448
+
449
+ case type
450
+ when :integer
451
+ # look for a belongs_to on this object
452
+ if col.to_s.ends_with?("_id")
453
+ # guess the association name label
454
+
455
+
456
+ assoc_name = col.to_s.gsub("_id","")
457
+ assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
458
+ if assoc.nil?
459
+ puts "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
460
+ exit
461
+ end
462
+
463
+
464
+ assoc_class = eval(assoc.class_name)
465
+
466
+ if assoc_class.column_names.include?("name")
467
+ display_column = "name"
468
+ elsif assoc_class.column_names.include?("to_label")
469
+ display_column = "to_label"
470
+ elsif assoc_class.column_names.include?("full_name")
471
+ display_column = "full_name"
472
+ elsif assoc_class.column_names.include?("display_name")
473
+ display_column = "display_name"
474
+ elsif assoc_class.column_names.include?("email")
475
+ display_column = "email"
476
+ else
477
+ puts "*** Oops: 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} 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)"
478
+ end
479
+
480
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{assoc_name.to_s})}\"}
481
+ #{col_spaces_prepend}= f.collection_select(:#{col.to_s}, #{assoc_class}.all, :id, :#{display_column}, {prompt: true, selected: @#{singular}.#{col.to_s} }, class: 'form-control')
482
+ #{col_spaces_prepend} %label.small.form-text.text-muted
483
+ #{col_spaces_prepend} #{col.to_s.humanize}"
484
+
485
+ else
486
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if @#{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
487
+ #{col_spaces_prepend}= f.text_field :#{col.to_s}, value: #{singular}.#{col.to_s}, class: 'form-control', size: 4, type: 'number'
488
+ #{col_spaces_prepend} %label.form-text
489
+ #{col_spaces_prepend} #{col.to_s.humanize}\n"
490
+ end
491
+ when :string
492
+ limit ||= 256
493
+ if limit <= 256
494
+ field_output(col, nil, limit, col_identifier)
495
+ else
496
+ text_area_output(col, limit, col_identifier)
497
+ end
498
+
499
+ when :text
500
+ limit ||= 256
501
+ if limit <= 256
502
+ field_output(col, nil, limit, col_identifier)
503
+ else
504
+ text_area_output(col, limit, col_identifier)
505
+ end
506
+ when :float
507
+ limit ||= 256
508
+ field_output(col, nil, limit, col_identifier)
509
+
510
+
511
+ when :datetime
512
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
513
+ #{col_spaces_prepend}= datetime_field_localized(f, :#{col.to_s}, #{singular}.#{col.to_s}, '#{col.to_s.humanize}', #{@auth ? @auth+'.timezone' : 'nil'})"
514
+ when :date
515
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
516
+ #{col_spaces_prepend}= date_field_localized(f, :#{col.to_s}, #{singular}.#{col.to_s}, '#{col.to_s.humanize}', #{@auth ? @auth+'.timezone' : 'nil'})"
517
+ when :time
518
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
519
+ #{col_spaces_prepend}= time_field_localized(f, :#{col.to_s}, #{singular}.#{col.to_s}, '#{col.to_s.humanize}', #{@auth ? @auth+'.timezone' : 'nil'})"
520
+ when :boolean
521
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
522
+ #{col_spaces_prepend}%span
523
+ #{col_spaces_prepend} #{col.to_s.humanize}
524
+ #{col_spaces_prepend}= f.radio_button(:#{col.to_s}, '0', checked: #{singular}.#{col.to_s} ? '' : 'checked')
525
+ #{col_spaces_prepend}= f.label(:#{col.to_s}, value: 'No', for: '#{singular}_#{col.to_s}_0')
526
+
527
+ #{col_spaces_prepend}= f.radio_button(:#{col.to_s}, '1', checked: #{singular}.#{col.to_s} ? 'checked' : '')
528
+ #{col_spaces_prepend}= f.label(:#{col.to_s}, value: 'Yes', for: '#{singular}_#{col.to_s}_1')
529
+ "
530
+ end
531
+
532
+ }.join("\n")
533
+ return res
534
+ end
535
+
536
+
537
+ def all_line_fields
538
+ columns = @columns.count + 1
539
+ perc_width = (100/columns).floor
540
+
541
+ col_identifer = ".col"
542
+ @columns.map { |col|
543
+ type = eval("#{singular_class}.columns_hash['#{col}']").type
544
+ limit = eval("#{singular_class}.columns_hash['#{col}']").limit
545
+ sql_type = eval("#{singular_class}.columns_hash['#{col}']").sql_type
546
+
547
+ case type
548
+ when :integer
549
+ # look for a belongs_to on this object
550
+ if col.to_s.ends_with?("_id")
551
+
552
+ assoc_name = col.to_s.gsub("_id","")
553
+
554
+
555
+ assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
556
+
557
+ if assoc.nil?
558
+ puts "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
559
+ exit
560
+ end
561
+
562
+ assoc_class = eval(assoc.class_name)
563
+
564
+ if assoc_class.column_names.include?("name")
565
+ display_column = "name"
566
+ elsif assoc_class.column_names.include?("to_label")
567
+ display_column = "to_label"
568
+ elsif assoc_class.column_names.include?("full_name")
569
+ display_column = "full_name"
570
+ elsif assoc_class.column_names.include?("display_name")
571
+ display_column = "display_name"
572
+ elsif assoc_class.column_names.include?("email")
573
+ display_column = "email"
574
+ else
575
+ puts "*** Oops: 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} 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)"
576
+ end
577
+
578
+ "#{col_identifer}
579
+ = #{singular}.#{assoc.name.to_s}.try(:#{display_column}) || '<span class=\"content alert-danger\">MISSING</span>'.html_safe"
580
+
581
+ else
582
+ "#{col_identifer}
583
+ = #{singular}.#{col}"
584
+ end
585
+ when :float
586
+ width = (limit && limit < 40) ? limit : (40)
587
+ "#{col_identifer}
588
+ = #{singular}.#{col}"
589
+
590
+ when :string
591
+ width = (limit && limit < 40) ? limit : (40)
592
+ "#{col_identifer}
593
+ = #{singular}.#{col}"
594
+ when :text
595
+ "#{col_identifer}
596
+ = #{singular}.#{col}"
597
+ when :datetime
598
+ "#{col_identifer}
599
+ - unless #{singular}.#{col}.nil?
600
+ = #{singular}.#{col}.in_time_zone(current_timezone).strftime('%m/%d/%Y @ %l:%M %p ') + timezonize(current_timezone)
601
+ - else
602
+ %span.alert-danger
603
+ MISSING
604
+ "
605
+ when :date
606
+ ".cell
607
+ - unless #{singular}.#{col}.nil?
608
+ = #{singular}.#{col}
609
+ - else
610
+ %span.alert-danger
611
+ MISSING
612
+ "
613
+ when :time
614
+ "#{col_identifer}
615
+ - unless #{singular}.#{col}.nil?
616
+ = #{singular}.#{col}.in_time_zone(current_timezone).strftime('%l:%M %p ') + timezonize(current_timezone)
617
+ - else
618
+ %span.alert-danger
619
+ MISSING
620
+ "
621
+ when :boolean
622
+ "#{col_identifer}
623
+ - if #{singular}.#{col}.nil?
624
+ %span.alert-danger
625
+ MISSING
626
+ - elsif #{singular}.#{col}
627
+ YES
628
+ - else
629
+ NO
630
+ "
631
+ end
632
+ }.join("\n")
633
+ end
634
+
635
+
636
+ def controller_descends_from
637
+ if defined?(@namespace.titlecase + "::BaseController")
638
+ @namespace.titlecase + "::BaseController"
639
+ else
640
+ "ApplicationController"
641
+ end
642
+ end
643
+
644
+
645
+ def destroy_action
646
+ return false if @self_auth
647
+ return !@no_delete
648
+ end
649
+
650
+ def create_action
651
+ return false if @self_auth
652
+ return !@no_create
653
+ end
654
+
655
+ def namespace_with_slash
656
+ if @namespace
657
+ "#{@namespace}/"
658
+ else
659
+ ""
660
+ end
661
+ end
662
+
663
+ private # thor does something fancy like sending the class all of its own methods during some strange run sequence
664
+ # does not like public methods
665
+
666
+ def cc_filename_with_extensions(name, file_format = format)
667
+ [name, file_format].compact.join(".")
668
+ end
669
+ end
670
+
671
+ end
672
+
673
+
674
+
@@ -0,0 +1,5 @@
1
+ - if resource.errors.any?
2
+ #error_explanation
3
+ - resource.errors.full_messages.each do |message|
4
+ %div.alert.alert-danger
5
+ = message
@@ -0,0 +1,7 @@
1
+ - unless notice.nil?
2
+ %div.alert.alert-notice.alert-dismissible
3
+ = notice
4
+
5
+ - unless alert.nil?
6
+ %div.alert.alert-danger.alert-dismissible
7
+ = alert