loco_motion-rails 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +880 -0
  4. data/app/components/daisy/actions/button_component.html.haml +7 -0
  5. data/app/components/daisy/actions/button_component.rb +52 -0
  6. data/app/components/daisy/actions/dropdown_component.html.haml +13 -0
  7. data/app/components/daisy/actions/dropdown_component.rb +48 -0
  8. data/app/components/daisy/actions/modal_component.html.haml +31 -0
  9. data/app/components/daisy/actions/modal_component.rb +92 -0
  10. data/app/components/daisy/actions/swap_component.html.haml +17 -0
  11. data/app/components/daisy/actions/swap_component.rb +56 -0
  12. data/app/components/daisy/actions/theme_controller_component.html.haml +5 -0
  13. data/app/components/daisy/actions/theme_controller_component.rb +8 -0
  14. data/app/components/daisy/data_display/accordion_component.html.haml +4 -0
  15. data/app/components/daisy/data_display/accordion_component.rb +82 -0
  16. data/app/components/daisy/data_display/avatar_component.html.haml +9 -0
  17. data/app/components/daisy/data_display/avatar_component.rb +60 -0
  18. data/app/components/daisy/data_display/badge_component.html.haml +2 -0
  19. data/app/components/daisy/data_display/badge_component.rb +27 -0
  20. data/app/components/daisy/data_display/card_component.html.haml +17 -0
  21. data/app/components/daisy/data_display/card_component.rb +53 -0
  22. data/app/components/daisy/data_display/carousel_component.html.haml +3 -0
  23. data/app/components/daisy/data_display/carousel_component.rb +17 -0
  24. data/app/components/daisy/data_display/chat_component.html.haml +14 -0
  25. data/app/components/daisy/data_display/chat_component.rb +38 -0
  26. data/app/components/daisy/data_display/collapse_component.html.haml +13 -0
  27. data/app/components/daisy/data_display/collapse_component.rb +37 -0
  28. data/app/components/daisy/data_display/countdown_component.html.haml +24 -0
  29. data/app/components/daisy/data_display/countdown_component.rb +70 -0
  30. data/app/components/daisy/data_display/countdown_controller.js +78 -0
  31. data/app/components/daisy/data_display/diff_component.html.haml +6 -0
  32. data/app/components/daisy/data_display/diff_component.rb +25 -0
  33. data/app/components/daisy/data_display/kbd_component.html.haml +2 -0
  34. data/app/components/daisy/data_display/kbd_component.rb +21 -0
  35. data/app/components/daisy/data_display/stat_component.html.haml +27 -0
  36. data/app/components/daisy/data_display/stat_component.rb +41 -0
  37. data/app/components/daisy/data_display/table_component.html.haml +14 -0
  38. data/app/components/daisy/data_display/table_component.rb +148 -0
  39. data/app/components/daisy/data_display/timeline_component.html.haml +7 -0
  40. data/app/components/daisy/data_display/timeline_component.rb +8 -0
  41. data/app/components/daisy/data_display/timeline_event_component.html.haml +28 -0
  42. data/app/components/daisy/data_display/timeline_event_component.rb +47 -0
  43. data/app/components/daisy/feedback/alert_component.html.haml +8 -0
  44. data/app/components/daisy/feedback/alert_component.rb +19 -0
  45. data/app/components/daisy/layout/join_component.rb +15 -0
  46. data/app/components/daisy/navigation/bottom_nav_component.rb +59 -0
  47. data/app/components/daisy/navigation/breadcrumbs_component.html.haml +7 -0
  48. data/app/components/daisy/navigation/breadcrumbs_component.rb +15 -0
  49. data/app/components/daisy/navigation/link_component.html.haml +4 -0
  50. data/app/components/daisy/navigation/link_component.rb +34 -0
  51. data/app/components/daisy/navigation/menu_component.html.haml +3 -0
  52. data/app/components/daisy/navigation/menu_component.rb +49 -0
  53. data/app/components/daisy/navigation/navbar_component.html.haml +4 -0
  54. data/app/components/daisy/navigation/navbar_component.rb +12 -0
  55. data/app/components/daisy/navigation/steps_component.rb +40 -0
  56. data/app/components/daisy/navigation/tabs_component.html.haml +4 -0
  57. data/app/components/daisy/navigation/tabs_component.rb +107 -0
  58. data/app/components/hero/icon_component.rb +18 -0
  59. data/lib/daisy/helpers.rb +61 -0
  60. data/lib/daisy.rb +19 -0
  61. data/lib/loco_motion/base_component.rb +371 -0
  62. data/lib/loco_motion/basic_component.rb +18 -0
  63. data/lib/loco_motion/component_config.rb +165 -0
  64. data/lib/loco_motion/engine.rb +8 -0
  65. data/lib/loco_motion/errors.rb +33 -0
  66. data/lib/loco_motion.rb +48 -0
  67. metadata +408 -0
data/README.md ADDED
@@ -0,0 +1,880 @@
1
+ <!-- omit from toc -->
2
+ # loco_motion
3
+
4
+ Crazy fast Rails development with modern tools and components leveraging
5
+ ViewComponent, TailwindCSS, DaisyUI and more!
6
+
7
+ ![image](./docs/assets/images/loco-chats.png)
8
+
9
+ _**DISCLAIMER**_
10
+
11
+ This project is in active development and many changes occur with every release!
12
+ In particular, new Daisy components are being added frequently and older
13
+ components are being updated with new features meaning the APIs are very likely
14
+ to change!
15
+
16
+ We plan to publish the docs site to a publicly available URL soon, but until
17
+ then, you can run the docs by cloning the repository and running `make all` (or
18
+ `make all-quick` if you've already run `make all` or `make rebuild` previously)
19
+ and visiting http://localhost:3000/ in your browser.
20
+
21
+ Please reach out by opening an
22
+ [Issue](https://github.com/profoundry-us/loco_motion/issues) if you've found a
23
+ bug or starting a
24
+ [Discussion](https://github.com/profoundry-us/loco_motion/discussions) if you
25
+ have a question!
26
+
27
+ Please open a Discussion / Issue **before** starting a Pull Request to make sure
28
+ we aren't already working on the suggested feature / bug, and to ensure that
29
+ your solution is aligned with our goals.
30
+
31
+ - [About](#about)
32
+ - [Getting Started](#getting-started)
33
+ - [Installing / Setting up Rails](#installing--setting-up-rails)
34
+ - [Install HAML (Optional)](#install-haml-optional)
35
+ - [Install DaisyUI (Optional)](#install-daisyui-optional)
36
+ - [Try Out Your Application](#try-out-your-application)
37
+ - [Debugging](#debugging)
38
+ - [Testing](#testing)
39
+ - [Authentication](#authentication)
40
+ - [Web Console](#web-console)
41
+ - [BetterErrors (Optional)](#bettererrors-optional)
42
+ - [LocoMotion Components](#locomotion-components)
43
+ - [Install](#install)
44
+ - [Using Components](#using-components)
45
+ - [Setting a Base Component Class](#setting-a-base-component-class)
46
+ - [Developing](#developing)
47
+ - [Tooling](#tooling)
48
+ - [TODO / Next Steps](#todo--next-steps)
49
+
50
+
51
+ ## About
52
+
53
+ loco_motion is both a set of philosophies and paradigms for developing robust
54
+ web applications in Ruby on Rails, as well gems and tools to help you execute
55
+ on your vision quickly and reliably.
56
+
57
+ It includes standards for your
58
+
59
+ * Development Environment
60
+ * Testing / Debugging
61
+ * CSS / Page Markup
62
+ * Components / Libraries
63
+ * Releasing / Hosting
64
+ * and much more!
65
+
66
+ You can use as much or as little of the frameworks and philosophies provided,
67
+ and you can customize it all to your heart's content.
68
+
69
+ ## Getting Started
70
+
71
+ We recommend using Docker to get your project setup from the beginning. Even
72
+ before you run the `rails new` command. This ensures that you have a stable
73
+ development environment, no matter what OS or system you're using to develop.
74
+
75
+ It also allows you to troubleshoot and debug the application since the
76
+ development container is so small and simple with very few dependencies.
77
+
78
+ You can download it from https://www.docker.com/.
79
+
80
+ Once you have that downloaded, open a terminal, and create a new directory for
81
+ your project. You can put it anywhere, but we recommend a directory structure
82
+ similar to the following:
83
+
84
+ ```shell
85
+ mkdir -p ~/Development/mycompany/myproject
86
+ ```
87
+
88
+ Now, change into that directory:
89
+
90
+ ```shell
91
+ cd ~/Development/mycompany/myproject
92
+ ```
93
+
94
+ Look in the `examples` directory for basic `docker-compose.yml`, `Dockerfile`,
95
+ `dev/Dockerfile`, and `entrypoint.sh` files to get you started and give you a
96
+ place to run commands. Copy these into your project directory.
97
+
98
+ Next, we recommend using a [Makefile](/examples/Makefile) (also in
99
+ `examples`) to create shortcuts for running your various commands. `make` will
100
+ run on just about any operating system, and provides a self-documenting list of
101
+ all of the ways that you typically interact with your application. This means
102
+ that other developers can quickly see the common use-cases, but will also have a
103
+ starting point if they need to customize any of the commands for their
104
+ particular setup.
105
+
106
+ Copy this `Makefile` into your top-level project directory as well.
107
+
108
+ Your directory structure should look like this:
109
+
110
+ ```txt
111
+ - ~/Development
112
+ - mycompany
113
+ - myproject
114
+ - Dockerfile
115
+ - Makefile
116
+ - dev
117
+ - Dockerfile
118
+ - docker-compose.yml
119
+ - entrypoint.sh
120
+ ```
121
+
122
+ Finally, we recommend [VSCode](https://code.visualstudio.com/) as your code
123
+ editor, but this is purely preference. It has a lot of plugins that make it
124
+ really customizable, but utlimately, you should use whatever editor makes you
125
+ most comfortable during development.
126
+
127
+ You should now be able to run `make dev` in a terminal inside your project
128
+ directory to build and run all of the containers.
129
+
130
+ Once they have all built and started, in a separate terminal, you can run
131
+ `make dev-shell` to open a Bash shell into your development container.
132
+
133
+ Congratulations! You're ready to create your Rails app!
134
+
135
+ ## Installing / Setting up Rails
136
+
137
+ Once you're inside of the development container, everything should be setup and
138
+ ready for you to install Ruby on Rails.
139
+
140
+ Change into the app directory which is mapped to your local machine and run the
141
+ `rails new` command:
142
+
143
+ > [!NOTE]
144
+ > If you want to use something other than PostgreSQL or TailwindCSS, you can
145
+ > change that here. These are just our recommendations.
146
+
147
+ > [!TIP]
148
+ > We tend to recommend that you lag behind on the latest version of Ruby as
149
+ > it can occassionally have issues building the Rails project. But you can
150
+ > swap it to the latest inside of the `dev/Dockerfile` by changing the `FROM`
151
+ > line at the top.
152
+
153
+ ```shell
154
+ cd /home/app && rails new . --skip --database=postgresql --javascript=esbuild --css=tailwind
155
+ ```
156
+
157
+ If you run into trouble with the above Rails command, this should get you back
158
+ to a good starting point without having to blow away any changes you might have
159
+ made to the dev files.
160
+
161
+ ```shell
162
+ rm -rf .dockerignore .git .gitattributes .gitignore .node-version .ruby-version\
163
+ Gemfile README.md Rakefile app bin config config.ru
164
+ ```
165
+
166
+ Once complete, you should now be able to exit out of the dev container and kill
167
+ the running docker containers with <kbd>Ctrl-C</kbd> in the running terminal, or
168
+ you can open a new terminal and run `make down`.
169
+
170
+ Open the newly created `config/database.yml` file and add the following three
171
+ lines under the `default` key:
172
+
173
+ ```yaml
174
+ host: db
175
+ username: postgres
176
+ password: password
177
+ ```
178
+
179
+ Now, uncomment the `app` section in your `docker-compose.yml` file and run
180
+ `make app` to build the application.
181
+
182
+ After a minute or two, everything should be booted up and you should see output
183
+ similar to the following:
184
+
185
+ ```txt
186
+ myproject-app-1 | == Restarting application server ==
187
+ myproject-app-1 | => Booting Puma
188
+ myproject-app-1 | => Rails 7.1.2 application starting in development
189
+ myproject-app-1 | => Run `bin/rails server --help` for more startup options
190
+ myproject-app-1 | Puma starting in single mode...
191
+ myproject-app-1 | * Puma version: 6.4.0 (ruby 3.3.0-p-1) ("The Eagle of Durango")
192
+ myproject-app-1 | * Min threads: 5
193
+ myproject-app-1 | * Max threads: 5
194
+ myproject-app-1 | * Environment: development
195
+ myproject-app-1 | * PID: 1
196
+ myproject-app-1 | * Listening on http://0.0.0.0:3000
197
+ myproject-app-1 | Use Ctrl-C to stop
198
+ ```
199
+
200
+ Congratulations!
201
+
202
+ You can now visit [http://localhost:3000](http://localhost:3000) in your web
203
+ browser and see your running Rails application!
204
+
205
+ ### Install HAML (Optional)
206
+
207
+ While you can use the default ERB templating system that comes with Rails, we
208
+ highly recommend using [HAML](https://haml.info/) instead as it provides a much
209
+ cleaner language for your template files.
210
+
211
+ Drop this at the bottom of your `Gemfile`:
212
+
213
+ > [!NOTE]
214
+ > We suggest keeping your custom gems alphabetized at the bottom.
215
+
216
+ ```yaml
217
+ # App-Specific Gems
218
+ gem "haml-rails", "~> 2.0"
219
+ ```
220
+
221
+ And add the following to your `Gemfile` in the `group :development` section:
222
+
223
+ ```yaml
224
+ gem 'html2haml'
225
+ ```
226
+
227
+ Next, open up a Docker shell in the app container using `make app-shell` and
228
+ run `bundle` to install the HAML gem.
229
+
230
+ Next, open up your `tailwind.config.js` file and replace the line for `erb`
231
+ views with `haml` views:
232
+
233
+ ```js
234
+ module.exports = {
235
+ content: [
236
+ './app/views/**/*.html.haml',
237
+ // ...
238
+ ]
239
+ ```
240
+
241
+ Finally, you can run the following command to replace all of your `.erb`
242
+ files with `.haml` versions:
243
+
244
+ ```bash
245
+ HAML_RAILS_DELETE_ERB=true rails haml:erb2haml
246
+ ```
247
+
248
+ You should see output similar to the following:
249
+
250
+ ```text
251
+ --------------------------------------------------------------------------------
252
+ Generating HAML for app/views/layouts/application.html.erb...
253
+ Generating HAML for app/views/layouts/mailer.html.erb...
254
+ Generating HAML for app/views/layouts/mailer.text.erb...
255
+ --------------------------------------------------------------------------------
256
+ HAML generated for the following files:
257
+ app/views/layouts/application.html.erb
258
+ app/views/layouts/mailer.html.erb
259
+ app/views/layouts/mailer.text.erb
260
+ --------------------------------------------------------------------------------
261
+ Deleting original .erb files.
262
+ --------------------------------------------------------------------------------
263
+ Task complete!
264
+ ```
265
+
266
+ ### Install DaisyUI (Optional)
267
+
268
+ Next up, let's utilize a mighty combo for our CSS layer!
269
+
270
+ [TailwindCSS](https://tailwindcss.com/) is a utility-based CSS framework which
271
+ allows you to easily build your own components by piecing together the utility
272
+ classes that you need.
273
+
274
+ For example, to make a rounded button, you might do something like this:
275
+
276
+ ```haml
277
+ %button.px-4.py-2.border.rounded-lg
278
+ My Button
279
+ ```
280
+
281
+ > [!IMPORTANT]
282
+ > We _highly_ recommend using Tailwind for every project and have already
283
+ > installed it as part of the `rails new` command above.
284
+
285
+ [DaisyUI](https://daisyui.com/) takes a more traditional route and provides a
286
+ set of classes that utilize Tailwind to create the components for you. This
287
+ means your button above would look more like this:
288
+
289
+ ```haml
290
+ %button.btn
291
+ My Button
292
+ ```
293
+
294
+ If you want pure customization or are building your own UI components from
295
+ scratch, we recommend that you stick with Tailwind by itself.
296
+
297
+ However, if you're working on a project and want a good starting point for UI
298
+ components, you might checkout DaisyUI or a simliar Tailwind-based UI library.
299
+
300
+ DaisyUI is a plugin for Tailwind, so installing it is dead simple. Just open up
301
+ an app shell by running `make app-shell` in the terminal and run the following
302
+ command:
303
+
304
+ ```shell
305
+ yarn add daisyui@latest --dev
306
+ ```
307
+
308
+ Next, edit your `tailwind.config.js` file to add it as a plugin:
309
+
310
+ > [!IMPORTANT]
311
+ > Make sure to add a `,` to the previous line if you put it at the bottom.
312
+
313
+ ```js
314
+ module.exports = {
315
+ //...
316
+ plugins: [require("daisyui")],
317
+ }
318
+ ```
319
+
320
+ > [!IMPORTANT]
321
+ > Moving forward, this guide will assume you have installed DaisyUI, so some of
322
+ > the example view files will utilize these CSS classes.
323
+
324
+ ### Try Out Your Application
325
+
326
+ Now that we have everything installed and running, let's build a few simple
327
+ parts of a Rails application to test that everything is working properly!
328
+
329
+ By default, only the Rails application is running, but we now need to build
330
+ and bundle our Javascript and CSS.
331
+
332
+ Open up your `Procfile.dev` and tell the Rails server to bind to `0.0.0.0`:
333
+
334
+ ```
335
+ web: env RUBY_DEBUG_OPEN=true bin/rails server -b 0.0.0.0
336
+ ```
337
+
338
+ Next, you'll need to update the `Dockerfile` to tell Docker how to start
339
+ your app using Foreman.
340
+
341
+ Change the following line:
342
+
343
+ ```Dockerfile
344
+ CMD ["rails", "server", "-b", "0.0.0.0"]
345
+ ```
346
+
347
+ to
348
+
349
+ ```Dockerfile
350
+ CMD ["./bin/dev"]
351
+ ```
352
+
353
+ Since we're using Docker, you might also want to edit your `bin/setup` file
354
+ to automatically remove any old PID files that might be lying around from a bad
355
+ container shutdown.
356
+
357
+ Add the following lines right above the last few lines that restart the
358
+ application server:
359
+
360
+ ```sh
361
+ puts "\n== Removing old PID files =="
362
+ system! "rm -rf /home/app/tmp/pids/server.pid"
363
+ ```
364
+
365
+ Finally, you can kill your running docker containers (either using
366
+ <kbd>Ctrl-C</kbd>, opening a new terminal in your project folder and running
367
+ `make down`, or using the Docker UI to stop all of the containers).
368
+
369
+ Now restart using `make app`.
370
+
371
+ > [!TIP]
372
+ > Once you have stabalized your Dockerfile and any dependencies, you can run
373
+ > `make app-quick` to launch the containers without rebuilding.
374
+ >
375
+ > In this case, since we changed our `Dockerfile`, we still need to use the
376
+ > regular `make app` command.
377
+
378
+ You should be able to test that everything is working by altering a few files so
379
+ you can see some custom output:
380
+
381
+ ```ruby
382
+ # config/routes.rb
383
+
384
+ root "application#test"
385
+ ```
386
+
387
+ ```ruby
388
+ # app/controllers/application_controller.rb
389
+
390
+ class ApplicationController < ActionController::Base
391
+ def test
392
+ render html: 'Test', layout: true
393
+ end
394
+ end
395
+ ```
396
+
397
+ ```haml
398
+ # app/views/layouts/application.html.haml
399
+
400
+ # Just modify the body & yield lines to look like this
401
+
402
+ %body
403
+ .m-2.p-2.rounded.bg-red-400
404
+ = yield
405
+ ```
406
+
407
+ Now visit [http://localhost:3000](http://localhost:3000) and you should
408
+ see a red, rounded box with the word "Test"!
409
+
410
+ If you also installed, DaisyUI, we can test that as well. Add some additional
411
+ code to the bottom of the `application.html.haml` file:
412
+
413
+ ```haml
414
+ # app/views/layouts/application.html.haml
415
+
416
+ # Leave the html / head code above
417
+
418
+ %body
419
+ .m-2.p-2.rounded.bg-red-400
420
+ = yield
421
+
422
+ # Add this
423
+ .btn
424
+ Test Button
425
+ ```
426
+
427
+ If everything worked, you should see a gray button that changes when
428
+ you hover and click on it!
429
+
430
+ > [!CAUTION]
431
+ > Once you're done playing around with this, you should undo your changes to the
432
+ > layout so that it doesn't cause confusion in later parts of this guide.
433
+
434
+ ## Debugging
435
+
436
+ The latest version of Rails makes it much easier to debug within a Docker
437
+ container as it automatically starts a remote debugger for you.
438
+
439
+ Add the word `debugger` anywhere in your code (perhaps the `test` method of your
440
+ `ApplicationController`), reload the page (it will look like it's hanging), and
441
+ then run `make app-debug` in a separate terminal.
442
+
443
+ This will connect to the remote debugger instance which will be stopped at your
444
+ `debugger` line.
445
+
446
+ ## Testing
447
+
448
+ Before we start creating a bunch of models, controllers, and other pieces of
449
+ code, it's good to get a solid testing foundation in place. Rails ships with
450
+ [MiniTest](https://guides.rubyonrails.org/testing.html) out of the box and many
451
+ people prefer this as it's built-in and is essentially just Ruby code.
452
+
453
+ However, many larger teams opt to utilize [RSpec](https://rspec.info/) which is
454
+ a Behavior Driven Development (BDD) framework whose tests utilize the english
455
+ language to help you build relevant test cases. It also has a large ecosystem of
456
+ plugins which can accelerate your development.
457
+
458
+ Which one you choose is up to you, but after developing many applications, we
459
+ recommned Rspec with [factory_bot](https://github.com/thoughtbot/factory_bot)
460
+ and [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers).
461
+
462
+ Finally, although both libraries offer some functionality for testing your user
463
+ interface, we recommend utilizing [Cypress](https://www.cypress.io/) instead as
464
+ it more closely mimics the real user experience in a browser and it allows you
465
+ to see in real-time what is happening, including in-browser debugging!
466
+
467
+ > [!NOTE]
468
+ > One thing to note about Cypress, however, is that it is Javascript-based and
469
+ > thus requires you to write tests in Javascript. If you are only famililar with
470
+ > Ruby, you might want to stick with Rspec or Minitest when you first start your
471
+ > project, and expand into using Cypress once you are comfortable learning a new
472
+ > lanugage / framework.
473
+
474
+ ## Authentication
475
+
476
+ There are a **lot** of different ways to handle user authentication in Ruby on
477
+ Rails. Because of this, many gems have popped up to help you handle this. The
478
+ two most popular ones are [OmniAuth](https://github.com/omniauth/omniauth) and
479
+ [Devise](https://github.com/heartcombo/devise).
480
+
481
+ We recommend starting with OmniAuth because it has a very simple `:developer`
482
+ authentication strategy which will allow you to get started very quickly, and
483
+ it allows you to
484
+ [integrate with devise](https://github.com/heartcombo/devise#omniauth) or a
485
+ service like [Auth0](https://auth0.com/) later if you choose.
486
+
487
+ > [!TIP]
488
+ > You can always find the latest setup documentation on OmniAuth's README.
489
+
490
+ Add the relevant gems to your application's `Gemfile` and re-run
491
+ `bundle install`:
492
+
493
+ ```Gemfile
494
+ gem 'omniauth'
495
+ gem "omniauth-rails_csrf_protection"
496
+ ```
497
+
498
+ After that has finished, you'll need to restart your Rails server.
499
+
500
+ > [!TIP]
501
+ > Although you can do this by using <kbd>Ctrl-C</kbd> and re-running `make
502
+ > app-quick`, a faster way to restart only the web server is to create a
503
+ > temporary file named `restart.txt`.
504
+ >
505
+ > You can easily do this by running `touch tmp/restart.txt` in a terminal!
506
+
507
+ Next, create an OmniAuth initializer:
508
+
509
+ ```ruby
510
+ # config/initializers/omniauth.rb
511
+
512
+ Rails.application.config.middleware.use OmniAuth::Builder do
513
+ provider :developer if Rails.env.development?
514
+ end
515
+ ```
516
+
517
+ We'll need to setup a few routes:
518
+
519
+ ```ruby
520
+ # config/routes.rb
521
+
522
+ get '/auth/:provider/callback', to: 'sessions#create'
523
+ get '/login', to: 'sessions#new'
524
+ ```
525
+
526
+ Finally, we'll need to add the relevant sessions controller and view:
527
+
528
+ ```ruby
529
+ # app/controllers/sessions_controller.rb
530
+
531
+ class SessionsController < ApplicationController
532
+ def new
533
+ render :new
534
+ end
535
+
536
+ def create
537
+ user_info = request.env['omniauth.auth']
538
+ raise user_info # Your own session management should be placed here.
539
+
540
+ session[:user_info] = user_info.to_hash
541
+
542
+ redirect_to root_path
543
+ end
544
+ end
545
+ ```
546
+
547
+ ```haml
548
+ =# app/views/sessions/new.html.haml
549
+
550
+ - if Rails.env.development?
551
+ = form_tag('/auth/developer', method: 'post', data: {turbo: false}) do
552
+ %button.btn{ type: 'submit' }
553
+ Login with Developer
554
+ ```
555
+
556
+ From here, you can login by visiting http://localhost:3000/login, clicking the
557
+ button, and entering a random name and email address.
558
+
559
+ It should throw an error and show you the line that it failed on
560
+ (`raise user_info`).
561
+
562
+ This is not terribly helpful as you can't easily inspect the variable and see
563
+ it's value.
564
+
565
+ In general, you'd want to set this to something like `session[:user_info]` and
566
+ integrate it into your application flow.
567
+
568
+ When you're ready for it to work, just delete or comment out the
569
+ `raise user_info` line.
570
+
571
+ However, this gives us an opportune time to get some better error management.
572
+ So let's do that first!
573
+
574
+ ## Web Console
575
+
576
+ At this point, if you look in your Docker logs, you'll probably see a line like
577
+ the following:
578
+
579
+ ```text
580
+ Cannot render console from 172.23.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1
581
+ ```
582
+
583
+ > [!NOTE]
584
+ > Your IP address may be different! Take note of what IP the error says.
585
+
586
+ Because we're running inside Docker, we have a different network than what Rails
587
+ typically expects (127.0.0.1) and it blocks the default web console that loads
588
+ when an error happens.
589
+
590
+ This is easy to fix, we just need to take the IP address in the error message
591
+ above and add the following line to our `config/environments/development.rb`
592
+ file:
593
+
594
+ ```ruby
595
+ # Fix console permissions for Docker
596
+ config.web_console.permissions = '172.23.0.1'
597
+ ```
598
+
599
+ Restart the application and refresh the page. You should see the same error
600
+ appear, but now, you should see a black console at the bottom of the screen that
601
+ allows you to interact with the application.
602
+
603
+ Type the following in the console and hit enter:
604
+
605
+ ```ruby
606
+ user_info.to_hash
607
+ ```
608
+
609
+ You should see some information about the user you just logged in with.
610
+
611
+ You can run pretty much any code in this console that you would run inside your
612
+ controllers, views, models, etc.
613
+
614
+ In fact, when I'm debugging an issue, I often find a point just above where I'm
615
+ wanting to look, type something non-existant like `asdf` in my Rails code, and
616
+ then refresh the page.
617
+
618
+ This will stop the application where the `asdf` was found and allows you to
619
+ interact with your application and see exactly what's going on.
620
+
621
+ ## BetterErrors (Optional)
622
+
623
+ [BetterErrors](https://github.com/BetterErrors/better_errors) provides (in our
624
+ humble opinion) a slightly better interface for the errors that sometimes happen
625
+ in a Rails application.
626
+
627
+ In particular, we like how it lays out the stack trace to the left of the code
628
+ and console and adds a bit more styling to the page to make it easier to read.
629
+
630
+ It's also very easy to install!
631
+
632
+ Add the following to your `Gemfile` and re-run `bundle install` inside of the
633
+ Docker app container (`make app-shell`).
634
+
635
+ > [!TIP]
636
+ > You can also just kill (using <kbd>Ctrl-C</kbd>) and restart the container
637
+ > using `make app-quick` as this process attempts to install any gems for you.
638
+
639
+
640
+ ```Gemfile
641
+ # Gemfile
642
+
643
+ group :development do
644
+ gem "better_errors"
645
+ gem "binding_of_caller"
646
+ end
647
+ ```
648
+
649
+ > [!IMPORTANT]
650
+ > It is imperitive that you put these in the `:development` tag so that they
651
+ > cannot load in production.
652
+ >
653
+ > This would lead to a **massive** security risk!
654
+
655
+ Again, because we're running inside of Docker, we'll need to tell BetterErrors
656
+ that it's allowed to render for our IP address.
657
+
658
+ Add the following to the `config/environments/development.rb` file (make sure
659
+ the IP address matches the one you used for the Web Console above):
660
+
661
+ ```ruby
662
+ # Allow BetterErrors to render
663
+ BetterErrors::Middleware.allow_ip! '172.23.0.1'
664
+ ```
665
+
666
+ ## LocoMotion Components
667
+
668
+ In addition to the recommendations / suggestions above, LocoMotion also provides
669
+ a full set of UI components to help you build robust and full-featured apps.
670
+
671
+ > [!CAUTION]
672
+ > The LocoMotion components are being actively developed and are NOT ready for
673
+ > production / public use (currently they are just some example components while
674
+ > I get everything setup). I'm mainly adding the docs here so that I remember
675
+ > how to set them up properly when they are ready for release.
676
+
677
+ ### Install
678
+
679
+ Add the following to your `Gemfile` and re-run `bundle`:
680
+
681
+ ```Gemfile
682
+ # Gemfile
683
+
684
+ gem "loco_motion", github: "profoundry-us/loco_motion", branch: "main", require: "loco_motion"
685
+
686
+ # or
687
+
688
+ gem "loco_motion-rails", "0.0.6", require: "loco_motion"
689
+ ```
690
+
691
+ Next add the following lines to the `contents` section of your
692
+ `tailwind.config.js` to import / build the proper files:
693
+
694
+ ```js
695
+ const { execSync } = require('child_process');
696
+
697
+ let locoBundlePath = execSync('bundle show loco_motion').toString().trim();
698
+
699
+ module.exports = {
700
+ content:[
701
+ `${locoBundlePath}/app/components/**/*.{rb,js,html.haml}`,
702
+
703
+ // ...
704
+ ]
705
+ }
706
+ ```
707
+
708
+ > [!WARNING]
709
+ > Note that this will not output anything if it fails to find the right
710
+ > directory, so your CSS may stop working if you update the gem and forget to
711
+ > update this setting.
712
+
713
+ Next, if you're using any of the components that require JavaScript (like the
714
+ Countdown component), you'll need to add the library as a dependency and include
715
+ those controllers in your `application.js` file.
716
+
717
+ ```sh
718
+ npm add @profoundry-us/loco_motion
719
+ ```
720
+
721
+ or
722
+
723
+ ```sh
724
+ yarn add @profoundry-us/loco_motion
725
+ ```
726
+
727
+ Then inside your `application.js` file, make sure to import and register the
728
+ relevant controllers.
729
+
730
+ ```js
731
+ import { Application } from "@hotwired/stimulus"
732
+
733
+ import { CountdownController } from "@profoundry-us/loco_motion"
734
+
735
+ const application = Application.start()
736
+
737
+ application.register("countdown", CountdownController)
738
+
739
+ export { application }
740
+ ```
741
+
742
+ ### Using Components
743
+
744
+ Back in the `app/layouts/application.html.haml` file, replace the `body` with
745
+ the following code and refresh your page.
746
+
747
+ ```haml
748
+ %body
749
+ .m-2.p-2.rounded.bg-red-400
750
+ = session[:user_info].inspect
751
+
752
+ %div
753
+ = render(Daisy::Actions::ButtonComponent.new(title: "Click Me"))
754
+
755
+ %div
756
+ = daisy_button(css: "btn-primary") do
757
+ Click Me Too
758
+
759
+ = yield
760
+ ```
761
+
762
+ You should see a few buttons and the user info that we saved from OmniAuth
763
+ represented as a Ruby hash! Any other content you have will be rendered below.
764
+
765
+ ### Setting a Base Component Class
766
+
767
+ Sometimes, you may want to override the way that LocoMotion handles things, or
768
+ provide some functionality yourself in a sub-class of our components. Since you
769
+ can't have a class inherit from two classes, we give you a way to override the
770
+ base class that all of our components inherit from.
771
+
772
+ This allows you to define a class that inherits from `LocoMotion::BaseComponent`
773
+ and then adds any special methods or overrides to our default components.
774
+
775
+ Create a file called `app/components/application_component.rb` with the following
776
+ contents:
777
+
778
+ ```ruby
779
+ class ApplicationComponent < LocoMotion::BaseComponent
780
+ end
781
+ ```
782
+
783
+ Then add the following to `config/initializers/loco_motion.rb`.
784
+
785
+
786
+ ```ruby
787
+ LocoMotion.configure do |config|
788
+
789
+ # Override the base component class to inherit from our ApplicationComponent
790
+ # so that we can add our own overrides / methods.
791
+ Rails.application.config.after_initialize do
792
+ config.base_component_class = ApplicationComponent
793
+ end
794
+
795
+ end
796
+ ```
797
+
798
+ > [!NOTE]
799
+ > It doesn't have to inherit from `ApplicationComponent`, you can use any class
800
+ > you want, so you could create a separate `CustomizedLocoMotionComponent` class
801
+ > so that you don't have any conflicts with your `ApplicationComponent`.
802
+
803
+ ## Developing
804
+
805
+ To work on LocoMotion, first clone the repository and make sure you have Docker
806
+ installed and running on your machine.
807
+
808
+ You should then be able to run `make rebuild` in the project directory and then
809
+ `make all-quick` to start the services.
810
+
811
+ > [!NOTE]
812
+ >
813
+ > We use `npm link` within the `docs/demo/bin/dev` script to enable quick
814
+ > editing of the JavaScript library files so you don't have to publish a new
815
+ > package during testing.
816
+
817
+ From here, you can access the demo site at http://localhost:3000 and the YARD
818
+ docs at http://localhost:8808/docs/yard
819
+
820
+ You can type `make demo-shell` to open a shell inside the demo Docker container,
821
+ or `make loco-shell` to get a shell inside the gem's Docker container.
822
+
823
+ See the `Makefile` for all available commands.
824
+
825
+ > [!WARNING]
826
+ >
827
+ > Right now, Rails doesn't auto-reload the LocoMotion library files when they
828
+ > change, so you might have to restart your server to get it to pickup the
829
+ > changes.
830
+ >
831
+ > ```sh
832
+ > make demo-restart
833
+ > ```
834
+
835
+ ### Tooling
836
+
837
+ For VSCode, you may want to add the following to your settings to get
838
+ TailwindCSS Intellisense working properly.
839
+
840
+ ```json
841
+ "tailwindCSS.emmetCompletions": true,
842
+ "tailwindCSS.includeLanguages": {
843
+ "haml": "html",
844
+ "ruby": "html",
845
+ },
846
+ "files.associations": {
847
+ "*.html.haml": "haml"
848
+ },
849
+ "tailwindCSS.experimental.classRegex": [
850
+ [ "add_css\\(:[a-z]+, ?\"([^\"]*)\"", "([a-zA-Z0-9\\-:]+)" ],
851
+ [ "css: ?\"([^\"]*)\"", "([a-zA-Z0-9\\-:]+)" ],
852
+ [ "class: ?\"([^\"]*)\"", "([a-zA-Z0-9\\-:]+)" ],
853
+ [ "(\\.[\\w\\-.]+)[\\n\\=\\{\\s]", "([\\w\\-]+)" ],
854
+ ],
855
+ ```
856
+
857
+ ## TODO / Next Steps
858
+
859
+ There is a LOT left to be done. We're not currently seeking assistance, but if
860
+ you feel very strongly that you'd like to contribute, please reach out through
861
+ the GitHub Discussions feature and let us know!
862
+
863
+ - [x] Basic versions of DaisyUI Actions
864
+ - [x] Basic versions of DaisyUI Data Display
865
+ - [x] Basic versions of DaisyUI Navigation
866
+ - [ ] Basic versions of DaisyUI Feedback
867
+ - [ ] Basic versions of DaisyUI Data Input
868
+ - [ ] Basic versions of DaisyUI Layout
869
+ - [ ] Basic versions of DaisyUI Mockup
870
+ - [ ] Get YARD docs rendering with (better) Markdown
871
+ - [x] Extract relevant pieces into a yard-loco_motion plugin
872
+ - [ ] Publish Gem
873
+ - [x] Publish NPM package
874
+ - [ ] Update YARD plugin to add `@part`s
875
+ - [x] Extract doc callouts into a doc component (and / or the Daisy component)
876
+ - [ ] Choose and recommend / document a pagination gem
877
+ - [ ] Discuss caching techniques / setup
878
+ - [ ] Create / publish a production version of the demo site
879
+ - [ ] Create / publish a production version of the docs site
880
+ - [ ] Update demo site to allow for a different docs site using ENV var