# Hanami 2 actions/views structure

**URL:** <https://discourse.hanakai.org/t/hanami-2-actions-views-structure/650>\
**Category:** proposals\
**Created:** [February 16, 2022, 9:12am UTC](https://discourse.hanakai.org/t/hanami-2-actions-views-structure/650 "2022-02-16T09:12:01Z")\
**Posts on this page:** 2\
**Page:** 1

<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:** [February 16, 2022, 9:12am UTC](https://discourse.hanakai.org/t/hanami-2-actions-views-structure/650/1 "2022-02-16T09:12:02Z")

</div>

# Option 1

## Directory Structure

```auto
lib/
  app_template/
    action.rb # AppTemplate::Action < Hanami::Action
    view.rb # AppTemplate::View < Hanami::View
    views/
      context.rb # AppTemplate::Views::Context < Hanami::View::Context
      part.rb # AppTemplate::Views::Part < Hanami::View::Part
slices/
  main/
    lib/
       action.rb # Main::Action < AppTemplate::Action
       view.rb # Main::View < AppTemplate::View
       actions/
         authentication.rb # Main::Actions::Authentication # CUSTOM MODULE
       views/
         context.rb # Main::Views::Context < AppTemplate::Views::Context
         part.rb # Main::Views::Part < AppTemplate::Views::Part
         part_builder.rb # Main::Views::PartBuilder < Hanami::View::PartBuilder # OPTIONAL
         helpers/
           authentication.rb # Main::Views::Helpers::Authentication # CUSTOM MODULE
         parts/
           article.rb # Main::Views::Parts::Article < Main::Views::Part
    actions/
      home/
        index.rb # Main::Actions::Home::Index < Main::Action
    views/
      home/
        index.rb # Main::Views::Home::Index < Main::View

```

## CLI UX

```auto
bundle exec hanami generate view main parts.foo
# => Error `parts' is a reserved namespace

bundle exec hanami generate view main helpers.foo
# => Error `helpers' is a reserved namespace

```

## Notes

- Views and Actions have almost identical structure
- `lib/app_template` contains action/view code that is inherited by all the slices’ actions/views
- `slices/main/lib` contains action/view code that is inherited by all the actions/views of the `main` slice
- `slices/main/{actions,views}` contains concrete actions/views for the `main` slice
- `Main::Views::{Helpers,Parts}` are reserved namespaces to avoid name clashes with concrete views
- It’s recommended to put custom action modules in `slices/main/lib/actions` under the `Main::Actions` namespace
- It’s recommended to put custom view modules in `slices/main/lib/views/helpers` under the `Main::Views::Helpers` namespace

* * *

# Option 2

## Directory Structure

```auto
lib/
  app_template/
    action.rb # AppTemplate::Action < Hanami::Action
    view.rb # AppTemplate::View < Hanami::View
    views/
      context.rb # AppTemplate::Views::Context < Hanami::View::Context
      part.rb # AppTemplate::Views::Part < Hanami::View::Part
slices/
  main/
    lib/
       action.rb # Main::Action < AppTemplate::Action
       view.rb # Main::View < AppTemplate::View
    actions/
      authentication.rb # Main::Actions::Authentication # CUSTOM MODULE
      home/
        index.rb # Main::Actions::Home::Index < Main::Action
    views/
      context.rb # Main::Views::Context < AppTemplate::Views::Context
      part.rb # Main::Views::Part < AppTemplate::Views::Part
      part_builder.rb # Main::Views::PartBuilder < Hanami::View::PartBuilder # OPTIONAL
      helpers/
        authentication.rb # Main::Views::Helpers::Authentication # CUSTOM MODULE
      parts/
        article.rb # Main::Views::Parts::Article < Main::Views::Part
      home/
        index.rb # Main::Views::Home::Index < Main::View

```

## CLI UX

```auto
bundle exec hanami generate view main parts.foo
# => Error `parts' is a reserved namespace

bundle exec hanami generate view main helpers.foo
# => Error `helpers' is a reserved namespace

```

## Notes

- Views and Actions have almost identical structure
- `lib/app_template` contains action/view code that is inherited by all the slices’ actions/views
- `slices/main/{actions,views}` contains concrete actions/views AND base classes for the `main` slice
- `Main::Views::{Helpers,Parts}` are reserved namespaces to avoid name clashes with concrete views
- It’s recommended to put custom action modules in `slices/main/actions` under the `Main::Actions` namespace
- It’s recommended to put custom view modules in `slices/main/views/helpers` under the `Main::Views::Helpers` namespace

* * *

# Option 3

## Directory Structure

```auto
lib/
  app_template/
    action/
      base.rb # AppTemplate::Action::Base < Hanami::Action
    view/
      base.rb # AppTemplate::View::Base < Hanami::View
      context.rb # AppTemplate::View::Context < Hanami::View::Context
      part.rb # AppTemplate::View::Part < Hanami::View::Part
slices/
  main/
    lib/
       action/
         base.rb # Main::Action::Base < AppTemplate::Action::Base
         authentication.rb # Main::Action::Authentication # CUSTOM MODULE
       view/
         base.rb # Main::View::Base < AppTemplate::View::Base
         context.rb # Main::View::Context < AppTemplate::View::Context
         part.rb # Main::View::Part < AppTemplate::View::Part
         part_builder.rb # Main::View::PartBuilder < Hanami::View::PartBuilder # OPTIONAL
         helpers/
           authentication.rb # Main::View::Helpers::Authentication # CUSTOM MODULE
         parts/
           article.rb # Main::View::Parts::Article < Main::View::Part
    actions/
      home/
        index.rb # Main::Actions::Home::Index < Main::Action::Base
    views/
      home/
        index.rb # Main::Views::Home::Index < Main::View::Base

```

## Notes

- Views and Actions have almost identical structure
- Singular namespaces are for base classes, plural namespaces are for concrete actions/views
- `lib/app_template` contains action/view code that is inherited by all the slices’ actions/views
- `slices/main/{action,view}` contains base classes AND utility code for the `main` slice
- It’s recommended to put custom action modules in `slices/main/action` under the `Main::Action` namespace
- It’s recommended to put custom view modules in `slices/main/view/helpers` under the `Main::View::Helpers` namespace

---

<div class="post-metadata">

**Author:** ![timriley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/timriley/32/621_2.png) [@timriley](https://discourse.hanakai.org/u/timriley)\
**Post date:** [February 16, 2022, 10:17am UTC](https://discourse.hanakai.org/t/hanami-2-actions-views-structure/650/2 "2022-02-16T10:17:01Z")

</div>

Thanks for laying these out, @jodosha, it’s supremely helpful!

I think **Option 3** is the most extensible, but at the cost of it perhaps not feeling as nice if you never add extra classes related to your base action or view, etc.

However we know this will _definitely_ happen for nearly every non-trivial Hanami app, because we’ll be generating a per-slice context class, and the views will want part classes, etc.

**Option 1** might _feel_ nicer in some usages, since you can just inherit from `< Main::View` instead of `< Main::View::Base` , but it comes with added cost about having to worry about name pollution of your pluralised `Views` namespace, plus the fact that some users may wonder why we’re populating `Main::Views` classes via two different directories.

My own instinctive lean is towards **Option 3** , but I realise I probably have a different sense for what feels good in application structures to what we might want to present to our users by default.

OTOH, that could be a signal, and perhaps we should _lean into_ being different here, because we can _teach_ our users something via that difference, that e.g. having a whole namespace for your base action and view classes is useful because you _should_ be decomposing that behaviour into smaller units (which is in fact what is encouraged by our action/view library design too).

With all of that said, I do acknowledge that how the Hanami framework presents itself to our users via its file and class structures is something you care a lot about, so I don’t want to push you down a road that feels uncomfortable to you. We should each trust each other to make these decisions like these 😄
