Skip to content

Instantly share code, notes, and snippets.

@bestie
Created October 24, 2015 20:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bestie/c640208979e469e67acb to your computer and use it in GitHub Desktop.
Save bestie/c640208979e469e67acb to your computer and use it in GitHub Desktop.
class ApplicationController
private
def core_application
CoreApplication.new
end
def adapter
RailsAdapter.new(self)
end
def current_user_id
session["user_id"]
end
def not_found
# render a custom page or override and handle polymorphically
end
end
class FollowsController < ApplicationController
def create
core_application.create_follow(adapter)
end
def render(args)
# For legacy reasons the same template for Javascript is rendered for all
# follow operations. This is a good example of customizing delivery
# mechanism concerns on a controller by controller basis.
super(args.merge(file: "update_follow_link"))
end
end
require "forwardable"
class RailsAdapter
extend Forwardable
def initialize(controller)
@controller = controller
end
attr_reader :controller
private :controller
def_delegators :params, :fetch
def_delegators :controller, :not_found, :current_user_id
def params
@params ||= controller.params.to_hash
end
# Here we handle our app's legacy response concerns:
# Sometimes we wish to perform a straight render for objects that we can show
# on a dedicated page.
def success_and_show(payload)
controller.render(locals: payload)
end
# For objects without dedicated pages, likes and follows for example, we
# either redirect back or update the page with some JavaScript depending on
# the client's capability.
def success_and_stay(payload)
controller.respond_to do |format|
format.html { controller.redirect_back }
format.js { controller.render(locals: payload) }
end
end
end
class CoreApplication
def create_follow(delivery)
with_user(delivery.current_user_id, not_found: not_found(delivery)) { |follower|
with_user(delivery.fetch("followed_id"), not_found: not_found(delivery)) { |followed|
# Here we take advantage of blocks and lexical scoping to layer up
# multiple find operations, unburdening the use case object from
# finding its two users.
CreateFollowing.new(
follower: follower,
followed: followed,
responder: delivery,
).call
}
}
end
private
def not_found(delivery)
delivery.method(:not_found)
end
# This application is still using ActiveRecord and has no repository layer.
# Defining a few methods like this will work for a while until repositories
# are extracted.
def with_user(id, not_found:, &success)
user = User.find_by_id(id)
if user
success.call(user)
else
not_found.call
end
end
end
class CreateFollowing
def initialize(follower:, followed:, responder:)
@follower = follower
@followed = followed
@responder = responder
end
attr_reader :follower, :followed, :responder, :follow
private :follower, :followed, :responder, :follow
def call
# We are sure that we have two users here so not too much can go wrong
create_follow
respond_successfully
end
private
def create_follow
@follow ||= follower.follow(followed)
end
def respond_successfully
responder.success_and_stay(follow: follow)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment