Skip to content

Instantly share code, notes, and snippets.

@jgaskins
Created June 25, 2013 19:27
Show Gist options
  • Save jgaskins/5861556 to your computer and use it in GitHub Desktop.
Save jgaskins/5861556 to your computer and use it in GitHub Desktop.
PORO controllers in a Rails-like framework
# A PORO controller can be just an object that takes the request, response,
# and streaming-socket objects into the constructor. It can do the typical
# ActionController things, like get the objects it needs and tell the response
# to render the view with those objects.
class WidgetsController
attr_accessor :request, :response, :stream
def initialize(request, response, stream_socket)
@request = request
@response = response
@stream = stream_socket
end
def index
@widgets = Widget.all
response.render widgets: @widgets
end
end
# To make testing easier, just extract the widget assignment to its own method:
class WidgetsController
# ...
def index
response.render widgets: all_widgets
end
private
def all_widgets
@widgets ||= Widget.all
end
end
# You could test this controller with a unit test (let's pretend we wrote this first).
describe WidgetsController do
let(:request) { double('Request') }
let(:response) { double('Response') }
let(:stream) { double('Stream Socket') }
let(:widget) { double('Widget') }
let(:controller) { WidgetsController.new(request, response, stream) }
it 'renders the list of all widgets' do
controller.stub(all_widgets: [widget])
response.should_receive(:render).with(widgets: [widget])
controller.index
end
end
# If you aren't using streaming, you could make it an optional argument and
# cut down on test doubles. If you aren't doing anything with the request
# (like params or format), you can use an anonymous stub there to reduce
# headspace even more.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment