How to Reuse Relations Across Slices in Hanami?

Hi everyone,

I’m new to Hanami and trying to structure my application correctly. I need some guidance on how to properly share relations across slices.

Since relations define our low-level data sources, my understanding is that they should be defined once and reused in repositories across different slices. Is this the recommended approach? If so, how can I achieve this?

For example, I have a relation defined in app/relations/books.rb, and I want to use it in my slices/web/repos/book_repo.rb. However, when I try to reference it in the repository, I get the following error:

undefined local variable or method 'books' for an instance of Web::Repos::BookRepo

Here’s a simplified version of my setup:

Relation (Defined at the application level)

# /app/relations/books.rb
module MyApp
  module Relations
    class Books < MyApp::DB::Relation
      schema :books, infer: true
    end
  end
end

Repository (Inside a slice)

# /slices/web/repos/book_repo.rb
module Web
  module Repos
    class BookRepo < Web::DB::Repo
      def all
        books.to_a
      end
    end
  end
end

What is the correct way to access the books relation inside my slice’s repository? Should I be explicitly importing or registering it somewhere?

Any help or best practices would be greatly appreciated!

Hi everyone,

I believe I’ve found a solution after reading a great discussion in this forum.

To properly share relations across slices, the slice should not have its own db folder. You can achieve this by generating the slice with the --skip-db option:

hanami generate slice web --skip-db

Additionally, it’s necessary to enable relation sharing by configuring the application to import database settings from the parent:

module MyApp
  class App < Hanami::App
    config.db.import_from_parent = true
  end
end

Does this approach align with best practices, or am I unintentionally relying on a side effect?

Any feedback or recommendations would be greatly appreciated! :blush:

No, this is precisely what import_from_parent is intended to do. I believe you have the right mindset here; Relations defined in app/ that are shared across slices, and slice-specific Repos is what I would recommend.

However, there’s no harm in having Slice-specific Relations, depending on how specialized the scope logic gets. If you end up collecting stuff in your Relation that doesn’t belong in other Slice contexts, splitting that up is an option. But you probably don’t need to start out like that.

2 Likes