# Can a 3rd party gem "inject" itself into app initialization?

**URL:** <https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723>\
**Category:** questions\
**Created:** [November 15, 2022, 7:39pm UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723 "2022-11-15T19:39:57Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![trevorturk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/trevorturk/32/562_2.png) [@trevorturk](https://discourse.hanakai.org/u/trevorturk)\
**Post date:** [November 15, 2022, 7:39pm UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723/1 "2022-11-15T19:39:57Z")

</div>

Hello,

I’m attempting to make a contribution to the `alba` ruby gem so that it could automatically configure the itself when it’s installed in the context of a Hanami or Rails application.

Alba is a JSON serialization gem which requires calling `Alba.inflector = SomeInflector` to transform keys into `lowerCamel` etc. By default, the `inflector` is `nil` but I’d like it to be automatically set to `:active_support` for a Rails app and `:dry` for a Hanami app.

I believe I found the “correct” way to do this in Rails ([Add Alba::Railtie to set default inflector in Rails apps by trevorturk · Pull Request #274 · okuramasafumi/alba · GitHub](https://github.com/okuramasafumi/alba/pull/274/files)) but I’m having trouble finding a similar option in Hanami.

I noticed that Hanami doesn’t automatically require 3rd party gems, and there seems to be a nice system for creating your own initializers etc, but I haven’t found a way for a `provider` to submit a block of code to be executed when the app is initialized, etc. (I’m not sure if the `provider` system is what I’m looking for, tbh!)

No worries at all if this isn’t possible (or isn’t advisable) but I’d love any advice from someone with more experience than me.

Thanks!

---

<div class="post-metadata">

**Author:** ![jodosha](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/jodosha/32/710_2.png) [@jodosha](https://discourse.hanakai.org/u/jodosha)\
**Post date:** [November 17, 2022, 6:37pm UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723/2 "2022-11-17T18:37:29Z")

</div>

@trevorturk Please try with providers:

`config/providers/alba.rb`

```ruby
# frozen_string_literal: true

Hanami.application.register_provider :alba do
  prepare do
    require "alba"
    Alba.inflector = target["inflector"]
  end
end

```

cc: @timriley

---

<div class="post-metadata">

**Author:** ![trevorturk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/trevorturk/32/562_2.png) [@trevorturk](https://discourse.hanakai.org/u/trevorturk)\
**Post date:** [November 18, 2022, 5:48pm UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723/3 "2022-11-18T17:48:26Z")

</div>

Thank you so much for the reply!

I gave this a shot and wasn’t able to get it working quite as I expected. It looks to me like the `prepare` block isn’t being called, at least not when I would expect it.

Here’s the relevant line where I would expect to see an exception raised: [Add Alba::Railtie to set default inflector in Rails apps by trevorturk · Pull Request #274 · okuramasafumi/alba · GitHub](https://github.com/okuramasafumi/alba/pull/274/files#diff-1f9add2cb5f0cb7e36d1fc0f5f22d706f45a11044654aaf8ca5b56bcb26d5efbR8)

Here’s the Hanami app I’m using to test: [bookshelf/Gemfile at main · trevorturk/bookshelf · GitHub](https://github.com/trevorturk/bookshelf/blob/main/Gemfile#L35-L36)

Here’s the terminal output from my testing:

```auto
~/Code/hanami/bookshelf (master #) $ hanami console
bookshelf[development]> require 'alba'
RuntimeError: this file is loaded
from /Users/trevorturk/Code/alba/lib/alba/hanami_provider.rb:3:in `<top (required)>'

~/Code/hanami/bookshelf (master #) $ hanami console
bookshelf[development]> require 'alba'
RuntimeError: register_provider is called
from /Users/trevorturk/Code/alba/lib/alba/hanami_provider.rb:6:in `block in <top (required)>'

~/Code/hanami/bookshelf (master #) $ hanami console
bookshelf[development]> require 'alba'
=> true

```

In this test, I have 3 `raise` calls where I’m raising an exception to test things out. In the first case, you can see the file is required as expected. In the second case, you can see `register_provider` is called. In the third case, you can see the `prepare` block isn’t being called, or else I’d expect to see another exception saying `RuntimeError: prepare is called`.

Perhaps I’m misunderstanding when the `prepare` block is expected to be called, though. I’m only just running `hanami console` and then `require "alba"` which I thought may be enough to trigger the `prepare` block being called.

Apologies for all the noise here. I hope I’ve provided enough detail to explain my issue. Please let me know if I can provide anything else, or if there’s something else for me to test, etc.

Thank you!

---

<div class="post-metadata">

**Author:** ![alassek](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/alassek/32/532_2.png) [@alassek](https://discourse.hanakai.org/u/alassek)\
**Post date:** [November 21, 2022, 7:30pm UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723/4 "2022-11-21T19:30:27Z")

</div>

As far as I can tell, the Hanami console does not finalize your container. So that means the provider is lazy-loaded. You can trigger this provider by running `Hanami.app.prepare(:alba)` or just `Hanami.prepare` for all providers.

I _think_ during a full system boot your providers should be started for you. Is that a correct assumption @jodosha?

---

<div class="post-metadata">

**Author:** ![trevorturk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/trevorturk/32/562_2.png) [@trevorturk](https://discourse.hanakai.org/u/trevorturk)\
**Post date:** [November 21, 2022, 8:39pm UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723/5 "2022-11-21T20:39:34Z")

</div>

Thank you for the suggestions! I’m not sure if I’m testing things correctly, but I don’t believe I see the intended behavior here…

```auto
$ hanami console

bookshelf[development]> Hanami.app.prepare(:alba)
Dry::System::ProviderNotFoundError: Provider :alba not found

Hanami.prepare
=> Bookshelf::App

bookshelf[development]> require 'alba'
=> true

bookshelf[development]> Alba.inflector
=> nil

```

So, perhaps it seems like the provider isn’t being set. Keeping in mind, the `register_provider` call is happening in the gem, but still when I `require 'alba'` the other exceptions are raised, but the `register_provider` block doesn’t seem to be called.

---

<div class="post-metadata">

**Author:** ![trevorturk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/trevorturk/32/562_2.png) [@trevorturk](https://discourse.hanakai.org/u/trevorturk)\
**Post date:** [November 22, 2022, 3:19pm UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723/6 "2022-11-22T15:19:53Z")

</div>

I was reading through the Hanami 2.0 docs (congrats!) and found this section: [V2.0: Booting | Hanami Guides](https://guides.hanamirb.org/v2.0/app/booting/) which helped me understand the system a bit better, and I think we may have things working as expected when we call `Hanami.boot`:

```auto
$ hanami console
bookshelf[development]> require 'alba'
=> true
bookshelf[development]> Alba.inflector
=> nil
bookshelf[development]> Hanami.boot
RuntimeError: prepare is called
from alba/lib/alba/hanami_provider.rb:8

```

This is what I was hoping to see. And then, to see things working without the debugging exceptions in place:

```auto
~/Code/hanami/bookshelf (main) $ hanami console
bookshelf[development]> require 'alba'
=> true
bookshelf[development]> Alba.inflector
=> nil
bookshelf[development]> Hanami.boot
=> Bookshelf::App
bookshelf[development]> Alba.inflector
=> #<Dry::Inflector>

```

And then I think we’re all set.

So, I think we can chalk this up to me not understanding a few things about Hanami:

- Hanami’s default app scaffold doesn’t call `Bundler.require` etc, so you need to `require 'alba'` somewhere
- Hanami only makes providers lazy loadable when you call `Hanami.prepare` but doesn’t fully load them (including calling the `prepare` block)
- `Hanami.boot` fully loads all providers, so we see the behavior I expected

I think this all makes sense architecturally, just a bit less “magic” than Rails but with the benefit of a more flexible and performant system etc.

If anyone has comments or feedback, I’d love any advice you may have. I’ll try to wrap up the PR for the Alba gem, and I hope this conversation will be helpful for other gem authors that want to have Hanami providers built-in.

As a note, I would say that `Hanami.prepare` not calling the `prepare` block may be a bit confusing. Perhaps it would be worth considering adjusting the naming, but I understand with 2.0 just released that may be difficult, and I think this is easily attributable to my being new to Hanami generally.

Thanks!

---

<div class="post-metadata">

**Author:** ![alassek](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/alassek/32/532_2.png) [@alassek](https://discourse.hanakai.org/u/alassek)\
**Post date:** [November 22, 2022, 8:48pm UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723/7 "2022-11-22T20:48:56Z")

</div>

I think this is not quite how you want to develop a third-party provider, this is pretty new stuff so I would not be surprised if this is undocumented outside of a CHANGELOG.

Providers come from [dry-system](https://dry-rb.org/gems/dry-system/1.0/providers/), not from Hanami per se. This means that you really want to write a dry-system provider that can be used by anything built with dry-system, Hanami included.

First, build an actual class instance instead of using the DSL

```ruby
require "dry/system/provider/source"

module Alba
  class Provider < Dry::System::Provider::Source
    def prepare
      require 'alba'
    end

    def start
      Alba.inflector = target_container["inflector"]
    end
  end
end

```

Then, you can detect Hanami and inject it automatically. This is the best of both worlds: if someone is not using Hanami but _does_ have dry-system, they can still use this.

```ruby
if defined?(Hanami)
  Hanami.app.register_provider(:alba, source: Alba::Provider)
end

```

---

<div class="post-metadata">

**Author:** ![trevorturk](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/trevorturk/32/562_2.png) [@trevorturk](https://discourse.hanakai.org/u/trevorturk)\
**Post date:** [November 23, 2022, 12:12am UTC](https://discourse.hanakai.org/t/can-a-3rd-party-gem-inject-itself-into-app-initialization/723/8 "2022-11-23T00:12:44Z")

</div>

Ok, that’s great advice, thank you. I’ve updated the Alba PR. (It won’t let me post the link again for some reason, apologies.)

Please do let me know if you have any feedback on the specifics – for example, we could change the name of the file “dry\_system\_provider” and check `if defined?(Dry::System::Provider)` – I’m not sure if linguistically we want to stay at the `Dry::System` level, though, so I kept the names shorter.

Also, please let me know if this would be useful in any Hanami docs. I see the guides are fairly new, and I don’t want to propose a new section for gem authors etc, but it may be worth considering establishing recommended practices for others like me, and I’d be happy to contribute if helpful.

Thanks again!
