Skip to content

Commit

Permalink
Merge pull request #8 from Interfolio/jlt/class-organization
Browse files Browse the repository at this point in the history
JLT: Start a class organization for Ruby Classes
  • Loading branch information
joseluistorres committed Sep 29, 2020
2 parents 48d59e6 + 5f29738 commit ee40f56
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 0 deletions.
98 changes: 98 additions & 0 deletions class_organization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
## Class Organization

In Ruby, Classes are processed from top to bottom. Therefore, order matters (most of the time). For example, sometimes included Modules will need to refer to constants in the including Class. So constants should be defined before Module inclusions are specified. Otherwise we’re free to organize our Classes how we want but thoughtful organization makes the story a Class tells easier to understand.

In general, let the following set of rules be your guide for class organization in Ruby Classes:

1. Put more general / more important things at the top of a Class.
2. Put more specific / less important things next.
3. Group collaborating methods in close proximity using a top-down flow.
```ruby
def my_composed_method
a
b
end

def a
# ...
end

def b
# ...
end
```
1. **Note**: If it is proving difficult to group collaborating methods in close proximity then that may be an indicator that the Class is doing too much. Look for secondary responsibilities that can be broken out into a new Object.


```ruby
require "my_class" # Require any functionality needed for the whole Class

# MyNamespace is a context where multiple classes either interact with each other or are used in the same domain context.
# MyClass is a ... # Document the purpose of this Class
class MyNamespace::MyClass < MyNamespace::MyBaseClass # Class definition with fully qualified Superclass (when applicable)
MY_CONSTANT = "MyConstantValue".freeze # Constants; May apply to included modules as well so must come first

Error = Class.new(StandardError) # Other types of Constants like StandardError derivatives; May also be used by included modules

extend MyExtension # Extensions

include MyMixin # Mixins (Less specific than Extensions)

as_abstract_class # Important macros

before_validation # Callbacks — in callback order
before_save
after_create

attr_accessor # Virtual Attributes
attr_writer
attr_reader

belongs_to :my_associated_object # Associations

has_one :my_other_related_object # Less "important" Object associations

validates :my_attribute,
presence: true # Validations

delegate :some_method,
to: :my_associated_obj # Delegations

scope :my_scope, → { } # Scopes

def self.my_class_method... # Class Methods

def initialize... # Initialize Method

concerning :<SomeConcern>s do
# ...
end

def display_name... # Display Methods

def my_important_method... # Important Instance Methods → Less Important Instance Methods

def my_risky_method
# Code that may raise a StandardError
rescue => ex # De-dented to method level — doesn't require begin/end; Also helps encourage Single Responsibility Principle
# Log exception, etc.
end

private

def inspect... # Inspect Methods

def my_private_method... # Private Methods

class MySubClass # Classes only intended for use by the current Class
end
end
```

## Coding Style

This is our team style guide. It is impartial and generally accepted by the Ruby community. So be it for us.
- Note: there will be rare exceptions on some of the guidelines. That is OK.

Also, consider the [Rails Style Guide](https://github.com/bbatsov/rails-style-guide).
We don't necessarily follow these 100%. But they're useful guides when in doubt.
69 changes: 69 additions & 0 deletions rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,75 @@ AllCops:
Rails:
Enabled: true

Layout/ClassStructure:
Enabled: true
Categories:
module_inclusion:
- extend
- include
- prepend
callbacks:
- before_validation
- after_validation
- before_save
- around_save
- before_create
- around_create
- after_create
- before_update
- around_update
- after_update
- after_save
- before_destroy
- around_destroy
- after_destroy
- after_commit
- after_rollback
- after_initialize
- after_find
mounted_uploaders:
- mount_uploader
attributes:
- attr_accessor
- attr_reader
- attr_writer
- serialize
associations:
- belongs_to
- has_one
- has_many
- has_and_belongs_to_many
- accepts_nested_attributes_for
validations:
- validation_flag
- validates
- validates_associated
- validates_with
- validates_each
delegations:
- delegate
scopes:
- scope
concerning_blocks:
- concerning
ExpectedOrder:
# - constants
- module_inclusion
- callbacks
- mounted_uploaders
- attributes
- associations
- validations
- delegations
- scopes
- public_class_methods
- initializer
- concerning_blocks
- public_methods
- predicates
- protected_methods
- private_methods

#################
# Overrides #
#################
Expand Down

0 comments on commit ee40f56

Please sign in to comment.