hot-glue 0.5.23.1 → 0.5.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +108 -11
- data/lib/generators/hot_glue/field_factory.rb +2 -1
- data/lib/generators/hot_glue/fields/association_field.rb +1 -1
- data/lib/generators/hot_glue/fields/attachment_field.rb +12 -2
- data/lib/generators/hot_glue/fields/boolean_field.rb +4 -4
- data/lib/generators/hot_glue/fields/enum_field.rb +2 -2
- data/lib/generators/hot_glue/fields/field.rb +26 -16
- data/lib/generators/hot_glue/fields/text_field.rb +1 -1
- data/lib/generators/hot_glue/layout/builder.rb +2 -2
- data/lib/generators/hot_glue/markup_templates/erb.rb +4 -1
- data/lib/generators/hot_glue/scaffold_generator.rb +31 -15
- data/lib/generators/hot_glue/templates/controller.rb.erb +10 -6
- data/lib/generators/hot_glue/templates/erb/_list.erb +6 -0
- data/lib/generators/hot_glue/templates/system_spec.rb.erb +20 -9
- data/lib/hotglue/version.rb +1 -1
- data/script/test +3 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c2b46bf01f0742356ab56ad4cd139534becbe919b8e38ac8d166f8ca1c1c47c
|
4
|
+
data.tar.gz: b697f19f9928249d693632ff040f7ebb97ddf396fd8fb8d74b60f3abfe3a6bca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ad16ec01f21d5ac9013cbbc0ee2e364cce4deec8ff52544d34438c641a4009d763ff953e70813d2f4b5e5b35904959ca49b5fea50dc8187c254c0bc0a19850c
|
7
|
+
data.tar.gz: f7cbb297d36077486c6983b0dfebee09b32871b316f28fe215f3578df5054445f337d372e13b55d84f44f30a6e4e0de776df14cb3137a4ec12c8e481ed38abba
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hot-glue (0.5.
|
4
|
+
hot-glue (0.5.25)
|
5
5
|
ffaker (~> 2.16)
|
6
6
|
kaminari (~> 1.2)
|
7
7
|
rails (> 5.1)
|
@@ -139,7 +139,7 @@ GEM
|
|
139
139
|
mini_mime (1.1.2)
|
140
140
|
mini_portile2 (2.8.4)
|
141
141
|
minitest (5.16.3)
|
142
|
-
net-imap (0.
|
142
|
+
net-imap (0.4.1)
|
143
143
|
date
|
144
144
|
net-protocol
|
145
145
|
net-pop (0.1.2)
|
data/README.md
CHANGED
@@ -664,13 +664,16 @@ For booleans shown as checkboxes or switches, it affects only the view output as
|
|
664
664
|
|
665
665
|
You will need to separately specify them as show-only if you want them to be non-editable.
|
666
666
|
|
667
|
-
|
667
|
+
Notice that each modifiers can be used with specific field types.
|
668
668
|
|
669
|
-
| modifier
|
670
|
-
|
671
|
-
| $
|
672
|
-
| truthy label\|falsy label | specify a binary switch with a pipe (\|) character if the value is truthy, it will display as "truthy label" if the value is falsy, it will display as "falsy label" |
|
673
|
-
|
|
669
|
+
| user modifier | what it does | Field types | | |
|
670
|
+
|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|---|---|
|
671
|
+
| $ | wraps output in `number_to_currency()` | floats and integers | | |
|
672
|
+
| (truthy label)\|(falsy label) | specify a binary switch with a pipe (\|) character if the value is truthy, it will display as "truthy label" if the value is falsy, it will display as "falsy label" | booleans, datetimes, dates, times | | |
|
673
|
+
| partials | applies to enums only, you must have a partial whose name matches each enum type | enums only | | |
|
674
|
+
| tinymce | applies to text fields only, be sure to setup TineMCE globally | text fields only | | |
|
675
|
+
|
676
|
+
Except for "(truthy label)" and "(falsy label)" which represent the labels you should specify separated by the pipe character (|), use the modifier exactly as shown.
|
674
677
|
|
675
678
|
### `--pundit`
|
676
679
|
If you enable Pundit, your controllers will look for a Policy that matches the name of the thing being built.
|
@@ -891,10 +894,15 @@ Produces ONLY the controller spec file, nothing else.
|
|
891
894
|
Produces all the files except the spec file.
|
892
895
|
|
893
896
|
|
894
|
-
### `--no-paginate`
|
897
|
+
### `--no-paginate` (default: false)
|
895
898
|
|
896
899
|
Omits pagination. (All list views have pagination by default.)
|
897
900
|
|
901
|
+
### `--paginate-per-page-selector` (default: false)
|
902
|
+
|
903
|
+
Show a small drop-down below the list to let the user choose 10, 25, or 100 results per page.
|
904
|
+
|
905
|
+
|
898
906
|
### `--no-list`
|
899
907
|
|
900
908
|
Omits list action. Only makes sense to use this if want to create a view where you only want the create button or to navigate to the update screen alternative ways. (The new/create still appears, as well the edit, update & destroy actions are still created even though there is no natural way to navigate to them.)
|
@@ -1402,8 +1410,99 @@ end
|
|
1402
1410
|
|
1403
1411
|
```
|
1404
1412
|
|
1413
|
+
|
1414
|
+
### TinyMCE
|
1415
|
+
1. `bundle add tinymce-rails` to add it to your Gemfile
|
1416
|
+
|
1417
|
+
2. Add this inside of your `<head>` tag (at the bottom is fine)
|
1418
|
+
```
|
1419
|
+
<%= tinymce_assets %>
|
1420
|
+
```
|
1421
|
+
3. Then, also inside of your `<head>` tag, add this:
|
1422
|
+
```
|
1423
|
+
<script>
|
1424
|
+
TinyMCERails.configuration.default = {
|
1425
|
+
selector: "textarea.tinymce",
|
1426
|
+
cache_suffix: "?v=6.7.0",
|
1427
|
+
menubar: "insert view format table tools",
|
1428
|
+
toolbar: ["bold italic | link | undo redo | forecolor backcolor | bullist numlist outdent indent | table | uploadimage | code"],
|
1429
|
+
plugins: "table,fullscreen,image,code,searchreplace,wordcount,visualblocks,visualchars,link,charmap,directionality,nonbreaking,media,advlist,autolink,lists",
|
1430
|
+
images_upload_url: "/uploader/image"
|
1431
|
+
};
|
1432
|
+
|
1433
|
+
</script>
|
1434
|
+
```
|
1435
|
+
|
1436
|
+
Then to `application.js` add
|
1437
|
+
|
1438
|
+
```
|
1439
|
+
import "./tinymce_init"
|
1440
|
+
|
1441
|
+
```
|
1442
|
+
|
1443
|
+
create a file `tinymce_init.js` with this content
|
1444
|
+
|
1445
|
+
```
|
1446
|
+
const reinitTiny = () => {
|
1447
|
+
tinymce.init({
|
1448
|
+
selector: 'textarea.tinymce', // Add the appropriate selector for your textareas
|
1449
|
+
// Other TinyMCE configuration options
|
1450
|
+
});
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
window.addEventListener('turbo:before-fetch-response', () => {
|
1454
|
+
tinymce.remove();
|
1455
|
+
tinymce.init({selector:'textarea.tinymce'});
|
1456
|
+
})
|
1457
|
+
|
1458
|
+
window.addEventListener('turbo:frame-render', reinitTiny)
|
1459
|
+
window.addEventListener('turbo:render', reinitTiny)
|
1460
|
+
```
|
1461
|
+
|
1462
|
+
Once you have completed this setup, you can now use `--modify` with the modifier `tinymce`.
|
1463
|
+
|
1464
|
+
For example, to display the field `my_story` on the object `Thing`, you'd generate with:
|
1465
|
+
|
1466
|
+
```
|
1467
|
+
bin/rails generate Thing --include=my_story --modify='my_story{tinymce}'
|
1468
|
+
```
|
1469
|
+
|
1405
1470
|
# VERSION HISTORY
|
1406
1471
|
|
1472
|
+
#### 2023-10-16 - v0.5.25
|
1473
|
+
|
1474
|
+
- Fixes scoping on Pundit-built controllers; even when using pundit we should still wrap to the current build's own ownership scope (#132
|
1475
|
+
- don't write to the nav file if we're building a nested controller (#134)
|
1476
|
+
- adds system specs for self-auth feature
|
1477
|
+
- Pagination Fixes:
|
1478
|
+
|
1479
|
+
A new flag `--paginate-per-page-selector` (default false) will allow you to show a small drop-down to let the user choose 10, 25, or 100 results per page.
|
1480
|
+
|
1481
|
+
To get pagination to work, choose either #1 OR #2 below. #1 will replace the templates in app/views/kaminari so don't do that if you have modified them since first generating them out of Kaminari.
|
1482
|
+
|
1483
|
+
1. Replace the kaminari gem with my fork and regenerate your templates
|
1484
|
+
bundle remove kaminari
|
1485
|
+
bundle add kaminari --git="https://github.com/jasonfb/kaminari.git" --branch="master"
|
1486
|
+
bundle install
|
1487
|
+
rm -rf app/views/kaminari
|
1488
|
+
rails g kaminari:config
|
1489
|
+
|
1490
|
+
|
1491
|
+
2. Go into app/views/kaminari/ and modify each template in this folder by adding ` 'data-turbo-action': 'advance'` to all of the links (which mostly appear in this code as the `link_to_unless` helper-- add the parameter onto the end of the calls to those helpers.)
|
1492
|
+
|
1493
|
+
|
1494
|
+
|
1495
|
+
#### 2023-10-07 - v0.5.24
|
1496
|
+
|
1497
|
+
- TinyMCE implementation. See 'TinyMCE' above.
|
1498
|
+
Note: I also plan to implement ActionText as an alternative. However, because TinyMCE is implemented with a `text` field type an ActionText is implemented with a Rails-specific `rich_text` field type, the two mechanisms will be incompatible with one another. TinyMCE has an annoying drawback in how it works with Turbo refreshes (not very consistently), and style of loading Javascript is discordant with Rails moving forward. So I am leaving this implementation as experimental.
|
1499
|
+
- Spec Savestart code: In the behavior specs, there is a code marker (start & end) where you can insert custom code that gets saved between
|
1500
|
+
build. The start code maker has changed from `#HOTGLUE-SAVESTART` to `# HOTGLUE-SAVESTART`
|
1501
|
+
and the end code marker has changed from `#HOTGLUE-END` to `# HOTGLUE-END`. This now conforms to Rubocop.
|
1502
|
+
Be sure to do find & replace in your existing projects to keep your custom code.
|
1503
|
+
- Fix for specs for attachment fields. If you have attachments fields, you must have a sample file at `spec/fixtures/glass_button.png`
|
1504
|
+
- Pundit now correctly protects the `index` action (authorize was missing before)
|
1505
|
+
|
1407
1506
|
#### 2023-10-01 - v0.5.23
|
1408
1507
|
|
1409
1508
|
- You can now use the modify flag on enum type fields to display a partial with the same name of that enum type.
|
@@ -1897,7 +1996,5 @@ To run only the internal specs, use
|
|
1897
1996
|
|
1898
1997
|
`rspec spec`
|
1899
1998
|
|
1900
|
-
Internal Test coverage as of 2023-
|
1901
|
-
|
1902
|
-
<img width="1202" alt="Screen Shot 2023-02-10 at 4 43 59 PM" src="https://user-images.githubusercontent.com/59002/218204736-5740505b-1ec8-456f-b0fb-9c359f6f7037.png">
|
1903
|
-
|
1999
|
+
Internal Test coverage as of 2023-10-15 (v0.5.24)
|
2000
|
+
All Files ( 86.29% covered at 75.64 hits/line )
|
@@ -55,10 +55,11 @@ class FieldFactory
|
|
55
55
|
class_name: generator.singular_class,
|
56
56
|
alt_lookups: generator.alt_lookups,
|
57
57
|
singular: generator.singular,
|
58
|
+
self_auth: generator.self_auth,
|
58
59
|
update_show_only: generator.update_show_only,
|
59
60
|
attachment_data: generator.attachments[name.to_sym],
|
60
61
|
sample_file_path: generator.sample_file_path,
|
61
|
-
|
62
|
+
modify_as: generator.modify_as[name.to_sym] || nil,
|
62
63
|
display_as: generator.display_as[name.to_sym] || nil,
|
63
64
|
default_boolean_display: generator.default_boolean_display)
|
64
65
|
end
|
@@ -10,7 +10,7 @@ class AssociationField < Field
|
|
10
10
|
update_show_only: ,
|
11
11
|
hawk_keys: , auth: , sample_file_path:, ownership_field: ,
|
12
12
|
attachment_data: nil , layout_strategy: , form_placeholder_labels: nil,
|
13
|
-
form_labels_position:,
|
13
|
+
form_labels_position:, modify_as: , self_auth: )
|
14
14
|
super
|
15
15
|
|
16
16
|
@assoc_model = eval("#{class_name}.reflect_on_association(:#{assoc})")
|
@@ -4,7 +4,7 @@ class AttachmentField < Field
|
|
4
4
|
display_as:,
|
5
5
|
singular:, update_show_only:, hawk_keys:, auth:,
|
6
6
|
sample_file_path: nil, attachment_data:, ownership_field:, layout_strategy: ,
|
7
|
-
form_placeholder_labels: , form_labels_position:,
|
7
|
+
form_placeholder_labels: , form_labels_position:, modify_as:, self_auth: )
|
8
8
|
super
|
9
9
|
|
10
10
|
@attachment_data = attachment_data
|
@@ -14,7 +14,17 @@ class AttachmentField < Field
|
|
14
14
|
nil
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
17
|
+
def spec_list_view_natural_assertion
|
18
|
+
"within('div.#{singular}--#{name}') do
|
19
|
+
img = page.find('img')
|
20
|
+
expect(img['src']).to end_with('glass_button.png')
|
21
|
+
end"
|
22
|
+
|
23
|
+
# "expect(page).to have_content(#{singular}#{1}.#{name})"
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def spec_setup_and_change_act(which_partial = nil)
|
18
28
|
" attach_file(\"#{singular}[#{name.to_s}]\", \"#{sample_file_path}\")"
|
19
29
|
end
|
20
30
|
|
@@ -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? &&
|
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? &&
|
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
|
@@ -60,9 +60,9 @@ class BooleanField < Field
|
|
60
60
|
"<% if #{singular}.#{name}.nil? %>
|
61
61
|
<span class='alert-danger'>MISSING</span>
|
62
62
|
<% elsif #{singular}.#{name} %>
|
63
|
-
#{
|
63
|
+
#{modify_as[:binary][:truthy]}
|
64
64
|
<% else %>
|
65
|
-
#{
|
65
|
+
#{modify_as[:binary][:falsy]}
|
66
66
|
<% end %>"
|
67
67
|
else
|
68
68
|
"<% if #{singular}.#{name}.nil? %>
|
@@ -41,7 +41,7 @@ class EnumField < Field
|
|
41
41
|
res = "<%= f.collection_select(:#{name}, enum_to_collection_select(#{enum_definer}), :key, :value, {selected: #{singular}.#{name} }, class: 'form-control') %>"
|
42
42
|
|
43
43
|
|
44
|
-
if
|
44
|
+
if modify_as && modify_as[:enum] == :partials
|
45
45
|
res << partial_render
|
46
46
|
end
|
47
47
|
res
|
@@ -61,7 +61,7 @@ class EnumField < Field
|
|
61
61
|
<span class='alert-danger'>Missing #{name}</span>
|
62
62
|
<% else %>"
|
63
63
|
|
64
|
-
if
|
64
|
+
if modify_as && modify_as[:enum] == :partials
|
65
65
|
res << partial_render
|
66
66
|
else
|
67
67
|
res << "<%= #{enum_definer}[#{singular}.#{name}.to_sym] %>"
|
@@ -1,7 +1,9 @@
|
|
1
1
|
class Field
|
2
2
|
attr_accessor :assoc_model, :assoc_name, :assoc_class, :associations, :alt_lookups, :auth,
|
3
|
-
:assoc_label, :class_name, :default_boolean_display, :display_as, :form_placeholder_labels,
|
4
|
-
:
|
3
|
+
:assoc_label, :class_name, :default_boolean_display, :display_as, :form_placeholder_labels,
|
4
|
+
:form_labels_position,
|
5
|
+
:hawk_keys, :layout_strategy, :limit, :modify_as, :name, :object, :sample_file_path,
|
6
|
+
:self_auth,
|
5
7
|
:singular_class, :singular, :sql_type, :ownership_field,
|
6
8
|
:update_show_only
|
7
9
|
|
@@ -16,12 +18,13 @@ class Field
|
|
16
18
|
form_placeholder_labels: ,
|
17
19
|
hawk_keys: nil,
|
18
20
|
layout_strategy: ,
|
19
|
-
|
21
|
+
modify_as: , #note non-standard naming as to avoid collision with Ruby reserved word modify
|
20
22
|
name: ,
|
21
23
|
ownership_field: ,
|
22
24
|
sample_file_path: nil,
|
23
25
|
singular: ,
|
24
|
-
update_show_only
|
26
|
+
update_show_only:,
|
27
|
+
self_auth:
|
25
28
|
)
|
26
29
|
@name = name
|
27
30
|
@layout_strategy = layout_strategy
|
@@ -35,9 +38,10 @@ class Field
|
|
35
38
|
@form_placeholder_labels = form_placeholder_labels
|
36
39
|
@ownership_field = ownership_field
|
37
40
|
@form_labels_position = form_labels_position
|
38
|
-
@
|
41
|
+
@modify_as = modify_as
|
39
42
|
@display_as = display_as
|
40
43
|
|
44
|
+
@self_auth = self_auth
|
41
45
|
@default_boolean_display = default_boolean_display
|
42
46
|
|
43
47
|
# TODO: remove knowledge of subclasses from Field
|
@@ -72,7 +76,7 @@ class Field
|
|
72
76
|
if !modify_binary?
|
73
77
|
"expect(page).to have_content(new_#{name})"
|
74
78
|
else
|
75
|
-
"expect(page).to have_content('#{
|
79
|
+
"expect(page).to have_content('#{modify_as[:binary][:truthy]}'"
|
76
80
|
end
|
77
81
|
end
|
78
82
|
|
@@ -82,12 +86,16 @@ class Field
|
|
82
86
|
end
|
83
87
|
|
84
88
|
def spec_list_view_natural_assertion
|
85
|
-
|
89
|
+
if !self_auth
|
90
|
+
"expect(page).to have_content(#{singular}#{1}.#{name})"
|
91
|
+
else
|
92
|
+
"expect(page).to have_content(current_#{singular}.#{name})"
|
93
|
+
end
|
86
94
|
end
|
87
95
|
|
88
96
|
def spec_list_view_assertion
|
89
97
|
if modify_binary?
|
90
|
-
"expect(page).to have_content('#{
|
98
|
+
"expect(page).to have_content('#{modify_as[:binary][:truthy]}'"
|
91
99
|
else
|
92
100
|
spec_list_view_natural_assertion
|
93
101
|
end
|
@@ -107,7 +115,7 @@ class Field
|
|
107
115
|
end
|
108
116
|
|
109
117
|
def viewable_output
|
110
|
-
if
|
118
|
+
if modify_as
|
111
119
|
modified_display_output
|
112
120
|
else
|
113
121
|
"<%= #{singular}.#{name} %>"
|
@@ -115,11 +123,13 @@ class Field
|
|
115
123
|
end
|
116
124
|
|
117
125
|
def modified_display_output
|
118
|
-
if
|
126
|
+
if modify_as[:cast] && modify_as[:cast] == "$"
|
119
127
|
"<%= number_to_currency(#{singular}.#{name}) %>"
|
120
|
-
elsif
|
121
|
-
"<%= #{singular}.#{name} ? '#{
|
122
|
-
elsif
|
128
|
+
elsif modify_as[:binary]
|
129
|
+
"<%= #{singular}.#{name} ? '#{modify_as[:binary][:truthy]}' : '#{modify_as[:binary][:falsy]}' %>"
|
130
|
+
elsif modify_as[:tinymce]
|
131
|
+
|
132
|
+
elsif modify_as[:enum]
|
123
133
|
"<%= render partial: #{singular}.#{name}, locals: {#{singular}: #{singular}} %>"
|
124
134
|
end
|
125
135
|
end
|
@@ -128,16 +138,16 @@ class Field
|
|
128
138
|
" <%= 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"
|
129
139
|
end
|
130
140
|
|
131
|
-
def text_area_output(field_length )
|
141
|
+
def text_area_output(field_length, extra_classes: "")
|
132
142
|
lines = field_length % 40
|
133
143
|
if lines > 5
|
134
144
|
lines = 5
|
135
145
|
end
|
136
|
-
"<%= f.text_area :#{name}, class: 'form-control', autocomplete: 'off', cols: 40, rows: '#{lines}'" + ( form_placeholder_labels ? ", placeholder: '#{name.to_s.humanize}'" : "") + " %>"
|
146
|
+
"<%= f.text_area :#{name}, class: 'form-control#{extra_classes}', autocomplete: 'off', cols: 40, rows: '#{lines}'" + ( form_placeholder_labels ? ", placeholder: '#{name.to_s.humanize}'" : "") + " %>"
|
137
147
|
end
|
138
148
|
|
139
149
|
def modify_binary? # safe
|
140
|
-
!!(
|
150
|
+
!!(modify_as && modify_as[:binary])
|
141
151
|
end
|
142
152
|
|
143
153
|
def display_boolean_as
|
@@ -16,7 +16,7 @@ class TextField < Field
|
|
16
16
|
if sql_type == "varchar" || sql_type == "character varying"
|
17
17
|
field_output( nil, limit || 40)
|
18
18
|
else
|
19
|
-
text_area_output( 65536)
|
19
|
+
text_area_output( 65536, extra_classes: (modify_as == {tinymce: 1} ? " tinymce" : "" ))
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -17,7 +17,7 @@ module HotGlue
|
|
17
17
|
|
18
18
|
@generator = generator
|
19
19
|
|
20
|
-
@
|
20
|
+
@modify_as = generator.modify_as
|
21
21
|
@display_as = generator.display_as
|
22
22
|
@columns = generator.columns
|
23
23
|
@smart_layout = generator.smart_layout
|
@@ -46,7 +46,7 @@ module HotGlue
|
|
46
46
|
|
47
47
|
},
|
48
48
|
buttons: { size: @buttons_width},
|
49
|
-
|
49
|
+
modify_as: @modify_as,
|
50
50
|
display_as: @display_as
|
51
51
|
}
|
52
52
|
|
@@ -105,7 +105,10 @@ module HotGlue
|
|
105
105
|
else
|
106
106
|
columns_map[col].form_field_output
|
107
107
|
end
|
108
|
-
|
108
|
+
# byebug
|
109
|
+
@tinymce_stimulus_controller = (columns_map[col].modify_as == {tinymce: 1} ? "data-controller='tiny-mce' " : "")
|
110
|
+
|
111
|
+
add_spaces_each_line( "\n <span #{@tinymce_stimulus_controller}class='<%= \"alert-danger\" if #{singular}.errors.details.keys.include?(:#{field_error_name}) %>' #{'style="display: inherit;"'} >\n" +
|
109
112
|
add_spaces_each_line( (form_labels_position == 'before' ? the_label || "" : "") +
|
110
113
|
+ " <br />\n" + field_result +
|
111
114
|
(form_labels_position == 'after' ? the_label : "") , 4) +
|
@@ -18,10 +18,12 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
18
18
|
source_root File.expand_path('templates', __dir__)
|
19
19
|
attr_accessor :alt_lookups, :attachments, :auth, :big_edit, :button_icons, :bootstrap_column_width, :columns,
|
20
20
|
:default_boolean_display,
|
21
|
-
:display_as, :downnest_children, :downnest_object, :hawk_keys, :layout_object,
|
21
|
+
:display_as, :downnest_children, :downnest_object, :hawk_keys, :layout_object,
|
22
|
+
:modify_as,
|
22
23
|
:nest_with, :path, :plural, :sample_file_path, :show_only_data, :singular,
|
23
24
|
:singular_class, :smart_layout, :stacked_downnesting, :update_show_only, :ownership_field,
|
24
|
-
:layout_strategy, :form_placeholder_labels, :form_labels_position, :pundit
|
25
|
+
:layout_strategy, :form_placeholder_labels, :form_labels_position, :pundit,
|
26
|
+
:self_auth
|
25
27
|
|
26
28
|
class_option :singular, type: :string, default: nil
|
27
29
|
class_option :plural, type: :string, default: nil
|
@@ -46,6 +48,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
46
48
|
class_option :no_controller, type: :boolean, default: false
|
47
49
|
class_option :no_list, type: :boolean, default: false
|
48
50
|
class_option :no_paginate, type: :boolean, default: false
|
51
|
+
class_option :paginate_per_page_selector, type: :boolean, default: false
|
49
52
|
class_option :big_edit, type: :boolean, default: false
|
50
53
|
class_option :show_only, type: :string, default: ""
|
51
54
|
class_option :update_show_only, type: :string, default: ""
|
@@ -204,7 +207,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
204
207
|
puts "show only field #{@show_only}}"
|
205
208
|
end
|
206
209
|
|
207
|
-
@
|
210
|
+
@modify_as = {}
|
208
211
|
if !options['modify'].empty?
|
209
212
|
|
210
213
|
modify_input = options['modify'].split(",")
|
@@ -213,13 +216,14 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
213
216
|
key, lookup_as = $1, $2
|
214
217
|
|
215
218
|
if ["$"].include?($2)
|
216
|
-
@
|
219
|
+
@modify_as[key.to_sym] = {cast: $2}
|
217
220
|
elsif $2.include?("|")
|
218
221
|
binary = $2.split("|")
|
219
|
-
@
|
222
|
+
@modify_as[key.to_sym] = {binary: {truthy: binary[0], falsy: binary[1]}}
|
220
223
|
elsif $2 == "partial"
|
221
|
-
@
|
222
|
-
|
224
|
+
@modify_as[key.to_sym] = {enum: :partials}
|
225
|
+
elsif $2 == "tinymce"
|
226
|
+
@modify_as[key.to_sym] = {tinymce: 1}
|
223
227
|
else
|
224
228
|
raise "unknown modification direction #{$2}"
|
225
229
|
end
|
@@ -293,6 +297,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
293
297
|
|
294
298
|
@no_create = options['no_create'] || false
|
295
299
|
@no_paginate = options['no_paginate'] || false
|
300
|
+
@paginate_per_page_selector = options['paginate_per_page_selector']
|
301
|
+
|
296
302
|
@big_edit = options['big_edit']
|
297
303
|
|
298
304
|
@no_edit = options['no_edit'] || false
|
@@ -715,17 +721,19 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
715
721
|
if File.exist?(dest_file)
|
716
722
|
existing_file = File.open(dest_file)
|
717
723
|
existing_content = existing_file.read
|
718
|
-
if existing_content =~ /\#HOTGLUE-SAVESTART/
|
719
|
-
if existing_content !~ /\#HOTGLUE-END/
|
720
|
-
raise "Your file at #{dest_file} contains a #HOTGLUE-SAVESTART marker without #HOTGLUE-END"
|
724
|
+
if existing_content =~ /\# HOTGLUE-SAVESTART/
|
725
|
+
if existing_content !~ /\# HOTGLUE-END/
|
726
|
+
raise "Your file at #{dest_file} contains a # HOTGLUE-SAVESTART marker without # HOTGLUE-END"
|
721
727
|
end
|
722
|
-
@existing_content = existing_content[(existing_content =~ /\#HOTGLUE-SAVESTART/)..(existing_content =~ /\#HOTGLUE-END/) - 1]
|
723
|
-
@existing_content << "#HOTGLUE-END"
|
728
|
+
@existing_content = existing_content[(existing_content =~ /\# HOTGLUE-SAVESTART/)..(existing_content =~ /\# HOTGLUE-END/) - 1]
|
729
|
+
@existing_content << "# HOTGLUE-END"
|
724
730
|
|
731
|
+
else
|
732
|
+
@existing_content = " # HOTGLUE-SAVESTART\n # HOTGLUE-END"
|
725
733
|
end
|
726
734
|
existing_file.rewind
|
727
735
|
else
|
728
|
-
@existing_content = " #HOTGLUE-SAVESTART\n #HOTGLUE-END"
|
736
|
+
@existing_content = " # HOTGLUE-SAVESTART\n # HOTGLUE-END"
|
729
737
|
end
|
730
738
|
|
731
739
|
template "system_spec.rb.erb", dest_file
|
@@ -744,6 +752,14 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
744
752
|
singular_class.gsub("::", "_").underscore
|
745
753
|
end
|
746
754
|
|
755
|
+
def factory_testing_name
|
756
|
+
if !@self_auth
|
757
|
+
"#{singular}1"
|
758
|
+
else
|
759
|
+
"current_#{singular}"
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
747
763
|
def spec_related_column_lets
|
748
764
|
@columns_map.collect { |col, col_object|
|
749
765
|
col_object.spec_related_column_lets
|
@@ -769,7 +785,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
769
785
|
end
|
770
786
|
|
771
787
|
def regenerate_me_code
|
772
|
-
"rails generate hot_glue:scaffold #{ @meta_args[0][0] } #{@meta_args[1].collect { |x| x.gsub(/\s*=\s*([\S\s]+)/, '=\'\1\'') }.join(" ")}"
|
788
|
+
"bin/rails generate hot_glue:scaffold #{ @meta_args[0][0] } #{@meta_args[1].collect { |x| x.gsub(/\s*=\s*([\S\s]+)/, '=\'\1\'') }.join(" ")}"
|
773
789
|
end
|
774
790
|
|
775
791
|
def object_parent_mapping_as_argument_for_specs
|
@@ -1089,7 +1105,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1089
1105
|
def insert_into_nav_template
|
1090
1106
|
# how does this get called(?)
|
1091
1107
|
nav_file = "#{Rails.root}/app/views/#{namespace_with_trailing_dash}_nav.html.#{@markup}"
|
1092
|
-
if include_nav_template
|
1108
|
+
if include_nav_template && @nested_set.none?
|
1093
1109
|
append_text = " <li class='nav-item'>
|
1094
1110
|
<%= link_to '#{@list_label_heading}', #{path_helper_plural}, class: \"nav-link \#{'active' if nav == '#{plural_name}'}\" %>
|
1095
1111
|
</li>"
|
@@ -66,20 +66,24 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
66
66
|
def load_<%= singular_name %>
|
67
67
|
@<%= singular_name %> = (<%= auth_object.gsub("@",'') %><%= " if params.include?(:#{@nested_set[0][:singular]}_id)" if @nested_set.any? && @nested_set[0][:optional] %>)<% if @nested_set.any? && @nested_set[0][:optional] %> || <%= class_name %>.find(params[:id])<% end %>
|
68
68
|
end<% end %>
|
69
|
+
<% if @paginate_per_page_selector %>def per
|
70
|
+
params[:per] || 10
|
71
|
+
end
|
69
72
|
|
70
|
-
def load_all_<%= plural %><% if @pundit %>
|
71
|
-
@<%= plural_name %> = policy_scope(<%=
|
73
|
+
<% end %>def load_all_<%= plural %><% if @pundit %>
|
74
|
+
@<%= plural_name %> = policy_scope(<%= object_scope %>).page(params[:page])<%= n_plus_one_includes %><%= ".per(per)" if @paginate_per_page_selector %>
|
72
75
|
authorize @<%= plural_name %>.all<% else %> <% if !@self_auth %>
|
73
|
-
@<%= plural_name %> = <%= object_scope.gsub("@",'') %>.page(params[:page])<%=
|
76
|
+
@<%= plural_name %> = <%= object_scope.gsub("@",'') %><%= n_plus_one_includes %>.page(params[:page])<%= ".per(per)" if @paginate_per_page_selector %><%= " if params.include?(:#{ @nested_set.last[:singular]}_id)" if @nested_set.any? && @nested_set[0] && @nested_set[0][:optional] %><% if @nested_set[0] && @nested_set[0][:optional] %>
|
74
77
|
@<%= plural_name %> = <%= class_name %>.all<% end %><% else %>
|
75
|
-
@<%= plural_name %> = <%= class_name %>.where(id: <%= auth_object.gsub("@",'') %>.id)<%= n_plus_one_includes %><% end %>
|
78
|
+
@<%= plural_name %> = <%= class_name %>.where(id: <%= auth_object.gsub("@",'') %>.id)<%= n_plus_one_includes %>.page(params[:page])<%= ".per(per)" if @paginate_per_page_selector %><% end %>
|
76
79
|
<% end %>
|
77
80
|
end
|
78
81
|
|
79
82
|
def index
|
80
83
|
load_all_<%= plural %><% if @pundit %>
|
81
84
|
rescue Pundit::NotAuthorizedError
|
82
|
-
flash[:alert] = "You are not authorized to perform this action."
|
85
|
+
flash[:alert] = "You are not authorized to perform this action."
|
86
|
+
render "layouts/error"<% end %>
|
83
87
|
end
|
84
88
|
|
85
89
|
<% if create_action %> def new<% if @object_owner_sym %>
|
@@ -155,7 +159,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
155
159
|
<% end %>
|
156
160
|
modified_params = modify_date_inputs_on_params(<% if @update_show_only %>update_<% end %><%= singular_name %>_params.dup<%= controller_update_params_tap_away_alt_lookups %><%= controller_update_params_tap_away_magic_buttons %>, <%= current_user_object %>, <%= datetime_fields_list %>) <% if @object_owner_sym && eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %>
|
157
161
|
modified_params = modified_params.merge(<%= @object_owner_sym %>: <%= @object_owner_eval %>) <% elsif @object_owner_optional && any_nested? %>
|
158
|
-
modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <% elsif
|
162
|
+
modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <% elsif ! @object_owner_eval.empty? && !@self_auth%>
|
159
163
|
modified_params = modified_params.merge(<%= @object_owner_eval %>) <% end %><% if !merge_lookups.empty? %>
|
160
164
|
modified_params = modified_params.merge(<%= merge_lookups %>)
|
161
165
|
<% end %>
|
@@ -51,6 +51,12 @@
|
|
51
51
|
<%= @nested_set.collect{|arg| " .merge(defined?(#{arg[:singular]}) ? {#{arg[:singular]}: #{arg[:singular]}} : {})"}.join("\n") %>
|
52
52
|
%>
|
53
53
|
<\% end %>
|
54
|
+
<% if @paginate_per_page_selector %>
|
55
|
+
<\%= form_with url: things_path, method: :get do |f| %>
|
56
|
+
Show per page
|
57
|
+
<\%= f.collection_select "per", [10, 25, 100], :to_s, :to_s, {prompt: true, selected: params[:per]}, {onChange: "this.form.submit();"} %>
|
58
|
+
<\% end %>
|
59
|
+
<% end %>
|
54
60
|
<%= @no_paginate ? "" : paginate %>
|
55
61
|
<% end %>
|
56
62
|
</div>
|
@@ -2,9 +2,9 @@
|
|
2
2
|
if (eval(@singular_class).instance_methods.include?(display_class.to_s))
|
3
3
|
item1_addOns << "#{display_class}: FFaker::Name.name"
|
4
4
|
end
|
5
|
-
item1_addOns << ", " + @columns_map.collect{|col, col_object|
|
5
|
+
item1_addOns << ", \n " + @columns_map.collect{|col, col_object|
|
6
6
|
col_object.spec_setup_let_arg
|
7
|
-
}.compact.join(", ")
|
7
|
+
}.compact.join(", \n ")
|
8
8
|
%>require 'rails_helper'
|
9
9
|
|
10
10
|
describe 'interaction for <%= controller_class_name %>' do
|
@@ -14,7 +14,18 @@ describe 'interaction for <%= controller_class_name %>' do
|
|
14
14
|
<%= @existing_content %>
|
15
15
|
<% unless @god %>let(:<%= @auth %>) {create(:<%= @auth.gsub('current_', '') %>)}<% end %>
|
16
16
|
<%= spec_related_column_lets %>
|
17
|
-
|
17
|
+
<% unless @self_auth %> let!(:<%= singular %>1) {
|
18
|
+
<%= singular %> = create(:<%= singular %><%= object_parent_mapping_as_argument_for_specs %> <%= item1_addOns %> )
|
19
|
+
<%= @attachments.collect{ |attachment|
|
20
|
+
" #{singular}.#{ attachment[0].to_s }.attach(
|
21
|
+
io: File.open('spec/fixtures/glass_button.png'),
|
22
|
+
filename: 'glass_button.png',
|
23
|
+
content_type: 'image/png')"
|
24
|
+
}.join("\n")
|
25
|
+
%>
|
26
|
+
<%=singular%>.save!
|
27
|
+
<%=singular%>
|
28
|
+
}<% end %>
|
18
29
|
<%= objest_nest_factory_setup %> <% unless @god || (@existing_content && @existing_content.include?("login_as")) %>
|
19
30
|
before do
|
20
31
|
login_as(<%= @auth %>)
|
@@ -53,25 +64,25 @@ describe 'interaction for <%= controller_class_name %>' do
|
|
53
64
|
describe "edit & update" do
|
54
65
|
it "should return an editable form" do
|
55
66
|
visit <%= path_helper_plural %>
|
56
|
-
find("a.edit-<%= singular %>-button[href='/<%= namespace_with_slash %><%= plural %>/#{<%=
|
67
|
+
find("a.edit-<%= singular %>-button[href='/<%= namespace_with_slash %><%= plural %>/#{<%= factory_testing_name %>.id}/edit']").click
|
57
68
|
|
58
|
-
expect(page).to have_content("Editing #{<%=
|
69
|
+
expect(page).to have_content("Editing #{<%= factory_testing_name %>.<%= @display_class %>.squish || "(no name)"}")
|
59
70
|
<%= capybara_make_updates(:update) %>
|
60
71
|
click_button "Save"
|
61
|
-
within("turbo-frame#<%= @namespace %>__#{dom_id(<%=
|
72
|
+
within("turbo-frame#<%= @namespace %>__#{dom_id(<%= factory_testing_name %>)} ") do
|
62
73
|
<%= " " + @columns_map.map{ |col, col_object|
|
63
74
|
if @attachments.keys.collect(&:to_sym).include?(col)
|
64
75
|
elsif @show_only.include?(col)
|
65
76
|
else
|
66
77
|
col_object.spec_make_assertion
|
67
78
|
end
|
68
|
-
}.compact.join("\n
|
79
|
+
}.compact.join("\n ")
|
69
80
|
%>
|
70
81
|
end
|
71
82
|
end
|
72
|
-
end <% end %>
|
83
|
+
end <% end %><% if destroy_action %>
|
73
84
|
|
74
|
-
|
85
|
+
describe "destroy" do
|
75
86
|
it "should destroy" do
|
76
87
|
visit <%= path_helper_plural %>
|
77
88
|
accept_alert do
|
data/lib/hotglue/version.rb
CHANGED
data/script/test
CHANGED
@@ -30,7 +30,9 @@ bin/rails generate hot_glue:scaffold Pet --gd
|
|
30
30
|
|
31
31
|
bin/rails generate hot_glue:scaffold Human --gd
|
32
32
|
|
33
|
-
|
33
|
+
bin/rails generate hot_glue:scaffold User --no-create --self-auth
|
34
|
+
|
35
|
+
|
34
36
|
#rails generate hot_glue:scaffold Jkl --gd
|
35
37
|
#rails generate hot_glue:scaffold Appointment --hawk=pets --gd
|
36
38
|
#rails generate hot_glue:scaffold Family --gd
|
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.5.
|
4
|
+
version: 0.5.25
|
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: 2023-10-
|
11
|
+
date: 2023-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -143,7 +143,7 @@ licenses:
|
|
143
143
|
metadata:
|
144
144
|
source_code_uri: https://github.com/hot-glue-for-rails/hot-glue
|
145
145
|
homepage: https://heliosdev.shop/hot-glue
|
146
|
-
funding: https://school.
|
146
|
+
funding: https://school.jfbcodes.com/8188
|
147
147
|
post_install_message: |
|
148
148
|
---------------------------------------------
|
149
149
|
Welcome to Hot Glue - A Scaffold Building Companion for Hotwire + Turbo-Rails
|