hot-glue 0.6.22 → 0.6.24

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.
@@ -154,8 +154,12 @@ class AssociationField < Field
154
154
 
155
155
 
156
156
 
157
+ if modify_as && modify_as[:include_blank]
158
+ include_blank = ", include_blank: true"
159
+ end
160
+
157
161
  (is_owner ? "<% unless @#{assoc_name} %>\n" : "") +
158
- " <%= f.collection_select(:#{name}, #{hawked_association}, :id, :#{display_column}, { prompt: true, selected: #{singular}.#{name} }, class: 'form-control'#{data_attr}) %>\n" +
162
+ " <%= f.collection_select(:#{name}, #{hawked_association}, :id, :#{display_column}, { prompt: true, selected: #{singular}.#{name}#{include_blank} }, class: 'form-control'#{data_attr}) %>\n" +
159
163
  (is_owner ? "<% else %>\n <%= @#{assoc_name}.#{display_column} %>" : "") +
160
164
  (is_owner ? "\n<% end %>" : "")
161
165
  end
@@ -1,6 +1,6 @@
1
1
  class RelatedSetField < Field
2
2
 
3
- attr_accessor :assoc_name, :assoc_class, :assoc
3
+ attr_accessor :assoc_name, :assoc_class, :assoc, :label_field, :hawk
4
4
 
5
5
  def initialize( scaffold: , name: )
6
6
  super
@@ -17,15 +17,23 @@ class RelatedSetField < Field
17
17
 
18
18
  @assoc_class = eval(@related_set_model.try(:class_name))
19
19
 
20
- name_list = [:name, :to_label, :full_name, :display_name, :email]
21
20
 
22
- if assoc_class && name_list.collect{ |field|
23
- assoc_class.respond_to?(field.to_s) || assoc_class.instance_methods.include?(field)
24
- }.none?
25
- exit_message = "Oops: Missing a label for `#{assoc_class}`. Can't find any column to use as the display label for the #{@assoc_name} association on the #{class_name} model. TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name 5) email. You can implement any of these directly on your`#{assoc_class}` model (can be database fields or model methods) or alias them to field you want to use as your display label. Then RERUN THIS GENERATOR. (Field used will be chosen based on rank here.)"
26
- raise(HotGlue::Error, exit_message)
27
- end
21
+ @deets = scaffold.related_sets[name.to_sym]
22
+
23
+ if @deets[:label_field].nil?
24
+ @label_field = "label"
28
25
 
26
+ # name_list = [:name, :to_label, :full_name, :display_name, :email]
27
+ #
28
+ # if assoc_class && name_list.collect{ |field|
29
+ # assoc_class.respond_to?(field.to_s) || assoc_class.instance_methods.include?(field)
30
+ # }.none?
31
+ # exit_message = "Oops: Missing a label for `#{assoc_class}`. Can't find any column to use as the display label for the #{@assoc_name} association on the #{class_name} model. TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name 5) email. You can implement any of these directly on your`#{assoc_class}` model (can be database fields or model methods) or alias them to field you want to use as your display label. Then RERUN THIS GENERATOR. (Field used will be chosen based on rank here.)"
32
+ # raise(HotGlue::Error, exit_message)
33
+ # end
34
+ else
35
+ @label_field = @deets[:label_field]
36
+ end
29
37
  end
30
38
 
31
39
 
@@ -35,11 +43,23 @@ class RelatedSetField < Field
35
43
  if pundit
36
44
  disabled_syntax << ", {disabled: ! #{class_name}Policy.new(#{auth}, @#{singular}).role_ids_able?}"
37
45
  end
38
- " <%= f.collection_check_boxes :#{association_ids_method}, #{association_class_name}.all, :id, :label, {}#{disabled_syntax} do |m| %>
46
+ " <%= f.collection_check_boxes :#{association_ids_method}, #{record_scope}, :id, :#{label_field}, {}#{disabled_syntax} do |m| %>
39
47
  <%= m.check_box %> <%= m.label %><br />
40
48
  <% end %>"
41
49
  end
42
50
 
51
+ def record_scope
52
+ if hawk.nil?
53
+ "#{association_class_name}.all"
54
+ else
55
+ hawk
56
+ end
57
+ end
58
+
59
+ def label_field
60
+ @label_field
61
+ end
62
+
43
63
  def association_ids_method
44
64
  eval("#{class_name}.reflect_on_association(:#{name})").class_name.underscore + "_ids"
45
65
  end
@@ -49,7 +69,7 @@ class RelatedSetField < Field
49
69
  end
50
70
 
51
71
  def viewable_output
52
- "<%= #{singular}.#{name}.collect(&:label).join(\", \") %>"
72
+ "<%= #{singular}.#{name}.collect(&:#{label_field}).join(\", \") %>"
53
73
  end
54
74
  end
55
75
 
@@ -31,7 +31,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
31
31
  :search_clear_button, :search_autosearch, :include_object_names,
32
32
  :stimmify, :stimmify_camel, :hidden_create, :hidden_update,
33
33
  :invisible_create, :invisible_update, :phantom_create_params,
34
- :phantom_update_params
34
+ :phantom_update_params, :lazy
35
35
  # important: using an attr_accessor called :namespace indirectly causes a conflict with Rails class_name method
36
36
  # so we use namespace_value instead
37
37
 
@@ -303,6 +303,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
303
303
  @modify_as[key.to_sym] = {typeahead: 1, nested: nested}
304
304
  elsif $2 == "timezone"
305
305
  @modify_as[key.to_sym] = {timezone: 1, badges: $3}
306
+ elsif $2 == "include_blank"
307
+ @modify_as[key.to_sym] = {include_blank: true}
306
308
  elsif $2 == "none"
307
309
  @modify_as[key.to_sym] = {none: 1, badges: $3}
308
310
  else
@@ -507,17 +509,38 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
507
509
  puts "NESTING: #{@nested_set}"
508
510
  end
509
511
 
512
+ if @nested_set.any?
513
+ @lazy = true
514
+ end
515
+
510
516
  # related_sets
511
517
  related_set_input = options['related_sets'].split(",")
512
518
  @related_sets = {}
513
519
  related_set_input.each do |setting|
514
- name = setting.to_sym
515
- association_ids_method = eval("#{singular_class}.reflect_on_association(:#{setting.to_sym})").class_name.underscore + "_ids"
516
- class_name = eval("#{singular_class}.reflect_on_association(:#{setting.to_sym})").class_name
517
520
 
518
- @related_sets[setting.to_sym] = { name: setting.to_sym,
521
+ if setting.include?("{") && setting.include?("[")
522
+ setting =~ /(.*){(.*)}\[(.*)\]/
523
+ key, label, hawk = $1, $2 , $3
524
+ elsif setting.include?("{") && !setting.include?("[")
525
+ setting =~ /(.*){(.*)}/
526
+ key, label = $1, $2 , $3
527
+ elsif setting.include?("[") && !setting.include?("{")
528
+ setting =~ /(.*)\[(.*)\]/
529
+ key, hawk = $1, $2
530
+ else
531
+
532
+ key = setting
533
+ label = "label"
534
+ end
535
+
536
+ association_ids_method = eval("#{singular_class}.reflect_on_association(:#{key.to_sym})").class_name.underscore + "_ids"
537
+ class_name = eval("#{singular_class}.reflect_on_association(:#{key.to_sym})").class_name
538
+
539
+ @related_sets[key.to_sym] = { name: key.to_sym,
519
540
  association_ids_method: association_ids_method,
520
- class_name: class_name }
541
+ class_name: class_name,
542
+ label_field: label,
543
+ hawk: hawk }
521
544
  end
522
545
 
523
546
  if @related_sets.any?
@@ -587,6 +610,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
587
610
  setting =~ /(.*){(.*)}/
588
611
  key, lookup_as = $1, $2
589
612
 
613
+
614
+
590
615
  if !eval("#{class_name}.reflect_on_association(:#{key.to_s.gsub("_id","")})")
591
616
  raise "couldn't find association for #{key} in the object #{class_name}"
592
617
  end
@@ -1534,6 +1559,10 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
1534
1559
  res -= %w{_list _line index}
1535
1560
  end
1536
1561
 
1562
+ if @lazy
1563
+ res << '_lazy_list'
1564
+ end
1565
+
1537
1566
  res
1538
1567
  end
1539
1568
 
@@ -86,6 +86,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
86
86
  authorize @<%= plural_name %><% elsif @pundit && @pundit_policy_override %>
87
87
  skip_authorization
88
88
  raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.index?<% end %>
89
+ <% if @lazy %>render layout: (params[:__lazy].present? ? false : true)<% end %>
89
90
  rescue Pundit::NotAuthorizedError
90
91
  flash[:alert] = 'You are not authorized to perform this action.'
91
92
  render 'layouts/error'<% end %>
@@ -164,7 +165,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
164
165
  raise Pundit::NotAuthorizedError if ! <%= @pundit_policy_override %>.show?<% end %>
165
166
  redirect_to <%= HotGlue.optionalized_ternary(namespace: @namespace,
166
167
  target: @singular,
167
- top_level: false,
168
+ top_level: true,
168
169
  nested_set: @nested_set,
169
170
  modifier: 'edit_',
170
171
  with_params: true,
@@ -280,20 +281,19 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
280
281
  # <%= rs[:association_ids_method] %>: modified_params[:<%= rs[:association_ids_method] %>>]} syntax for Pundit
281
282
  modified_relations = { <%= rs[:association_ids_method] %>: modified_params[:<%= rs[:association_ids_method] %>] }
282
283
  return unless modified_params[:<%= rs[:association_ids_method] %>].present?
283
- policy_check = <%= singular_class %>Policy.new(current_user, @<%= singular %>,
284
- modified_relations:).method("#{action}?".to_sym).call
284
+ policy_check = <%= singular_class %>Policy.new(current_user, @<%= singular %>).method("#{action}?".to_sym).call
285
285
  return if policy_check
286
286
  raise Pundit::NotAuthorizedError, message: @<%= singular %>.errors.collect{|k| "#{k.attribute} #{k.message}"}.join(" ")
287
287
  end<% end %><% end %>
288
288
 
289
289
  def <%=singular_name%>_params
290
- fields = <%= ((fields_filtered_for_strong_params - @show_only) + @magic_buttons.collect{|x| "__#{x}"} + @phantom_create_params.split(",")).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? %>
290
+ fields = <%= ((fields_filtered_for_strong_params - @show_only) + @magic_buttons.collect{|x| "__#{x}"} + @phantom_create_params.split(",")).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? %>
291
291
  params.require(:<%= testing_name %>).permit(fields)
292
292
  end<% if @update_show_only %>
293
293
 
294
294
  <% unless @no_edit %>
295
295
  def update_<%=singular_name%>_params
296
- fields = <%= ((fields_filtered_for_strong_params - @update_show_only) + @magic_buttons.collect{|x| "__#{x}"} + @phantom_update_params.split(",")).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? %>
296
+ fields = <%= ((fields_filtered_for_strong_params - @update_show_only) + @magic_buttons.collect{|x| "__#{x}"} + @phantom_update_params.split(",")).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? %>
297
297
  <%= (fields_filtered_for_strong_params - @update_show_only).collect{|col|
298
298
  # TODO : fields not on show only also not invisible should be checked here
299
299
  # for _able? methods and added only when able
@@ -2,8 +2,7 @@
2
2
  <%= form_fields_html %>
3
3
 
4
4
  <div class="<%= @layout_strategy.column_classes_for_button_column %>">
5
- <\%= link_to "Cancel", <%=
6
- @nested_set.none? ? path_helper_plural : edit_parent_path_helper %>, {class: "btn btn-secondary"} %><% if @no_field_form %>
5
+ <\%= link_to "Cancel", <%= path_helper_plural %> + (params[:page] ? "?page=" + params[:page] : ""), {class: "btn btn-secondary"} %><% if @no_field_form %>
7
6
  <\%= f.hidden_field "_________" %><% end %>
8
7
  <\%= f.submit "Save", class: "btn btn-primary pull-right" %>
9
8
  </div>
@@ -0,0 +1,7 @@
1
+ <\%= tag.turbo_frame id: "<%= @namespace %>__<%= plural %>-list" <%= nested_for_turbo_id_list_constructor %>,
2
+ src: <%= path_helper_plural %> + "?__lazy",
3
+ loading: "lazy" do %>
4
+
5
+ <div class="text-muted">Loading ...</div>
6
+
7
+ <\% end %>
@@ -1,7 +1,5 @@
1
1
  <%= all_line_fields %>
2
2
 
3
-
4
-
5
3
  <% if @downnest_children.any? && ! @big_edit %>
6
4
  <% each_downnest_width = @downnest_children.count == 1 ? 33 : (53/@downnest_children.count).floor %>
7
5
  <% if @stacked_downnesting %><div class="<%= @layout_strategy.downnest_portal_stacked_column_width %> scaffold-downnest" ><% end %>
@@ -44,6 +42,6 @@
44
42
  <% end %>
45
43
 
46
44
  <% unless @no_edit %>
47
- <\%= link_to "Edit <% if @button_icons == 'font-awesome' %><i class='fa fa-1x fa-list-alt'></i><% end %>".html_safe, <%= edit_path_helper %>, <% if @big_edit %>'data-turbo' => 'false', <% end %>disable_with: "Loading...", class: "edit-<%= singular %>-button btn btn-primary btn-sm" %>
45
+ <\%= link_to "Edit <% if @button_icons == 'font-awesome' %><i class='fa fa-1x fa-list-alt'></i><% end %>".html_safe, <%= edit_path_helper %> + (params[:page] ? "?page=#{params[:page]}" : ""), <% if @big_edit %>'data-turbo' => 'false', <% end %>disable_with: "Loading...", class: "edit-<%= singular %>-button btn btn-primary btn-sm" %>
48
46
  <% end %>
49
47
  </div>
@@ -1,6 +1,6 @@
1
1
  <\% if @<%= singular %>.errors.none? %>
2
2
  <\%= turbo_stream.replace "<%= @namespace %>__<%= plural %>-list" + <%= nested_for_turbo_nested_constructor %> do %>
3
- <\%= render partial: "list", locals: {<%= plural %>: @<%= plural %><% if @nested_set.any? %>, <%= @nested_set.collect{|arg| "#{arg[:singular]}: @#{arg[:singular]}"}.join(", ") %>, nested_for: '<%= @nested_set.collect{|arg| "\"#{arg[:singular]}-\#{@#{arg[:singular]}.id}\""}.join("__") %>' <% end %> } %>
3
+ <\%= render partial: "list", locals: {<%= plural %>: @<%= plural %><% if @nested_set.any? %>, <%= @nested_set.collect{|arg| "#{arg[:singular]}: @#{arg[:singular]}"}.join(", ") %>, nested_for: "<%= @nested_set.collect{|arg| "#{arg[:singular]}-\#{@#{arg[:singular]}.id}"}.join("__") %>" <% end %> } %>
4
4
 
5
5
  <\% end %>
6
6
  <\% end %>
@@ -36,7 +36,8 @@
36
36
  <% downnest_object_name = downnest[:name] %>
37
37
  <% downnest_style = @layout_strategy.downnest_style %>
38
38
 
39
- <\%= render partial: "<%= namespace_with_trailing_dash %><%= downnest_object_name %>/list", locals: {<%= @singular %>: @<%= @singular %>, <%= downnest[:polymorph_as] || downnest[:name] %>: @<%= @singular %>.<%= downnest[:polymorph_as] || downnest[:name] %><% if @nested_set.any? %>, <%= @nested_set.collect{|x| "#{x[:singular]}: @#{x[:singular]}"}.join(", ") %>, nested_for: "<%= @nested_set.collect{|x| "#{x[:singular]}-" + "\#{" + "@#{x[:singular]}.id}"}.join("__") %>__<%= singular %>-#{@<%= @singular %>.id}" <% end %> } \%>
39
+ <\%= render partial: "<%= namespace_with_trailing_dash %><%= downnest_object_name %>/lazy_list", locals: {<%= @singular %>: @<%= @singular %>, <%= @nested_set.collect{|x| "#{x[:singular]}: @#{x[:singular]}"}.join(", ") %><%= @nested_set.any? ? "," : "" %> nested_for: "<%= (@nested_set).collect{|x| "#{x[:singular]}-" + "\#{" + "@#{x[:singular]}.id}"}.join("__") %><%= "__" if @nested_set.any? %><%= singular %>-#{@<%= @singular %>.id}" } \%>
40
+
40
41
  </div>
41
42
  <% end %>
42
43
  </div>
@@ -6,6 +6,7 @@
6
6
 
7
7
  <%= @layout_strategy.page_begin %>
8
8
  <\%= render partial: '<%= list_path_partial %>',
9
- locals: {<%= plural %>: @<%= plural %>}<%= @nested_set.collect{|arg| ".merge(@" + arg[:singular] + " ? {nested_for: \"" + arg[:singular] + "-\#{@" + arg[:singular] + ".id}\"" + ", " + arg[:singular] + ": @" + arg[:singular] + "} : {})"}.join() %> \%>
9
+ locals: {<%= plural %>: @<%= plural %> <% if @nested_set.any? %>, nested_for: "<%= @nested_set.collect{|n| "#{n[:singular]}-\#{@#{n[:singular]}.id}"}.join("__") %>", <%= @nested_set.collect{|n| "#{n[:singular]}: @#{n[:singular]}"}.join(", ") %><% end %>
10
+ } \%>
10
11
  <%= @layout_strategy.page_end %>
11
12
  </div>
data/lib/hot-glue.rb CHANGED
@@ -25,7 +25,7 @@ module HotGlue
25
25
  def self.optionalized_ternary(namespace: nil,
26
26
  target:,
27
27
  nested_set:,
28
- prefix: nil, # is this used
28
+ prefix: "", # is this used
29
29
  modifier: "",
30
30
  with_params: false,
31
31
  top_level: false,
@@ -35,33 +35,33 @@ module HotGlue
35
35
 
36
36
 
37
37
  if nested_set.nil? || nested_set.empty?
38
- return modifier + "#{(namespace + '_') if namespace}#{target}_path" + (("(#{instance_sym}#{target})" if put_form) || "")
39
- elsif nested_set[0][:optional] == false
38
+ return modifier + "#{(namespace + '_') if namespace}#{prefix}#{target}_path" + (("(#{instance_sym}#{target})" if put_form) || "")
40
39
 
40
+ else
41
41
  res = modifier + ((namespace + "_" if namespace) || "") + nested_set.collect{|x|
42
42
  x[:singular] + "_"
43
- }.join() + target + "_path" + (("(#{nested_set.collect{
43
+ }.join() + prefix + target + "_path" + (("(#{nested_set.collect{
44
44
  |x| instance_sym + x[:singular] }.join(",")
45
45
  }#{ put_form ? ',' + (instance_last_item ? "@" : instance_sym) + target : '' })") || "")
46
46
 
47
47
  res
48
-
49
- else
48
+ # else
49
+ # raise "optional nested set is deprecated"
50
50
  # copy the first item, make a ternery in this cycle, and recursively move to both the
51
51
  # is present path and the is optional path
52
52
 
53
- nonoptional = nested_set[0].dup
54
- nonoptional[:optional] = false
55
- rest_of_nest = nested_set[1..-1]
56
-
57
- is_present_path = HotGlue.optionalized_ternary(
58
- namespace: namespace,
59
- target: target,
60
- modifier: modifier,
61
- top_level: top_level,
62
- with_params: with_params,
63
- put_form: put_form,
64
- nested_set: [nonoptional, *rest_of_nest])
53
+ # nonoptional = nested_set[0].dup
54
+ # nonoptional[:optional] = false
55
+ # rest_of_nest = nested_set[1..-1]
56
+ #
57
+ # is_present_path = HotGlue.optionalized_ternary(
58
+ # namespace: namespace,
59
+ # target: target,
60
+ # modifier: modifier,
61
+ # top_level: top_level,
62
+ # with_params: with_params,
63
+ # put_form: put_form,
64
+ # nested_set: [nonoptional, *rest_of_nest])
65
65
 
66
66
  # is_missing_path = HotGlue.optionalized_ternary(
67
67
  # namespace: namespace,
@@ -72,7 +72,7 @@ module HotGlue
72
72
  # put_form: put_form,
73
73
  # nested_set: rest_of_nest )
74
74
  #
75
- return "#{is_present_path}"
75
+ # return "#{is_present_path}"
76
76
  end
77
77
  end
78
78
 
@@ -1,5 +1,5 @@
1
1
  module HotGlue
2
2
  class Version
3
- CURRENT = '0.6.22'
3
+ CURRENT = '0.6.24'
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.22
4
+ version: 0.6.24
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-07-28 00:00:00.000000000 Z
11
+ date: 2025-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -115,6 +115,7 @@ files:
115
115
  - lib/generators/hot_glue/templates/erb/_edit.erb
116
116
  - lib/generators/hot_glue/templates/erb/_flash_notices.erb
117
117
  - lib/generators/hot_glue/templates/erb/_form.erb
118
+ - lib/generators/hot_glue/templates/erb/_lazy_list.erb
118
119
  - lib/generators/hot_glue/templates/erb/_line.erb
119
120
  - lib/generators/hot_glue/templates/erb/_list.erb
120
121
  - lib/generators/hot_glue/templates/erb/_nav.html.erb