Skip to content

Instantly share code, notes, and snippets.

@javierav
Last active August 3, 2021 18:17
Show Gist options
  • Save javierav/c657f2b4286bf3253c624ad6e473135d to your computer and use it in GitHub Desktop.
Save javierav/c657f2b4286bf3253c624ad6e473135d to your computer and use it in GitHub Desktop.
class ApplicationService
include Callable
include Publishable
end
module CallableService
extend ActiveSupport::Concern
module ClassMethods
def call(*params, &block)
s = new(*params)
klass = Class.new do
def initialize(instance)
@instance = instance
end
def method_missing(method_name, *args, &block)
@instance.on(method_name, &block)
end
end
block.call(klass.new(s)) if block
s.call
end
end
end
PostsController < ApplicationController
def create
respond_to do |format|
Posts::Create.call(create_params) do |on|
on.success do |post|
format.html { redirect_to post_path(post) }
format.json { render json: post }
end
on.failure do |errors|
format.html { render :new }
format.json { render json: errors }
end
end
end
end
end
class Posts::Create < ApplicationService
on :success, :add_event_to_log, :email_to_user
def initialize(params)
@params = params
end
def call
create_post
if @post.persisted?
publish :success, @post
else
publish :failure, @post.errors.details
end
end
private
def create_post
@post = Post.create(@params)
end
def add_event_to_log
EventLog.create(...)
end
def email_to_user
PostMailer.with(...).create_to_user.deliver_later
end
end
module Publishable
extend ActiveSupport::Concern
module ClassMethods
def self.on(event, *methods)
methods.each { |m| __listeners[event.to_sym] << m.to_sym }
end
def self.__listeners
@__listeners ||= Hash.new { |hash, key| hash[key] = [] }
end
end
def on(event, &block)
__listeners[event.to_sym] << block if block
end
private
def publish(event, *params)
self.class.__listeners[event.to_sym].each { |m| send(m) }
__listeners[event.to_sym].each { |block| block.call(*params) }
[event] + params
end
def __listeners
@__listeners ||= Hash.new { |hash, key| hash[key] = [] }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment