hot-glue 0.6.17 → 0.6.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6abeaf2b7456e5f554928c58bb5deae7fb01a0c664ad0d717572f20c6185537
4
- data.tar.gz: da58696031065cf910116374477ce9f8f3b388bef0a2ad756289953b70a31d8b
3
+ metadata.gz: 9e7085c942cab4dc377c75180d546b57f6ca76bdb3c96f3b2a837d1fdd887b0f
4
+ data.tar.gz: 04fd50131e53977f25c8817c7fd7bd33e34cb0aa784c995394c94302491b1426
5
5
  SHA512:
6
- metadata.gz: 626a8d361bef7d74109406ba5beae46b0daf4db297c2f95fcd92431bc1b6f9ea97d224acb8ef898bb0281b8cb3bc369d5507f6956751da137c4e5ecb4e3a93d5
7
- data.tar.gz: 3a646740022a5c699051ad99c400178f1abdafc911a9c1e40c400b52a16458f3181e98ed73e0e6db8fc64fdaa8829b93f8432efcf4026873dbb2236708c2308e
6
+ metadata.gz: fa984faeba62c9303c5ae0c64b32143e054289380ffdfecf2f0d457c7b2c2d69912b69901d78ee6fff75f1e6997ed19e86a4cc00a8c048341fbf2505e687a984
7
+ data.tar.gz: 052122bbbc7d15c134653efc4da2b74df8400447eccae13d395627bd5d79b2a616f612c97ac995f07b563a8589c9609406320562616f7efe637b94d7289a5e8a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hot-glue (0.6.17)
4
+ hot-glue (0.6.18)
5
5
  ffaker (~> 2.16)
6
6
  kaminari (~> 1.2)
7
7
  rails (> 5.1)
data/README.md CHANGED
@@ -680,15 +680,49 @@ For the `$` modifier only, if the field name ends with `_cents`, the modifier wi
680
680
 
681
681
  ### `--alt-foreign-key-lookup=`
682
682
 
683
- Use for a join table to specify that a field should be looked up by a different field
683
+ Use for a join table to specify that a field should be looked up by a different field. For example, when you want to lookup a user by a (complete) email address.
684
684
 
685
+ In these contexts, the lookup must be exact match to the text entered (no partial matches supported).
685
686
 
686
- `./bin/rails generate hot_glue:scaffold AccountUser --alt-foreign-key-lookup=user_id{email}`
687
+ Use `+` to map to the `find_or_create_by` method. (Without `+` it will use `find_by`.)
688
+
689
+ This is accomlished using a little magic of a lookup field called `__lookup_X_Y` passed in the form parameters.
690
+
691
+ The lookup field is used to look up the associated record, then deleted from the params.
692
+
693
+ #### When used in `--gd` mode
694
+ The lookup will use the base class and have access to all records.
695
+ `user = User.find_or_create_by!(email: params[:__lookup_email])`
696
+ `modified_params.tap { |hs| hs.delete(:__lookup_target_email)}`
697
+ `modified_params.merge!(user: user)`
698
+
699
+ Example 1
700
+ `./bin/rails generate hot_glue:scaffold AccountUser --gd --alt-foreign-key-lookup=user_id{email}`
687
701
 
688
702
  Here we are specifying that the `user_id` field should be looked up by the `email` field on the User table.
689
703
  If no existing user exists, we create one because we are using the `find_or_create_by!` method.
690
704
 
705
+ ### When used with a Hawk
706
+
707
+ A hawk applied to the same field will be enforced within this mechanism.
708
+
709
+ Example #2
710
+ `bin/rails generate hot_glue:scaffold Appointment --gd --alt-foreign-key-lookup='user_id{email}' --hawk='user_id{current_user.family}'`
711
+
712
+
713
+ Whether or not in Gd mode, the hawk is enforced by scoping the find to the hawk's scope
714
+ ```
715
+ user = current_user.family.users.find_by(email: appointment_params[:__lookup_user_email] )
716
+ modified_params.tap { |hs| hs.delete(:__lookup_user_email)}
717
+ @appointment = Appointment.new(modified_params.merge(user: user))
718
+ ```
719
+
720
+
721
+
722
+ ### With Factory
723
+
691
724
  Use with a factory pattern like this one:
725
+
692
726
  ```
693
727
  class AccountUserFactory
694
728
  attr_accessor :account_user
@@ -712,9 +746,17 @@ end
712
746
  this works with a factory creation syntax like so:
713
747
 
714
748
  ```
715
- --factory-creation='factory = AccountUserFactory.new(params: account_user_params, account: account)
749
+ rails generate hot_glue:scaffold AccountUser --alt-foreign-key-lookup=user_id{email} --factory-creation='factory = AccountUserFactory.new(params: account_user_params, account: account)
716
750
  ```
717
- *See the `--factory-creation` section.
751
+
752
+ In this example, the lookup is *not performed inside of the create action*, because it is assumed you will do so yourself inside of your factory.
753
+
754
+ As you see in the example above, params is passed to your factory and it is the `account_user_params` fromm the controller.
755
+
756
+ #### Warning:
757
+ When building a non-Gd controller with a `--alt-foreign-key-lookup`, if you don't also hawk the same field you will get an error.
758
+
759
+ To fix, either hawk the field or use with a factory creation pattern. This is because the associated object is on your graph but Hot Glue doesn't know how to securly load it without knowing its relationship to the current user. Use the `--hawk` mechanism to specify that relationship, and the lookup mechanism will integrate nicely.
718
760
 
719
761
 
720
762
 
@@ -1401,6 +1443,16 @@ If you leave the 2nd parameter blank when using the 3rd parameter, it will defau
1401
1443
 
1402
1444
  `--attachments='avatar{thumbnail||direct}'`
1403
1445
 
1446
+ #### `--attachments` Long form syntax with 4 parameters
1447
+
1448
+ The final (4th) parameter should be `dropzone` to enable dropzone support for this attachment.
1449
+
1450
+ ```
1451
+ bin/rails generate hot_glue:scaffold Video --auth='current_user' --auth-identifier='user' --namespace='account_dashboard' --nested='account' --smart-layout --attachments='video_file{thumbnail||direct|dropzone}'
1452
+ ```
1453
+
1454
+ See below for dropzone details.
1455
+
1404
1456
 
1405
1457
  #### For S3 Setup
1406
1458
 
@@ -1902,7 +1954,38 @@ These automatic pickups for partials are detected at build time. This means that
1902
1954
 
1903
1955
  # VERSION HISTORY
1904
1956
 
1905
- #### 2025-05-0097 - v0.6.17
1957
+ #### 2025-06-10 v0.6.19
1958
+
1959
+ • Fixes magic button output behavior to correctly show the string returned by the bang menthod
1960
+ • Fixes internal syntax of modify_as for modified fields; note default is now 'Yes' and 'No' for radio buttons
1961
+ • fixes destroy behavior with explicit .destroy! and ActiveRecord::RecordNotDestroyed; documents previously undocumented 4th parameter for attachment input
1962
+
1963
+
1964
+ #### 2025-05-18 v0.6.18
1965
+ • Significant additions to `--alt-foreign-key-lookup` which can now work:
1966
+ - on its own, without needing a factory (`--factory-creation`)
1967
+ - with a factory
1968
+ - with our without the hawk
1969
+ - in Gd mode
1970
+ - if not in Gd mode, use with `--factory-creation` or use with the `--hawk`
1971
+
1972
+ See notes above for details.
1973
+
1974
+ example apps
1975
+ https://github.com/hot-glue-for-rails/HGHumanSpaMay25
1976
+ https://github.com/hot-glue-for-rails/HGAltLookups11
1977
+
1978
+
1979
+ • Adds Integer as searchable field
1980
+
1981
+ _ foo and bar are integers _
1982
+
1983
+ `rails g hot_glue:scaffold Thing --include=foo,bar --search=set --search-fields=foo,bar`
1984
+
1985
+ • On show only association fields, view output is now safe-nil using `&` to not crash if the association doesn't exist.
1986
+
1987
+
1988
+ #### 2025-05-09 - v0.6.17
1906
1989
 
1907
1990
 
1908
1991
  • Adds Stimulus JS & `--stimmify` or `--stimmify=xyz`
@@ -1935,6 +2018,7 @@ https://jasonfleetwoodboldt.com/courses/rails-7-crash-course/rails-7-stimulus-js
1935
2018
  • Adds `--hidden` option
1936
2019
  Pass a list of fields, like include or show-only. This will make the field hidden on the form *but still updated via its submission*
1937
2020
 
2021
+ • Show only fields associations are now safe-nil using `&` to not crash if the association doesn't exist
1938
2022
 
1939
2023
 
1940
2024
 
@@ -143,6 +143,27 @@ module HotGlue
143
143
  end
144
144
  end
145
145
 
146
+ def integer_query_constructor(match, search)
147
+ if match.blank? || search.blank?
148
+ nil
149
+ else
150
+ case match
151
+ when '='
152
+ "= #{search.to_i}"
153
+ when '≥'
154
+ ">= #{search.to_i}"
155
+ when '>'
156
+ "> #{search.to_i}"
157
+ when '≤'
158
+ "<= #{search.to_i}"
159
+ when '<'
160
+ "< #{search.to_i}"
161
+ else
162
+ nil
163
+ end
164
+ end
165
+ end
166
+
146
167
  def enum_constructor(field_name, value, **args)
147
168
  return nil if value.blank?
148
169
  ["#{field_name} = ?", value]
@@ -82,25 +82,23 @@ class AssociationField < Field
82
82
  display_column = HotGlue.derrive_reference_name(assoc_class_name)
83
83
 
84
84
 
85
- "<%= #{singular}.#{assoc_name}.#{display_column} %>"
85
+ "<%= #{singular}.#{assoc_name}&.#{display_column} %>"
86
86
  end
87
87
 
88
88
  def form_field_output
89
89
  assoc_name = name.to_s.gsub("_id","")
90
+
91
+
90
92
  assoc = eval("#{class_name}.reflect_on_association(:#{assoc_name})")
91
- if alt_lookup.keys.include?(name.to_sym)
92
- alt = alt_lookup[:lookup_as]
93
+
94
+ if alt_lookup.keys.include?(name)
93
95
  assoc_name = name.to_s.gsub("_id","")
94
96
  assoc = eval("#{class_name}.reflect_on_association(:#{assoc_name})")
95
97
 
96
- alt = alt_lookup[:lookup_as]
98
+ lookup_field = alt_lookup[name][:lookup_as]
99
+ assoc = alt_lookup[name][:assoc].downcase
97
100
  parts = name.split('_')
98
- "<%= f.text_field :__lookup_#{alt}, value: @#{singular}.#{assoc_name}.try(:#{alt}), placeholder: \"search by #{alt}\" " + (stimmify ? ", 'data-#{@stimmify}-target': '#{camelcase_name}' " : "") + "%>"
99
-
100
- # if modify_as
101
- # modified_display_output
102
- # else
103
- # end
101
+ "<%= f.text_field :__lookup_#{assoc}_#{lookup_field}, value: @#{singular}.#{assoc_name}&.#{lookup_field}, placeholder: \"#{lookup_field}\" " + (stimmify ? ", 'data-#{@stimmify}-target': '#{camelcase_name}' " : "") + "%>"
104
102
  elsif modify_as && modify_as[:typeahead]
105
103
  search_url = "#{namespace ? namespace + "_" : ""}" +
106
104
  modify_as[:nested].join("_") + ( modify_as[:nested].any? ? "_" : "") +
@@ -150,7 +148,7 @@ class AssociationField < Field
150
148
  if @stimmify
151
149
  col_target = HotGlue.to_camel_case(name.to_s.gsub("_", " "))
152
150
  data_attr = ", data: {'#{@stimmify}-target': '#{col_target}'} "
153
- els
151
+ else
154
152
  data_attr = ""
155
153
  end
156
154
 
@@ -188,11 +186,9 @@ class AssociationField < Field
188
186
 
189
187
  if assoc_class
190
188
  display_column = HotGlue.derrive_reference_name(assoc_class.to_s)
191
-
192
189
  "<%= #{singular}.#{assoc}.try(:#{display_column}) || '<span class=\"content \">MISSING</span>'.html_safe %>"
193
190
  else
194
191
  "<%= #{singular}.#{assoc}.try(:to_label) || '<span class=\"content \">MISSING</span>'.html_safe %>"
195
-
196
192
  end
197
193
 
198
194
  end
@@ -274,5 +270,33 @@ class AssociationField < Field
274
270
  end
275
271
  end
276
272
 
273
+ def prelookup_syntax
274
+ field = @alt_lookup[name.to_s]
275
+ if field[:with_create]
276
+
277
+ method_name = "find_or_create_by"
277
278
 
279
+ else
280
+ method_name = "find_by"
281
+ end
282
+ field_name = field[:assoc].downcase.gsub("_id","")
283
+ assoc_class = field[:assoc].classify
284
+
285
+ assoc = plural
286
+
287
+ ## TODO: add the hawk here
288
+ res = +""
289
+ if @hawk_keys[name.to_sym]
290
+ res << "#{field_name} = #{@hawk_keys[name.to_sym][:bind_to].first}.#{method_name}(#{field[:lookup_as]}: #{singular}_params[:__lookup_#{field[:assoc].downcase}_#{field[:lookup_as]}] )"
291
+ elsif @god
292
+ assoc_name = field[:assoc]
293
+ res << "#{field_name} = #{assoc_class}.#{method_name}(#{field[:lookup_as]}: #{singular}_params[:__lookup_#{field[:assoc].downcase}_#{field[:lookup_as]}] )"
294
+ else
295
+ raise "Field #{field_name} is an alt lookup in a non-Gd context which is a security vulnerability"
296
+ end
297
+
298
+ res << "\n modified_params.tap { |hs| hs.delete(:__lookup_#{field[:assoc].downcase}_#{field[:lookup_as]})}"
299
+ return res
300
+
301
+ end
278
302
  end
@@ -23,9 +23,9 @@ class BooleanField < Field
23
23
 
24
24
  def radio_button_display
25
25
  " <%= f.radio_button(:#{name}, '0', checked: #{singular}.#{name} ? '' : 'checked', class: '#{@layout_strategy.form_checkbox_input_class}') %>\n" +
26
- " <%= f.label(:#{name}, value: '#{modify_binary? && modify_as[name.to_sym][:binary][:falsy] || 'No'}', for: '#{singular}_#{name}_0') %>\n" +
26
+ " <%= f.label(:#{name}, value: '#{modify_binary? && modify_as[:binary][:falsy] || 'No'}', for: '#{singular}_#{name}_0') %>\n" +
27
27
  " <br /> <%= f.radio_button(:#{name}, '1', checked: #{singular}.#{name} ? 'checked' : '' , class: '#{@layout_strategy.form_checkbox_input_class}') %>\n" +
28
- " <%= f.label(:#{name}, value: '#{modify_binary? && modify_as[name.to_sym][:binary][:truthy] || 'Yes'}', for: '#{singular}_#{name}_1') %>\n"
28
+ " <%= f.label(:#{name}, value: '#{modify_binary? && modify_as[:binary][:truthy] || 'Yes'}', for: '#{singular}_#{name}_1') %>\n"
29
29
  end
30
30
 
31
31
  def checkbox_display
@@ -59,9 +59,9 @@ class BooleanField < Field
59
59
  "<% if #{singular}.#{name}.nil? %>
60
60
  <span class=''>MISSING</span>
61
61
  <% elsif #{singular}.#{name} %>
62
- #{modify_as[name.to_sym][:binary][:truthy]}
62
+ #{modify_as[:binary][:truthy]}
63
63
  <% else %>
64
- #{modify_as[name.to_sym][:binary][:falsy]}
64
+ #{modify_as[:binary][:falsy]}
65
65
  <% end %>"
66
66
  else
67
67
  "<% if #{singular}.#{name}.nil? %>
@@ -75,11 +75,11 @@ class BooleanField < Field
75
75
  end
76
76
 
77
77
  def truthy_value
78
- modify_as[name.to_sym][:binary][:truthy] || 'Yes'
78
+ modify_as[:binary][:truthy] || 'Yes'
79
79
  end
80
80
 
81
81
  def falsy_value
82
- modify_as[name.to_sym][:binary][:falsy] || 'No'
82
+ modify_as[:binary][:falsy] || 'No'
83
83
  end
84
84
 
85
85
  def label_class
@@ -6,7 +6,7 @@ class Field
6
6
  :self_auth,
7
7
  :singular_class, :singular, :sql_type, :ownership_field,
8
8
  :update_show_only, :namespace, :pundit, :plural,
9
- :stimmify, :hidden, :attachment_data
9
+ :stimmify, :hidden, :attachment_data, :god
10
10
 
11
11
 
12
12
  def initialize(
@@ -25,7 +25,7 @@ class Field
25
25
  @form_placeholder_labels = scaffold.form_placeholder_labels
26
26
  @ownership_field = scaffold.ownership_field
27
27
  @form_labels_position = scaffold.form_labels_position
28
- @modify_as = scaffold.modify_as
28
+ @modify_as = scaffold.modify_as[name.to_sym] # note whenever used as field, don't relookup the key
29
29
  @display_as = scaffold.display_as
30
30
  @pundit = scaffold.pundit
31
31
  @plural = scaffold.plural
@@ -35,6 +35,7 @@ class Field
35
35
  @stimmify = scaffold.stimmify
36
36
  @hidden = scaffold.hidden
37
37
  @attachment_data = scaffold.attachments[name.to_sym]
38
+ @god = scaffold.god
38
39
 
39
40
 
40
41
  # TODO: remove knowledge of subclasses from Field
@@ -112,7 +113,7 @@ class Field
112
113
  end
113
114
 
114
115
  def viewable_output
115
- if modify_as[:modify]
116
+ if modify_as
116
117
  modified_display_output(show_only: true)
117
118
  else
118
119
  field_view_output
@@ -158,7 +159,6 @@ class Field
158
159
  # end
159
160
  # res = "<span class='badge <%= #{badge_code} %>'>" + res + "</span>"
160
161
  # end
161
- # byebug
162
162
  res
163
163
  end
164
164
 
@@ -225,4 +225,6 @@ class Field
225
225
  false
226
226
  end
227
227
 
228
+ def prelookup_syntax; nil; end
229
+
228
230
  end
@@ -29,6 +29,26 @@ class IntegerField < Field
29
29
  end
30
30
 
31
31
  def search_field_output
32
- raise "Integer search not implemented"
32
+ " <div>" +
33
+ "\n <%= f.select 'q[0][#{name}_match]', options_for_select([['', ''], ['=', '='], " +
34
+ "\n ['≥', '≥'], ['>', '>'], " +
35
+ "\n ['≤', '≤'], ['<', '<']], @q[\'0\']['#{name}_match'] ), {} ," +
36
+ "\n { class: 'form-control match' } %>"+
37
+ "\n <%= f.text_field 'q[0][#{name}_search]', {value: @q[\'0\'][:#{name}_search], autocomplete: 'off', size: 4, class: 'form-control', type: 'number'} %>" +
38
+ "\n </div>"
33
39
  end
40
+
41
+
42
+ def where_query_statement
43
+ ".where(\"#{name} \#{#{name}_query }\")"
44
+ end
45
+
46
+ def load_all_query_statement
47
+ "#{name}_query = integer_query_constructor(@q['0'][:#{name}_match], @q['0'][:#{name}_search])"
48
+ end
49
+
50
+ def code_to_reset_match_if_search_is_blank
51
+ " @q['0'][:#{name}_match] = '' if @q['0'][:#{name}_search] == ''"
52
+ end
53
+
34
54
  end
@@ -20,7 +20,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
20
20
  :big_edit, :button_icons, :bootstrap_column_width,
21
21
  :columns,
22
22
  :default_boolean_display,
23
- :display_as, :downnest_children, :downnest_object, :hawk_keys, :layout_object,
23
+ :display_as, :downnest_children, :downnest_object, :god, :hawk_keys, :layout_object,
24
24
  :modify_as,
25
25
  :nest_with, :path, :plural, :sample_file_path, :show_only_data, :singular,
26
26
  :singular_class, :smart_layout, :stacked_downnesting,
@@ -84,7 +84,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
84
84
 
85
85
  # determines if labels appear within the rows of the VIEWABLE list (does NOT affect the list heading)
86
86
  class_option :inline_list_labels, default: nil # default is set below
87
- class_option :factory_creation, default: ''
87
+ class_option :factory_creation, default: nil
88
88
  class_option :alt_foreign_key_lookup, default: '' #
89
89
  class_option :attachments, default: ''
90
90
  class_option :stacked_downnesting, default: false
@@ -437,7 +437,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
437
437
  @related_sets = {}
438
438
  related_set_input.each do |setting|
439
439
  name = setting.to_sym
440
- byebug
441
440
  association_ids_method = eval("#{singular_class}.reflect_on_association(:#{setting.to_sym})").class_name.underscore + "_ids"
442
441
  class_name = eval("#{singular_class}.reflect_on_association(:#{setting.to_sym})").class_name
443
442
 
@@ -480,7 +479,10 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
480
479
  end
481
480
  end
482
481
 
483
- @factory_creation = options['factory_creation'].gsub(";", "\n")
482
+ unless options['factory_creation'].nil?
483
+ @factory_creation = options['factory_creation'].gsub(";", "\n")
484
+ end
485
+
484
486
  identify_object_owner
485
487
  setup_fields
486
488
 
@@ -506,6 +508,9 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
506
508
  setting =~ /(.*){(.*)}/
507
509
  key, lookup_as = $1, $2
508
510
 
511
+ if !eval("#{class_name}.reflect_on_association(:#{key.to_s.gsub("_id","")})")
512
+ raise "couldn't find association for #{key} in the object #{class_name}"
513
+ end
509
514
  assoc = eval("#{class_name}.reflect_on_association(:#{key.to_s.gsub("_id","")}).class_name")
510
515
 
511
516
  data = {lookup_as: lookup_as.gsub("+",""),
@@ -514,7 +519,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
514
519
  @alt_lookups[key] = data
515
520
  end
516
521
 
517
- puts "------ ALT LOOKUPS for #{@alt_lookups}"
522
+
518
523
 
519
524
  # @update_alt_lookups = @alt_lookups.collect{|key, value|
520
525
  # @update_show_only.include?(key) ?
@@ -578,6 +583,18 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
578
583
  end
579
584
  end
580
585
 
586
+
587
+ puts "------ ALT LOOKUPS for #{@alt_lookups}"
588
+ @alt_lookups.each do |key, value|
589
+ if !@columns_map[key.to_sym].is_a?(AssociationField)
590
+ raise "You specified an alt-lookup for #{key} but that field is not an association field"
591
+ elsif !@columns_map[key.to_sym]
592
+ raise "You specified an alt-lookup for #{key} but that field does not exist in the list of columns"
593
+ elsif !@god && !@hawk_keys.include?(key.to_sym)
594
+ raise "You specified an alt-lookup for #{key} in non-Gd mode but this would leave the lookup unprotected. To fix, use with --hawk or with --factory-creation "
595
+ end
596
+ end
597
+
581
598
  # search
582
599
  @search = options['search']
583
600
  if @search == 'set'
@@ -677,7 +694,6 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
677
694
  if options["hawk"]
678
695
  options['hawk'].split(",").each do |hawk_entry|
679
696
  # format is: abc_id[thing]
680
-
681
697
  if hawk_entry.include?("{")
682
698
  hawk_entry =~ /(.*){(.*)}/
683
699
  key, hawk_to = $1, $2
@@ -687,6 +703,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
687
703
  end
688
704
 
689
705
  hawk_scope = key.gsub("_id", "").pluralize
706
+
690
707
  if eval(singular_class + ".reflect_on_association(:#{key.gsub('_id', '')})").nil?
691
708
  raise "Could not find `#{key.gsub('_id', '')}` association; add this to the #{singular_class} class: \nbelongs_to :#{key.gsub('_id', '')} "
