Last active
December 22, 2015 17:40
-
-
Save dvanderbeek/7e9fa870e1cfddd03895 to your computer and use it in GitHub Desktop.
An example of the "Hexagonal Rails" concept from Matt Wynne
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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