A Ruby Ecosystem for Web Apps

I’m currently looking into Hanami as an alternative to Rails :slight_smile: One big advantage Rails has over a lot of solutions (not just in the Ruby world, but in general) is the ecosystem of libraries around it. I think this is hard to replicate. So my thought was: What if the ecosystem wasn’t “Hanami” but “Rails/Rack applications” instead? This would allow the smaller Ruby frameworks like Hanami, Brut and Yippee to join forces instead of implementing the same functionality multiple times. Rails has a longer history of “sherlocking” popular solutions over the years (for example, Active Storage & Solid Queue) which drained a lot of energy out of the original projects. I propose to not follow that pattern, and instead of putting everything in the box, offer recipes to integrate solutions.

The Core of Hanami

In my humble opinion, the core of Hanami would be: Code Loading, Routing, Controllers, Views, Form Handling, Caching, integration with an asset pipeline and the model layer. The model layer is a bit more complicated, but I would like to leave this out of this discussion. The one thing I see missing here is internationalization, as it is closely integrated with the view layer. There is a discussion about it here.

Authentication

I think authentication is an excellent example. @timriley wrote a great post on how to use Rodauth with Hanami (Discussion). For me, Rodauth would definitely be the first thing to try when setting up a Hanami app.

Authorization

For Authorization, I think Pundit and CanCanCan should both just work :thinking:

Jobs (Background Processing, Recurring Jobs)

Sidekiq is definitely a solid choice in this area, and I assume it will just work with Hanami. For people that want to store their jobs in the database, I’m not sure if there is a good option:

  • SolidQueue and GoodJob are both bound to ActiveJob/Rails
  • Que could be an option (for PostgreSQL only) and looks maintained

So I would probably go with either Sidekiq or Que here.

File Uploads

Looking at the solutions at Ruby Toolbox:

  • carrierwave still seems to be maintained - it is slightly bound to Rails, but might work?
    • refile was an attempt by the same team to “do it better this time”, but the last commit is over 5 years ago.
  • paperclip is deprecated
  • shrine is really independent of the framework. But activity on it seems to have gone down quite a lot.
  • The others all seem to be dead

So I’m not sure what I would go with here.

Mails

Not sure. The mail gem is at the core of ActionMailer, but I think it is quite attractive to have a solution that can also work with transactional email providers, as this is what I commonly use in production. Anyone got any ideas here?

Deployment

Both a classic setup with Capistrano and something like Ansible or a PaaS solution would work. For people who want a Container-based solution, kamal would work as well, but I’m not sure how many want to use a solution from 37signals :wink:

Logging & Instrumentation

Structured logging would be quite good. semantic_logger should work. For further instrumentation, I’m not sure. I would also be interested to see how well rack-mini-profiler works. I regularly use it in Rails app, and think it is quite helpful.

Testing

Both Minitest and RSpec will work with Hanami.

In short, YES. You see the vision. Welcome! :cherry_blossom: :sun_with_face:

Every part of Hanami is modular, both in terms of letting you swap things out of the full-stack framework, while letting users use libraries from Hanami that they like.

Tim gave a talk that touched on this, where he highlighted Roda, Phlex, and Shrine as Ruby gems that can be used across the ecosystem. I have some ideas about how to make this easier in Hanami by letting users easily create custom generators.

As for Brut and Yippee specifically, they both have different angles and visions of how they want to make Ruby web apps. This is good! They’re welcome to use any piece of Hanami that they’d like, but it’s also fine that they haven’t yet. We’ll support them if they do, and also. most importantly, support users who mix-and-match. (Specifically the forthcoming SQlite-only DB layer that will be part of Yippee is of great interest to me personally.)

Additionally, we want to support Rails libraries as well. In the spirit of welcoming all Ruby uses, and also specifically to provide a path for people who want to migrate from Rails incrementally.

Thanks for articulating this!

Thanks a lot! And thanks for the warm welcome :heart:

I just watched this brilliant talk, and it gives me a lot of positive energy :heart_eyes:

2 Likes

IMO Shrine is still a gold-standard for file uploads; and the slower commits/activity don’t necessarily bother me when working on my own projects. It’s remarkably stable, versatile, and slots in nicely in a bunch of places.

(Not saying you were trying to dismiss shrine, just wanted to say that it still works great! :grinning_face_with_smiling_eyes:)

1 Like

I was about to say the same thing. Shrine is stable, feature-complete, and framework-agnostic.

Thanks for this! I didn’t know Que. Not having Redis as a dependency is definitely a plus.

For Deployment, Caprover has treated me well. I’ve been using it in production for four years now on five different servers with dozens of apps, and it’s very reliable. Deployment can go either direct to the server, though GH Actions, or any other CI/CD flow.

1 Like

Thank you both! Hands-on knowledge about a solution working well was what I was searching for, so thanks for recommending Shrine. I will definitely check it out!

The last time I used Que is a few years ago, but back then it was working great. I think it is definitely worth a look!

caprover: Never heard about it, will take a look!

1 Like

This is doable with Mail gem. You just need to write a little delivery method class. Here’s what I quickly assembled to support Mailgun (using their gem):

require "bundler/inline"

gemfile do
  source "https://rubygems.org"
  gem "mail"
  gem "mailgun-ruby"
end

MG_KEY = "your-key"
MG_DOMAIN = "sandbo-yours.mailgun.org"

require "mailgun-ruby"
require "mail"

class MailgunDelivery
  def initialize(_options)
    @client =  Mailgun::Client.new(MG_KEY)
  end

  def settings
    {}
  end

  def deliver!(mail)
    @client.send_message(MG_DOMAIN, from: mail.from, to: mail.to, subject: mail.subject, text: mail.body)
  end
end

Mail.defaults do
  delivery_method MailgunDelivery
end

mail = Mail.new do
  from "sender@example.com"
  to "recipient@example.com"
  subject "testing mailgun"
  body "this is a test"
end

mail.deliver!

It could perhaps be nice if next version of hanami-mailer would contain predefined delivery methods for the popular services.

As for upload, I’d cast another vote for Shrine. This is what I use, but I agree that its maintenance story could be better.

I’ll weight in with couple preferences:

File Uploads Shrine is the most complete, flexible and well designed tool in the market for me. Using ActiveStorage in rails was always a bit annoying to me with all the magic and bloated object interfaces. As others said, I wouldn’t be discouraged by slower commit rate in recent years - it just works.

Deployment I’ve used coolify and have been really happy with it. Free, full control over your system and multiple ways to deploy. Yes you need a VPS but I prefer that over any cloud solution nowadays, every day. I really recommend I am currently using dockerfile + github based deployment.

It could perhaps be nice if next version of hanami-mailer would contain predefined delivery methods for the popular services.

I did not know that you could override the delivery method on the mail gem :open_mouth: Thanks for that! I think offering either pre-defined methods or docs on how to add the most popular services is an excellent idea :clap:

Shrine:

So much love for Shrine <3 I definitely need to check it out :smiley:

Deployment I’ve used coolify and have been really happy with it.

Thanks for sharing :person_bowing:

@moonglum I’m also investigating ways that the Bridgetown framework can promote agnostic gems / Rack solutions / etc., including a way to integrate with Hanami (aka add static sites at /blog, /docs, etc.). Bridgetown’s own dynamic server functionality is powered by Roda under the hood so it offers some compatibility with Roda plugins as well.

2 Likes

Pagy should also be on that list :slight_smile:

Very good point! I’m using Bridgetown for years for my homepage (so thanks, by the way <3). In my head, it is stored as a static site generator, because that’s the way I use it. But you are right: It should definitely be on the radar here as well :+1:

1 Like

Last time I checked Pagy worked “with any ORM”, as long as it implements some kind of active record pattern. Which means it does not really work well for ROM. Perhaps now things look a bit different.

(oh wow, for some reason this post sit in draft for two weeks and I did not notice that :see_no_evil_monkey:)

Taking a quick, superficial look at the documentation and code for this, it looks like making it work with a Relation dataset would be possible. I’m not sure about Repo.