692
709
  end
@@ -836,6 +853,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
836
853
  :confirmation_token, :confirmed_at,
837
854
  :confirmation_sent_at, :unconfirmed_email
838
855
 
856
+
857
+ # TODO: this should exclude any nested parents
839
858
  @exclude_fields.push(@ownership_field.to_sym) if !@ownership_field.nil?
840
859
 
841
860
  @columns = @the_object.columns.map(&:name).map(&:to_sym).reject { |field| @exclude_fields.include?(field) }
@@ -844,7 +863,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
844
863
  @columns = @the_object.columns.map(&:name).map(&:to_sym).reject { |field| !@include_fields.include?(field) }
845
864
  end
846
865
 
847
- @columns = @columns -@nested_set.collect { |set| (set[:singular] + "_id").to_sym }
866
+ @columns = @columns - @nested_set.collect { |set| (set[:singular] + "_id").to_sym }
848
867
 
849
868
  if @attachments.any?
850
869
  puts "Adding attachments-as-columns: #{@attachments}"
@@ -888,8 +907,21 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
888
907
  end
889
908
 
890
909
  def creation_syntax
891
- if @factory_creation == ''
892
- "@#{singular } = #{ class_name }.new(modified_params)"
910
+ if @factory_creation.nil? && ! @alt_lookups.any?
911
+ ( @hawk_keys.any? ? "modified_params = hawk_params({#{ hawk_to_ruby }}, modified_params)\n " : "") + "@#{singular } = #{ class_name }.new(modified_params)"
912
+ elsif @factory_creation.nil? && @alt_lookups.any?
913
+
914
+ prelookup_syntax = @alt_lookups.collect{|lookup, data|
915
+ col = @columns_map[lookup.to_sym]
916
+ col.prelookup_syntax
917
+ }.join("\n")
918
+
919
+ prelookup_syntax + "\n @#{singular } = #{ class_name }.new(modified_params" +
920
+ (@alt_lookups.any? ? (".merge(" + @alt_lookups.collect{|lookup,field|
921
+ field_name = lookup.gsub("_id","")
922
+ "#{field_name}: #{field_name}"
923
+ }.join(",") + ")" ) : "") + ")"
924
+
893
925
  else
894
926
  res = +"begin
895
927
  #{@factory_creation}
@@ -954,10 +986,11 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
954
986
 
955
987
  template "system_spec.rb.erb", dest_file
956
988
  end
957
-
958
- if File.exist?("#{filepath_prefix}app/views#{namespace_with_dash}/_errors.#{@markup}")
959
- File.delete("#{filepath_prefix}app/views#{namespace_with_dash}/_errors.#{@markup}")
960
- end
989
+ # if !File.exist?("#{filepath_prefix}app/views#{namespace_with_dash}/_errors.#{@markup}")
990
+ # # File.delete("#{filepath_prefix}app/views#{namespace_with_dash}/_errors.#{@markup}")
991
+ #
992
+ # template "_errors.erb", File.join("#{filepath_prefix}app/views#{namespace_with_dash}", "_errors.#{@markup}")
993
+ # end
961
994
  end
962
995
 
963
996
  def spec_foreign_association_merge_hash
@@ -27,10 +27,12 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
27
27
  def <%= @nested_set[0][:singular] %><% if @god
28
28
  next_object = nil
29
29
  collect_objects = @nested_set.reverse.collect {|x|
30
- if eval("#{next_object || class_name}.reflect_on_association(:#{x[:singular]})").nil?
31
- raise "***** Unable to find the association `#{x[:singular]}` on the class #{next_object || class_name} ..... you probably want to add `belongs_to :#{x}` to the #{next_object || class_name} object?"
30
+ if eval("#{next_object || class_name}.reflect_on_association(:#{x[:singular]})").nil? #&& eval("! #{next_object || class_name}.instance_methods.include?(:#{x[:singular]})")
31
+ raise "***** Unable to find the association `#{x[:singular]}` on the class #{next_object || class_name} ..... you probably want to add `belongs_to :#{x[:singular]}` to the #{next_object || class_name} object?"
32
32
  end
33
+ # if eval("#{next_object || class_name}.reflect_on_association(:#{x[:singular]})")
33
34
  next_object = eval("#{next_object || class_name}.reflect_on_association(:#{x[:singular]})").class_name
35
+ # end
34
36
  }
35
37
  root_object = collect_objects.last
36
38
  else
@@ -110,11 +112,10 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
110
112
  modified_params = modified_params.merge(<%= @object_owner_sym %>: <%= @object_owner_eval %>) <% elsif @object_owner_optional && any_nested? %>
111
113
  modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <% end %>
112
114
 
113
- <% if @hawk_keys.any? %>
114
- modified_params = hawk_params({<%= hawk_to_ruby %>}, modified_params)<% end %>
115
115
  <%= controller_attachment_orig_filename_pickup_syntax %>
116
116
  <%= creation_syntax %>
117
- <% if @pundit %><% @related_sets.each do |key, related_set| %>
117
+
118
+ <% if @pundit %><% @related_sets.each do |key, related_set| %>
118
119
  check_<%= related_set[:association_ids_method].to_s %>_permissions(modified_params, :create)<% end %><% end %>
119
120
  <% if @pundit && !@pundit_policy_override %>
120
121
  authorize @<%= singular %><% elsif @pundit && @pundit_policy_override %>
@@ -185,8 +186,13 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
185
186
  flash[:alert] = nil
186
187
  <% @magic_buttons.each do |button| %>
187
188
  if <%= singular_name %>_params[:__<%= button %>]
188
- @<%= singular_name %>.<%= button %>!
189
- flash[:notice] << "<% singular %> <%= button.titlecase %>."
189
+
190
+ if res = @<%= singular_name %>.<%= button %>!
191
+ flash[:notice] << "<% singular %> <%= button.titlecase %>"
192
+ flash[:notice] << " #{res}" if res.is_a?(String)
193
+ else
194
+ flash[:alert] = " <%= button.titlecase %> failed."
195
+ end
190
196
  end
191
197
  <% end %>
192
198
 
@@ -195,8 +201,20 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
195
201
  modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <% end %>
196
202
  <% if @pundit %><% @related_sets.each do |key, related_set| %>
197
203
  check_<%= related_set[:association_ids_method].to_s %>_permissions(modified_params, :update)<% end %><% end %>
204
+ <% if (@alt_lookups.any?) %>
205
+ <%= @alt_lookups.collect{|lookup, data|
206
+ @columns_map[lookup.to_sym].prelookup_syntax unless @update_show_only.include?(lookup.to_sym)
207
+ }.join("\n") %>
208
+ <% elsif @factory_creation %>
198
209
 
199
- <% if @hawk_keys.any? %> modified_params = hawk_params({<%= hawk_to_ruby %>}, modified_params)<% end %>
210
+ <% end %>
211
+ <% if (@alt_lookups.keys.collect(&:to_sym) - @update_show_only).any? %>
212
+ modified_params.merge!(<%= @alt_lookups.collect{|lookup,field|
213
+ field_name = lookup.gsub("_id","")
214
+ "#{field_name}: #{field_name}" unless @update_show_only.include?(lookup.to_sym)
215
+ }.join(",") %>)
216
+ <% end %>
217
+ <% if @hawk_keys.any? %> modified_params = hawk_params({<%= hawk_to_ruby %>}, modified_params)<% end %>
200
218
  <%= controller_attachment_orig_filename_pickup_syntax %>
201
219
  <% if @pundit && !@pundit_policy_override %>
202
220
  authorize @<%= singular_name %>
@@ -221,6 +239,11 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
221
239
  <% end %>
222
240
  else
223
241
  flash[:alert] = "<%= singular_name.titlecase %> could not be saved. #{@hawk_alarm}"
242
+ <%= @alt_lookups.collect{ |k,v|
243
+ assoc = k.gsub("_id","")
244
+ "@#{singular }.#{k} = #{class_name}.find(@#{singular }.id).person.id if @#{singular }.errors.include?(:#{assoc})"
245
+
246
+ }.join("\n") %>
224
247
  @action = 'edit'
225
248
  <% unless @big_edit %>render :update<% else %>render :edit<% end %>, status: :unprocessable_entity
226
249
  end<% if @pundit %>
@@ -236,9 +259,9 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
236
259
  skip_authorization
237
260
  raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.destroy?<% end %>
238
261
  begin
239
- @<%=singular_name%>.destroy
262
+ @<%=singular_name%>.destroy!
240
263
  flash[:notice] = '<%= singular_name.titlecase %> successfully deleted'
241
- rescue ActiveRecordError => e
264
+ rescue ActiveRecord::RecordNotDestroyed => e
242
265
  flash[:alert] = '<%= singular_name.titlecase %> could not be deleted'
243
266
  end
244
267
  <%= post_action_parental_updates.join("\n ") %>
@@ -261,12 +284,12 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
261
284
  end<% end %><% end %>
262
285
 
263
286
  def <%=singular_name%>_params
264
- params.require(:<%= testing_name %>).permit(<%= ((fields_filtered_for_strong_params - @show_only ) + @magic_buttons.collect{|x| "__#{x}"}).collect{|sym| ":#{sym}"}.join(", ") %><%= ", " + @related_sets.collect{|key, rs| "#{rs[:association_ids_method]}: []"}.join(", ") if @related_sets.any? %><%= ", " + @alt_lookups.collect{|k,v| ":__lookup_#{v[:lookup_as]}" }.join(", ") if @alt_lookups.any? %>)
287
+ params.require(:<%= testing_name %>).permit(<%= ((fields_filtered_for_strong_params - @show_only ) + @magic_buttons.collect{|x| "__#{x}"}).collect{|sym| ":#{sym}"}.join(", ") %><%= ", " + @related_sets.collect{|key, rs| "#{rs[:association_ids_method]}: []"}.join(", ") if @related_sets.any? %><%= ", " + @alt_lookups.collect{|k,v| ":__lookup_#{v[:assoc].downcase}_#{v[:lookup_as]}" }.join(", ") if @alt_lookups.any? %>)
265
288
  end<% if @update_show_only %>
266
289
 
267
290
  <% unless @no_edit %>
268
291
  def update_<%=singular_name%>_params
269
- params.require(:<%= testing_name %>).permit(<%= ((fields_filtered_for_strong_params - @update_show_only) + @magic_buttons.collect{|x| "__#{x}"}).collect{|sym| ":#{sym}"}.join(", ") %><%= ", " + @related_sets.collect{|key, rs| "#{rs[:association_ids_method]}: []"}.join(", ") if @related_sets.any? %>)
292
+ params.require(:<%= testing_name %>).permit(<%= ((fields_filtered_for_strong_params - @update_show_only) + @magic_buttons.collect{|x| "__#{x}"}).collect{|sym| ":#{sym}"}.join(", ") %><%= ", " + @related_sets.collect{|key, rs| "#{rs[:association_ids_method]}: []"}.join(", ") if @related_sets.any? %><%= ", " + @alt_lookups.collect{|k,v| ":__lookup_#{v[:assoc].downcase}_#{v[:lookup_as]}" }.join(", ") if @alt_lookups.any? %>)
270
293
  end<% end %>
271
294
  <% end %>
272
295
 
@@ -1,5 +1,5 @@
1
1
  module HotGlue
2
2
  class Version
3
- CURRENT = '0.6.17'
3
+ CURRENT = '0.6.19'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hot-glue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.17
4
+ version: 0.6.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Fleetwood-Boldt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-08 00:00:00.000000000 Z
11
+ date: 2025-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails