loco_motion-rails 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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