The app is organized into "modules" (not Ruby modules), like "Core", "Admin", "Directory", etc.
Each module contains models, controllers, and every other related class.
When I say "modules", I'm actually talking about domains, so why call them modules? I'm actually torn on this as I like how "modules" fits much better. But I also know it can be confusing. On the other hand, the only part where the word "modules" actually appears in code is in the directory name (
app/modules/<module_name>
).
base_model.rb
base_model/create.rb
base_model/find.rb
- R in CRUDbase_model/update.rb
base_model/delete.rb
If there are several ways a record can be created, updated, etc., we can have classes such as:
base_model/create/guest.rb
base_model/update/by_admin.rb
Example Usage:
BaseModel::Create.(attributes)
BaseModel::Update::ByAdmin.(attributes)
Some devs would frown at using the shorthand for
.call
, but I feel it really fits here with the "action-like" class naming.
Examples:
base_model/form.rb
base_model/form/create.rb
base_model/form/update.rb
base_model/form/signup.rb
Example Usage:
class BaseModelsController < ApplicationController
def new
@form = BaseModel::Form.new(create_base_model_params)
# or @form = BaseModel::Form::Create.new(create_base_model_params)
assert_policy! @form, :new?
end
def create
# Using custom method to pass in the user:
@form = BaseModel::Form::Create.for(current_user, create_base_model_params)
assert_policy! @form, :create?
if @form.valid?
# Create class should handle form object automatically
BaseModel::Create.(@form)
redirect_to '...'
end
end
def edit
@form = BaseModel::Form::Update.find(params[:id])
assert_policy! @form, :edit?
end
def update
@form = BaseModel::Form::Update.(params[:id], update_base_model_params)
assert_policy! @form, :update?
if @form.valid?
# Update class should handle form object automatically through its attributes
BaseModel::Update.(@form)
redirect_to '...'
end
end
private
def create_base_model_params
params.require(:base_model).permit(:a, :b)
end
def update_base_model_params
create_base_model_params
end
end
Should handle decorating a Form
object.
- BaseModel::Decorator.new(@form).tap do |base_model|
Also handle service objects:
@base_model = BaseModel::Find.(params[:id])
BaseModel::Decorator.new(@base_model)
# Collections:
@base_models = BaseModel::Find.recent()
BaseModel::Decorator.collection(@base_models) # Decorates each record
Store/run complex SQL queries
base_model/query/search.rb
base_model/query/geo.rb
Example Usage:
@base_models = BaseModel::Query::Geo.close_to(lat: -89, lng: 20, radius: 20.km)
# Distance would already been stored by previous call:
@base_models.by_distance.page(1).per(20)