hot-glue 0.6.15 → 0.6.17

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: 4e3993f35ba9d926cec0a205bb06708be83c2d72012eaafebce6cb384da07a92
4
- data.tar.gz: 509b98c64699c6561435d63da9b0ae6afe2924d6c1624dbcedf1a3288a5dfc0d
3
+ metadata.gz: a6abeaf2b7456e5f554928c58bb5deae7fb01a0c664ad0d717572f20c6185537
4
+ data.tar.gz: da58696031065cf910116374477ce9f8f3b388bef0a2ad756289953b70a31d8b
5
5
  SHA512:
6
- metadata.gz: b3d097f4f7130718597c9024173980e2d7b59826d4bb355ce34c22f70f0fec01e6265784007bdc296f41e0cd232d96d7a1ed2e0b055a6f7dbb1eef644fac5da7
7
- data.tar.gz: 83905ccb51e15676d2dff4253f656ef29a330272ed0549ebbbb74a7272ee9aa42b04491ba4ef88c2bf9fb84ec047991da89fa027e519cf048f3197bd7687ccd1
6
+ metadata.gz: 626a8d361bef7d74109406ba5beae46b0daf4db297c2f95fcd92431bc1b6f9ea97d224acb8ef898bb0281b8cb3bc369d5507f6956751da137c4e5ecb4e3a93d5
7
+ data.tar.gz: 3a646740022a5c699051ad99c400178f1abdafc911a9c1e40c400b52a16458f3181e98ed73e0e6db8fc64fdaa8829b93f8432efcf4026873dbb2236708c2308e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hot-glue (0.6.14)
4
+ hot-glue (0.6.17)
5
5
  ffaker (~> 2.16)
6
6
  kaminari (~> 1.2)
7
7
  rails (> 5.1)
@@ -140,7 +140,7 @@ GEM
140
140
  mini_mime (1.1.2)
141
141
  mini_portile2 (2.8.4)
142
142
  minitest (5.16.3)
143
- net-imap (0.5.6)
143
+ net-imap (0.5.8)
144
144
  date
145
145
  net-protocol
146
146
  net-pop (0.1.2)
data/README.md CHANGED
@@ -790,6 +790,23 @@ end
790
790
  Because Hot Glue detects the `*_able?` methods at build time, if you add them to your policy, you will have to rebuild your scaffold.
791
791
 
792
792
 
793
+ ### `--pundit-policy-override`
794
+ if you use the flag `--pundit-policy-override` your controller operations will bypass the invisible (pundit provided) access control and use the pundit policy you specify.
795
+
796
+ example
797
+
798
+ `rails generate hot_glue:scaffold Invoice --gd --pundit-policy-override='UniqueInvoicePolicy'`
799
+
800
+ You will implement a Pundit policy for `UniqueInvoicePolicy` and it should implement actions with question mark `?` endings corresponding to the same actions you are building, `new?`, `create?`, `edit?`, `update?`, and `destroy?`
801
+
802
+ If provided, the output code looks something like (in this example, showing the `edit?` method)
803
+
804
+ ```
805
+ skip_authorization
806
+ raise Pundit::NotAuthorizedError if ! UniqueInvoicePolicy.edit?
807
+ ```
808
+
809
+
793
810
  ### `--show-only=`
794
811
  (separate field names by COMMA)
795
812
 
@@ -851,6 +868,92 @@ Remember, if there's a corresponding `*_able?` method on the policy, it will be
851
868
  As shown in the method `name_able?` of the example ThingPolicy above, if this field on your policy returns true, the field will be editable. If it returns false, the field will be viewable (read-only).
852
869
 
853
870
 
871
+ ### `--hidden`
872
+
873
+ Separate list of fields.
874
+
875
+ These fields will be hidden from the form but will exist as hidden_field, and so the update will still work.
876
+
877
+
878
+ EXAMPLE:
879
+
880
+ ```
881
+ bin/rails generate hot_glue:scaffold Wrapper --namespace='account_dashboard' --no-nav-menu --big-edit --smart-layout --stimmify --hidden=raw_source
882
+ ```
883
+
884
+ In the `wrappers` folder, I am using a special sticky partial `_edit_within_form.html.erb`, which contains code preserved from build-to-build and included in the form:
885
+
886
+
887
+ ```
888
+ <div class="row" style="position: relative; width: 100%; overflow: auto;">
889
+ <div class="col-md-12">
890
+ <div id="wrapper__raw_source"
891
+ style="position: static">
892
+
893
+ <div id="wrapper__raw_source-toolbar">
894
+
895
+ </div>
896
+
897
+
898
+ <div cols="60"
899
+ data-wrapper-form-target="editor"
900
+ id="wrapper__raw_source-editor" >
901
+ </div>
902
+ </div>
903
+
904
+
905
+ </div>
906
+ </div>
907
+ <div class="col-md-2">
908
+ </div>
909
+ ```
910
+
911
+
912
+ Then, create a `app/javascript/controllers/wrapper_form_controller.js` file with the following code:
913
+
914
+ ```javascript
915
+
916
+
917
+ import { Controller } from "@hotwired/stimulus"
918
+
919
+ import {basicSetup} from "codemirror"
920
+ import {EditorView} from "@codemirror/view"
921
+
922
+ // Connects to data-controller="wrapper-form"
923
+ export default class extends Controller {
924
+ static targets = ['rawSource', 'name', 'nameWrapper', 'editor'];
925
+
926
+ connect() {
927
+ console.log("WrapperFormController connected")
928
+ this.account_id = this.element.dataset['accountId']
929
+ this.crusade_id = this.element.dataset['crusadeId']
930
+ this.wrapper_id = this.element.dataset['wrapperId']
931
+
932
+ const view = new EditorView({
933
+ doc: this.rawSourceTarget.value,
934
+ parent: this.editorTarget,
935
+ extensions: [basicSetup]
936
+ })
937
+
938
+ this.view = view;
939
+ this.element.addEventListener('submit', this.formSubmit.bind(this))
940
+ // this.previewButtonTarget.addEventListener('click', this.previewClick.bind(this))
941
+ }
942
+
943
+ formSubmit(event) {
944
+ this.rawSourceTarget.value = this.view.state.doc.toString();
945
+ }
946
+ }
947
+ ```
948
+
949
+ Notice we are also using `--stimmify` to decorate the form with a Stimulus controller.
950
+
951
+ The code above uses Code Mirror to act as a code editor, which requires pulling the value off the hidden form element (putting it into the code mirror interface) and pushing it back into the hidden form element when the Submit button is clicked.
952
+
953
+
954
+
955
+
956
+
854
957
  ### `--ujs_syntax=true` (Default is set automatically based on whether you have turbo-rails installed)
855
958
 
856
959
  If you are pre-Turbo (UJS), your delete buttons will come out like this:
@@ -1364,6 +1467,54 @@ Then run:
1364
1467
  This will 1) copy the dropzone_controller.js file into your app and 2) add the dropzone css into your app's application.css or application.bootstrap.css file.
1365
1468
 
1366
1469
 
1470
+ ### Attach Stimulus JS Controllers to Your Forms with `--stimmify` or `--stimmify=xyz`
1471
+
1472
+ Automatically build the new and edit form with `data-controller='xyz'` to attach cooresponding stimulus controllers.
1473
+
1474
+ If you use the shorthand (specify no `=`) your stimulus controller's name will be inferred from the Singular form of the scaffolding beild built, with dashes for underscores, and ending with `-form`
1475
+
1476
+ `@singular.gsub("_", "-") + "-form"`
1477
+
1478
+ (For example, `rails g hot_glue:scaffold Thing --stimmy` generates a form that looks like
1479
+
1480
+ ```
1481
+ <%= form_with model: thing,
1482
+ url: things_path(account,crusade,email_template),
1483
+ html: {
1484
+ 'data-controller': "thing-form"
1485
+ }
1486
+ %>
1487
+ ...
1488
+
1489
+ ```
1490
+
1491
+ Note that your fields also appended with `data-thing-target=abc` and also `data-thing-target=abcWrapper`
1492
+ (assuming `thing` is the scaffold being built and abc is the field name)
1493
+
1494
+
1495
+ Here, we are building a `thing` scaffold. The field `name` is decorated twice: once for the wrapper span and again for the specific form element itself.
1496
+ ```
1497
+ <span class="" data-thing-form-target="nameWrapper">
1498
+ <input value="asdfadf" autocomplete="off" size="40" class="form-control" type="" data-thing-form-target="name" name="thing[name]" id="thing_name">
1499
+
1500
+
1501
+ <label class="text-muted small form-text" for="">Name</label>
1502
+ </span>
1503
+ ```
1504
+
1505
+ Your stimulus controller will need two targets for each field:
1506
+
1507
+ ```
1508
+ static targets = ['name', 'nameWrapper'];
1509
+ ```
1510
+ You can interact with the wrapper for things like clicks or hovers, or to hide/show the entire box surrounding the form element.
1511
+
1512
+ Use the form field element itself to affect things like enabled or the value of the field.
1513
+
1514
+
1515
+ For a crash course on Stimulus, see
1516
+ https://jasonfleetwoodboldt.com/courses/rails-7-crash-course/rails-7-stimulus-js-basics-with-importmap-rails/
1517
+
1367
1518
 
1368
1519
 
1369
1520
  ### `--factory-creation={ ... }`
@@ -1751,6 +1902,76 @@ These automatic pickups for partials are detected at build time. This means that
1751
1902
 
1752
1903
  # VERSION HISTORY
1753
1904
 
1905
+ #### 2025-05-0097 - v0.6.17
1906
+
1907
+
1908
+ • Adds Stimulus JS & `--stimmify` or `--stimmify=xyz`
1909
+
1910
+ Automatically build the new and edit form with `data-controller='xyz'` to attach stimulus
1911
+
1912
+ If you use the shorthand (specify no `=`) your stimulus controller's name will be inferred from the Singular form of the scaffolding beild built, with dashes for underscores, and ending with `-form`
1913
+
1914
+ (For example, `rails g hot_glue:scaffold Thing --stimmy` generates a form that looks like
1915
+
1916
+ ```
1917
+ <%= form_with model: thing,
1918
+ url: things_path(account,crusade,email_template),
1919
+ html: {
1920
+ 'data-controller': "thing-form"
1921
+ }
1922
+ %>
1923
+ ...
1924
+
1925
+ ```
1926
+
1927
+ Note that your fields also appended with `data-thing-target=abc` and also `data-thing-target=abcWrapper`
1928
+
1929
+ See section "Attach Stimulus JS Controllers to Your Forms with `--stimmify` or `--stimmify=xyz`"
1930
+
1931
+ For a crash course on Stimulus, see
1932
+ https://jasonfleetwoodboldt.com/courses/rails-7-crash-course/rails-7-stimulus-js-basics-with-importmap-rails/
1933
+
1934
+
1935
+ • Adds `--hidden` option
1936
+ 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
+
1938
+
1939
+
1940
+
1941
+
1942
+ #### 2025-03-31 v0.6.16
1943
+
1944
+ • Bootstrap Tab Panes For Downnested Portals
1945
+ Downnested portals are now built with bootstrap tab panes (always) and are no longer stacked on top of one another.
1946
+
1947
+ It looks like this:
1948
+ https://getbootstrap.com/docs/5.0/components/navs-tabs/#javascript-behavior
1949
+
1950
+ • inline_list_labels can be set in hot_glue.yml
1951
+ • typeaheads nested inside of routes are fixed
1952
+ • switches back to current_timezone implementation, displaying times relative to the user's set timezone
1953
+ • load all code now sets query parameters
1954
+
1955
+ • Pundit Policy Override
1956
+ if you use the flag `--pundit-policy-override` your controller operations will bypass the invisible (pundit provided) access control and use the pundit policy you specify.
1957
+
1958
+ example
1959
+
1960
+ `rails generate hot_glue:scaffold Invoice --gd --pundit-policy-override='UniqueInvoicePolicy'`
1961
+
1962
+ Implement `UniqueInvoicePolicy` using actions with question mark `?` endings corresponding to the same actions you are building, `new?`, `create?`, `edit?`, `update?`, and `destroy?`
1963
+
1964
+
1965
+ • Bootstrap column builder has been changed.
1966
+ The bootstrap column bulder previously defaulted all real columns to col-sm-2 (or whichever bootstrap column with you set)
1967
+
1968
+ The builder has been refactored to allow for a per-column width generated automatically by the builder. If there are unused bootstrap columns, the builder will add width to the first columns in your layout, making them wider.
1969
+
1970
+
1971
+
1972
+
1973
+
1974
+
1754
1975
  #### 2025-03-17 - v0.6.15
1755
1976
 
1756
1977
  • now store on your current_user model (this is automatically passed into the method modify_date_inputs_on_params). HG will set user-inputted values correctly to daylight savings time during April-Nov months only (#195)
@@ -12,8 +12,6 @@ require_relative "fields/uuid_field"
12
12
  require_relative "fields/attachment_field"
13
13
  require_relative "fields/related_set_field"
14
14
 
15
-
16
-
17
15
  class FieldFactory
18
16
  attr_accessor :field, :class_name
19
17
  def initialize(type: , name: , generator: )
@@ -51,26 +49,29 @@ class FieldFactory
51
49
  end
52
50
  @class_name = class_name
53
51
 
52
+ if field_class.nil?
53
+ raise "Field type could be identified #{name} "
54
+ end
54
55
 
55
- @field = field_class.new(name: name,
56
- layout_strategy: generator.layout_strategy,
57
- form_placeholder_labels: generator.form_placeholder_labels,
58
- form_labels_position: generator.form_labels_position,
59
- ownership_field: generator.ownership_field,
60
- hawk_keys: generator.hawk_keys,
61
- auth: generator.auth,
62
- class_name: generator.singular_class,
63
- alt_lookup: generator.alt_lookups[name] || nil,
64
- singular: generator.singular,
65
- self_auth: generator.self_auth,
66
- update_show_only: generator.update_show_only,
67
- attachment_data: generator.attachments[name.to_sym],
68
- sample_file_path: generator.sample_file_path,
69
- modify_as: generator.modify_as[name.to_sym] || nil,
70
- plural: generator.plural,
71
- display_as: generator.display_as[name.to_sym] || nil,
72
- default_boolean_display: generator.default_boolean_display,
73
- namespace: generator.namespace_value,
74
- pundit: generator.pundit )
56
+ @field = field_class.new(scaffold: generator, name: name)
57
+ # layout_strategy: generator.layout_strategy,
58
+ # form_placeholder_labels: generator.form_placeholder_labels,
59
+ # form_labels_position: generator.form_labels_position,
60
+ # ownership_field: generator.ownership_field,
61
+ # hawk_keys: generator.hawk_keys,
62
+ # auth: generator.auth,
63
+ # class_name: generator.singular_class,
64
+ # alt_lookup: generator.alt_lookups[name] || nil,
65
+ # singular: generator.singular,
66
+ # self_auth: generator.self_auth,
67
+ # update_show_only: generator.update_show_only,
68
+ # attachment_data: generator.attachments[name.to_sym],
69
+ # sample_file_path: generator.sample_file_path,
70
+ # modify_as: generator.modify_as[name.to_sym] || nil,
71
+ # plural: generator.plural,
72
+ # display_as: generator.display_as[name.to_sym] || nil,
73
+ # default_boolean_display: generator.default_boolean_display,
74
+ # namespace: generator.namespace_value,
75
+ # pundit: generator.pundit )
75
76
  end
76
77
  end
@@ -5,17 +5,8 @@ class AssociationField < Field
5
5
 
6
6
  attr_accessor :assoc_name, :assoc_class, :assoc, :alt_lookup
7
7
 
8
- def initialize( alt_lookup: ,
9
- class_name: ,
10
- default_boolean_display:, display_as: ,
11
- name: , singular: ,
12
- update_show_only: ,
13
- hawk_keys: , auth: , sample_file_path:, ownership_field: ,
14
- attachment_data: nil , layout_strategy: , form_placeholder_labels: nil,
15
- form_labels_position:, modify_as: , self_auth: , namespace:, pundit: , plural: )
8
+ def initialize(scaffold: , name: )
16
9
  super
17
-
18
-
19
10
  @assoc_model = eval("#{class_name}.reflect_on_association(:#{assoc})")
20
11
 
21
12
  if assoc_model.nil?
@@ -97,14 +88,14 @@ class AssociationField < Field
97
88
  def form_field_output
98
89
  assoc_name = name.to_s.gsub("_id","")
99
90
  assoc = eval("#{class_name}.reflect_on_association(:#{assoc_name})")
100
-
101
- if alt_lookup
91
+ if alt_lookup.keys.include?(name.to_sym)
102
92
  alt = alt_lookup[:lookup_as]
103
93
  assoc_name = name.to_s.gsub("_id","")
104
94
  assoc = eval("#{class_name}.reflect_on_association(:#{assoc_name})")
105
95
 
106
96
  alt = alt_lookup[:lookup_as]
107
- "<%= f.text_field :__lookup_#{alt}, value: @#{singular}.#{assoc_name}.try(:#{alt}), placeholder: \"search by #{alt}\" %>"
97
+ 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}' " : "") + "%>"
108
99
 
109
100
  # if modify_as
110
101
  # modified_display_output
@@ -156,8 +147,17 @@ class AssociationField < Field
156
147
  end
157
148
 
158
149
 
150
+ if @stimmify
151
+ col_target = HotGlue.to_camel_case(name.to_s.gsub("_", " "))
152
+ data_attr = ", data: {'#{@stimmify}-target': '#{col_target}'} "
153
+ els
154
+ data_attr = ""
155
+ end
156
+
157
+
158
+
159
159
  (is_owner ? "<% unless @#{assoc_name} %>\n" : "") +
160
- " <%= f.collection_select(:#{name}, #{hawked_association}, :id, :#{display_column}, {prompt: true, selected: #{singular}.#{name} }, class: 'form-control') %>\n" +
160
+ " <%= f.collection_select(:#{name}, #{hawked_association}, :id, :#{display_column}, { prompt: true, selected: #{singular}.#{name} }, class: 'form-control'#{data_attr}) %>\n" +
161
161
  (is_owner ? "<% else %>\n <%= @#{assoc_name}.#{display_column} %>" : "") +
162
162
  (is_owner ? "\n<% end %>" : "")
163
163
  end
@@ -1,25 +1,6 @@
1
1
  class AttachmentField < Field
2
2
  attr_accessor :attachment_data
3
- def initialize(alt_lookup:,
4
- attachment_data:,
5
- plural:,
6
- auth:,
7
- class_name:,
8
- display_as:, singular:,
9
- default_boolean_display: ,
10
- form_placeholder_labels: ,
11
- form_labels_position:,
12
- hawk_keys:,
13
- layout_strategy: ,
14
- name:,
15
- namespace:,
16
- modify_as:,
17
- ownership_field:,
18
- pundit: ,
19
- sample_file_path: nil,
20
- self_auth:,
21
- update_show_only:
22
- )
3
+ def initialize(scaffold:, name:)
23
4
  super
24
5
 
25
6
  @attachment_data = attachment_data
@@ -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[:binary][:falsy] || 'No'}', for: '#{singular}_#{name}_0') %>\n" +
26
+ " <%= f.label(:#{name}, value: '#{modify_binary? && modify_as[name.to_sym][: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[:binary][:truthy] || 'Yes'}', for: '#{singular}_#{name}_1') %>\n"
28
+ " <%= f.label(:#{name}, value: '#{modify_binary? && modify_as[name.to_sym][:binary][:truthy] || 'Yes'}', for: '#{singular}_#{name}_1') %>\n"
29
29
  end
30
30
 
31
31
  def checkbox_display
@@ -38,16 +38,16 @@ class BooleanField < Field
38
38
 
39
39
  def form_field_display
40
40
  if display_boolean_as.nil?
41
-
42
41
  end
42
+
43
43
  "<span class='#{@layout_strategy.form_checkbox_wrapper_class} #{'form-switch' if display_boolean_as == 'switch'}'>\n" +
44
44
  (if display_boolean_as == 'radio'
45
- radio_button_display
46
- elsif display_boolean_as == 'checkbox'
47
- checkbox_display
48
- elsif display_boolean_as == 'switch'
49
- switch_display
50
- end) + "</span> \n"
45
+ radio_button_display
46
+ elsif display_boolean_as == 'checkbox'
47
+ checkbox_display
48
+ elsif display_boolean_as == 'switch'
49
+ switch_display
50
+ end) + "</span> \n"
51
51
  end
52
52
 
53
53
  def form_field_output
@@ -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[:binary][:truthy]}
62
+ #{modify_as[name.to_sym][:binary][:truthy]}
63
63
  <% else %>
64
- #{modify_as[:binary][:falsy]}
64
+ #{modify_as[name.to_sym][: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[:binary][:truthy] || 'Yes'
78
+ modify_as[name.to_sym][:binary][:truthy] || 'Yes'
79
79
  end
80
80
 
81
81
  def falsy_value
82
- modify_as[:binary][:falsy] || 'No'
82
+ modify_as[name.to_sym][:binary][:falsy] || 'No'
83
83
  end
84
84
 
85
85
  def label_class
@@ -10,8 +10,10 @@ class DateField < Field
10
10
 
11
11
 
12
12
  def form_field_output
13
- "<%= date_field_localized(f, :#{name}, #{singular}.#{name}, label: '#{ name.to_s.humanize }') %>"
14
- end
13
+ parts = name.to_s.split('_')
14
+ camelcase_name = parts.map(&:capitalize).join
15
+ "<%= date_field_localized(f, :#{name}, #{singular}.#{name}, label: '#{ name.to_s.humanize }'" + (stimmify ? ", html: {'data-#{@stimmify}-target': '#{camelcase_name}'}" : "") + ") %>"
16
+ end
15
17
 
16
18
  def line_field_output
17
19
  "<% unless #{singular}.#{name}.nil? %>
@@ -31,14 +31,20 @@ class EnumField < Field
31
31
  end
32
32
 
33
33
  def form_field_output
34
+ if @stimmify
35
+ col_target = HotGlue.to_camel_case(name.to_s.gsub("_", " "))
36
+ data_attr = ", data: {'#{@stimmify}-target': '#{col_target}'} "
37
+ end
38
+
34
39
  enum_type = eval("#{class_name}.columns.select{|x| x.name == '#{name}'}[0].sql_type")
40
+
35
41
  if eval("defined? #{class_name}.#{enum_type}_labels") == "method"
36
42
  enum_definer = "#{class_name}.#{enum_type}_labels"
37
43
  else
38
44
  enum_definer = "#{class_name}.defined_enums['#{name}']"
39
45
  end
40
46
 
41
- res = "<%= f.collection_select(:#{name}, enum_to_collection_select(#{enum_definer}), :key, :value, {include_blank: true, selected: #{singular}.#{name} }, class: 'form-control') %>"
47
+ res = "<%= f.collection_select(:#{name}, enum_to_collection_select(#{enum_definer}), :key, :value, {include_blank: true, selected: #{singular}.#{name} }, class: 'form-control' #{data_attr} )%>"
42
48
 
43
49
 
44
50
  if modify_as && modify_as[:enum] == :partials
@@ -5,50 +5,37 @@ class Field
5
5
  :hawk_keys, :layout_strategy, :limit, :modify_as, :name, :object, :sample_file_path,
6
6
  :self_auth,
7
7
  :singular_class, :singular, :sql_type, :ownership_field,
8
- :update_show_only, :namespace, :pundit, :plural
8
+ :update_show_only, :namespace, :pundit, :plural,
9
+ :stimmify, :hidden, :attachment_data
10
+
9
11
 
10
12
  def initialize(
11
- auth: ,
12
- attachment_data: nil,
13
- class_name: ,
14
- alt_lookup: ,
15
- default_boolean_display: ,
16
- display_as: ,
17
- form_labels_position:,
18
- form_placeholder_labels: ,
19
- hawk_keys: nil,
20
- layout_strategy: ,
21
- modify_as: , #note non-standard naming as to avoid collision with Ruby reserved word modify
22
- name: ,
23
- ownership_field: ,
24
- sample_file_path: nil,
25
- singular: ,
26
- update_show_only:,
27
- self_auth:,
28
- namespace:,
29
- pundit: ,
30
- plural:
13
+ scaffold:, name:
14
+
31
15
  )
32
16
  @name = name
33
- @layout_strategy = layout_strategy
34
- @alt_lookup = alt_lookup
35
- @singular = singular
36
- @class_name = class_name
37
- @update_show_only = update_show_only
38
- @hawk_keys = hawk_keys
39
- @auth = auth
40
- @sample_file_path = sample_file_path
41
- @form_placeholder_labels = form_placeholder_labels
42
- @ownership_field = ownership_field
43
- @form_labels_position = form_labels_position
44
- @modify_as = modify_as
45
- @display_as = display_as
46
- @pundit = pundit
47
- @plural = plural
48
-
49
- @self_auth = self_auth
50
- @default_boolean_display = default_boolean_display
51
- @namespace = namespace
17
+ @layout_strategy = scaffold.layout_strategy
18
+ @alt_lookup = scaffold.alt_lookups
19
+ @singular = scaffold.singular
20
+ @class_name = scaffold.singular_class
21
+ @update_show_only = scaffold.update_show_only
22
+ @hawk_keys = scaffold.hawk_keys
23
+ @auth = scaffold.auth
24
+ @sample_file_path = scaffold.sample_file_path
25
+ @form_placeholder_labels = scaffold.form_placeholder_labels
26
+ @ownership_field = scaffold.ownership_field
27
+ @form_labels_position = scaffold.form_labels_position
28
+ @modify_as = scaffold.modify_as
29
+ @display_as = scaffold.display_as
30
+ @pundit = scaffold.pundit
31
+ @plural = scaffold.plural
32
+ @self_auth = scaffold.self_auth
33
+ @default_boolean_display = scaffold.default_boolean_display
34
+ @namespace = scaffold.namespace_value
35
+ @stimmify = scaffold.stimmify
36
+ @hidden = scaffold.hidden
37
+ @attachment_data = scaffold.attachments[name.to_sym]
38
+
52
39
 
53
40
  # TODO: remove knowledge of subclasses from Field
54
41
  unless self.class == AttachmentField || self.class == RelatedSetField
@@ -125,7 +112,7 @@ class Field
125
112
  end
126
113
 
127
114
  def viewable_output
128
- if modify_as
115
+ if modify_as[:modify]
129
116
  modified_display_output(show_only: true)
130
117
  else
131
118
  field_view_output
@@ -179,20 +166,34 @@ class Field
179
166
  if modify_as && modify_as[:timezone]
180
167
  "<%= f.time_zone_select :#{name}, ActiveSupport::TimeZone.all, {}, {class: 'form-control'} %>"
181
168
  else
182
- " <%= f.text_field :#{name}, value: #{singular}.#{name}, autocomplete: 'off', size: #{width}, class: 'form-control', type: '#{type}'" + (form_placeholder_labels ? ", placeholder: '#{name.to_s.humanize}'" : "") + " %>\n " + "\n"
169
+ parts = name.split('_')
170
+ camelcase_name = parts.first + parts[1..].map(&:capitalize).join
171
+ " <%= f.text_field :#{name}, value: #{singular}.#{name}, autocomplete: 'off', size: #{width}, class: 'form-control', type: '#{type}'" + (form_placeholder_labels ? ", placeholder: '#{name.to_s.humanize}'" : "") + (stimmify ? ", 'data-#{@stimmify}-target': '#{camelcase_name}' " : "") + " %>\n " + "\n"
183
172
  end
184
173
  end
185
174
 
175
+ def hidden_output
176
+ parts = name.split('_')
177
+ camelcase_name = parts.first + parts[1..].map(&:capitalize).join
178
+ "<%= f.hidden_field :#{name}, value: #{singular}.#{name} " +
179
+ (@stimmify ? ", 'data-#{@stimmify}-target': '#{camelcase_name}' " : "") +
180
+ " %>"
181
+ end
182
+
186
183
  def text_area_output(field_length, extra_classes: "")
187
184
  lines = field_length % 40
188
185
  if lines > 5
189
186
  lines = 5
190
187
  end
191
- "<%= f.text_area :#{name}, class: 'form-control#{extra_classes}', autocomplete: 'off', cols: 40, rows: '#{lines}'" + ( form_placeholder_labels ? ", placeholder: '#{name.to_s.humanize}'" : "") + " %>"
188
+
189
+ parts = name.split('_')
190
+ camelcase_name = parts.first + parts[1..].map(&:capitalize).join
191
+ "<%= f.text_area :#{name}, class: 'form-control#{extra_classes}', autocomplete: 'off', cols: 40, rows: '#{lines}'" + ( form_placeholder_labels ? ", placeholder: '#{name.to_s.humanize}'" : "") +
192
+ (@stimmify ? ", 'data-#{@stimmify}-target': '#{camelcase_name}' " : "") + " %>"
192
193
  end
193
194
 
194
- def modify_binary? # safe
195
- !!(modify_as && modify_as[:binary])
195
+ def modify_binary?
196
+ !!(modify_as && modify_as[name.to_sym] && modify_as[name.to_sym][:binary])
196
197
  end
197
198
 
198
199
  def display_boolean_as
@@ -201,8 +202,8 @@ class Field
201
202
  @default_boolean_display = "radio"
202
203
  end
203
204
 
204
- if display_as
205
- return display_as[:boolean] || "radio"
205
+ if display_as[name.to_sym]
206
+ return display_as[name.to_sym][:boolean] || "radio"
206
207
  else
207
208
  return @default_boolean_display
208
209
  end