I was always a fan of having an easy way to spin up scaffold rails applications with a single console command. For people like me, who test out every week a new idea, getting rid of all the manual work related to the repeatable configuration can mean a lot.
It's even more useful if your company has service-oriented architecture and new projects are being added in a regular manner.
In the Rails ecosystem, there are plenty of solutions for doing it, one example is Rails Composer gem that allows you to easily spin-up rails applications from a collection of different recipes.
In this episode, I'll show you how we can easily spin-up Hanami applications in a similar manner. There is no manual coding required, just a simple command in the terminal, and you have a fully working Hanami application with the Persistence and View layer preconfigured.
If you are asking yourself - why this is useful, if Hanami 2.1 also has a view and persistence components in place, ready to use - then here is my explanation.
Hanami 2.1 officially comes with ROM for persistence and Hanami-View for view and templating engines. However, nothing stops you from getting rid of those components, and replace them with something else, or extend if needed.
For the view layer, there are plenty of great solutions out there, for example:
- Trailblazer Cells
- View Component
Depending on the need and context, you may need different solutions for your app, and Hanami does not stop you from doing it!
However, even if you'll come with one view engine, there are multiple templating languages you could set as your go-to in your project, like:
- ...and others
This already brings different configuration possibilities and arrangments but we won't stop here.
Now let's assume, you'd like to replace your default ROM integration with raw Sequel, or disable persistence completely. Do you want to go with adjusting it over and over in your side projects, or tons of new clients, if you are developing applications for small clients?
What about other integrations, like replacing
rspec with a different test framework, or integrations for CI or deployment?
All that can be scripted out, and the good news is, that ruby community already started making those pre-defined solutions!
I recently found that Brooke Kuhlmann, the author of Alchemists.io, came up with a new gem, named Hanamismith, that allows you to quickly spin up a complete, pre-configured Hanami application. At the moment it comes with the HTMX integration. It's a great response for Rails' Hotwire and I am very much excited about this integration and the possibilities it brings.
I hope, that with enough interest, different options and integrations will be added to
hanamismith soon, so we can all play with different configuration sets to find our favorite ones.
Let me try it out very quickly
First I need to install the
hanamismith gem in order to use executable commands it provides
gem install hanamismith
Having this, I can spin my new project with some useful options. I'll add
no git flag, because I already have a single git repository for all my hanami mastery episodes.
Then I'll append the
github flag to add some GitHub templates, and
github CI for the GitHub actions configuration.
hanamismith --build hanamimastery --no-git --git_hub --git_hub_ci
After hitting enter, my application is built. We may get into the project folder and check out what had been created.
You can see here that we have a standard Hanami 2 application created, but with some additional features.
First of all, I have the .github folder added, with a simple CI configuration setup, the issue, and pull request templates included. This may need a little adjustment, especially in my case, when I don't have it stored in the root of my repository - but it's already a huge time saver for me.
Then in the providers' folder, you can find the persistence provider, with a complete ROM integration in place. If I'll run my project now, it'll crash because I don't have my Postgres database created yet.
hanami server > FATAL: database "hanamimastery_development" does not exist (PG::ConnectionBad)
Let me add it and check out what happens.
createdb hanamimastery_development ➜ hanamimastery git:(main) ✗ hanami server  Puma starting in cluster mode...  * Puma version: 6.0.2 (ruby 3.2.0-p0) ("Sunflower")  * Min threads: 5  * Max threads: 5  * Environment: development  * Master PID: 55509  * Workers: 8  * Restarts: (✔) hot (✖) phased  * Preloading application  * Listening on http://0.0.0.0:2300  Use Ctrl-C to stop lib/puma/launcher.rb:304:in `write': No such file or directory @ rb_sysopen - tmp/server.pid (Errno::ENOENT) from
Hm... It crashed again, because it cannot write to the
tmp directory. I think I just need to create it via the
mkdir tmp hanami server  Puma starting in cluster mode...  * Puma version: 6.0.2 (ruby 3.2.0-p0) ("Sunflower")  * Min threads: 5  * Max threads: 5  * Environment: development  * Master PID: 55872  * Workers: 8  * Restarts: (✔) hot (✖) phased  * Preloading application  * Listening on http://0.0.0.0:2300  Use Ctrl-C to stop  - Worker 0 (PID: 56028) booted in 0.01s, phase: 0  - Worker 1 (PID: 56029) booted in 0.01s, phase: 0  - Worker 2 (PID: 56030) booted in 0.01s, phase: 0  - Worker 3 (PID: 56031) booted in 0.01s, phase: 0  - Worker 4 (PID: 56032) booted in 0.01s, phase: 0  - Worker 5 (PID: 56033) booted in 0.01s, phase: 0  - Worker 6 (PID: 56034) booted in 0.01s, phase: 0  - Worker 7 (PID: 56035) booted in 0.01s, phase: 0
Now, everything seems to work fine. Visiting my browser at
localhost on port
2300 will show me the landing page.
Hanamismith Home page
Let's check out how the view rendering is done here. Visiting
Gemfile will show us that hanami-view is configured together with
erb, and in the slices, we have a pre-generated slice, named Main, with the homepage endpoint configured.
When I'll open the show template of my homepage, and update the content inside, I should see my updates after refreshing the page, without the need to restart the server.
Updated Home page view
You may already see that some basic styles had been applied to the document, but if we'll check the Layout, you'll see that it's just an inline CSS defined within the HTML head.
What's interesting though, is the HTMX integration, which allows you to add HTML components with extra abilities, like sending ajax requests and replacing only parts of the document when the request is completed.
Let me show it to you. By adding div wrapper with a button inside, I can define some HTMX properties now, to manipulate the button behavior.
I will set it to send the post request on click, and when a successful response will be received, we are going to replace the parent div content using the incoming response body as a new div content.
<div id="parent"> <button hx-post="/subscribe" hx-swap="outerHTML" hx-target="#parent"> Click Me to subscribe! </button> </div>
Now when I click it, my button will send an ajax request to the server. Nothing else happens, because I don't have this route defined yet.
Thanks to the new generators though, adding it is extremely simple.
I am going to add a new action named subscribe within the main slice. I will use a simplified URL, and set the HTTP method to POST.
hanami g action home.subscribe --slice=main --url='/subscribe' --http=post
Then in the newly created action, let's replace a default response body with the nice notification message and check out the browser again.
Yaay! It works!
With this, You may now add real functionality to your app.
Unfortunately, that's all I have for you today.
Hanamismith is a great start and I would love this gem to evolve. If you also want it to become better, feel free to contribute by adding additional features and configuration options :).
Become an awesome subscriber!
I want to especially thank my recent sponsors,
and all the Hanami Mastery PRO subscirbers, for supporting this project, I really appreciate it!
Add your suggestion to our discussion panel!
I'll gladly cover them in the future episodes! Thank you!