hot-glue 0.6.18 → 0.6.20
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +334 -227
- data/lib/generators/hot_glue/fields/association_field.rb +1 -1
- data/lib/generators/hot_glue/fields/boolean_field.rb +6 -6
- data/lib/generators/hot_glue/fields/field.rb +5 -5
- data/lib/generators/hot_glue/layout/builder.rb +15 -6
- data/lib/generators/hot_glue/markup_templates/erb.rb +63 -15
- data/lib/generators/hot_glue/scaffold_generator.rb +46 -6
- data/lib/generators/hot_glue/templates/controller.rb.erb +28 -12
- data/lib/hotglue/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -321,6 +321,166 @@ TitleCase class name of the thing you want to build a scaffolding for.
|
|
321
321
|
|
322
322
|
(note: Your `Thing` object must `belong_to` an authenticated `User` or alternatively you must create a Gd controller, see below.)
|
323
323
|
|
324
|
+
|
325
|
+
## FLAGS (Options with no values)
|
326
|
+
These options (flags) also uses `--` syntax but do not take any values. (Notice no equal sign.) Everything is assumed (default) to be false unless specified.
|
327
|
+
|
328
|
+
|
329
|
+
### `--stacked-downnesting`
|
330
|
+
|
331
|
+
This puts the downnested portals on top of one another (stacked top to bottom) instead of side-by-side (left to right). This is useful if you have a lot of downnested portals and you want to keep the page from getting too wide.
|
332
|
+
|
333
|
+
|
334
|
+
|
335
|
+
### `--god` or `--gd`
|
336
|
+
|
337
|
+
Use this flag to create controllers with no root authentication. You can still use an auth_identifier, which can be useful for a meta-leval authentication to the controller.
|
338
|
+
|
339
|
+
For example, FOR ADMIN CONTROLLERS ONLY, supply a auth_identifier and use `--god` flag.
|
340
|
+
|
341
|
+
In Gd mode, the objects are loaded directly from the base class (these controllers have full access)
|
342
|
+
```
|
343
|
+
def load_thing
|
344
|
+
@thing = Thing.find(params[:id])
|
345
|
+
end
|
346
|
+
|
347
|
+
```
|
348
|
+
|
349
|
+
### `--button-icons` (default is no icons)
|
350
|
+
You can specify this either as builder flag or as a config setting (in `config/hot_glue.yml`)
|
351
|
+
Use `font-awesome` for Font Awesome or `none` for no icons.
|
352
|
+
|
353
|
+
|
354
|
+
### `--specs-only`
|
355
|
+
|
356
|
+
Produces ONLY the controller spec file, nothing else.
|
357
|
+
|
358
|
+
|
359
|
+
### `--no-specs`
|
360
|
+
|
361
|
+
Produces all the files except the spec file.
|
362
|
+
|
363
|
+
|
364
|
+
### `--no-paginate` (default: false)
|
365
|
+
|
366
|
+
Omits pagination. (All list views have pagination by default.)
|
367
|
+
|
368
|
+
### `--paginate-per-page-selector` (default: false)
|
369
|
+
|
370
|
+
Show a small drop-down below the list to let the user choose 10, 25, or 100 results per page.
|
371
|
+
|
372
|
+
|
373
|
+
### `--no-list`
|
374
|
+
|
375
|
+
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.)
|
376
|
+
|
377
|
+
|
378
|
+
|
379
|
+
### `--no-create`
|
380
|
+
|
381
|
+
Omits new & create actions.
|
382
|
+
|
383
|
+
### `--no-delete`
|
384
|
+
|
385
|
+
Omits delete button & destroy action.
|
386
|
+
|
387
|
+
### `--no-controller`
|
388
|
+
|
389
|
+
Omits controller.
|
390
|
+
|
391
|
+
### `--no-list`
|
392
|
+
|
393
|
+
Omits list views.
|
394
|
+
|
395
|
+
`--new-button-position` (above, below; default: above)
|
396
|
+
Show the new button above or below the list.
|
397
|
+
|
398
|
+
`--downnest-shows-headings` (default: false)
|
399
|
+
Show headings above downnested portals.
|
400
|
+
|
401
|
+
|
402
|
+
### `--big-edit`
|
403
|
+
|
404
|
+
If you do not want inline editing of your list items but instead want to fallback to full-page style behavior for your edit views, use `--big-edit`.
|
405
|
+
|
406
|
+
The user will be taken to a full-screen edit page instead of an edit-in-place interaction.
|
407
|
+
|
408
|
+
When using `--big-edit`, any downnested portals will be displayed on the edit page instead of on the list page.
|
409
|
+
|
410
|
+
Big edit makes all edit and magic button operations happen using `'data-turbo': false`, fully reloading the page and submitting HTML requests instead of TURBO_STREAM requests.
|
411
|
+
|
412
|
+
Likewise, the controller's `update` action always redirects instead of using Turbo.
|
413
|
+
|
414
|
+
|
415
|
+
### `--display-list-after-update`
|
416
|
+
|
417
|
+
After an update-in-place normally only the edit view is swapped out for the show view of the record you just edited.
|
418
|
+
|
419
|
+
Sometimes you might want to redisplay the entire list after you make an update (for example, if your action removes that record from the result set).
|
420
|
+
|
421
|
+
To do this, use flag `--display-list-after-update`. The update will behave like delete and re-fetch all the records in the result and tell Turbo to swap out the entire list.
|
422
|
+
|
423
|
+
### `--with-turbo-streams`
|
424
|
+
|
425
|
+
If and only if you specify `--with-turbo-streams`, your views will contain `turbo_stream_from` directives. Whereas your views will always contain `turbo_frame_tags` (whether or not this flag is specified) and will use the Turbo stream replacement mechanism for non-idempotent actions (create & update). This flag just brings the magic of live-reload to the scaffold interfaces themselves.
|
426
|
+
|
427
|
+
**_To test_**: Open the same interface in two separate browser windows. Make an edit in one window and watch your edit appear in the other window instantly.
|
428
|
+
|
429
|
+
This happens using two interconnected mechanisms:
|
430
|
+
|
431
|
+
1) by default, all Hot Glue scaffold is wrapped in `turbo_frame_tag`s. The id of these tags is your namespace + the Rails dom_id(...). That means all Hot Glue scaffold is namespaced to the namespaces you use and won't collide with other turbo_frame_tag you might be using elsewhere
|
432
|
+
|
433
|
+
2) by appending **model callbacks**, we can automatically broadcast updates to the users who are using the Hot Glue scaffold. The model callbacks (after_update_commit and after_destroy_commit) get appended automatically to the top of your model file. Each model callback targets the scaffold being built (so just this scaffold), using its namespace, and renders the line partial (or destroys the content in the case of delete) from the scaffolding.
|
434
|
+
|
435
|
+
please note that *creating* and *deleting* do not yet have a full & complete implementation: Your pages won't re-render the pages being viewed cross-peer (that is, between two users using the app at the same time) if the insertion or deletion causes the pagination to be off for another user.
|
436
|
+
|
437
|
+
|
438
|
+
### `--no-list-label`
|
439
|
+
Omits list LABEL itself above the list. (Do not confuse with the list heading which contains the field labels.)
|
440
|
+
|
441
|
+
Note that list labels may be automatically omitted on downnested scaffolds.
|
442
|
+
|
443
|
+
|
444
|
+
### `--no-list-heading`
|
445
|
+
|
446
|
+
Omits the heading of column names that appears above the 1st row of data.
|
447
|
+
|
448
|
+
### `--include-object-names`
|
449
|
+
|
450
|
+
When you are "Editing X" we specify that X is a ___ (author, book, room, etc)
|
451
|
+
|
452
|
+
e.g. "Editing author Edgar Allan Poe" vs "Editing Edgar Allan Poe"
|
453
|
+
|
454
|
+
Can also be specified globally in `config/hot_glue.yml`
|
455
|
+
|
456
|
+
## Nav Templates and `--no-nav-menu`
|
457
|
+
At the namespace level, you can have a file called `_nav.html.erb` to create tabbed bootstrap nav
|
458
|
+
|
459
|
+
To create the file for the first time (at each namespace), start by running
|
460
|
+
```
|
461
|
+
bin/rails generate hot_glue:nav_template --namespace=xyz
|
462
|
+
```
|
463
|
+
|
464
|
+
This will append the file `_nav.html.erb` to the views folder at `views/xyz`. To begin, this file contains only the following:
|
465
|
+
|
466
|
+
```
|
467
|
+
<ul class='nav nav-tabs'>
|
468
|
+
</ul>
|
469
|
+
```
|
470
|
+
|
471
|
+
Once the file is present, any further builds in this namespace will:
|
472
|
+
|
473
|
+
1) Append to this `_nav.html.erb` file, adding a tab for the new built scaffold
|
474
|
+
2) On the list view of the scaffold being built, it will include a render to the _nav partial, passing the name of the currently-viewed thing as the local variable `nav` (this is how the nav template knows which tab to make active).
|
475
|
+
```
|
476
|
+
<%= render partial: "owner/nav", locals: {nav: "things"} %>
|
477
|
+
```
|
478
|
+
(In this example `owner/` is the namespace and `things` is the name of the scaffold being built)
|
479
|
+
|
480
|
+
To suppress this behavior, add `--no-nav-menu` to the build command and the _nav template will not be touched.
|
481
|
+
|
482
|
+
|
483
|
+
|
324
484
|
## Options With Arguments
|
325
485
|
|
326
486
|
All options begin with two dashes (`--`) and a followed by an `=` and a value
|
@@ -348,7 +508,6 @@ end
|
|
348
508
|
|
349
509
|
```
|
350
510
|
|
351
|
-
|
352
511
|
### `--nested=`
|
353
512
|
|
354
513
|
This object is nested within another tree of objects, and there is a nested route in your `routes.rb` file with the specified parent controllers above this controller. When specifying the parent(s), be sure to use **singular case**.
|
@@ -771,8 +930,7 @@ Hot Glue gives you automatic field level access control if you create `*_able?`
|
|
771
930
|
The `*_able?` method should return true or false depending on whether or not the field can be edited. No distinction is made between the `new` and `edit` contexts. You may check if the record is new using `new_record?`.
|
772
931
|
|
773
932
|
|
774
|
-
**The `*_able?` method is used by Hot Glue only on the new and edit actions
|
775
|
-
|
933
|
+
**The `*_able?` method is used by Hot Glue only on the new and edit actions and also affects the strong parameters, so you no longer need to incorporate it into your policy's `update?` method
|
776
934
|
|
777
935
|
Add one `*_able?` method to the policy for each field you want to allow field-level access control.
|
778
936
|
|
@@ -781,12 +939,8 @@ Replace `*` with the name of the field you want under access control. Remember t
|
|
781
939
|
When the method returns true, the field will be displayed to the user (and allowed) for editing.
|
782
940
|
When the method returns false, the field will be displayed as read-only (viewable) to the user.
|
783
941
|
|
784
|
-
Important: These special fields determine *only* display behavior (new and edit), not create and update.
|
785
|
-
|
786
|
-
For create & update field-level access control, you must also implement the `update?` method on the Policy. Notice how in the example policy below, the `update?` method uses the `name_able?` method when it is checking if the name field can be updated, tying the feature together.
|
787
|
-
|
788
942
|
You can set Pundit to be enabled globally on the whole project for every build in `config/hot_glue.yml` (then you can leave off the `--pundit` flag from the scaffold command)
|
789
|
-
`:
|
943
|
+
`:pundit:` (all builds in that project will use Pundit)
|
790
944
|
|
791
945
|
|
792
946
|
Here's an example `ThingPolicy` that would allow **editing the name field** only if:
|
@@ -808,14 +962,11 @@ class ThingPolicy < ApplicationPolicy
|
|
808
962
|
end
|
809
963
|
|
810
964
|
def update?
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
else
|
817
|
-
return true
|
818
|
-
end
|
965
|
+
!@user.is_admin?
|
966
|
+
end
|
967
|
+
|
968
|
+
def edit?
|
969
|
+
!@user.is_admin?
|
819
970
|
end
|
820
971
|
|
821
972
|
class Scope < Scope
|
@@ -828,12 +979,11 @@ class ThingPolicy < ApplicationPolicy
|
|
828
979
|
end
|
829
980
|
```
|
830
981
|
|
831
|
-
|
832
982
|
Because Hot Glue detects the `*_able?` methods at build time, if you add them to your policy, you will have to rebuild your scaffold.
|
833
983
|
|
834
984
|
|
835
|
-
### `--pundit-policy-override
|
836
|
-
if you
|
985
|
+
### `--pundit-policy-override=`
|
986
|
+
if you pass a custom pundit class to `--pundit-policy-override=` your controller operations will bypass the invisible (pundit provided) access control and use the pundit policy you specify.
|
837
987
|
|
838
988
|
example
|
839
989
|
|
@@ -849,6 +999,8 @@ If provided, the output code looks something like (in this example, showing the
|
|
849
999
|
```
|
850
1000
|
|
851
1001
|
|
1002
|
+
|
1003
|
+
|
852
1004
|
### `--show-only=`
|
853
1005
|
(separate field names by COMMA)
|
854
1006
|
|
@@ -860,7 +1012,7 @@ IMPORTANT: By default, all fields that begin with an underscore (`_`) are automa
|
|
860
1012
|
This is for fields you want globally non-editable by users in your app. For example, a counter cache or other field set only by a backend mechanism.
|
861
1013
|
|
862
1014
|
|
863
|
-
### `--update-show-only
|
1015
|
+
### `--update-show-only=`
|
864
1016
|
(separate field names by COMMA)
|
865
1017
|
|
866
1018
|
• Make this field appear as viewable only for the edit action (and not allowed in the update action).
|
@@ -909,18 +1061,19 @@ Remember, if there's a corresponding `*_able?` method on the policy, it will be
|
|
909
1061
|
|
910
1062
|
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).
|
911
1063
|
|
912
|
-
|
913
|
-
### `--hidden
|
914
|
-
|
1064
|
+
### `--hidden=` (affects both create + update actions)
|
1065
|
+
### `--create-hidden=`
|
1066
|
+
### `--update-hidden=`
|
1067
|
+
TODO: RENAME ME TO INVISIBLE
|
915
1068
|
Separate list of fields.
|
916
1069
|
|
917
|
-
These fields will
|
1070
|
+
These fields will exist on the create or update form exist as hidden_field, and so the update will still work._
|
918
1071
|
|
919
1072
|
|
920
1073
|
EXAMPLE:
|
921
1074
|
|
922
1075
|
```
|
923
|
-
bin/rails generate hot_glue:scaffold Wrapper --namespace='account_dashboard' --no-nav-menu --big-edit --smart-layout --stimmify --
|
1076
|
+
bin/rails generate hot_glue:scaffold Wrapper --namespace='account_dashboard' --no-nav-menu --big-edit --smart-layout --stimmify --invisible=raw_source
|
924
1077
|
```
|
925
1078
|
|
926
1079
|
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:
|
@@ -992,7 +1145,77 @@ Notice we are also using `--stimmify` to decorate the form with a Stimulus contr
|
|
992
1145
|
|
993
1146
|
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.
|
994
1147
|
|
1148
|
+
### `--invisible=`
|
1149
|
+
### `--create-invisible=`
|
1150
|
+
### `--update-invisible=`
|
1151
|
+
(two lists are maintained: create and update. any fields on the unnamed invisible list will be invisible on both create and update actions)
|
1152
|
+
|
1153
|
+
If a field is on the invisible list, the policy will be checked for a `_able?` method.
|
1154
|
+
If this method returns true, displayed like a normal editable field.
|
1155
|
+
|
1156
|
+
If the policy doesn't allow editing, this field will be made invisible: completely removed from the form.
|
1157
|
+
|
1158
|
+
Like show only, these will check for `*_able?` methods on the object or Policy and will only display the field if the method returns true.
|
995
1159
|
|
1160
|
+
It will also block the field from being updated on the backend, so don't use this if you want to create a hidden_field tag but still allow the controller to update it. (For that, see `--hidden=`.)
|
1161
|
+
|
1162
|
+
|
1163
|
+
Like show-only, note special behavior with pundit.
|
1164
|
+
|
1165
|
+
A field can be marked invisible and show-only, in which case the invisible rule take prescedence when the access control is denied (field removed from form) but th show-only rule takes prescedance when the access control is granted,
|
1166
|
+
|
1167
|
+
Hidden can be used with invisible. In this case, the access control will be applied to the field. When editable, the hidden field output will be used.
|
1168
|
+
|
1169
|
+
Must be used with Pundit. Without pundit, see other alternatives: hidden fields, show only fields, or just removing the field completely by using the exclude list or leaving it off the include list.
|
1170
|
+
|
1171
|
+
| | | Pundit | | |
|
1172
|
+
|----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---|---|
|
1173
|
+
| fields not on any of these other lists | Included as editable on both the create + update actions or as viewable if Policy access control returns false | Without pundit, everything is editable. With pundit, the Policy is checked for an `_able?` method for each field at build time. When this method returns false, the field is viewable. | | |
|
1174
|
+
| Show only | Viewable only (non-editable) on both create + edit/update overriding whatever Policy returns. | Without pundit, this field is viewable only. Overrides whatever policy returns. | | |
|
1175
|
+
| Update Show only | Viewable only on the update screen or if Pundit doesn't allow editing | Same as above but apply only to the update screen. | | |
|
1176
|
+
| Invisible | Displayed in the HTML output and received by the controller for create or update action but shown as a hidden_field on the HTML, invisible to the user. You should use this if you want to construct your own form input or set the value via Javascript | Cannot be used without Pundit. With pundit, fields editable via the policy are editable on the screen (unless they are also show-only, in which case they are visible) and non-editable via the policy are made invisible (completely removed) from the screen. | | |
|
1177
|
+
| Hidden | Not displayed or updatable if the field respond false to _able? or the Policy doesn't allow. | Unrelated to pundit Policy | | |
|
1178
|
+
| | | | | |
|
1179
|
+
|
1180
|
+
|
1181
|
+
Pundit calls the policy for every action, including the index action. In these cases it passes an association instead of a single record.
|
1182
|
+
|
1183
|
+
Normally, field level access control that applies for show only and invisible is affects each record, in the list view, new page, or edit page.
|
1184
|
+
|
1185
|
+
For that reason, your `_able?` methods may check the individual records, except in the case of the `index` action for which the pundit policy has no individual record.
|
1186
|
+
|
1187
|
+
For these special cases, you might want to hide the entire column itself when the `_able?` return false on the association call (not in the context any of any record).
|
1188
|
+
|
1189
|
+
You'd want to do this for a global switch, unrelated to the record, to show or hide the column itself. When using invisible fields, the column headings are check against the policy's `_able?` fields, too, but since this called on the list, the entire set of objects being returned by the list is passed to the policy. (For example `policy(@things)`)
|
1190
|
+
|
1191
|
+
This makes it impossible to make your access control depend solely on the record itself, so can be used only for context-based access control that is applied to the column headings.
|
1192
|
+
|
1193
|
+
|
1194
|
+
In a case like this, you'll want the `_able?` method on the policy to know if the object is a record or many records.
|
1195
|
+
|
1196
|
+
```
|
1197
|
+
class ThingPolicy < ApplicationPolicy
|
1198
|
+
attr_reader :user, :thing
|
1199
|
+
|
1200
|
+
def initialize(user, thing)
|
1201
|
+
@user = user
|
1202
|
+
@thing = thing
|
1203
|
+
end
|
1204
|
+
|
1205
|
+
def ccc_able?
|
1206
|
+
if thing.is_a?(Thing) # a thing is not a Thing when it is an active relation of many things
|
1207
|
+
!!thing.bbb # show or hide ccc based on whether or not bbb is true
|
1208
|
+
else
|
1209
|
+
current_user.is_admin? # show or hide the column heading for ccc based on whether or not the current user is an admin
|
1210
|
+
end
|
1211
|
+
end
|
1212
|
+
# more policy method here ...
|
1213
|
+
end
|
1214
|
+
```
|
1215
|
+
Here, for all CRUD actions, the object is a thing, and so the editablility of ccc is dependent on bbb being true.
|
1216
|
+
If thing is not a Thing, then it is active relation (so this applies to the column headings) and we show it only to admins.
|
1217
|
+
|
1218
|
+
Remember, since the `_able?` methods are not otherwise called during Pundit's index cycle, this applies only to the list column headings and has no bearing on create, update, read, delete for which the access control can be anything you want that is available to the Poilcy.
|
996
1219
|
|
997
1220
|
|
998
1221
|
|
@@ -1014,7 +1237,7 @@ and also fix any Rails apps created since October 2021 by fixing the Gemfile. De
|
|
1014
1237
|
https://stackoverflow.com/questions/70671324/new-rails-7-turbo-app-doesnt-show-the-data-turbo-confirm-alert-messages-dont-f
|
1015
1238
|
|
1016
1239
|
|
1017
|
-
### `--magic-buttons
|
1240
|
+
### `--magic-buttons=`
|
1018
1241
|
If you pass a list of magic buttons (separated by commas), they will appear in the button area on your list.
|
1019
1242
|
|
1020
1243
|
It will be assumed there will be corresponding bang methods on your models.
|
@@ -1035,8 +1258,13 @@ Finally, you can raise an ActiveRecord error which will also get passed to the u
|
|
1035
1258
|
|
1036
1259
|
For more information see [Example 6 in the Tutorial](https://school.jfbcodes.com/8188)
|
1037
1260
|
|
1261
|
+
You can also define methods on your model that have the same name as the button with `_able?` at the end.
|
1262
|
+
(Prior to v0.6.20, these methods expected names with `able?` but no underscore.)
|
1263
|
+
|
1264
|
+
The button will be display as disabled if the method returns false.
|
1038
1265
|
|
1039
|
-
|
1266
|
+
|
1267
|
+
### `--downnest=`
|
1040
1268
|
|
1041
1269
|
Automatically create subviews down your object tree. This should be the name of a has_many relationship based from the current object.
|
1042
1270
|
You will need to build scaffolding with the same name for the related object as well. On the list view, the object you are currently building will be built with a sub-view list of the objects related from the given line.
|
@@ -1048,11 +1276,6 @@ Can now be created with more space (wider) by adding a `+` to the end of the dow
|
|
1048
1276
|
|
1049
1277
|
The 'Abcs' portal will display as 5 bootstrap columns instead of the typical 4. (You may use multiple ++ to keep making it wider but the inverse with minus is not supported
|
1050
1278
|
|
1051
|
-
### `--stacked-downnesting`
|
1052
|
-
|
1053
|
-
This puts the downnested portals on top of one another (stacked top to bottom) instead of side-by-side (left to right). This is useful if you have a lot of downnested portals and you want to keep the page from getting too wide.
|
1054
|
-
|
1055
|
-
|
1056
1279
|
|
1057
1280
|
### `--record-scope=`
|
1058
1281
|
|
@@ -1071,113 +1294,9 @@ scope :is_open, -> {where(state == 'open')}
|
|
1071
1294
|
|
1072
1295
|
Now all records displayed through the generated controller
|
1073
1296
|
|
1074
|
-
## FLAGS (Options with no values)
|
1075
|
-
These options (flags) also uses `--` syntax but do not take any values. Everything is assumed (default) to be false unless specified.
|
1076
|
-
|
1077
|
-
### `--god` or `--gd`
|
1078
|
-
|
1079
|
-
Use this flag to create controllers with no root authentication. You can still use an auth_identifier, which can be useful for a meta-leval authentication to the controller.
|
1080
|
-
|
1081
|
-
For example, FOR ADMIN CONTROLLERS ONLY, supply a auth_identifier and use `--god` flag.
|
1082
|
-
|
1083
|
-
In Gd mode, the objects are loaded directly from the base class (these controllers have full access)
|
1084
|
-
```
|
1085
|
-
def load_thing
|
1086
|
-
@thing = Thing.find(params[:id])
|
1087
|
-
end
|
1088
|
-
|
1089
|
-
```
|
1090
|
-
|
1091
|
-
### `--button-icons` (default is no icons)
|
1092
|
-
You can specify this either as builder flag or as a config setting (in `config/hot_glue.yml`)
|
1093
|
-
Use `font-awesome` for Font Awesome or `none` for no icons.
|
1094
|
-
|
1095
|
-
|
1096
|
-
### `--specs-only`
|
1097
|
-
|
1098
|
-
Produces ONLY the controller spec file, nothing else.
|
1099
|
-
|
1100
|
-
|
1101
|
-
### `--no-specs`
|
1102
|
-
|
1103
|
-
Produces all the files except the spec file.
|
1104
|
-
|
1105
|
-
|
1106
|
-
### `--no-paginate` (default: false)
|
1107
|
-
|
1108
|
-
Omits pagination. (All list views have pagination by default.)
|
1109
|
-
|
1110
|
-
### `--paginate-per-page-selector` (default: false)
|
1111
|
-
|
1112
|
-
Show a small drop-down below the list to let the user choose 10, 25, or 100 results per page.
|
1113
|
-
|
1114
|
-
|
1115
|
-
### `--no-list`
|
1116
|
-
|
1117
|
-
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.)
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
### `--no-create`
|
1122
|
-
|
1123
|
-
Omits new & create actions.
|
1124
|
-
|
1125
|
-
### `--no-delete`
|
1126
|
-
|
1127
|
-
Omits delete button & destroy action.
|
1128
|
-
|
1129
|
-
### `--no-controller`
|
1130
|
-
|
1131
|
-
Omits controller.
|
1132
|
-
|
1133
|
-
### `--no-list`
|
1134
|
-
|
1135
|
-
Omits list views.
|
1136
|
-
|
1137
|
-
`--new-button-position` (above, below; default: above)
|
1138
|
-
Show the new button above or below the list.
|
1139
|
-
|
1140
|
-
`--downnest-shows-headings` (default: false)
|
1141
|
-
Show headings above downnested portals.
|
1142
|
-
|
1143
|
-
|
1144
|
-
### `--big-edit`
|
1145
|
-
|
1146
|
-
If you do not want inline editing of your list items but instead want to fallback to full-page style behavior for your edit views, use `--big-edit`.
|
1147
|
-
|
1148
|
-
The user will be taken to a full-screen edit page instead of an edit-in-place interaction.
|
1149
|
-
|
1150
|
-
When using `--big-edit`, any downnested portals will be displayed on the edit page instead of on the list page.
|
1151
|
-
|
1152
|
-
Big edit makes all edit and magic button operations happen using `'data-turbo': false`, fully reloading the page and submitting HTML requests instead of TURBO_STREAM requests.
|
1153
|
-
|
1154
|
-
Likewise, the controller's `update` action always redirects instead of using Turbo.
|
1155
|
-
|
1156
|
-
|
1157
|
-
### `--display-list-after-update`
|
1158
|
-
|
1159
|
-
After an update-in-place normally only the edit view is swapped out for the show view of the record you just edited.
|
1160
|
-
|
1161
|
-
Sometimes you might want to redisplay the entire list after you make an update (for example, if your action removes that record from the result set).
|
1162
|
-
|
1163
|
-
To do this, use flag `--display-list-after-update`. The update will behave like delete and re-fetch all the records in the result and tell Turbo to swap out the entire list.
|
1164
|
-
|
1165
|
-
### `--with-turbo-streams`
|
1166
|
-
|
1167
|
-
If and only if you specify `--with-turbo-streams`, your views will contain `turbo_stream_from` directives. Whereas your views will always contain `turbo_frame_tags` (whether or not this flag is specified) and will use the Turbo stream replacement mechanism for non-idempotent actions (create & update). This flag just brings the magic of live-reload to the scaffold interfaces themselves.
|
1168
|
-
|
1169
|
-
**_To test_**: Open the same interface in two separate browser windows. Make an edit in one window and watch your edit appear in the other window instantly.
|
1170
|
-
|
1171
|
-
This happens using two interconnected mechanisms:
|
1172
|
-
|
1173
|
-
1) by default, all Hot Glue scaffold is wrapped in `turbo_frame_tag`s. The id of these tags is your namespace + the Rails dom_id(...). That means all Hot Glue scaffold is namespaced to the namespaces you use and won't collide with other turbo_frame_tag you might be using elsewhere
|
1174
|
-
|
1175
|
-
2) by appending **model callbacks**, we can automatically broadcast updates to the users who are using the Hot Glue scaffold. The model callbacks (after_update_commit and after_destroy_commit) get appended automatically to the top of your model file. Each model callback targets the scaffold being built (so just this scaffold), using its namespace, and renders the line partial (or destroys the content in the case of delete) from the scaffolding.
|
1176
|
-
|
1177
|
-
please note that *creating* and *deleting* do not yet have a full & complete implementation: Your pages won't re-render the pages being viewed cross-peer (that is, between two users using the app at the same time) if the insertion or deletion causes the pagination to be off for another user.
|
1178
1297
|
|
1179
1298
|
|
1180
|
-
### `--related-sets
|
1299
|
+
### `--related-sets=`
|
1181
1300
|
|
1182
1301
|
Used to show a checkbox set of related records. The relationship should be a `has_and_belongs_to_many` or a `has_many through:` from the object being built.
|
1183
1302
|
|
@@ -1196,58 +1315,43 @@ Note this leaves open a privileged escalation attack (a security vulnerability).
|
|
1196
1315
|
To fix this, you'll need to use Pundit with special syntax designed for this purpose. Please see [Example #17 in the Hot Glue Tutorial](https://school.jfbcodes.com/8188)
|
1197
1316
|
|
1198
1317
|
|
1199
|
-
|
1200
|
-
|
1201
|
-
Note that on a per model basis, you can also globally omit the label or set a unique label value using
|
1202
|
-
`@@table_label_singular` and `@@table_label_plural` on your model objects.
|
1203
|
-
|
1204
|
-
You have three options to specify labels explicitly with a string, and 1 option to specify a global name for which the words "Delete ___" and "New ___" will be added.
|
1205
|
-
|
1206
|
-
If no `--label` is specified, it will be inferred to be the Capitalized version of the name of the thing you are building, with spaces for two or more words.
|
1207
|
-
|
1208
|
-
### `--label`
|
1318
|
+
### `--label=`
|
1209
1319
|
|
1210
1320
|
The general name of the thing, will be applied as "New ___" for the new button & form. Will be *pluralized* for list label heading, so if the word has a non-standard pluralization, be sure to specify it in `config/inflictions.rb`
|
1211
1321
|
|
1212
1322
|
If you specify anything explicitly, it will be used.
|
1213
1323
|
If not, a specification that exists as `@@tabel_label_singular` from the Model will be used.
|
1214
|
-
If this does not exist, the Titleized (capitalized) version of the model name.
|
1324
|
+
If this does not exist, the Titleized (capitalized) version of the model name.
|
1215
1325
|
|
1216
|
-
### `--list-label-heading
|
1326
|
+
### `--list-label-heading=`
|
1217
1327
|
The plural of the list of things at the top of the list.
|
1218
1328
|
If not, a specification that exists as `@@tabel_label_plural` from the Model will be used.
|
1219
1329
|
If this does not exist, the UPCASE (all-uppercase) version of the model name.
|
1220
1330
|
|
1221
|
-
### `--new-button-label
|
1222
|
-
|
1223
|
-
(
|
1331
|
+
### `--new-button-label=`
|
1332
|
+
Overrides the button on the list that the user clicks onto to create a new record.
|
1333
|
+
(Default is to follow the same rules described in the `--label` option but with the word "New" prepended.)
|
1224
1334
|
|
1225
|
-
### `--new-form-heading
|
1335
|
+
### `--new-form-heading=`
|
1226
1336
|
The text at the top of the new form that appears when the new input entry is displayed.
|
1227
|
-
(
|
1228
|
-
|
1229
|
-
### `--no-list-label`
|
1230
|
-
Omits list LABEL itself above the list. (Do not confuse with the list heading which contains the field labels.)
|
1231
|
-
|
1232
|
-
Note that list labels may be automatically omitted on downnested scaffolds.
|
1233
|
-
|
1337
|
+
(Default follows the same rules described in the `--label` option but with the word "New" prepended.)
|
1234
1338
|
|
1235
1339
|
## Field Labels
|
1236
1340
|
|
1237
|
-
### `--form-labels-position
|
1341
|
+
### `--form-labels-position=` (default: `after`; options are **before**, **after**, and **omit**)
|
1238
1342
|
By default form labels appear after the form inputs. To make them appear before or omit them, use this flag.
|
1239
1343
|
|
1240
1344
|
See also `--form-placeholder-labels` to use placeolder labels.
|
1241
1345
|
|
1242
1346
|
|
1243
|
-
### `--form-placeholder-labels
|
1347
|
+
### `--form-placeholder-labels=` (default: false)
|
1244
1348
|
|
1245
1349
|
When set to true, fields, numbers, and text areas will have placeholder labels.
|
1246
1350
|
Will not apply to dates, times, datetimes, dropdowns (enums + foreign keys), or booleans.
|
1247
1351
|
|
1248
1352
|
See also setting `--form-labels-position` to control position or omit normal labels.
|
1249
1353
|
|
1250
|
-
### `--inline-list-labels
|
1354
|
+
### `--inline-list-labels=` (before, after, omit; default: omit)
|
1251
1355
|
|
1252
1356
|
Determines if field label will appear on the LIST VIEW. Note that because Hot Glue has no separate show route or page, this affects the `_show` template which is rendered as a partial from the LIST view.
|
1253
1357
|
|
@@ -1256,25 +1360,12 @@ Because the labels are already in the heading, this is `omit` by default. (Use w
|
|
1256
1360
|
Use `before` to make the labels come before or `after` to make them come after. See Version 0.5.1 release notes for an example.
|
1257
1361
|
|
1258
1362
|
|
1259
|
-
### `--no-list-heading`
|
1260
|
-
|
1261
|
-
Omits the heading of column names that appears above the 1st row of data.
|
1262
|
-
|
1263
|
-
### `--include-object-names`
|
1264
|
-
|
1265
|
-
When you are "Editing X" we specify that X is a ___ (author, book, room, etc)
|
1266
|
-
|
1267
|
-
e.g. "Editing author Edgar Allan Poe" vs "Editing Edgar Allan Poe"
|
1268
|
-
|
1269
|
-
Can also be specified globally in `config/hot_glue.yml`
|
1270
|
-
|
1271
|
-
|
1272
1363
|
### Code insertions
|
1273
1364
|
|
1274
|
-
`--code-before-create
|
1275
|
-
`--code-after-create
|
1276
|
-
`--code-before-update
|
1277
|
-
`--code-after-update
|
1365
|
+
### `--code-before-create=`
|
1366
|
+
### `--code-after-create=`
|
1367
|
+
### `--code-before-update=`
|
1368
|
+
### `--code-after-update=`
|
1278
1369
|
|
1279
1370
|
Insert some code into the `create` action or `update` actions.
|
1280
1371
|
The **before code** is called _after authorization_ but _before saving_ (which creates the record, or fails validation).
|
@@ -1283,9 +1374,8 @@ Both should be wrapped in quotation marks when specified in the command line, an
|
|
1283
1374
|
(Notice the funky indentation of the lines in the generated code. Adjust you input to get the indentation correct.)
|
1284
1375
|
|
1285
1376
|
|
1286
|
-
## Searching
|
1287
1377
|
|
1288
|
-
### `--search
|
1378
|
+
### `--search=` (options: simple, set, false predicate, default: false)
|
1289
1379
|
|
1290
1380
|
|
1291
1381
|
#### Set Search
|
@@ -1336,24 +1426,12 @@ Here's how you would add a search interface to Example #1 in the [Hot Glue Tutor
|
|
1336
1426
|
bin/rails generate Book --include=name,author_id --search=set --search-fields=name,author_id
|
1337
1427
|
```
|
1338
1428
|
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
#### Predicate
|
1429
|
+
#### Predicate Search
|
1344
1430
|
NOT IMPLEMENTED YET
|
1345
1431
|
TODO: implement me
|
1346
1432
|
|
1347
1433
|
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
## Special Features
|
1355
|
-
|
1356
|
-
### `--attachments`
|
1434
|
+
### `--attachments=`
|
1357
1435
|
|
1358
1436
|
#### ActiveStorage Quick Setup
|
1359
1437
|
(For complete docs, refer to https://guides.rubyonrails.org/active_storage_overview.html)
|
@@ -1397,7 +1475,7 @@ If it finds one, it will render thumbnails from the attachment variant `thumb`.
|
|
1397
1475
|
|
1398
1476
|
If using the shortform syntax and Hot Glue does **not find a variant** called `thumb` at the code generation time, it will build scaffolding without thumbnails.
|
1399
1477
|
|
1400
|
-
#### `--attachments
|
1478
|
+
#### `--attachments=` Long form syntax with 1 parameter
|
1401
1479
|
|
1402
1480
|
**--attachments='_attachment name_{_variant name_}'**
|
1403
1481
|
|
@@ -1417,7 +1495,7 @@ end
|
|
1417
1495
|
If using the long-form syntax with 1 parameter and Hot Glue does not find the specified variant declared in your attachment, it will stop and raise an error.
|
1418
1496
|
|
1419
1497
|
|
1420
|
-
#### `--attachments
|
1498
|
+
#### `--attachments=` Long form syntax with 1st and 2nd parameters
|
1421
1499
|
|
1422
1500
|
**--attachments='_attachment name_{_variant name_|_field for saving original filename_}'**
|
1423
1501
|
|
@@ -1431,7 +1509,7 @@ Note that the `orig_filename` is not part of the inputted parameters, it simply
|
|
1431
1509
|
|
1432
1510
|
Note: The 1st and 2nd parameters may be left empty (use `||`) but the 3rd and 4th parameters must either be specified or the parameter must be left off.
|
1433
1511
|
|
1434
|
-
#### `--attachments
|
1512
|
+
#### `--attachments=` Long form syntax with 1st, 2nd, and 3rd parameters
|
1435
1513
|
|
1436
1514
|
An optional 3rd parameter to the long-form syntax allows you to specify direct upload using the word "direct", which will add direct_upload: true to your f.file_field tags.
|
1437
1515
|
|
@@ -1443,6 +1521,16 @@ If you leave the 2nd parameter blank when using the 3rd parameter, it will defau
|
|
1443
1521
|
|
1444
1522
|
`--attachments='avatar{thumbnail||direct}'`
|
1445
1523
|
|
1524
|
+
#### `--attachments=` Long form syntax with 4 parameters
|
1525
|
+
|
1526
|
+
The final (4th) parameter should be `dropzone` to enable dropzone support for this attachment.
|
1527
|
+
|
1528
|
+
```
|
1529
|
+
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}'
|
1530
|
+
```
|
1531
|
+
|
1532
|
+
See below for dropzone details.
|
1533
|
+
|
1446
1534
|
|
1447
1535
|
#### For S3 Setup
|
1448
1536
|
|
@@ -1637,32 +1725,18 @@ Always:
|
|
1637
1725
|
|
1638
1726
|
Don't include this last line in your factory code.
|
1639
1727
|
|
1640
|
-
## Nav Templates and `--no-nav-menu`
|
1641
|
-
At the namespace level, you can have a file called `_nav.html.erb` to create tabbed bootstrap nav
|
1642
|
-
|
1643
|
-
To create the file for the first time (at each namespace), start by running
|
1644
|
-
```
|
1645
|
-
bin/rails generate hot_glue:nav_template --namespace=xyz
|
1646
|
-
```
|
1647
1728
|
|
1648
|
-
|
1729
|
+
# SPECIAL FEATURES
|
1649
1730
|
|
1650
|
-
```
|
1651
|
-
<ul class='nav nav-tabs'>
|
1652
|
-
</ul>
|
1653
|
-
```
|
1654
1731
|
|
1655
|
-
|
1732
|
+
## "Thing" Label
|
1656
1733
|
|
1657
|
-
|
1658
|
-
|
1659
|
-
```
|
1660
|
-
<%= render partial: "owner/nav", locals: {nav: "things"} %>
|
1661
|
-
```
|
1662
|
-
(In this example `owner/` is the namespace and `things` is the name of the scaffold being built)
|
1734
|
+
Note that on a per model basis, you can also globally omit the label or set a unique label value using
|
1735
|
+
`@@table_label_singular` and `@@table_label_plural` on your model objects.
|
1663
1736
|
|
1664
|
-
|
1737
|
+
You have three options to specify labels explicitly with a string, and 1 option to specify a global name for which the words "Delete ___" and "New ___" will be added.
|
1665
1738
|
|
1739
|
+
If no `--label` is specified, it will be inferred to be the Capitalized version of the name of the thing you are building, with spaces for two or more words.
|
1666
1740
|
|
1667
1741
|
|
1668
1742
|
## Automatic Base Controller
|
@@ -1705,7 +1779,7 @@ Child portals have the headings omitted automatically (there is a heading identi
|
|
1705
1779
|
|
1706
1780
|
|
1707
1781
|
|
1708
|
-
|
1782
|
+
## Note about enums
|
1709
1783
|
|
1710
1784
|
The Rails 7 enum implementation for Postgres is very slick but has a counter-intuitive facet.
|
1711
1785
|
|
@@ -1750,7 +1824,7 @@ Now, your labels will show up on the front-end as defined in the `_labels` ("Is
|
|
1750
1824
|
|
1751
1825
|
You can modify an enum so that instead of a drop down list, it displays a partial view that you must build. See the [v0.5.23 Release notes](https://github.com/hot-glue-for-rails/hot-glue#2023-10-01---v0523) for details.
|
1752
1826
|
|
1753
|
-
|
1827
|
+
## Validation Magic
|
1754
1828
|
|
1755
1829
|
Use ActiveRecord validations or hooks to validate your data. Hot Glue will automatically display the errors in the UI.
|
1756
1830
|
|
@@ -1768,7 +1842,7 @@ end
|
|
1768
1842
|
|
1769
1843
|
```
|
1770
1844
|
|
1771
|
-
|
1845
|
+
## Typeahead Foreign Keys
|
1772
1846
|
|
1773
1847
|
Let's go back to the first Books & Authors example.
|
1774
1848
|
assuming you have created
|
@@ -1866,7 +1940,7 @@ This means that to find users within the search, the essential piece of informat
|
|
1866
1940
|
--
|
1867
1941
|
|
1868
1942
|
|
1869
|
-
|
1943
|
+
## TinyMCE
|
1870
1944
|
1. `bundle add tinymce-rails` to add it to your Gemfile
|
1871
1945
|
|
1872
1946
|
2. Add this inside of your `<head>` tag (at the bottom is fine)
|
@@ -1944,21 +2018,54 @@ These automatic pickups for partials are detected at build time. This means that
|
|
1944
2018
|
|
1945
2019
|
# VERSION HISTORY
|
1946
2020
|
|
2021
|
+
|
2022
|
+
#### 2025-06-13 v0.6.20
|
2023
|
+
Breaking changes:
|
2024
|
+
• the setting in your hot_glue.yml file for `:pundit_default:` has been renamed just `:pundit:`.
|
2025
|
+
If you fail to rename it in your config file, hot glue will not build if it finds the old config setting.
|
2026
|
+
|
2027
|
+
• previously magic methods had a ability method that was the name of the magic method + `able?` as one word.
|
2028
|
+
this has been renamed to `_able?` and you must fix your cooresponding magic method ability methods by adding the underscore
|
2029
|
+
|
2030
|
+
|
2031
|
+
New Features
|
2032
|
+
• adds new invisibilty feature with `--invisible`, `--create-invisible`, and `--update-invisible` see docs above
|
2033
|
+
• changes previous `--hidden` into `--hidden`, `--create-hidden`, and `--update-hidden`. use hidden to apply to both fields
|
2034
|
+
• restores functionality of layout builder to magically distribute bootstrap 12 columns
|
2035
|
+
(4 columns use rows of 3 col widths; 2 columns use 6, 3 uses 4, etc). WHen using specified grouping mode, you
|
2036
|
+
probably want about 3 or 4 columns. When you have more than 5 it's difficult to build layouts that look good.
|
2037
|
+
|
2038
|
+
|
2039
|
+
|
2040
|
+
#### 2025-06-10 v0.6.19
|
2041
|
+
|
2042
|
+
• Fixes magic button output behavior to correctly show the string returned by the bang menthod
|
2043
|
+
• Fixes internal syntax of modify_as for modified fields; note default is now 'Yes' and 'No' for radio buttons
|
2044
|
+
• fixes destroy behavior with explicit .destroy! and ActiveRecord::RecordNotDestroyed; documents previously undocumented 4th parameter for attachment input
|
2045
|
+
|
2046
|
+
|
1947
2047
|
#### 2025-05-18 v0.6.18
|
1948
|
-
• Significant additions to `--alt-foreign-key-
|
1949
|
-
- on its
|
2048
|
+
• Significant additions to `--alt-foreign-key-lookup` which can now work:
|
2049
|
+
- on its own, without needing a factory (`--factory-creation`)
|
1950
2050
|
- with a factory
|
1951
2051
|
- with our without the hawk
|
1952
|
-
- in Gd mode
|
2052
|
+
- in Gd mode
|
2053
|
+
- if not in Gd mode, use with `--factory-creation` or use with the `--hawk`
|
1953
2054
|
|
1954
2055
|
See notes above for details.
|
1955
2056
|
|
1956
|
-
|
2057
|
+
example apps
|
2058
|
+
https://github.com/hot-glue-for-rails/HGHumanSpaMay25
|
2059
|
+
https://github.com/hot-glue-for-rails/HGAltLookups11
|
2060
|
+
|
2061
|
+
|
2062
|
+
• Adds Integer as searchable field
|
1957
2063
|
|
1958
2064
|
_ foo and bar are integers _
|
1959
2065
|
|
1960
2066
|
`rails g hot_glue:scaffold Thing --include=foo,bar --search=set --search-fields=foo,bar`
|
1961
2067
|
|
2068
|
+
• On show only association fields, view output is now safe-nil using `&` to not crash if the association doesn't exist.
|
1962
2069
|
|
1963
2070
|
|
1964
2071
|
#### 2025-05-09 - v0.6.17
|