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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: afd7653fa703e1bf60d018a359d175c3f99db44446e727c8e6efcea7076ed856
4
- data.tar.gz: 1796ccdc104e936c5416ef8068b1b148d4038f071822f1d62c24d7c0be97f658
3
+ metadata.gz: a742ee0c02993ed08614aafae1af82e86528f002b69a7213c8cd731518b14df3
4
+ data.tar.gz: 6bd0941019c42f2ce0eee5d94447098b748a0475726efd53554c1f62f3051f2f
5
5
  SHA512:
6
- metadata.gz: 5899771864cb198681bec532523d375319885cc65a48ffdc3b783af471fd37cc80c94a3e894cd8374829eef066e2a42fe9d9e6af323561de2198ea562ea8d5fe
7
- data.tar.gz: c86ad53fce047f3ce3e029dcf880cbed981d94f79ff1838a6a87288e141b2a33ac72dca01dbc7760937c7cf463da57d2fb56a0aeba3eb009b1781296019aba33
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-license?utm_source=github.com&utm_campaign=github_hot_glue_repo_funding_link",
2
- "https://jfb.teachable.com/p/hot-glue-in-depth-tutorial?utm_source=github.com&utm_campaign=github_hot_glue_repo_funding_link"]
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hot-glue (0.4.8)
4
+ hot-glue (0.4.8.1)
5
5
  ffaker (~> 2.16)
6
6
  kaminari (~> 1.2)
7
7
  rails (> 5.1)
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
- # Hot Glue Tutorial 
31
- ## [GET THE COURSE TODAY (includes Hot Glue License)](https://jfbcodes.com/courses/hot-glue-in-depth-tutorial/?utm_source=github.com&utm_campaign=github_hot_glue_readme_page) **only $60 USD!**
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. For the quick step-by-step to help you confirm
66
- 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
+ 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. It will install a config file that will save two preferences: layout (hotglue or bootstrap) and markup (erb or haml or slim).
100
+ Here you will set up and install Hot Glue for the first time.
96
101
 
97
- Once you run the installer, the installer will save what you set it to in `config/hot_glue.yml`. Newly generated scaffolds will use these two settings, but you can modify them just by modifying the config file (you don't need to re-run the installer)
102
+ It will install a config file that will save two preferences: layout (`hotglue` or `bootstrap`)
98
103
 
99
- If you do NOT specify `--layout=bootstrap`, then `hotglue` will be assumed. When constructing scaffold with bootstrap layout (at this time Hot Glue peeks into config/hot_glue.yml to see what you've set there), your views come out with divs that have classes like .container-fluid, .row, and .col. You'll need to install Bootstrap separately, any way you like, but jQuery is not required as Hot Glue does not rely on jQuery-dependant Bootstrap features.
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, I am only supporting & building against ERB. HAML and SLIM are not currently supported.
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 above.
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 Bootstraps 12-column grid.
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
- 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:
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. (note that in the form the labels are rendered again anyway)
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-06
855
-
856
- ![Screen Shot 2022-02-06 at 10 26 36 PM](https://user-images.githubusercontent.com/59002/152719855-fdd3da6d-8348-44b9-8753-b0e73eee8065.png)
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
- :downnest_children,
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
- @downnest_children = params[:downnest_children]
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
- downnest_children.each do |child|
36
- layout_object[:portals][child] = {size: 4}
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 = downnest_children.size
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
- @downnest_children_width = []
51
- @downnest_children.each_with_index{ |child, i| @downnest_children_width[i] = 4}
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
- display_column = HotGlue.derrive_reference_name(assoc.class_name)
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(assoc.class_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 = @singular.titleize.gsub(" ", "")
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
- downnest_children: @downnest_children,
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(assoc.class_name)
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 assoc.nil?
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
- assoc_class = eval(assoc.class_name)
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 #{assoc.class_name.upcase}. Can't find any column to use as the display label for the #{assoc.name.to_s} association on the #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, or 5) email directly on your #{assoc.class_name.upcase} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
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 @nested_args.any?
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
- else
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 || @nested_args.any? %><h4><%= plural.gsub("_", " ").upcase %></h4><% end %>
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 @downnest_children.any? %>
12
- <% each_downnest_width = @downnest_children.count == 1 ? 40 : (60/@downnest_children.count).floor %>
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
- <% @downnest_children.each_with_index do |downnest,i| %>
16
- <div class=" scaffold-col-heading<%= " col-sm-#{ @layout_object[:portals][downnest][:size] }" if @layout=="bootstrap" %>" <%= downnest_column_style %>>
17
- <strong>
18
- <%= downnest.titleize %>
19
- </strong>
20
- </div>
21
- <% end %>
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 <%= singular.titlecase %>", <%= new_path_name %>, disable_with: "Loading...", class: "new-<%= singular %>-button btn btn-primary pull-right <%= 'btn-sm' if @nested_args.any? %> " %>
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 <%= singular.titlecase %>
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
- <% @downnest_children.each_with_index do |downnest,i| %>
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
 
@@ -1,5 +1,5 @@
1
1
  module HotGlue
2
2
  class Version
3
- CURRENT = '0.4.8.1'
3
+ CURRENT = '0.4.9'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hot-glue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.8.1
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-09 00:00:00.000000000 Z
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://jfbcodes.com/p/hot-glue-in-depth-tutorial?utm_source=rubygems.org&utm_campaign=rubygems_link
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.4
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.