Module Unification / Resource Class/Module/Template organization for rails apps

rails

#1

The gem is Rails Module Unification https://github.com/NullVoxPopuli/rails_module_unification

I wrote this after spending about 2 years with Ember and really growing to like the ‘pods’ and soon to be module unification style of organizing files.

Here is the readme from the github:

What is this about?

With large rails application, the default architecture can result in a resource’s related files being very spread out through the overall project structure. For example, lets say you have 50 controllers, serializers, policies, and operations. That’s four different top level folders that spread out all the related objects. It makes sense do it this way, as it makes rails’ autoloading programmatically easy.

This gem provides a way to re-structure your app so that like-objects are grouped together.

All this gem does is add some new autoloading / path resolution logic. This gem does not provide any service/operation/policy/etc functionality.

All of this is optional, and can be slowly migrated to over time. Adding this gem does not force you to change your app.

The new structure

app/
├── channels/
├── models/
│   ├── data/
│   │   ├── post.rb
│   │   └── comment.rb
│   └── graph_data.rb
├── jobs/
├── mailers/
│   └── notification_mailer.rb
└── resources/
    ├── posts/
    │   ├── controller.rb
    │   ├── operation.rb
    │   ├── policy.rb
    │   └── serializer.rb
    └── comments/
        ├── controller.rb
        ├── serializer.rb
        └── views/
            ├── index.html.erb
            └── create.html.erb

Does this new structure mean you have to change the class names of all your classes? Nope. In the above example file structure, app/resources/posts/controller.rb still defines class PostsController < ApplicationController

Checkout the sample rails app in the tests directory.

The Convention

Say, for example, you have any class/module defined as:

module Api                    # {namespace
  module V3                   #  namespace}
    module UserServices       # {resource_name}{resource_type}
      module Authentication   # {class_path
        class OAuth2          #  class_path/file_name}
        end
      end
    end
  end
 end

As long as some part of the fully qualified class name (in this example: Api::V3::UserServices::Authentication::OAuth2) contains any of the defined keywords, the file will be found at app/resources/api/v3/users/services/authentication/oauth2.rb.

The pattern for this is: app/resources/:namespace/:resource_name/:resource_type/:class_path where:

  • :namespace is the namespace/parents of the UserService
  • :resource_type is a suffix that may be inferred by checking of the inclusion of the defined keywords (linked above)
  • :resource_name is the same module/class as what the resource_type is derived from, sans the resource_type
  • :class_path is the remaining namespaces and eventually the class that the target file defines.

So… what if you have a set of classes that don’t fit the pattern exactly? You can leave those files where they are currently, or move them to app/resources, if it makes sense to do so. Feel free to open an issue / PR if you feel the list of resource types needs updating.

Usage

gem 'rails_module_unification'

Including the gem in your gemfile enables the new structure.

Migrating

Each part of your app can be migrated gradually (either manually or automatically).

In order to automatically migrate resources, just run:

rake rmu:migrate_resource[Post]

This will move all unnamespaced classes that contain any of the supported resource suffixes to the app/resources/posts directory.

Configuration

# (Rails.root)/config/initializers/rails_module_unification.rb
RailsModuleUnification.directory = 'pods'