• Stars
    star
    147
  • Rank 251,347 (Top 5 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 8 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Group related classes together. No more silos. A solution to rails dystopia.

Drawers

Group related classes together. No more silos.

Gem Version Build Status Code Climate Test Coverage Dependency Status

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/
    │   ├── forms/
    │   │   └── new_post_form.rb
    │   ├── controller.rb  # or posts_controller.rb
    │   ├── operations.rb  # or post_operations.rb
    │   ├── policy.rb      # or post_policy.rb
    │   └── serializer.rb  # or post_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 'drawers'

Including the gem in your gemfile enables the new structure.

A note for ActiveModelSerializers

ActiveModelSerializers, by default, does not consider your controller's namespace when searching for searializers.

To address that problem, you'll need to add this to the serializer lookup chain

# config/initializers/active_model_serializers.rb
ActiveModelSerializers.config.serializer_lookup_chain.unshift(
  lambda do |resource_class, _, namespace|
    "#{namespace.name}::#{resource_class.name}Serializer" if namespace
  end
)

Note: as of 2016-11-04, only this branch of AMS supports a configurable lookup chain

Note: as of 2016-11-16, the master (>= v0.10.3) branch of AMS supports configurable lookup chain.

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/drawers.rb
Drawers.directory = 'pods'

Sets the folder for the new structure to be in the app/pods directory if you want the new structure separate from the main app files.

Co-Location of Tests / Specs

There are some mixed feelings about co-location of specs, so (by default), this monkey patch is not included.

# config/initializers/gems/rails.rb
module Rails
  class Engine
    # https://github.com/rails/rails/blob/5-1-stable/railties/lib/rails/engine.rb#L472-L479
    # https://github.com/rails/rails/blob/4-2-stable/railties/lib/rails/engine.rb#L468
    def eager_load!
      config.eager_load_paths.each do |load_path|
        matcher = /\A#{Regexp.escape(load_path.to_s)}\/(.*)\.rb\Z/
        # They key is the !(spec) added to the glob pattern.
        # You may need to modify this if your tests don't end with spec
        Dir.glob("#{load_path}/**/*!(spec).rb").sort.each do |file|
          require_dependency file.sub(matcher, '\1')
        end
      end
    end
  end
end

Your test suite command would then need to change to include the app directory.

rspec app/ spec/

And you'll still want to use the spec folder for spec_helper.rb, factories, and other support things.

Contributing

Feel free to open an issue, or fork and make a pull request.

All discussion is welcome :-)


The gem name 'Drawers' was provided by @bartboy011. Thanks @bartboy011!

The previous name of this gem was Rails Module Unification -- which, while a homage to its inspiration, Ember's Module Unification app architecture, it's quite a mouthful, and doesn't exactly make for a good gem name.

More Repositories

1

action_cable_client

A ruby client for interacting with Rails' ActionCable. -- Maintainers Wanted.
Ruby
251
star
2

emberclear

Encrypted Chat. No History. No Logs.
TypeScript
198
star
3

skinny_controllers

A pattern for allowing for easier testing of large projects' business logic
Ruby
89
star
4

ember-resources

An implementation of Resources with some helpful utilities
TypeScript
81
star
5

ember-query-params-service

Do you have controllers that _only_ parse query params? now you can get rid of them :)
TypeScript
57
star
6

eslint-plugin-decorator-position

ESLint plugin for enforcing decorator position
JavaScript
42
star
7

react-vs-ember

A subjective comparison of problem solving in react (and it's ecosystem) vs. ember. (Supporting code for blog series)
TypeScript
42
star
8

ember-data-resources

Resources for use with ember-data for reactive data (re)fetching
TypeScript
32
star
9

coc-ember

ember-language-server integration with coc, an intellisense / language server engine for (neo)vim
TypeScript
32
star
10

limber

Glimdown playground for documentation, demos, etc
TypeScript
31
star
11

ember-apply

Automatic integration and configuration from the EmberJS community
JavaScript
31
star
12

dotfiles

CSS
28
star
13

ember-statechart-component

Statecharts as components. No classes. Pure declarative state transitions.
TypeScript
28
star
14

ember-deep-tracked

Deep auto-tracking for when you just don't care, and want things to work (at the cost of performance in some situtations)
TypeScript
26
star
15

react-state-helpers

component state helpers for react to help reduce boilerplate and to not rely on redux for everything
JavaScript
25
star
16

ember-popperjs

Renderless Component for Popper.JS for you to easily make popovers in Ember.JS
JavaScript
23
star
17

static-route-paths

Depedency-free static route builder that can be used alongside any dynamic routing library to bring sanity to intellisense
TypeScript
23
star
18

ember-autostash-modifier

A modifier for syncing data to another location based on changing arguments.
JavaScript
22
star
19

ember-contextual-services

Services in Ember are scoped to the app as a whole and are singletons. Sometimes you don't want that. :) This addon provides ephemeral route-based services.
JavaScript
20
star
20

ember-addon-migrator

ember addon v1 to v2 migrator
JavaScript
19
star
21

optional-chaining-codemod

there should be more codemods for mundane stuff like this
JavaScript
16
star
22

qunit-assertions-extra

Collection of helpful assertions for use with qunit
TypeScript
16
star
23

aeonvera

A generic registration system aimed towards swing dance events (mirrored from gitlab)
Ruby
15
star
24

ember-three-boxes-demo

pretty graphics!
JavaScript
14
star
25

lazy_crud

Lazy way to implement common actions in controllers in Rails
Ruby
12
star
26

ember-repl

Tools for building playgrounds and repls with and for ember. Useful for interactive styleguides, too
TypeScript
12
star
27

highlightjs-glimmer

glimmer syntax highlighting with highlight.js
JavaScript
12
star
28

CryptoExchangeClient

Clients for multiple cryptocurrency exchanges. All clients have a shared interface for common actions.
F#
12
star
29

ember-tailwind-cli-demo

Demo of settingup tailwind 3 (cli) with emberjs
JavaScript
11
star
30

latency-tester

For debugging audio latency in headphones, VR, etc.
HTML
11
star
31

ember-computed-promise-monitor

Enable computed properties to be async-aware.
TypeScript
11
star
32

ember-jsqr

ember integration with jsQR - a very fast QR Code scanner
TypeScript
11
star
33

action-setup-pnpm

Correctly sets up node, pnpm, and cache for fastest possible pnpm installations
10
star
34

whats-new-in-ember-since-octane

Aggregate of features, patterns, etc across the ecosystem (not just ember)
10
star
35

ember-wordle

Ember implementation of the game: wordle, https://www.powerlanguage.co.uk/wordle/
JavaScript
9
star
36

ember-todomvc-tutorial

step-by-step guide to todomvc with ember
JavaScript
9
star
37

ember-lifecycle-component

A component with additional lifecycles for times when you may not need need a template.
JavaScript
9
star
38

case_transform-rust-extensions

Rust Extensions for the Ruby gem case_transform
Ruby
9
star
39

tanqueReact

p2p encrypted React-based Chat
JavaScript
8
star
40

ember-noop

helpers for conditional actions.
JavaScript
8
star
41

ember-component-stats

TypeScript
8
star
42

Iris-Recognition

iris recognition for imagerec
Objective-C
8
star
43

ember-msw-development

Do you want to test your API before the API is implemented? Is your API team slower than your frontend team? Do you need to mock data for devlepment and testing? Try MSW!
JavaScript
8
star
44

vite-demo

Ember + Vite
JavaScript
8
star
45

DynamicFluentBuilder.Net

The Fluent Builder Pattern without all the manual work!
C#
7
star
46

mesh-relay

relay server for mesh-chat
Ruby
7
star
47

ember-functions-as-modifiers-polyfill

Polyfill for https://github.com/emberjs/rfcs/pull/757
TypeScript
7
star
48

eslint-configs

My Preferred ESLint configs for all my projects. Uses only overrides so that they're easy to maintain and update
JavaScript
7
star
49

ember-ci-update

Tool to drastically reduce config and mental burden when managing CI
JavaScript
6
star
50

ember-addon-automated-ci

ember-cli-update blueprint to quickly bootstrap automated ci and maintenance
JavaScript
6
star
51

testing-library-ember

maybe one day @testing-library/ember. Based off of https://testing-library.com/docs/dom-testing-library/intro and https://github.com/emberjs/ember-test-helpers
JavaScript
6
star
52

project-linter

Create conventions for file placement for any kind of JS/TS project. React, Angular, Vue, Svelte, Ember, etc.
TypeScript
5
star
53

ember-spicy-forms

Form library that lets you handle the presentation
JavaScript
5
star
54

ember-lifecycle-utils

Utils for lifecycle-related things in Ember
JavaScript
5
star
55

Genre-Map

Genre Map of Electronic Music Genres
Ruby
5
star
56

ember-test-helpers-extra

Additional test helpers that build upon the primitives in @ember/test-helpers
TypeScript
4
star
57

emberconf-2019

HTML
4
star
58

crypto-exchange-client

A common typed interface for cryptocurrency REST and websocket clients
TypeScript
4
star
59

coc-glint

coc.nvim plugin for Glint, https://typed-ember.gitbook.io/glint/
TypeScript
4
star
60

spiced_rumby

A ruby gem that acts as a mesh-chat client.
Ruby
4
star
61

HH_Headset_Switchboard

Java
4
star
62

Pokemon-Information-Scraper

I java tool for scraping the pokemon info off of bulbapedia
4
star
63

ember-array-map-resource

Array.prototype.map, but as a Resource that prevents unneeded memory thrashing
TypeScript
4
star
64

glimdown

Plugin for the Unified ecosystem to use glimmer/ember in markdown
TypeScript
4
star
65

mesh-relay-phoenix

Relay for the mesh-chat network, written in Elixir, using Phoenix
Elixir
4
star
66

comsat

I replay selector and launcher for StarCraft 2
JavaScript
4
star
67

ubuntu-post-install-script

I've had to set up a lot of Ubuntu systems, and I'm tired of it! AUTOMATE!
Shell
4
star
68

active-inflector

TypeScript
3
star
69

rollup-plugin-glimmer-template-tag

Rollup plugin for providing support for both gjs and gts file formats
JavaScript
3
star
70

react-action-decorators

Because making event handling for everything is tiresome.
JavaScript
3
star
71

glimmer

Collection of resources for Glimmer, the language
HTML
3
star
72

baobab-ram

RAM visualizer, inspired by baobab, the Gnome Disk Usage Analyzer
JavaScript
3
star
73

meshchat-core

core functionality of meshchat implemented in ruby.
Ruby
3
star
74

demo-ember-dynamic-component-import

JavaScript
3
star
75

csharp-extensions

because csharp needs some help
C#
3
star
76

polaris-toucan-starter

Starter App using the Polaris edition of Ember along with the Toucan tailwind preset
JavaScript
3
star
77

polaris-starter

Get started with the Polaris Edition of Ember before it's released!
JavaScript
3
star
78

ember-function-component

Hooks and Function components in Ember, but without the "rules of hooks" from React
TypeScript
3
star
79

ultimate-accordion-ember-version

In collaboration with Isaac for a talk at the Framework Summit.
HTML
3
star
80

Sunset-Detector

Sunset Detector for CSSE 463 - Image Rec
Objective-C
3
star
81

signals-tutorial

HTML
2
star
82

git-workflow

Git workflows for projects
2
star
83

glimmer-tutorial

Interactive Tutorial
2
star
84

CSSE413-CTF-AI

A.I. project for CSSE413 at Rose-Hulman . We called it the "Overmind", cause we are all obsessed with Starcraft
Java
2
star
85

ember-shared-memory

share memory between instances of the same class/component or across any kind of class
JavaScript
2
star
86

ember-cli-swc-minifier

Addon to replace Terser with SWC for performant minification
JavaScript
2
star
87

gmusic-sync-service

A lightweight service for DJing google music
Ruby
2
star
88

changeset-recover

recover utility to generate changeset (https://github.com/changesets/changesets) entries when they'd previously been forgetten. Gives library maintainers a chance to double check merged work without fear of missing attribution in the CHANGELOG.
JavaScript
2
star
89

vitest-blueprint

ember-cli blueprint for boot-strapping vitest projects
JavaScript
2
star
90

rails-NPlusOneTests

Benchmarking various scenarios for handling n+1 in rails.
Ruby
2
star
91

library-provides-web-worker-in-ember-project

JavaScript
2
star
92

prismjs-glimmer

glimmer syntax highlighting with prism.js
JavaScript
2
star
93

MetaHash

Provides a subclass of Hash and a wrapper around Rails' serialize attribute for object-like access to hashes without validating existence of nested hashes
Ruby
2
star
94

ember-jSquirrels

Codemod that iterates through ember-addons on EmberObserver.com distracts jQuery, and submits PRs with the jSquirrels removed
JavaScript
2
star
95

gitlab-runner

Kubernetes + GCE configured gitlab-runner for docker-compose-powered C.I. workflows.
Shell
2
star
96

test-ember-vite-app

JavaScript
1
star
97

cjs-transform-in-ember

ember-auto-import would be easier, but here is how you import a cjs module
1
star
98

octane-ember-concurrency-repro

JavaScript
1
star
99

ember-cjs-transform-example

1
star
100

Hash-Pre-image-A.I.

Independent Study
C++
1
star