hot-glue 0.5.7 → 0.5.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -20,7 +20,7 @@ Hot Glue generates functionality that is quick and dirty. It lets you be crafty.
20
20
  * Automatically reads your models (make them, add relationships, **and** migrate your database before building your scaffolding!)
21
21
  * Excellent for CREATE-READ-UPDATE-DELETE (CRUD), lists with pagination
22
22
  * Great for prototyping, but you should learn Rails fundamentals first.
23
- * 'Packaged' with Devise, Kaminari, Rspec, FontAwesome (optional)
23
+ * 'Packaged' with Devise, Kaminari, Rspec
24
24
  * Create system specs automatically along with the generated code.
25
25
  * Nest your routes model-by-model for built-in poor man's authentication.
26
26
  * Throw the scaffolding away when your app is ready to graduate to its next phase.
@@ -38,10 +38,10 @@ Other than the opinionated differences and additional features, Hot Glue produce
38
38
 
39
39
  # Get Hot Glue
40
40
 
41
- ## [GET THE COURSE TODAY](https://jfbcodes.com/courses/hot-glue-in-depth-tutorial/?utm_source=github.com&utm_campaign=github_hot_glue_readme_page) **only $60 USD!**
41
+ ## [GET THE COURSE TODAY](https://school.jasonfleetwoodboldt.com/8188/?utm_source=github.com&utm_campaign=github_hot_glue_readme_page) **only $60 USD!**
42
42
 
43
43
 
44
- [![Hot Glue Course](https://user-images.githubusercontent.com/59002/189544503-6edbcd40-1728-4b13-ac9a-c7772ccb8284.jpg)](https://jfbcodes.com/courses/hot-glue-in-depth-tutorial/?utm_source=github.com&utm_campaign=github_hot_glue_readme_page)
44
+ [![Hot Glue Course](https://user-images.githubusercontent.com/59002/189544503-6edbcd40-1728-4b13-ac9a-c7772ccb8284.jpg)](https://school.jasonfleetwoodboldt.com/8188?utm_source=github.com&utm_campaign=github_hot_glue_readme_page)
45
45
 
46
46
  ---
47
47
  ---
@@ -62,106 +62,59 @@ Instantly get a simple CRUD interface
62
62
 
63
63
  _If you are on Rails 6, see [LEGACY SETUP FOR RAILS 6](https://github.com/jasonfb/hot-glue/README2.md) and complete those steps FIRST._
64
64
 
65
+ ## The Super-Quick Setup
66
+
67
+ https://jasonfleetwoodboldt.com/courses/stepping-up-rails/rails-quick-scripts/
68
+
69
+ Copy & paste the whole code block from each section into your terminal. (Pick only ONE option for each section.)
70
+
71
+
72
+ From section #1 (`rails new`), choose either (1) ImportMap Rails, (2) JSBundling, or (3) Shakapacker.
73
+
74
+ For Hot Glue, you will need:
75
+
76
+ Section #1 is to create a new Rails app. (Or you can do that yourself.)
77
+
78
+ Section #2 is to setup Rspec, FactoryBot, and Faker.
79
+
80
+ Section #4 is optional but highly recommended.
81
+
82
+ Section #5 is where you will pick a CSS Framework (Bootstrap, Tailwind, or none)
83
+
84
+ Section #6 is for two support gems (Kaminari) for Hot Glue
65
85
 
66
- ## 1. Rails 7 New App
86
+ Section #7 is for Hot Glue itself
67
87
 
68
- To run Turbo (which Hot Glue requires), you must either (1) be running an ImportMap-Rails app, or (2) be running a Node-compiled app using any of JSBundling, Shakapacker, or its alternatives.
88
+ You will also need section #8 to setup Devise if you want authentication.
69
89
 
70
- For reference, see https://jasonfleetwoodboldt.com/courses/stepping-up-rails/rails-7-do-i-need-importmap-rails/
71
90
 
72
- Once you create the new Rails app, you can skip to the 'Super-Quick Setup' below.
91
+ ## Step-By-Step Setup
92
+
93
+ ### 1. RAILS NEW
94
+ To understand the options for `rails new`, see [this post](https://jasonfleetwoodboldt.com/courses/rails-7-crash-course/rails-7-bootstrap/)
95
+
96
+ It is important that you know what kind of app you are creating (Importmap, JSBundling, or Shakapacker) because there are specific differences in how you will work with them. (Hot Glue is compatible with all 3 paradigms, but if you don't take the time to understand the setup, you will be confused as to why things aren't working.)
97
+
98
+ To run Turbo (which Hot Glue requires), you must either (1) be running an ImportMap-Rails app, or (2) be running a Node-compiled app using any of JSBundling, Shakapacker, or its alternatives.
73
99
 
74
100
  (1) To use ImportMap Rails, start with
75
- `rails new`
101
+ `rails new MyGreatApp`
76
102
 
77
103
  (For full instructions to install Bootstrap with Importmap, check out [these instructions](https://jasonfleetwoodboldt.com/courses/stepping-up-rails/importmap-rails-with-bootstrap-sprockets-stimulus-and-turbo-long-tutorial/))
78
104
 
79
105
  (2) To use JSBundling, start with
80
- `rails new --javascript=jsbundling`
106
+ `rails new MyGreatApp --javascript=esbuild`
81
107
 
82
108
 
83
109
  **If using JSBundling, make sure to use the new `./bin/dev` to start your server instead of the old `rails server` or else your Turbo interactions will not work correctly.**
84
110
  (If you want Bootstrap for a JSBundling app, install it following [these instructions](https://jasonfleetwoodboldt.com/courses/stepping-up-rails/rails-7-up-running-with-jsbundling-esbuild-stimulus-turbo-bootstrap-circleci/))
85
111
 
86
- (3) To use Shakapacker, start with `rails new --skip-javascript` and [see this post](https://jasonfleetwoodboldt.com/courses/react-heart-rails/rails-7-shakapacker-and-reactonrails-quick-setup-part-1/)
112
+ (3) To use Shakapacker, start with `rails new MyGreatApp --skip-javascript` and [see this post](https://jasonfleetwoodboldt.com/courses/react-heart-rails/rails-7-shakapacker-and-reactonrails-quick-setup-part-1/)
87
113
 
88
114
  (For the old method of installing Bootstrap [see this post](https://jasonfleetwoodboldt.com/courses/stepping-up-rails/rails-7-bootstrap/))
89
115
 
90
116
  (Remember, for Rails 6 you must go through the [LEGACY SETUP FOR RAILS 6](https://github.com/jasonfb/hot-glue/blob/main/README2.md) before continuing.)
91
117
 
92
- If you doing the 'Super-Quick Setup', you can skip the additional blog posts linked above because the steps in them are covered in the shell script(s) below.
93
-
94
- ## The Super-Quick Setup
95
-
96
- Be sure to do `git add .` and `git commit -m "initial commit"` after creating your new Rails 7 app.
97
-
98
- ```
99
- bundle add rspec-rails factory_bot_rails ffaker --group "development, test" &&
100
- git add . && git commit -m "adds gems" &&
101
- rails generate rspec:install &&
102
- git add . && git commit -m "adds rspec" &&
103
- rm app/assets/stylesheets/application.css &&
104
- echo "" > app/assets/stylesheets/application.scss &&
105
- sed -i '' -e 's/# gem "sassc-rails"//g' Gemfile && sed -i '' -e 's/# Use Sass to process CSS//g' Gemfile &&
106
- bundle install && bundle add sassc-rails && git add . && git commit -m "adds sassc-rails" &&
107
- rm -rf test/ && git add . && git commit -m "removes minitest" &&
108
- bundle add hot-glue && git add . && git commit -m "adds hot-glue" &&
109
- rails generate hot_glue:install --layout=bootstrap &&
110
- git add . && git commit -m "hot glue setup" &&
111
- bundle add bootstrap &&
112
- echo "\n@import 'bootstrap';\n" >> app/assets/stylesheets/application.scss
113
- sed -i '' -e 's/# Rails.application.config.assets.precompile += %w( admin.js admin.css )/Rails.application.config.assets.precompile += %w( application.scss )/g' config/initializers/assets.rb &&
114
- sed -i '' -e 's/Rails.application.configure do/Rails.application.configure do\n config.sass.inline_source_maps = true/g' config/environments/development.rb
115
- git add . && git commit -m "bootstrap install" &&
116
- bundle add font_awesome5_rails &&
117
- echo "\n@import 'font_awesome5_webfont';\n" >> app/assets/stylesheets/application.scss
118
- git add . && git commit -m "adds fontawesome" &&
119
- bundle add kaminari &&
120
- rails generate kaminari:views bootstrap4 &&
121
- git add . && git commit -m "adding kaminari and views" &&
122
- bundle add devise && bundle install &&
123
- git add . && git commit -m "adding devise gem" &&
124
- rails generate devise:install &&
125
- rails g devise:views &&
126
- sed -i '' -e 's/Rails.application.configure do/Rails.application.configure do\n config.action_mailer.default_url_options = { host: "localhost", port: 3000 }/g' config/environments/development.rb &&
127
- sed -i '' -e 's/# root "articles#index"//g' config/routes.rb &&
128
- sed -i '' -e 's/Rails.application.routes.draw do/Rails.application.routes.draw do\n root to: "welcome#index"/g' config/routes.rb &&
129
- git add . && git commit -m 'devise view fixes' &&
130
- rails generate controller Welcome &&
131
- sed -i '' -e 's/class WelcomeController < ApplicationController/class WelcomeController < ApplicationController\n def index\n\n end/g' app/controllers/welcome_controller.rb &&
132
- echo "hello world" > app/views/welcome/index.erb &&
133
- git add . && git commit -m "generates Welcome controller" &&
134
- sed -i '' -e 's/html: { method: :post }/html: { method: :post, 'data-turbo': false}/g' app/views/devise/confirmations/new.html.erb &&
135
- sed -i '' -e 's/ url: session_path(resource_name))/ url: session_path(resource_name), html: {"data-turbo": false})/g' app/views/devise/sessions/new.html.erb &&
136
- sed -i '' -e 's/ url: registration_path(resource_name))/ url: registration_path(resource_name), html: {"data-turbo": false})/g' app/views/devise/registrations/new.html.erb &&
137
- sed -i '' -e 's/, html: { method: :post })/, html: { method: :post, "data-turbo": false })/g' app/views/devise/passwords/new.html.erb &&
138
- git add . && git commit -m 'devise view fixes' &&
139
- rails generate model User name:string &&
140
- rails generate devise User && git add . && git commit -m "adds Users model with devise" &&
141
- && ./bin/setup && rails db:migrate &&
142
- git add . && git commit -m "schema file"
143
- ```
144
-
145
-
146
- For Importmap apps:
147
- ```
148
- ./bin/importmap pin "bootstrap@5.1.3" &&
149
- ./bin/importmap pin "@popperjs/core@2.11.2" &&
150
- git add . && git commit -m "pinning boostrap and popper js for bootstrap"
151
- ```
152
-
153
- For JSBundling & Shakapacker:
154
- ```
155
- echo "\ncss: yarn build:css --watch\n" >> Procfile.dev &&
156
- yarn add @popperjs/core bootstrap bootstrap-icons sass &&
157
- sed -i '' -e 's/\/\/= link_directory ..\/stylesheets .css//g' app/assets/config/manifest.js &&
158
- sed -i '' -e 's/ "scripts": {/ "scripts": {\n "build:css": "sass .\/app\/assets\/stylesheets\/application.scss:.\/app\/assets\/builds\/application.css --no-source-map --load-path=node_modules",/g' package.json &&
159
- yarn install &&
160
- git add . && git commit -m "adding bootstrap packages"
161
- ```
162
-
163
-
164
- ## Step-By-Step Setup
165
118
 
166
119
  ### 2. ADD RSPEC, FACTORY-BOT, AND FFAKER
167
120
 
@@ -180,9 +133,16 @@ end
180
133
 
181
134
  - Because you are not using Minitest, you can delete the `test/` folder at the root of your repository.
182
135
 
136
+ ### 3. CSS Bundling Rails (optional)
137
+
138
+ ```
139
+ bundle add cssbundling-rails
140
+ ./bin/rails css:install:bootstrap
141
+ ```
183
142
 
184
143
 
185
- ### 3. HOTGLUE INSTALLER
144
+
145
+ ### 4. HOTGLUE INSTALLER
186
146
  Add `gem 'hot-glue'` to your Gemfile & `bundle install`
187
147
 
188
148
  During in installation, you MUST supply a `--layout` flag.
@@ -212,29 +172,20 @@ default is `erb`. IMPORTANT: As of right now, HAML and SLIM are not currently su
212
172
 
213
173
 
214
174
  #### example installing ERB using Bootstrap layout:
215
- `rails generate hot_glue:install --markup=erb --layout=bootstrap`
175
+ `./bin/rails generate hot_glue:install --markup=erb --layout=bootstrap`
216
176
 
217
177
  #### Example installing using Hot Glue layout and the 'like_mountain_view' (Gmail-inspired) theme:
218
178
  `rails generate hot_glue:install --markup=erb --layout=hotglue --theme=like_mountain_view`
219
179
 
220
180
  The Hot Glue installer did several things for you in this step. Examine the git diffs or see 'Hot Glue Installer Notes' below.
221
181
 
222
-
223
- ### 4. Font-awesome (optional)
224
-
225
- I recommend
226
- https://github.com/tomkra/font_awesome5_rails
227
- or
228
- https://github.com/FortAwesome/font-awesome-sass
229
-
230
-
231
- ### 5. Devise
182
+ ### 4. Devise
232
183
  (If you are on Rails 6, you must do ALL of the steps in the Legacy Setup steps. Be sure not to skip **Legacy Step #5** below)
233
184
  https://github.com/jasonfb/hot-glue/blob/main/README2.md
234
185
 
235
186
  You MUST run the installer FIRST or else you will put your app into a non-workable state:
236
187
  ```
237
- rails generate devise:install
188
+ ./bin/rails generate devise:install
238
189
  ```
239
190
 
240
191
  IMPORTANT: Follow the instructions the Devise installer gives you, *Except Step 3*, you can skip this step:
@@ -249,7 +200,7 @@ IMPORTANT: Follow the instructions the Devise installer gives you, *Except Step
249
200
 
250
201
  Be sure to create primary auth model with:
251
202
 
252
- `rails generate devise User name:string`
203
+ `./bin/rails generate devise User name:string`
253
204
 
254
205
  Remember, you don't need to tell Devise that your User has an email, an encrypted password, a reset token, and a 'remember me' flag to let the user stay logged in.
255
206
 
@@ -257,21 +208,7 @@ Those features come by default with Devise, and you'll find the fields for them
257
208
 
258
209
  In this example above, you are creating all of those fields along with a simple 'name' (string) field for your User table.
259
210
 
260
-
261
- !!! Warning: as of 2022-09-19, Devise is still not compatible out-of-the-box with Rails Turbo.
262
-
263
- To fix this, run
264
- `rails generate devise:views`
265
-
266
-
267
- Then manually add `html: {'data-turbo' => "false"}` to all of the Devise forms. You will need to edit the following forms:
268
- `views/devise/sessions/new.html.erb`, `views/devise/registrations/edit.html.erb`,
269
- `views/devise/registrations/new.html.erb`, and
270
-
271
- Add the data-turbo false option in the html key of the form, shown in bold here:
272
-
273
- form_for(resource, as: resource_name, **html: {'data-turbo' => "false"},** url: session_path(resource_name) ) do |f|
274
-
211
+ Devise 4.9.0 is now fully compatible with Rails 7.
275
212
 
276
213
  #### Hot Glue Installer Notes
277
214
 
@@ -367,7 +304,7 @@ Alternatively, you can define your own driver like so:
367
304
  TitleCase class name of the thing you want to build a scaffoling for.
368
305
 
369
306
  ```
370
- rails generate hot_glue:scaffold Thing
307
+ ./bin/rails generate hot_glue:scaffold Thing
371
308
  ```
372
309
 
373
310
  (note: Your `Thing` object must `belong_to` an authenticated `User` or alternatively you must create a Gd controller, see below.)
@@ -381,7 +318,7 @@ All options begin with two dashes (`--`) and a followed by an `=` and a value
381
318
  pass `--namespace=` as an option to denote a namespace to apply to the Rails path helpers
382
319
 
383
320
 
384
- `rails generate hot_glue:scaffold Thing --namespace=dashboard`
321
+ `./bin/rails generate hot_glue:scaffold Thing --namespace=dashboard`
385
322
 
386
323
  This produces several views at `app/views/dashboard/things/` and a controller at`app/controllers/dashboard/things_controller.rb`
387
324
 
@@ -413,9 +350,9 @@ resources :invoices do
413
350
  end
414
351
  ```
415
352
 
416
- `rails generate hot_glue:scaffold Invoice`
353
+ `./bin/rails generate hot_glue:scaffold Invoice`
417
354
 
418
- `rails generate hot_glue:scaffold Line --nested=invoice`
355
+ `./bin/rails generate hot_glue:scaffold Line --nested=invoice`
419
356
 
420
357
 
421
358
  Remember, nested should match how the hierarchy of nesting is in your `routes.rb` file. (Which Hot Glue does not create or edit for you.)
@@ -437,11 +374,11 @@ end
437
374
 
438
375
  _For multi-level nesting use slashes to separate your levels of nesting._
439
376
 
440
- `rails generate hot_glue:scaffold Invoice`
377
+ `./bin/rails generate hot_glue:scaffold Invoice`
441
378
 
442
- `rails generate hot_glue:scaffold Line --nested=invoice`
379
+ `./bin/rails generate hot_glue:scaffold Line --nested=invoice`
443
380
 
444
- `rails generate hot_glue:scaffold Charge --nested=invoice/line`
381
+ `./bin/rails generate hot_glue:scaffold Charge --nested=invoice/line`
445
382
 
446
383
 
447
384
 
@@ -483,8 +420,8 @@ end
483
420
  Even though we have two routes pointed to **invoices**, both will go to the same controller (`app/controllers/admin/invoices_controller.rb`)
484
421
 
485
422
  ```
486
- rails generate hot_glue:scaffold User --namespace=admin --gd
487
- rails generate hot_glue:scaffold Invoice --namespace=admin --gd --nested=~users
423
+ ./bin/rails generate hot_glue:scaffold User --namespace=admin --gd
424
+ ./bin/rails generate hot_glue:scaffold Invoice --namespace=admin --gd --nested=~users
488
425
  ```
489
426
  Notice for the Invoice build, the parent user is *optionalized* (not 'optional'-- optionalized: to be made so it can be made optional).
490
427
 
@@ -506,7 +443,7 @@ If you use Devise, you probably already have a `current_user` method available i
506
443
 
507
444
  If you use a different object other than "User" for authentication, override using the `auth` option.
508
445
 
509
- `rails generate hot_glue:scaffold Thing --auth=current_account`
446
+ `./bin/rails generate hot_glue:scaffold Thing --auth=current_account`
510
447
 
511
448
  You will note that in this example it is presumed that the Account object will have an association for `things`
512
449
 
@@ -545,7 +482,7 @@ As well, the `after_sign_in_path_for(user)` here is a hook for Devise also that
545
482
  The default (do not pass `auth_identifier=`) will match the `auth` (So if you use 'account' as the auth, `authenticate_account!` will get invoked from your generated controller; the default is always 'user', so you can leave both auth and auth_identifier off if you want 'user')
546
483
 
547
484
 
548
- `rails generate hot_glue:scaffold Thing --auth=current_account --auth_identifier=login`
485
+ `./bin/rails generate hot_glue:scaffold Thing --auth=current_account --auth_identifier=login`
549
486
 
550
487
 
551
488
  In this example, the controller produced with:
@@ -559,7 +496,7 @@ However, the object graph anchors would continue to start from current_account.
559
496
 
560
497
  Use empty string to **turn this method off**:
561
498
 
562
- `rails generate hot_glue:scaffold Thing --auth=current_account --auth_identifier=''`
499
+ `./bin/rails generate hot_glue:scaffold Thing --auth=current_account --auth_identifier=''`
563
500
 
564
501
  In this case a controller would be generated that would have NO before_action to authenticate the account, but it would still treat the current_account as the auth root for the purpose of loading the objects.
565
502
 
@@ -580,7 +517,7 @@ The short form looks like this. It presumes there is a 'pets' association from `
580
517
 
581
518
  (The long form equivalent of this would be `--hawk=pet_id{current_user.pets}`)
582
519
 
583
- This is covered in [Example #3 in the Hot Glue Tutorial](https://jfb.teachable.com/courses/hot-glue-in-depth-tutorial/lectures/38584014)
520
+ This is covered in [Example #3 in the Hot Glue Tutorial](https://school.jasonfleetwoodboldt.com/8188)
584
521
 
585
522
  To hawk to a scope that is not the currently authenticated user, use the long form with `{...}`
586
523
  to specify the scope. Be sure to note to add the association name itself, like `users`:
@@ -590,7 +527,7 @@ to specify the scope. Be sure to note to add the association name itself, like `
590
527
  This would hawk the Appointment's `user_id` key to any users who are within the scope of the
591
528
  current_user's has_many association (so, for any other "my" family, would be `current_user.family.users`).
592
529
 
593
- This is covered in [Example #4 in the Hot Glue Tutorial](https://jfb.teachable.com/courses/hot-glue-in-depth-tutorial/lectures/38787505)
530
+ This is covered in [Example #4 in the Hot Glue Tutorial](https://school.jasonfleetwoodboldt.com/8188)
594
531
 
595
532
 
596
533
  ### `--plural=`
@@ -598,11 +535,11 @@ This is covered in [Example #4 in the Hot Glue Tutorial](https://jfb.teachable.c
598
535
  You don't need this if the pluralized version is just + "s" of the singular version.
599
536
  Only use for non-standard plurlizations, and be sure to pass it as TitleCase (as if you pluralized the model name which is non-standard for Rails)
600
537
 
601
- An better alternative is to define the non-standard plurlizations globally in your app.
538
+ An better alternative is to define the non-standard plurlizations globally in your app, which Hot Glue will respect.
602
539
 
603
540
  Make a file at `config/initializers/inflections.rb`
604
-
605
- # Add new inflection rules using the following format
541
+
542
+ Add new inflection rules using the following format:
606
543
  ```
607
544
  ActiveSupport::Inflector.inflections do |inflect|
608
545
  inflect.irregular 'clothing', 'clothes'
@@ -621,7 +558,7 @@ By default, all fields are included unless they are on the default exclude list.
621
558
  If you specify any exclude list, those excluded **and** the default exclude list will be excluded. (If you need any of the fields on the default exclude list, you must use `--include` instead.)
622
559
 
623
560
 
624
- `rails generate hot_glue:scaffold Account --exclude=password`
561
+ `./bin/rails generate hot_glue:scaffold Account --exclude=password`
625
562
 
626
563
 
627
564
  ### `--include=`
@@ -629,7 +566,7 @@ Separate field names by COMMA
629
566
 
630
567
  If you specify an include list, it will be treated as a whitelist: no fields will be included unless specified on the include list.
631
568
 
632
- `rails generate hot_glue:scaffold Account --include=first_name,last_name,company_name,created_at,kyc_verified_at`
569
+ `./bin/rails generate hot_glue:scaffold Account --include=first_name,last_name,company_name,created_at,kyc_verified_at`
633
570
 
634
571
  You may not specify both include and exclude.
635
572
 
@@ -774,7 +711,7 @@ The bang (`!`) methods can respond in one of four ways:
774
711
 
775
712
  This means you can be a somewhat lazy about your bang methods, but keep in mind the truth operator compares boolean true NOT any object is truth. So your return object must either be actually true (boolean), or an object that is string or string-like (responds to .to_s). Want to just say it didn’t work? Return false. Want to just say it was OK? Return true. Want to say it was successful but provide a more detailed response? Return a string.
776
713
 
777
- Finally, you can raise an ActiveRecord error which will also get passed to the user, but in the flash alert area
714
+ Finally, you can raise an ActiveRecord error which will also get passed to the user in the flash alert area.
778
715
 
779
716
  For more information see Example 5 in the Tutorial
780
717
 
@@ -791,6 +728,9 @@ Can now be created with more space (wider) by adding a `+` to the end of the dow
791
728
 
792
729
  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
793
730
 
731
+ ### `--stacked-downnesting`
732
+
733
+ 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.
794
734
 
795
735
 
796
736
  ## FLAGS (Options with no values)
@@ -853,7 +793,7 @@ To do this, use flag `--display-list-after-update`. The update will behave like
853
793
 
854
794
  ### `--with-turbo-streams`
855
795
 
856
- 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` (wether 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.
796
+ 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.
857
797
 
858
798
  **_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.
859
799
 
@@ -868,6 +808,7 @@ please note that *creating* and *deleting* do not yet have a full & complete imp
868
808
 
869
809
  ### `--alt-foreign-key-lookup` (Foreign Key Lookups)
870
810
 
811
+ Example #1
871
812
  `--alt-foreign-key-lookup=user_id{email}`
872
813
 
873
814
  Let's assume a `Company` `has_many :company_users` and also a `Company` `has_many :users, through: :company_users`
@@ -880,6 +821,19 @@ Let's say instead you don't want to expose the full list of all users to this co
880
821
 
881
822
  Instead of a drop-down, the interface will present an input box for the user to supply an *search by* email.
882
823
 
824
+ Example #2
825
+ ```
826
+ --alt-foreign-key-lookup='agent_id{email+}'
827
+ ```
828
+
829
+ First, assume the current able has a `belongs_to` association for `agent_id` to a foreign model, `Agent`
830
+
831
+ Here, we would build a scaffold that would treat the foreign key `agent_id` as an alt lookup, allowing the user to search for foreign records by email (the agent's email).
832
+
833
+ The `+` symbol indicates to automatically make a new `agent` record (without it, the agent_id will be set to nil if there is no associated agent record found -- this may cause the update to fail, unless `optional: true` is on the belongs_to association.)
834
+
835
+
836
+
883
837
  ** Note: Current implementation does not work in conjunction with hawked associations to protect against users from accessing associated records not within scope.**
884
838
  TODO: make it work with hawked associations to protect against users from accessing associated records not within scope
885
839
 
@@ -920,8 +874,6 @@ Omits list LABEL itself above the list. (Do not confuse with the list heading wh
920
874
  Note that list labels may be automatically omitted on downnested scaffolds.
921
875
 
922
876
 
923
-
924
-
925
877
  ## Field Labels
926
878
 
927
879
  ### `--form-labels-position` (default: `after`; options are **before**, **after**, and **omit**)
@@ -956,18 +908,178 @@ Omits the heading of column names that appears above the 1st row of data.
956
908
 
957
909
  ## Special Features
958
910
 
911
+ ### `--attachments`
912
+
913
+ #### ActiveStorage Quick Setup
914
+ (For complete docs, refer to https://guides.rubyonrails.org/active_storage_overview.html)
915
+
916
+ `brew install vips`
917
+ (for videos `brew install ffmpeg`)
918
+
919
+ ```
920
+ bundle add image_processing
921
+ ./bin/rails active_storage:install
922
+ ./bin/rails db:migrate
923
+ ```
924
+
925
+ Generate an images model:
926
+
927
+ `./bin/rails generate model Images name:string`
928
+
929
+ add to `app/model/image.rb`, giving it a variant called thumb (Note: Hot Glue will fallback to using a variant called "thumb" if you use the shorthand syntax. If you use the long syntax, you can specify the variant to use for displaying the image)
930
+
931
+ ```
932
+ has_one_attached :avatar do |attachable|
933
+ attachable.variant :thumb, resize_to_limit: [100, 100]
934
+ end
935
+ ```
936
+ Generate a Hot Glue scaffold with the attachment avatar appended to the field list (the shorthand syntax)
937
+
938
+ `./bin/rails generate hot_glue:scaffold Image --include='name:avatar' --gd --attachments='avatar'`
939
+
940
+ (Attachments behave like fields and follow the same layout rules used for fields, except that, unlike fields, when NOT using an --include list, they do not get automatically added. Thus, attachments are opt-in. You do not need to specify an attachment on the attachments list as ALSO being on the include list, but you can for the purpose of using the layout tricks discussed in Specified Grouping Mode to make the attachment appear on the layout where you want it to)
941
+
942
+ #### Caveats:
943
+ • If thumbnails aren't showing up, make sure you have
944
+
945
+ 1) installed vips, and
946
+ 2) used an image that supports ActiveStorage "variable" mechanism. The supported types are png, gif, jpg, pjpeg, tiff, bmp, vnd.adobe.photoshop, vnd.microsoft.icon, webp. see https://stackoverflow.com/a/61971660/3163663
947
+ To debug, make sure the object responds true to the variable? method.
948
+
949
+ If you use the shorthand syntax, Hot Glue looks for a variant "thumb" (what you see in the example above).
950
+
951
+ If it finds one, it will render thumbnails from the attachment variant `thumb`. To specify a variant name other than "thumb", use the first parameter below.
952
+
953
+ 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.
954
+
955
+ #### `--attachments` Long form syntax with 1 parameter
956
+
957
+ **--attachments='_attachment name_{_variant name_}'**
958
+
959
+ What if your variant is called something other than `thumb`
960
+
961
+ Use the long-form syntax specifying a variant name other than `thumb`. For example, `thumbnail`
962
+
963
+ `./bin/rails generate hot_glue:scaffold Image --include='name:avatar' --gd --attachments='avatar{thumbnail}'`
964
+
965
+ The model would look like this:
966
+ ```
967
+ has_one_attached :avatar do |attachable|
968
+ attachable.variant :thumbnail, resize_to_limit: [100, 100]
969
+ end
970
+ ```
971
+
972
+ 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.
973
+
974
+
975
+ #### `--attachments` Long form syntax with 1st and 2nd parameters
976
+
977
+ **--attachments='_attachment name_{_variant name_|_field for saving original filename_}'**
978
+
979
+ Grab the original file name of the uploaded file and stick it into a field called `name`
980
+
981
+ `./bin/rails generate hot_glue:scaffold Image --include='orig_filename:avatar' --gd --attachments='avatar{thumbnail|name} --show-only=name'`
982
+
983
+ Note: You must have a string field called `orig_filename`. It does not need to be visible, but if it is, it should be part of the `--show-only` list. (If it is not part of the show-only list, Hot Glue will overwrite it every time you upload a new file, making it so that any user's change might not stick.)
984
+
985
+ Note that the `orig_filename` is not part of the inputted parameters, it simply gets appended to the model **bypassing the Rails strong parameters mechanism**, which is why it is irrelevant if it is included in the field list and recommended that if you do include it, you make it show-only so as not to allow your users to edit or modify it.
986
+
987
+ 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.
988
+
989
+ #### `--attachments` Long form syntax with 1st, 2nd, and 3rd parameters
990
+
991
+ 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.
992
+
993
+ Simply specify a 3rd parameter of `direct` to enable this attachment to use direct upload.
994
+
995
+ **--attachments='avatar{thumbnail|orig_filename|direct}'**
996
+
997
+ If you leave the 2nd parameter blank when using the 3rd parameter, it will default to NOT saving the original filename:
998
+
999
+ `--attachments='avatar{thumbnail||direct}'`
1000
+
1001
+
1002
+ #### For S3 Setup
1003
+
1004
+
1005
+ ```
1006
+ bundle add aws-sdk-s3
1007
+ ```
1008
+
1009
+
1010
+ in `config/storage.yml`, enable this block and configure with the access key + secret associated with an AWS user that has permissions:
1011
+
1012
+ Also be sure to change `bucket`
1013
+
1014
+ ```
1015
+ # Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
1016
+ amazon:
1017
+ service: S3
1018
+ access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
1019
+ secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
1020
+ region: us-east-1
1021
+ bucket: your_bucket-<%= Rails.env %>
1022
+
1023
+ ```
1024
+
1025
+
1026
+ in development.rb or production.rb (or both), set
1027
+ ```
1028
+ config.active_storage.service = :amazon
1029
+ ```
1030
+
1031
+
1032
+ #### For Direct Upload Support
1033
+ 1.
1034
+ ```
1035
+ yarn add @rails/activestorage
1036
+ ```
1037
+
1038
+ 2. You need a job runner like sidekiq or delayed_job. I recommend sidekiq. Make sure to have it
1039
+
1040
+ - Start sidekiq with `bundle exec sidekiq` while you are testing
1041
+
1042
+ 3. Install ActiveStorage JS using:
1043
+
1044
+ `./bin/rails generate hot_glue:direct_upload_install`
1045
+
1046
+ AND be sure to use the 3rd parameter ('direct') when building a HG scaffold as explained above.
1047
+
1048
+
1049
+ #### For Dropzone support
1050
+ - Dropzone requires direct uploads, so you must have direct uploads enabled for the attachment you want to use dropzone with.
1051
+
1052
+
1053
+ - Direct uploads requires that you have configured your external storage (S3, etc) correctly. See the ActiveStorage guide.
1054
+
1055
+ `yarn add dropzone`
1056
+
1057
+
1058
+ (If you don't already have stimulus-rails, you will also need: `bundle add stimulus-rails` and `./bin/rails stimulus:install`)
1059
+
1060
+ Then run:
1061
+ ```
1062
+ ./bin/rails generate hot_glue:dropzone_install
1063
+ ```
1064
+ This will 1) copy the dropzone_controller.js file into your app and 2) add the dropzone css into your app's application.css or application.bootstrap.css file.
1065
+
1066
+
1067
+
959
1068
 
960
1069
  ### `--factory-creation={ ... }`
961
1070
 
962
1071
  The code you specify inside of `{` and `}` will be used to generate a new object. The factory should instantiate with any arguments (I suggest Ruby keyword arguments) and must provide a method that is the name of the thing.
963
1072
 
1073
+ You may use semi-colons to separate multiple lines of code.
1074
+
964
1075
  For example, a user Factory might be called like so:
965
1076
 
966
- `rails generate hot_glue:scaffold User --factory-creation={factory = UserFactory.new(params: user_params)} --gd`
1077
+ `./bin/rails generate hot_glue:scaffold User --factory-creation={factory = UserFactory.new(params: user_params)} --gd`
967
1078
 
968
1079
  (Note we are relying on the `user_params` method provided by the controller.)
969
1080
 
970
1081
  You must do one of two things:
1082
+
971
1083
  1) In the code you specify, set an instance variable `@user` to be the newly created thing. (Your code should contain something like `@thing = ` to trigger this option.)
972
1084
  2) Make a local variable called `factory` **and** have a method of the name of the object (`user`) on a local variable called `factory` that your code created
973
1085
 
@@ -999,6 +1111,18 @@ end
999
1111
  ```
1000
1112
 
1001
1113
 
1114
+ If you are using factory creation along with with alt lookups, be sure your factory code creates a local variable that follows this name
1115
+
1116
+ **<downcase association name>**_factory.<downcase association name>
1117
+
1118
+ Thus, your factory object must have a method of the same name as the factory being created which returns the thing that got created.
1119
+ (It can do the creation either on instantiation or when calling that method)
1120
+
1121
+ For example, assuming the example from above, we are going to do the lookup ourselves inside of our own `AgentFactory` object.)
1122
+
1123
+ ```
1124
+ agent_factory = AgentFactory.new(find_or_create_by_email: agent_company_params[:__lookup_email])
1125
+ ```
1002
1126
 
1003
1127
 
1004
1128
 
@@ -1008,6 +1132,7 @@ HotGlue will copy a file named base_controller.rb to the same folder where it tr
1008
1132
 
1009
1133
  The created controller will always have this base controller as its subclass. You are encouraged to implement functionality common to the *namespace* (shared between the controllers in the namespace) using this technique.
1010
1134
 
1135
+
1011
1136
  ## Special Table Labels
1012
1137
 
1013
1138
  If your object is very wordy (like MyGreatHook) and you want it to display in the UI as something shorter,
@@ -1041,6 +1166,7 @@ Child portals have the headings omitted automatically (there is a heading identi
1041
1166
  # Note about enums
1042
1167
 
1043
1168
  The Rails 7 enum implementation for Postgres is very slick but has a counter-intuitive facet.
1169
+
1044
1170
  Define your Enums in Postgres as strings:
1045
1171
  (database migration)
1046
1172
  ```
@@ -1064,25 +1190,79 @@ enum status: {
1064
1190
  }
1065
1191
  ```
1066
1192
 
1067
- To set the labels, use another class-level method that is a hash of keys-to-labels using a method named the same name as the enum method but with `_labels`
1193
+ To set the labels, use a class-level method that is a hash of keys-to-labels using a method named the same name as the enum method but with `_labels`
1068
1194
 
1069
1195
  If no `_labels` method exists, Hot Glue will fallback to using the Postgres-defined names.
1070
1196
  ```
1071
1197
  def self.status_labels
1072
1198
  {
1073
- pending: 'Is Pending',
1074
- active: 'Is active',
1075
- archived: 'Is Archived',
1199
+ pending: 'Is currently pending',
1200
+ active: 'Is really active',
1201
+ archived: 'Is done & archived',
1076
1202
  disabled: 'Is Disabled',
1077
1203
  waiting: 'Is Waiting'
1078
1204
  }
1079
1205
  ```
1080
1206
 
1081
- Now, your labels will show up as defined in the `_labels` ("Is Pending", etc) instead of the database-values.
1207
+ Now, your labels will show up on the front-end as defined in the `_labels` ("Is currently pending", etc) instead of the database-values.
1082
1208
 
1083
1209
 
1084
1210
  # VERSION HISTORY
1085
1211
 
1212
+ #### 2023-03-17 - v0.5.9
1213
+ - Attachments! You can use Hot Glue to seamlessly create an image, file, or video attachment. Please see the docs in new flag `--atachments` under the "Special Features" section
1214
+
1215
+ - Watch the demo on attachments here on YouTube: https://youtu.be/yJbjwReCr18
1216
+
1217
+ - Fixes to downnesting
1218
+
1219
+ - `--stacked-downnesting` flag — The Layout Builder now can stack downnesting portals instead of putting them side-by-side. When stacked, there is no limit to how many you can have and the entire stack takes up 4-bootstrap columns.
1220
+
1221
+ - Hot Glue has been moved on Github from my personal organization to a new organization named `hot-glue-for-rails`. The new Github url is: `https://github.com/hot-glue-for-rails/hot-glue`
1222
+
1223
+
1224
+ #### 2023-03-01 - v0.5.8
1225
+
1226
+ • Fixes spec assertions for enums to work with the enum `_label` field (when provided).
1227
+
1228
+ • Fixes `--form-label-position` (before/after) so that a carriage return is placed between the label & field correctly for either choice
1229
+
1230
+ • All spec files are now created in `spec/features/` folder (previously was `spec/system/` with `type: :feature`; they no longer have `type: :feature` as this is not necessary when they are in the `spec/features` folder)
1231
+
1232
+ • Corrects the hawk scope to only add the plural related entity when NOT using the shorthand `{ ... }`
1233
+
1234
+ • BEM (block element modifier)-style has been added list headings, show cells, edit cells. These class names will get added to the `<div>` tags for both the heading and cells.
1235
+
1236
+ The format is as follows:
1237
+
1238
+ For headings
1239
+ `heading--{singular}--{field name}-{field name}-{field name}`
1240
+
1241
+ For cells:
1242
+ `cell--{singular}--{field name}-{field name}-{field name}`
1243
+ use this to globally style different fields by object & field name
1244
+
1245
+ Note that if you have multiple fields inside one cell (for example, with specified grouping or smart layout), your fields names get concatenated using single-hyphens:
1246
+ For example, consider a customer scaffold with a first name & last name appearing in one cell. The cell itself will have a class of:
1247
+ `cell--customer--first_name-last_name`
1248
+
1249
+ If your cell contains only one field, for example, a phone number, it would look like this:
1250
+ `cell--customer--phone_number`
1251
+
1252
+ Tip: Use the _ends with_ and _starts with_ selectors, which can be used like this:.
1253
+
1254
+ ```
1255
+ div[class$="--phone_number"] {
1256
+ text-decoration: underline;
1257
+ }
1258
+ ```
1259
+
1260
+
1261
+ ```
1262
+
1263
+ ```
1264
+
1265
+
1086
1266
  #### 2023-02-13 - v0.5.7 - factory-creation, alt lookups, update show only, fixes to Enums, support for Ruby 3.2
1087
1267
  • See `--factory-creation` section.
1088
1268
 
@@ -1147,8 +1327,8 @@ License check has been removed (Hot Glue is now free to use for hobbyists and in
1147
1327
  #### 2022-03-23 - v0.5.2 - Hawked Foreign Keys
1148
1328
 
1149
1329
  - You can now protect your foreign keys from malicious input and also restrict the scope of drop downs to show only records with the specified access control restriction.
1150
- - [Example #3](https://jfb.teachable.com/courses/hot-glue-in-depth-tutorial/lectures/38584014) in the Hot Glue Tutorial shows you how to use the hawk to limit the scope to the logged in user.
1151
- - [Example #4](https://jfb.teachable.com/courses/hot-glue-in-depth-tutorial/lectures/38787505) in the Hot Glue Tutorial shows how to hawk to a non-usual scope, the inverse of the current user's belongs_to (that is, hawk the scope to X where current_user `belongs_to :x`)
1330
+ - [Example #3](https://school.jasonfleetwoodboldt.com/8188) in the Hot Glue Tutorial shows you how to use the hawk to limit the scope to the logged in user.
1331
+ - [Example #4](https://school.jasonfleetwoodboldt.com/8188) in the Hot Glue Tutorial shows how to hawk to a non-usual scope, the inverse of the current user's belongs_to (that is, hawk the scope to X where current_user `belongs_to :x`)
1152
1332
 
1153
1333
 
1154
1334
  #### 2022-03-12 - v0.5.1 - Inline List Labels