Skip to content

Instantly share code, notes, and snippets.

@dvanderbeek
Last active December 22, 2015 17:40
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 dvanderbeek/7e9fa870e1cfddd03895 to your computer and use it in GitHub Desktop.
Save dvanderbeek/7e9fa870e1cfddd03895 to your computer and use it in GitHub Desktop.
An example of the "Hexagonal Rails" concept from Matt Wynne
# Tell, Don't Ask.
# Easily plug in new listeners that respond to the API we have defined:
# create_succeeded, create_failed
# Benefits:
# * Clean controller
# * Small classes with single responsibilities
# * Easy to test each individually
# * No need for model-level callbacks, just plug in the relevant listeners
# * No if statements - easy to follow logic
class ObjectController
def create
creator = ObjectCreator.new(self, ObjectFeedWriter.new, ObjectMailer.new)
creator.create("Test 123")
end
def create_succeeded(name)
puts "Controller: success (#{name})"
end
def create_failed(name)
puts "Controller: failure (#{name})"
end
end
class ObjectCreator
attr_reader :listeners
CALLBACKS = {
"create" => {
"true" => :create_succeeded,
"false" => :create_failed,
}
}
def initialize(*listeners)
@listeners = listeners
end
def create(name)
# Create the object, and *tell* the listeners what happened
created = Object.create
notify_listeners(CALLBACKS["create"][created.to_s], name)
return created
end
def notify_listeners(callback, *args)
listeners.each do |listener|
listener.send(callback, *args) if listener.respond_to? callback
end
end
end
class Object
def self.create
# Just for this example so we can run this and get success / failure randomly
[true, false].sample
end
end
class ObjectFeedWriter
def create_succeeded(name)
puts "Feed writer: success (#{name})"
end
def create_failed(name)
puts "Feed writer: failure (#{name})"
end
end
class ObjectMailer
# Here, we can only respond to succeeded if we do not want to send mail in the case of a failure
def create_succeeded(name)
puts "Mailer: success (#{name})"
end
end
ObjectController.new().create
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment