Skip to content

Instantly share code, notes, and snippets.

@holderbaum
Created July 9, 2013 08:11
Show Gist options
  • Save holderbaum/5955588 to your computer and use it in GitHub Desktop.
Save holderbaum/5955588 to your computer and use it in GitHub Desktop.
# Application namespace
class Manager
def creating_community(*args, &blk)
CreatingCommunity.new(*args).call(&blk)
end
def loading_community(*args, &blk)
LoadingCommunity.new(*args).call(&blk)
end
def updating_community(*args, &blk)
UpdatingCommunity.new(*args).call(&blk)
end
end
# Models
class Manager::User < Struct.new(:id, :email)
end
class Manager::Community < Struct.new(:id, :name)
end
class Manager::CommunityManager < Struct.new(:id, :user, :community)
def is?(user)
self.user == user
end
end
# Contexts
class Manager::CreatingCommunity
SuccessResponse = Struct.new(:community_id)
FailureResponse = Struct.new(:community, :errors)
def initialize(user_id, attributes = {})
@user_id = user_id
@attributes = attributes
end
def call(&block)
# NOTE: declare on top of context
back = On.new(:success, :failure, &block)
user = repo.user.get(@user_id)
community = repo.community.new(attributes)
repo.community.save community
manager = repo.community_manager.new user, community
repo.community_manager.save manager
back.call :success, SuccessResponse.new(community.id)
rescue SavingError => e
back.call :failure, FailureResponse.new(community, e.errors)
end
end
class Manager::LoadingCommunity
# NOTE: POROs should be private
SuccessResponse = Struct.new(:community, :community_manager)
def initialize(community_id)
@community_id = community_id
end
def call(&block)
# NOTE: declare on top of context
back = On.new(:success, :not_found, &block)
# NOTE: could be a habit (nested context)
community = repo.communitiy.get(@community_id)
community_manager = repo.community_manager.find community
if community
back.call :success, SuccessResponse.new(community, community_manager)
else
back.call :not_found
end
end
end
class Manager::UpdatingCommunity
SuccessResponse = Struct.new(:community_id)
FailureResponse = Struct.new(:community, :errors)
def initialize(user_id, community_id, attributes = {})
@user_id = user_id
@community_id = community_id
@attributes = attributes
end
def call(&block)
# NOTE: declare on top of context
back = On.new(:success, :unauthorized, :failure, &block)
user = repo.user.get(@admin_id)
# NOTE: could be a habit (nested context)
community = repo.communitiy.get(@community_id)
community_manager = repo.community_manager.find(community)
back.call(:not_found) && return if community.nil?
if community_manager.is?(user)
community.update_attributes @attributes
repo.community.save community
back.call :success, SuccessResponse.new(community.id)
else
back.call :unauthorized
end
rescue SavingError => e
back.call :failure, FailureResponse.new(community, e.errors)
end
end
# config/initializers/manager.rb
manager = Manager.new(magically_loaded_config_object)
Rails.configuration.manager = manager
class ApplicationController
def manager
Rails.configuration.manager
end
end
# some controller
class CommunityController < ApplicationController
def show
manager.loading_community(params[:id]) do |callback|
callback.on :success do |result|
expose :community, CommunityPresenter.new(result.community, result.community_manager)
end
callback.on :not_found do
raise ActionController::RoutingError
end
end
end
def new
expose :community, CommunityFormPresenter.new
end
def create
manager.creating_community(current_user.id, params[:community]) do |callback|
callback.on :success do |result|
redirect_to community_url(result.community_id)
end
callback.on :failure do |result|
expose :community, CommunityFormPresenter.new(result.community, result.errors)
render :new
end
end
end
def edit
manager.loading_community(params[:id]) do |callback|
callback.on :success do |result|
expose :community, CommunityFormPresenter.new(result.community)
end
callback.on :not_found do
raise ActionController::RoutingError
end
end
end
def update
manager.updating_community(current_user.id, params[:id], params[:community]) do |callback|
callback.on :success do |result|
redirect_to edit_community_url(result.community_id)
end
callback.on :failure do |result|
expose :community, CommunityFormPresenter.new(result.community, result.errors)
render :edit
end
callback.on :not_found do
raise ActionController::RoutingError
end
callback.on :unauthorized do
render :status => rand
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment