hot-glue 0.4.8.1 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +2 -2
- data/Gemfile.lock +1 -1
- data/README.md +115 -73
- data/lib/generators/hot_glue/layout/builder.rb +19 -10
- data/lib/generators/hot_glue/markup_templates/erb.rb +4 -5
- data/lib/generators/hot_glue/scaffold_generator.rb +69 -22
- data/lib/generators/hot_glue/templates/controller.rb.erb +2 -2
- data/lib/generators/hot_glue/templates/erb/_list.erb +14 -10
- data/lib/generators/hot_glue/templates/erb/_new_button.erb +1 -1
- data/lib/generators/hot_glue/templates/erb/_new_form.erb +1 -1
- data/lib/generators/hot_glue/templates/erb/_show.erb +1 -1
- data/lib/generators/hot_glue/templates/erb/edit.erb +1 -1
- data/lib/hotglue/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a742ee0c02993ed08614aafae1af82e86528f002b69a7213c8cd731518b14df3
|
4
|
+
data.tar.gz: 6bd0941019c42f2ce0eee5d94447098b748a0475726efd53554c1f62f3051f2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bdfa2cdfbf27a138d53be2455df509345ec20f0f37d047a67e77d7365fff543a76e41504f3a1699a6eb24056ad939e55254ec6b4195c8647734d4b7f6eb288a
|
7
|
+
data.tar.gz: d123bf48ca0e1beb4eacdceeee934aaca4b6e6c6284a2c0c3f09e39caab94e9561bea7ccd8fcb92d6c8942df5ae855958270d2a8726a06dc3875fbfa6ec7b7d8
|
data/.github/FUNDING.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
custom: ["https://heliosdev.shop/hot-glue
|
2
|
-
"https://
|
1
|
+
custom: ["https://heliosdev.shop/p/hot-glue?utm_source=github.com&utm_campaign=github_hot_glue_repo_funding_link",
|
2
|
+
"https://jfbcodes.com/p/hot-glue-in-depth-tutorial?utm_source=github.com&utm_campaign=github_hot_glue_repo_funding_link"]
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -27,8 +27,10 @@ Hot Glue generates functionality that's quick and dirty. It lets you be crafty.
|
|
27
27
|
* Nest your routes model-by-model for built-in poor man's authentication.
|
28
28
|
* Throw the scaffolding away when your app is ready to graduate to its next phase.
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
|
31
|
+
# Get Hot Glue
|
32
|
+
## [Licence Only Option Now Available](https://heliosdev.shop/p/hot-glue/?utm_source=github.com&utm_campaign=github_hot_glue_readme_page) **only $50 USD!**
|
33
|
+
## [GET THE COURSE TODAY (includes Licence)](https://jfbcodes.com/courses/hot-glue-in-depth-tutorial/?utm_source=github.com&utm_campaign=github_hot_glue_readme_page) **only $60 USD!**
|
32
34
|
|
33
35
|
| | |
|
34
36
|
| ------------- | ------------- |
|
@@ -62,8 +64,11 @@ There are two ways to create new apps on Rails 7: With or without ImportMap. The
|
|
62
64
|
|
63
65
|
`rails new --css=bootstrap --javascript=webpack --database=postgresql`
|
64
66
|
|
65
|
-
Confirm that both Stimulus and Turbo are working.
|
66
|
-
|
67
|
+
Confirm that both Stimulus and Turbo are working.
|
68
|
+
|
69
|
+
**If using JSBundling, make sure to use the new `bin/dev rails` instead of the old `rails server` or else your Webpack will not compile.**
|
70
|
+
|
71
|
+
For the quick step-by-step to help you confirm that both Stimulus and Turbo are working for your new JSBundling-Rails/CSSBunlding-Rails setup [see this post](https://jasonfleetwoodboldt.com/courses/stepping-up-rails/rails-7-new-app-with-js-bundling-css-bundling/).
|
67
72
|
|
68
73
|
(Note that Bootstrap is optional for Hot Glue. Here, I am just showing you the default isntallation for simplicity.)
|
69
74
|
|
@@ -92,21 +97,13 @@ Purchase a license at https://heliosdev.shop/hot-glue-license
|
|
92
97
|
During in installation, you MUST supply a `--layout` flag.
|
93
98
|
|
94
99
|
### `--layout` flag (NOTE: haml and slim are no longer supported at this time)
|
95
|
-
Here you will set up and install Hot Glue for the first time.
|
100
|
+
Here you will set up and install Hot Glue for the first time.
|
96
101
|
|
97
|
-
|
102
|
+
It will install a config file that will save two preferences: layout (`hotglue` or `bootstrap`)
|
98
103
|
|
99
|
-
|
104
|
+
The installer will create `config/hot_glue.yml`.
|
100
105
|
|
101
|
-
|
102
|
-
If instead you install Hot Glue (or switch the setting) using the default layout mode (`--layout=hotglue`),
|
103
|
-
your scaffolding will be built using no-Bootstrap syntax: It has its own syntax with classes like
|
104
|
-
`.scaffold-container`,
|
105
|
-
`.scaffold-list`,
|
106
|
-
`.scaffold-row`, and
|
107
|
-
`.scaffold-cell`
|
108
|
-
|
109
|
-
During the installation, if your `--layout` flag is left unspecified or set to `hotglue` you must also pass `--theme` flag.
|
106
|
+
During the installation, if your `--layout` flag is set to `hotglue` you must also pass `--theme` flag.
|
110
107
|
|
111
108
|
the themes are:
|
112
109
|
• like_mountain_view (Google)
|
@@ -114,21 +111,12 @@ the themes are:
|
|
114
111
|
• like_bootstrap (bootstrap 4 copy)
|
115
112
|
• dark_knight (_The Dark Night_ (2008) inspired)
|
116
113
|
• like_cupertino (modern Apple-UX inspired)
|
117
|
-
• gradeschool (spiral bound/lined notebook inspired)
|
118
|
-
|
119
|
-
Please note that the scaffold is ** built with different market up for boostrap**, so you cannot switch between the Bootstrap and Hotglue layouts without rebuilding the scaffold.
|
120
|
-
|
121
|
-
(On the other hand, if you build within the Hotglue layout, all of the Hotglue theme files CAN be swapped out without rebuilding the scaffold.)
|
122
|
-
|
123
|
-
The themes are just SCSS files installed into app/assets/stylesheets. You can tweak or modify or remove them after they get installed.
|
124
|
-
|
125
114
|
|
126
115
|
### `--markup` flag
|
127
116
|
|
128
|
-
default is `erb`. IMPORTANT: As of right now,
|
117
|
+
default is `erb`. IMPORTANT: As of right now, HAML and SLIM are not currently supported.
|
129
118
|
|
130
119
|
|
131
|
-
## 3. RUN HOT-GLUE INSTALL:
|
132
120
|
### example installing ERB using Bootstrap layout:
|
133
121
|
`rails generate hot_glue:install --markup=erb --layout=bootstrap`
|
134
122
|
|
@@ -373,6 +361,34 @@ Then, finally the @charge will be loaded
|
|
373
361
|
|
374
362
|
This is "starfish access control" or "poor man's access control." It works when the current user has several things they can manage, and by extension can manage children of those things.
|
375
363
|
|
364
|
+
|
365
|
+
#### Optionalized Nested Parents
|
366
|
+
|
367
|
+
Add `~` in front of any nested parameter (any parent in the `--nest` list) you want to make optional. This creates a two-headed controller: It can operate with or without that optionalized parameter.
|
368
|
+
|
369
|
+
This is an advanced feature is to use **two duplicative routes to the same controller**. You can only use this feature with Gd controller.
|
370
|
+
|
371
|
+
Specify your controller *twice* in your routes.rb. Then, in your `--nest` setting, add `~` to any nested parent you want to **make optional**. "Make optional" means the controller will behave as-if it exists in two places: once, at the normal nest level. Then the same controller will 'exist' again one-level up in your routes. **If the route has sub-routes, you'll need to re-specify the entire subtree also**.
|
372
|
+
```
|
373
|
+
namespace :admin
|
374
|
+
resources :users do
|
375
|
+
resources :invoices
|
376
|
+
end
|
377
|
+
resources :invoices
|
378
|
+
end
|
379
|
+
```
|
380
|
+
|
381
|
+
Even though we have two routes pointed to invoices, both will go to the same controller (`invoices_controller.rb`)
|
382
|
+
|
383
|
+
```
|
384
|
+
rails generate hot_glue:scaffold User --namespace=admin --gd --downnest=invoices
|
385
|
+
rails generate hot_glue:scaffold Invoice --namespace=admin --gd --nest=~users
|
386
|
+
```
|
387
|
+
Notice for the Invoice build, the parent user is *optionalized* (not 'optional'-- optionalized: to be made so it can be made optional).
|
388
|
+
|
389
|
+
The Invoices controller, which is a Gd controller, will load the User if a user is specified in the route (`/admin/users/:user_id/invoices/`). It will ALSO work at `/admin/invoices` and will switch back into loading directly from the base class when routed this way.
|
390
|
+
|
391
|
+
|
376
392
|
|
377
393
|
### `--auth=`
|
378
394
|
|
@@ -396,28 +412,6 @@ It is also presumed that when viewing their own dashboard of things, the user wi
|
|
396
412
|
|
397
413
|
If you supply nesting (see below), your nest chain will automatically begin with your auth root object (see nesting)
|
398
414
|
|
399
|
-
#### Optionalized Nested Parents
|
400
|
-
|
401
|
-
Add `~` in front of any nested parameter (any parent in the `--nest` list) you want to make optional. This creates a two-headed controller: It can operate with or without that optionalized parameter.
|
402
|
-
|
403
|
-
This is an advanced feature is to use two duplicitous routes to the same controller. You can only use this feature with Gd controller. To use, specify your controller *twice* in your routes.rb. Then, in your `--nest` setting, add `~` to any nested parent you want to **make optional**. "Make optional" means the controller will behave as-if it exists in two places: once, at the normal nest level. Then the same controller will 'exist' again one-level up in your routes. **If the route has sub-routes, you'll need to re-specify the entire subtree also**.
|
404
|
-
```
|
405
|
-
namespace :admin
|
406
|
-
resources :users do
|
407
|
-
resources :invoices
|
408
|
-
end
|
409
|
-
resources :invoices
|
410
|
-
end
|
411
|
-
```
|
412
|
-
Hot Glue will build the scaffolding once for users and once again for invoice. Even though we have two routes pointed to invoices,
|
413
|
-
```
|
414
|
-
rails generate hot_glue:scaffold User --namespace=admin --gd --downnest=invoices
|
415
|
-
rails generate hot_glue:scaffold Invoice --namespace=admin --gd --nest=~users
|
416
|
-
```
|
417
|
-
Notice for the Invoice build, the parent user is *optionalized* (not 'optional'-- optionalized: to be made so it can be made optional). The Invoices controller, which is a Gd controller, will load the User if a user is specified in the route (`/admin/users/:user_id/invoices/`). It will ALSO work at `/admin/invoices` and will switch back into loading directly from the base class when routed this way.
|
418
|
-
|
419
|
-
|
420
|
-
|
421
415
|
|
422
416
|
### `--auth_identifier=`
|
423
417
|
|
@@ -525,7 +519,7 @@ With Bootstrap in specified grouping or smart layout mode, it automatically atte
|
|
525
519
|
|
526
520
|
Using Bootstrap with neither specified grouping nor smart layouts may make 12 columns, which will produce strange result. (Bootstrap is not designed to work with, for example, a 13-column layout.)
|
527
521
|
|
528
|
-
You should typically either specify your grouping or use smart layouts when building with Bootstrap, but if your use case does not fit the stacking feature you can specify neither and then you may have deal with the over-stuffed layouts as explained
|
522
|
+
You should typically either specify your grouping or use smart layouts when building with Bootstrap, but if your use case does not fit the stacking feature you can specify neither flag and then you may then have to deal with the over-stuffed layouts as explained.
|
529
523
|
|
530
524
|
|
531
525
|
|
@@ -533,7 +527,7 @@ You should typically either specify your grouping or use smart layouts when buil
|
|
533
527
|
|
534
528
|
Smart layouts are like specified grouping but Hot Glue does the work of figuring out how many fields you want in each column.
|
535
529
|
|
536
|
-
It will concatinate your fields into groups that will fit into the
|
530
|
+
It will concatinate your fields into groups that will fit into the Bootstrap's 12-column grid.
|
537
531
|
|
538
532
|
The effect will be that the fields will be stacked together into nicely fit columns.
|
539
533
|
|
@@ -553,7 +547,7 @@ If you're keeping track, that means we may have used 6 to 8 out of our Bootstrap
|
|
553
547
|
|
554
548
|
If we have 2 downnested portals and only the default buttons, that uses 10 out of 12 Bootstrap columns, leaving only 2 bootstrap columns for the fields.
|
555
549
|
|
556
|
-
|
550
|
+
The layout builder takes the number of columns left and then distributes the feilds 'evenly' among them. However, note that order specified translates to up-to-down within the column, and then left-to-right across the columns, like so:
|
557
551
|
|
558
552
|
A D G
|
559
553
|
|
@@ -622,7 +616,11 @@ Automatically create subviews down your object tree. This should be the name of
|
|
622
616
|
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.
|
623
617
|
|
624
618
|
The downnested child table (not to be confused with this object's `--nested` setting, where you are specifying this object's _parents_) is called a **child portal**. When you create a record in the child portal, the related record is automatically set to be owned by its parent (as specified by `--nested`). For an example, see the [v0.4.7 release notes](https://github.com/jasonfb/hot-glue/releases/tag/v0.4.7).
|
625
|
-
|
619
|
+
|
620
|
+
Can now be created with more space (wider) by adding a `+` to the end of the downnest name
|
621
|
+
- e.g. `--downnest=abc+,xyz`
|
622
|
+
|
623
|
+
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
|
626
624
|
|
627
625
|
|
628
626
|
|
@@ -665,7 +663,14 @@ Omits list action. Only makes sense to use this if you are create a view where y
|
|
665
663
|
|
666
664
|
### `--no-list-labels`
|
667
665
|
|
668
|
-
Omits list labels
|
666
|
+
Omits list labels at the top of the list.
|
667
|
+
|
668
|
+
### `--no-list-heading`
|
669
|
+
|
670
|
+
Omits the list heading.
|
671
|
+
|
672
|
+
(Note that on a per model basis, you can also globally omit the heading or set a unique value using
|
673
|
+
`@@table_label_singular` and `@@table_label_plural` on your model objects.)
|
669
674
|
|
670
675
|
### `--no-create`
|
671
676
|
|
@@ -697,10 +702,23 @@ HotGlue will copy a file named base_controller.rb to the same folder where it tr
|
|
697
702
|
|
698
703
|
Obviously, the created controller will always have this base controller as its subclass. In this way, you are encouraged to implement functionality common to the *namespace* (shared between the controllers in the namespace), using this technique.
|
699
704
|
|
705
|
+
## Special Table Labels
|
706
|
+
|
707
|
+
If your object is very wordy (like MyGreatHook) and you want it to display in the UI as something shorter,
|
708
|
+
add `@@table_label_plural = "The Things"` and `@@table_label_singular = "The Things"`.
|
709
|
+
|
710
|
+
Hot Glue will use this as the listing heading label and New record label. This affects only the UI only.
|
711
|
+
|
712
|
+
You can also set these to `nil` to omit the labels completely.
|
713
|
+
|
714
|
+
Child portals have the headings omitted automatically (there is a heading identifying them already on the parent view where they get included), or you can use the `--no-list-heading` on any specific build.
|
715
|
+
|
716
|
+
|
700
717
|
## Field Types Supported
|
701
718
|
|
702
719
|
- Integers that don't end with `_id`: displayed as input fields with type="number"
|
703
|
-
- Integers that do end with `_id` will be treated automatically as associations. You should have a Rails association defined. (Hot Glue will warn you if it can't find one.)
|
720
|
+
- Foreign keys: Integers that do end with `_id` will be treated automatically as associations. You should have a Rails association defined. (Hot Glue will warn you if it can't find one.)
|
721
|
+
- Note: if your foreign key has a nonusual class name, it should be using the `class_name:` in the model definition
|
704
722
|
- String: displayed as small input box
|
705
723
|
- Text: displayed as large textarea
|
706
724
|
- Float: displayed as input box
|
@@ -713,28 +731,52 @@ Obviously, the created controller will always have this base controller as its s
|
|
713
731
|
|
714
732
|
# VERSION HISTORY
|
715
733
|
|
734
|
+
#### 2022-02-14 - v0.4.9
|
735
|
+
• Fixed issue building models with namespaced class names (e.g. `Fruits::Apple` and `Fruits::Bannana`).
|
736
|
+
You can now build against these kinds of models natively (be sure to pass the full model name, with double-colon syntax).
|
737
|
+
|
738
|
+
• Also fixes issues when associations themselves were namespaced models.
|
739
|
+
|
740
|
+
• The N+1 Killer (!!!)
|
741
|
+
- N+1 queries for _any association_ built by the list are now automagically killed by the list controllers.
|
742
|
+
- Thanks to the work done back in Rails 5.2, Rails smartly uses either two queries to glob up the data OR one query with a LEFT OUTER JOIN if that's faster. You don't have to think about it. **Thanks Rails 5.2!**
|
743
|
+
- Hot Glue now adds `.includes(...)` if it is including an association when it loads the list view to eliminate the N+1s
|
744
|
+
- Bullet is still the best way to identify, find, & fix your N+1 queries is still highly recommended. https://github.com/flyerhzm/bullet
|
745
|
+
|
746
|
+
• Downnest children (portals) can now be created with more space (made wider) by adding one or more `+` to the end of the downnest name, denoting add 1 bootstrap column.
|
747
|
+
- e.g. `--downnest=abc+,xyz`
|
716
748
|
|
749
|
+
The "Abc" portal will take up 5 bootstrap columns and the Xyz portal will take up 4 columns. (++ to indicate 6, `+++` for 7, etc)
|
750
|
+
|
751
|
+
• Now that you can expand the downnest child portal width, you can easily give them too much width taking up more than 12 bootstrap columns.
|
752
|
+
The builder stops you from building if you have taken up too many bootstrap columns, are in _either_ **Smart Layout mode** or **Specified Grouping mode**.
|
753
|
+
However, this check is not in place if you are in neither mode, in which case you should watch out for building more than 12 bootstrap columns.
|
754
|
+
|
755
|
+
• To give a special label to a model, add `@@table_label_plural = "The Things"` and `@@table_label_singular = "The Thing"`.
|
756
|
+
This model will now have a list heading of "The Things" instead of its usual name.
|
757
|
+
For 'create buttons' and the 'New' screen, the builder will use the singular setting.
|
758
|
+
This affects all builds against that model and affects the UI (display) only.
|
759
|
+
All route names, table names, and variables are unaffected by this.
|
760
|
+
|
761
|
+
• You can also use `@@table_label_plural = nil` to set these tables to **omit** the label headings, or use the new flag...
|
762
|
+
|
763
|
+
• `--no-list-heading` (defaults to false but note several conditions when list headings are now hidden)
|
764
|
+
|
765
|
+
Omits the list heading. Note that the listing heading is omitted:
|
766
|
+
1) if there is no list,
|
767
|
+
2) if you set the `--no-list-heading` flag,
|
768
|
+
3) if the model has `@@table_label_plural = nil`, or
|
769
|
+
4) if you are constructing a nested child portal with only non-optionalized parents.
|
770
|
+
|
771
|
+
|
772
|
+
|
773
|
+
#### 2022-02-09 - v0.4.8.1 - Issue with Installer for v0.4.8
|
774
|
+
- There was an issue for the installer for v0.4.8. This new version v0.4.8.1 correts it.
|
717
775
|
|
718
776
|
|
719
777
|
#### 2022-02-07 - v0.4.8 Optionalized Nested Parents
|
720
778
|
- optionalized nested parents. to use add `~` in front of any nested parameter you want to make optional
|
721
779
|
|
722
|
-
- This is an advanced feature is to use two duplicitous routes to the same controller. You can only use this feature with Gd controller. To use, specify your controller *twice* in your routes.rb. Then, in your `--nest` setting, add `~` to any nested parent you want to **make optional**. "Make optional" means the controller will behave as-if it exists in two places: once, at the normal nest level. Then the same controller will 'exist' again one-level up in your routes. **If the route has sub-routes, you'll need to re-specify the entire subtree also**.
|
723
|
-
```
|
724
|
-
namespace :admin
|
725
|
-
resources :users do
|
726
|
-
resources :invoices
|
727
|
-
end
|
728
|
-
resoures :invoices
|
729
|
-
end
|
730
|
-
```
|
731
|
-
We will build the scaffolding once for users and once again for invoice. Even though we have two routes pointed to invoices,
|
732
|
-
```
|
733
|
-
rails generate hot_glue:scaffold User --namespace=admin --gd --downnest=invoices
|
734
|
-
rails generate hot_glue:scaffold Invoice --namespace=admin --gd --nest=~users
|
735
|
-
```
|
736
|
-
- Notice for the Invoice build, the parent user is *optionalized* (not 'optional'-- optionalized: to be made so it can be made optional). The Invoices controller, which is a Gd controller, will load the User if a user is specified in the route (`/admin/users/:user_id/invoices/`). It will ALSO work at `/admin/invoices` and will switch back into loading directly from the base class when routed this way.
|
737
|
-
- fixes to specified grouping mode-- the columns you specify now grab up the remaining bootstrap columns to fill space
|
738
780
|
|
739
781
|
#### 2022-01-26 - v0.4.7 `--nest` has been renamed to `--nested`; please use `--nested` moving forward
|
740
782
|
- `--alt-controller-name` feature from the last release has been removed, I have something better coming soon
|
@@ -851,8 +893,8 @@ COVERGE=on rake spec
|
|
851
893
|
--
|
852
894
|
--
|
853
895
|
|
854
|
-
Test coverage as of 2022-02-
|
855
|
-
|
856
|
-
![Screen Shot 2022-02-
|
896
|
+
Test coverage as of 2022-02-14 (v0.4.9)
|
897
|
+
|
898
|
+
![Screen Shot 2022-02-14 at 8 33 29 PM](https://user-images.githubusercontent.com/59002/153975911-30fa9c84-c8d8-49e7-bd5c-e2b958d6f10e.png)
|
857
899
|
|
858
900
|
|
@@ -4,13 +4,13 @@ module HotGlue
|
|
4
4
|
module Layout
|
5
5
|
class Builder
|
6
6
|
attr_reader :include_setting,
|
7
|
-
:
|
7
|
+
:downnest_object,
|
8
8
|
:buttons_width, :columns,
|
9
9
|
:smart_layout, :specified_grouping_mode
|
10
10
|
|
11
11
|
def initialize(params)
|
12
12
|
@include_setting = params[:include_setting]
|
13
|
-
@
|
13
|
+
@downnest_object = params[:downnest_object]
|
14
14
|
|
15
15
|
@buttons_width = params[:buttons_width]
|
16
16
|
|
@@ -32,23 +32,28 @@ module HotGlue
|
|
32
32
|
buttons: { size: @buttons_width}
|
33
33
|
}
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
end
|
35
|
+
# downnest_object.each do |child, size|
|
36
|
+
# layout_object[:portals][child] = {size: size}
|
37
|
+
# end
|
38
38
|
|
39
39
|
# smart layout: 2 columns per field; 4 column for EACH downnested portals, 2 column for buttons
|
40
|
-
how_many_downnest =
|
40
|
+
how_many_downnest = downnest_object.size
|
41
|
+
|
42
|
+
bootstrap_columns = (12 - @buttons_width )
|
43
|
+
|
44
|
+
bootstrap_columns = bootstrap_columns - (downnest_object.collect{|k,v| v}.sum)
|
41
45
|
|
42
|
-
bootstrap_columns = (12-@buttons_width )
|
43
|
-
bootstrap_columns = bootstrap_columns - (how_many_downnest*4)
|
44
46
|
available_columns = (bootstrap_columns / 2).floor # bascially turns the 12-column grid into a 6-column grid
|
45
47
|
|
46
48
|
if available_columns < 0
|
47
49
|
raise "Cannot build layout with #{how_many_downnest} downnested portals"
|
48
50
|
end
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
+
downnest_children_width = []
|
53
|
+
|
54
|
+
downnest_object.each do |child, size|
|
55
|
+
layout_object[:portals][child] = {size: size}
|
56
|
+
end
|
52
57
|
|
53
58
|
|
54
59
|
if smart_layout
|
@@ -56,6 +61,10 @@ module HotGlue
|
|
56
61
|
#
|
57
62
|
|
58
63
|
if columns.size > available_columns
|
64
|
+
if available_columns == 0
|
65
|
+
raise "Oopps... No available columns in SMART LAYOUT"
|
66
|
+
end
|
67
|
+
|
59
68
|
each_col_can_have = (columns.size.to_f / available_columns.to_f).round
|
60
69
|
|
61
70
|
layout_object[:columns][:container] = (0..available_columns-1).collect { |x|
|
@@ -94,9 +94,9 @@ module HotGlue
|
|
94
94
|
end
|
95
95
|
|
96
96
|
is_owner = col == ownership_field
|
97
|
-
|
97
|
+
assoc_class_name = assoc.active_record.name
|
98
|
+
display_column = HotGlue.derrive_reference_name(assoc_class_name)
|
98
99
|
|
99
|
-
# TODO: add is_owner && check if this nested arg is optional
|
100
100
|
(is_owner ? "<% unless @#{assoc_name} %>\n" : "") +
|
101
101
|
" <%= f.collection_select(:#{col}, #{assoc.class_name}.all, :id, :#{display_column}, {prompt: true, selected: @#{singular}.#{col} }, class: 'form-control') %>\n" +
|
102
102
|
(is_owner ? "<% else %>\n <%= @#{assoc_name}.#{display_column} %>" : "") +
|
@@ -209,9 +209,8 @@ module HotGlue
|
|
209
209
|
exit
|
210
210
|
# raise(HotGlue::Error,exit_message)
|
211
211
|
end
|
212
|
-
|
213
|
-
display_column = HotGlue.derrive_reference_name(
|
214
|
-
|
212
|
+
assoc_class_name = assoc.active_record.name
|
213
|
+
display_column = HotGlue.derrive_reference_name(assoc_class_name)
|
215
214
|
"<%= #{singular}.#{assoc.name.to_s}.try(:#{display_column}) || '<span class=\"content alert-danger\">MISSING</span>'.html_safe %>"
|
216
215
|
|
217
216
|
else
|
@@ -12,6 +12,15 @@ module HotGlue
|
|
12
12
|
class Error < StandardError
|
13
13
|
end
|
14
14
|
|
15
|
+
def self.construct_downnest_object(input)
|
16
|
+
res = input.split(",").map { |child|
|
17
|
+
child_name = child.gsub("+","")
|
18
|
+
extra_size = child.count("+")
|
19
|
+
{child_name => 4+extra_size}
|
20
|
+
}
|
21
|
+
Hash[*res.collect{|hash| hash.collect{|key,value| [key,value].flatten}.flatten}.flatten]
|
22
|
+
end
|
23
|
+
|
15
24
|
def self.optionalized_ternary(params)
|
16
25
|
namespace = params[:namespace] || nil
|
17
26
|
target = params[:target]
|
@@ -117,6 +126,8 @@ module HotGlue
|
|
117
126
|
class_option :markup, type: :string, default: nil # deprecated -- use in app config instead
|
118
127
|
class_option :layout, type: :string, default: nil # if used here it will override what is in the config
|
119
128
|
class_option :no_list_labels, type: :boolean, default: false
|
129
|
+
class_option :no_list_heading, type: :boolean, default: false
|
130
|
+
|
120
131
|
class_option :before_list_labels, type: :boolean, default: false
|
121
132
|
|
122
133
|
def initialize(*meta_args)
|
@@ -191,6 +202,12 @@ module HotGlue
|
|
191
202
|
|
192
203
|
|
193
204
|
@singular = args.first.tableize.singularize # should be in form hello_world
|
205
|
+
|
206
|
+
|
207
|
+
if @singular.include?("/")
|
208
|
+
@singular = @singular.split("/").last
|
209
|
+
end
|
210
|
+
|
194
211
|
@plural = options['plural'] || @singular + "s" # supply to override; leave blank to use default
|
195
212
|
@namespace = options['namespace'] || nil
|
196
213
|
|
@@ -217,9 +234,10 @@ module HotGlue
|
|
217
234
|
|
218
235
|
@nested = (!options['nested'].empty? && options['nested']) || nil
|
219
236
|
|
220
|
-
@singular_class =
|
221
|
-
@exclude_fields = []
|
237
|
+
@singular_class = args.first # note this is the full class name with a model namespace
|
222
238
|
|
239
|
+
|
240
|
+
@exclude_fields = []
|
223
241
|
@exclude_fields += options['exclude'].split(",").collect(&:to_sym)
|
224
242
|
|
225
243
|
if !options['include'].empty?
|
@@ -247,6 +265,8 @@ module HotGlue
|
|
247
265
|
@no_edit = options['no_edit'] || false
|
248
266
|
@no_list = options['no_list'] || false
|
249
267
|
@no_list_labels = options['no_list_labels'] || false
|
268
|
+
@no_list_heading = options['no_list_heading'] || false
|
269
|
+
|
250
270
|
@display_list_after_update = options['display_list_after_update'] || false
|
251
271
|
@smart_layout = options['smart_layout']
|
252
272
|
|
@@ -258,13 +278,13 @@ module HotGlue
|
|
258
278
|
@container_name = @layout == "hotglue" ? "scaffold-container" : "container-fluid"
|
259
279
|
@downnest = options['downnest'] || false
|
260
280
|
|
261
|
-
@downnest_children = []
|
262
|
-
|
281
|
+
@downnest_children = [] # TODO: defactor @downnest_children in favor of downnest_object
|
282
|
+
@downnest_object = {}
|
263
283
|
if @downnest
|
264
|
-
@downnest_children = @downnest.split(",")
|
284
|
+
@downnest_children = @downnest.split(",").map{|child| child.gsub("+","")}
|
285
|
+
@downnest_object = HotGlue.construct_downnest_object(@downnest)
|
265
286
|
end
|
266
287
|
|
267
|
-
|
268
288
|
if @god
|
269
289
|
@auth = nil
|
270
290
|
end
|
@@ -364,7 +384,7 @@ module HotGlue
|
|
364
384
|
|
365
385
|
builder = HotGlue::Layout::Builder.new({
|
366
386
|
include_setting: options['include'],
|
367
|
-
|
387
|
+
downnest_object: @downnest_object,
|
368
388
|
buttons_width: buttons_width,
|
369
389
|
columns: @columns,
|
370
390
|
smart_layout: @smart_layout
|
@@ -372,6 +392,7 @@ module HotGlue
|
|
372
392
|
@layout_object = builder.construct
|
373
393
|
|
374
394
|
@menu_file_exists = true if @nested_args.none? && File.exists?("#{Rails.root}/app/views/#{namespace_with_trailing_dash}_menu.#{@markup}")
|
395
|
+
|
375
396
|
end
|
376
397
|
|
377
398
|
def identify_object_owner
|
@@ -379,6 +400,7 @@ module HotGlue
|
|
379
400
|
|
380
401
|
if !@object_owner_sym.empty?
|
381
402
|
auth_assoc_field = auth_assoc + "_id" unless @god
|
403
|
+
|
382
404
|
assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
|
383
405
|
|
384
406
|
if assoc
|
@@ -422,6 +444,7 @@ module HotGlue
|
|
422
444
|
@columns = @the_object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) }
|
423
445
|
end
|
424
446
|
|
447
|
+
@associations = []
|
425
448
|
@columns.each do |col|
|
426
449
|
if col.to_s.starts_with?("_")
|
427
450
|
@show_only << col
|
@@ -431,11 +454,10 @@ module HotGlue
|
|
431
454
|
if col.to_s.ends_with?("_id")
|
432
455
|
# guess the association name label
|
433
456
|
assoc_name = col.to_s.gsub("_id","")
|
434
|
-
assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
|
435
457
|
|
436
458
|
|
437
459
|
begin
|
438
|
-
eval(
|
460
|
+
assoc_model = eval("#{singular_class}.reflect_on_association(:#{assoc_name}).active_record")
|
439
461
|
rescue NameError => e
|
440
462
|
exit_message = "*** Oops: The model #{singular_class} is missing an association for :#{assoc_name} or the model #{assoc_name.titlecase} doesn't exist. TODO: Please implement a model for #{assoc_name.titlecase}; your model #{singular_class.titlecase} should belong_to :#{assoc_name}. To make a controller that can read all records, specify with --god."
|
441
463
|
puts exit_message
|
@@ -443,20 +465,21 @@ module HotGlue
|
|
443
465
|
end
|
444
466
|
|
445
467
|
|
446
|
-
if
|
468
|
+
if assoc_model.nil?
|
447
469
|
exit_message = "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
|
448
470
|
puts exit_message
|
449
471
|
raise(HotGlue::Error,exit_message)
|
450
472
|
end
|
451
473
|
|
452
|
-
|
474
|
+
@associations << assoc_name.to_sym
|
475
|
+
assoc_class = eval(assoc_model.name)
|
453
476
|
name_list = [:name, :to_label, :full_name, :display_name, :email]
|
454
477
|
if name_list.collect{ |field|
|
455
478
|
assoc_class.column_names.include?(field.to_s) || assoc_class.instance_methods.include?(field)
|
456
479
|
}.any?
|
457
480
|
# do nothing here
|
458
481
|
else
|
459
|
-
exit_message = "*** Oops: Missing a label for
|
482
|
+
exit_message = "\n*** Oops: Missing a label for `#{assoc_class}`. Can't find any column to use as the display label for the #{assoc_name} association on the #{singular_class} model. TODO: Please implement just one of: \n1) name, \n2) to_label, \n3) full_name, \n4) display_name \n5) email \nYou can implement any of these directly on your`#{assoc_class}` model (can be database fields or model methods) or alias them to field you want to use as your display label. Then RERUN THIS GENERATOR. (Field used will be chosen based on rank here.)"
|
460
483
|
raise(HotGlue::Error,exit_message)
|
461
484
|
end
|
462
485
|
end
|
@@ -512,16 +535,12 @@ module HotGlue
|
|
512
535
|
end
|
513
536
|
|
514
537
|
def list_column_headings
|
515
|
-
if @
|
538
|
+
if @layout == "bootstrap"
|
539
|
+
column_width = @layout_object[:columns][:size_each]
|
540
|
+
col_identifier = "col-md-#{column_width}"
|
541
|
+
elsif @layout == "hotglue"
|
516
542
|
column_width = each_col * @columns.count
|
517
|
-
|
518
|
-
column_width = 0
|
519
|
-
end
|
520
|
-
|
521
|
-
if !@smart_layout
|
522
|
-
col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-1"
|
523
|
-
else
|
524
|
-
col_identifier = @layout == "hotglue" ? "scaffold-cell" : "col-md-2"
|
543
|
+
col_identifier = "scaffold-cell"
|
525
544
|
end
|
526
545
|
|
527
546
|
@template_builder.list_column_headings(
|
@@ -586,6 +605,10 @@ module HotGlue
|
|
586
605
|
@singular
|
587
606
|
end
|
588
607
|
|
608
|
+
def singular_class_name
|
609
|
+
@singular_class
|
610
|
+
end
|
611
|
+
|
589
612
|
def plural_name
|
590
613
|
plural
|
591
614
|
end
|
@@ -900,6 +923,22 @@ module HotGlue
|
|
900
923
|
@each_col ||= each_col
|
901
924
|
end
|
902
925
|
|
926
|
+
def list_label
|
927
|
+
if(eval("#{class_name}.class_variable_defined?(:@@table_label_plural)"))
|
928
|
+
eval("#{class_name}.class_variable_get(:@@table_label_plural)")
|
929
|
+
else
|
930
|
+
plural.gsub("_", " ").upcase
|
931
|
+
end
|
932
|
+
end
|
933
|
+
|
934
|
+
def thing_label
|
935
|
+
if(eval("#{class_name}.class_variable_defined?(:@@table_label_singular)"))
|
936
|
+
eval("#{class_name}.class_variable_get(:@@table_label_singular)")
|
937
|
+
else
|
938
|
+
singular.gsub("_", " ").upcase
|
939
|
+
end
|
940
|
+
end
|
941
|
+
|
903
942
|
def each_col
|
904
943
|
return col_width if @columns.count == 0
|
905
944
|
(col_width/(@columns.count)).to_i
|
@@ -1030,6 +1069,15 @@ module HotGlue
|
|
1030
1069
|
end
|
1031
1070
|
end
|
1032
1071
|
|
1072
|
+
|
1073
|
+
def n_plus_one_includes
|
1074
|
+
if @associations.any?
|
1075
|
+
".includes(" + @associations.map{|x| ":#{x.to_s}"}.join(", ") + ")"
|
1076
|
+
else
|
1077
|
+
""
|
1078
|
+
end
|
1079
|
+
end
|
1080
|
+
|
1033
1081
|
def nested_for_turbo_nested_constructor(top_level = true)
|
1034
1082
|
instance_symbol = "@" if top_level
|
1035
1083
|
instance_symbol = "" if !top_level
|
@@ -1052,7 +1100,6 @@ module HotGlue
|
|
1052
1100
|
end
|
1053
1101
|
end
|
1054
1102
|
|
1055
|
-
|
1056
1103
|
private # thor does something fancy like sending the class all of its own methods during some strange run sequence
|
1057
1104
|
# does not like public methods
|
1058
1105
|
def cc_filename_with_extensions(name, file_format = format)
|
@@ -56,8 +56,8 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
56
56
|
end<% end %>
|
57
57
|
|
58
58
|
def load_all_<%= plural %> <% if !@self_auth %>
|
59
|
-
@<%= plural_name %> = ( <%= object_scope.gsub("@",'') %>.page(params[:page])<%= " if params.include?(:#{ @nested_set.last[:singular]}_id)" if @nested_set[0] && @nested_set[0][:optional] %>) <% if @nested_set[0] && @nested_set[0][:optional] %> || <%= class_name %>.all<% end %> <% else %>
|
60
|
-
@<%= plural_name %> = <%= class_name %>.where(id: <%= auth_object.gsub("@",'') %>.id) # returns iterable even though this <%= singular_name %> is anly allowed access to themselves<% end %>
|
59
|
+
@<%= plural_name %> = ( <%= object_scope.gsub("@",'') %>.page(params[:page])<%= n_plus_one_includes %><%= " if params.include?(:#{ @nested_set.last[:singular]}_id)" if @nested_set[0] && @nested_set[0][:optional] %>) <% if @nested_set[0] && @nested_set[0][:optional] %> || <%= class_name %>.all<% end %> <% else %>
|
60
|
+
@<%= plural_name %> = <%= class_name %>.where(id: <%= auth_object.gsub("@",'') %>.id)<%= n_plus_one_includes %> # returns iterable even though this <%= singular_name %> is anly allowed access to themselves<% end %>
|
61
61
|
end
|
62
62
|
|
63
63
|
def index
|
@@ -1,6 +1,10 @@
|
|
1
1
|
<\%= turbo_frame_tag "<%= plural %>-list" <%= nested_for_turbo_id_list_constructor %> do %>
|
2
2
|
<div class="<%= @container_name %> scaffold-list">
|
3
|
-
<% unless @no_list || @
|
3
|
+
<% unless @no_list || @no_list_heading || (@nested_set.any? && !@nested_set.collect{|x| x[:optional]}.any?) %>
|
4
|
+
<% unless list_label.nil? %><h4>
|
5
|
+
<%= list_label %>
|
6
|
+
</h4><% end %>
|
7
|
+
<% end %>
|
4
8
|
|
5
9
|
<% unless @no_create %><%= '<%= render partial: "' + ((@namespace+"/" if @namespace) || "") + @controller_build_folder + '/new_button", locals: {}' + @nested_set.collect{|arg| ".merge(defined?(#{arg[:singular]}) ? {#{arg[:singular]}: #{arg[:singular]}} : {})"}.join() + ' %\>'.gsub('\\',"") %><br /><% end %>
|
6
10
|
|
@@ -8,17 +12,17 @@
|
|
8
12
|
<% unless @no_list_labels %>
|
9
13
|
<div class="row scaffold-heading-row">
|
10
14
|
<%= list_column_headings %>
|
11
|
-
<% if @
|
12
|
-
|
15
|
+
<% if @downnest_object.any? %>
|
16
|
+
<%# each_downnest_width = @downnest_object.count == 1 ? 40 : (60/@downnest_object.count).floor %>
|
13
17
|
<% downnest_column_style = @layout == "hotglue" ? 'style="flex-basis: ' + each_downnest_width.to_s + '%;' : "" %>
|
14
18
|
|
15
|
-
<% @
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
<% @downnest_object.each do |downnest,i| %>
|
20
|
+
<div class=" scaffold-col-heading<%= " col-sm-#{ @layout_object[:portals][downnest][:size] }" if @layout=="bootstrap" %>" <%= downnest_column_style %>>
|
21
|
+
<strong>
|
22
|
+
<%= downnest.titleize %>
|
23
|
+
</strong>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
22
26
|
<% end %>
|
23
27
|
|
24
28
|
<% button_column_style = @layout == "hotglue" ? 'style="flex-basis: 150px' : "" %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<\%= turbo_frame_tag "<%= singular %>-new" do %>
|
2
2
|
<div>
|
3
|
-
<\%= link_to "New <%=
|
3
|
+
<\%= link_to "New <%= thing_label %>", <%= new_path_name %>, disable_with: "Loading...", class: "new-<%= singular %>-button btn btn-primary pull-right <%= 'btn-sm' if @nested_args.any? %> " %>
|
4
4
|
</div>
|
5
5
|
<\% end %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<\%= turbo_frame_tag "<%= singular %>-new" do %>
|
2
2
|
<h3>
|
3
|
-
New <%=
|
3
|
+
New <%= thing_label %>
|
4
4
|
</h3>
|
5
5
|
<\%= form_with model: <%= singular %>, url: <%= form_path_new_helper %>, method: :post do |f| \%>
|
6
6
|
<\%= render partial: "<%= namespace_with_slash + @controller_build_folder %>/form",
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<% if @downnest_children.any? %>
|
4
4
|
<% each_downnest_width = @downnest_children.count == 1 ? 33 : (53/@downnest_children.count).floor %>
|
5
5
|
|
6
|
-
<% @
|
6
|
+
<% @downnest_object.each do |downnest, size| %>
|
7
7
|
|
8
8
|
<% downnest_object = eval("#{singular_class}.reflect_on_association(:#{downnest})") %>
|
9
9
|
<% if downnest_object.nil?; raise "no relationship for downnested portal `#{downnest}` found on `#{singular_class}`; please check relationship for has_many :#{downnest}"; end; %>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
<\% end %>
|
10
10
|
|
11
11
|
<h2>Editing <\%= @<%= @singular %>.<%= display_class %> %></h2>
|
12
|
-
<\%= form_with model: <%= "@" + singular%>, url: <%= form_path_edit_helper %> do |f| %>
|
12
|
+
<\%= form_with model: <%= "@" + singular %>, url: <%= form_path_edit_helper %> do |f| %>
|
13
13
|
<\%= render partial: "form", locals: {:<%= singular %> => <%= "@" + singular%>, f: f}<%= @nested_set.collect{|arg| ".merge(@#{arg[:singular]} ? {#{arg[:singular]}: @#{arg[:singular]}} : {})" }.join %> \%>
|
14
14
|
<\% end %>
|
15
15
|
|
data/lib/hotglue/version.rb
CHANGED
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.4.
|
4
|
+
version: 0.4.9
|
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: 2022-02-
|
11
|
+
date: 2022-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -125,7 +125,7 @@ files:
|
|
125
125
|
- lib/hot-glue.rb
|
126
126
|
- lib/hotglue/engine.rb
|
127
127
|
- lib/hotglue/version.rb
|
128
|
-
homepage: https://
|
128
|
+
homepage: https://heliosdev.shop/p/hot-glue?utm_source=rubygems.org&utm_campaign=rubygems_link
|
129
129
|
licenses:
|
130
130
|
- Commercial with free option
|
131
131
|
metadata:
|
@@ -149,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
149
|
- !ruby/object:Gem::Version
|
150
150
|
version: '0'
|
151
151
|
requirements: []
|
152
|
-
rubygems_version: 3.1.
|
152
|
+
rubygems_version: 3.1.6
|
153
153
|
signing_key:
|
154
154
|
specification_version: 4
|
155
155
|
summary: A gem to build Tubro Rails scaffolding.
|