Why We Teach Rack in our Ruby on the Server Bootcamp
When I teach our web services class Ruby on the Server, a question I
occasionally get from students is why we spend half of the first day learning about Rack.
After all, Rails is the heavyweight of the Ruby ecosystem, and what most people
come to learn about.
One of the core themes of the class is to demystify Rails, which has a lot of
features that people often describe as “magic.” When people say that, what
they usually mean is an interface with a level of abstraction that frees you
from needing to know what’s going on under the hood. It gives you that “it
just works” sensation. Being free to build your application without worrying
about the underlying implementation is wonderful, but sadly, many developers
never peel back the layers and attempt to understand how it works.
At Big Nerd Ranch, our approach is to teach the bare bones first. We apply this tactic over and
over throughout the week, from rendering an ERB template by hand to defining
resourceful HTTP routes and mapping them individually to controller actions. We
make you do it the hard way before we teach you the magical incantations. Think
of it as watching the Wizard of Oz backwards. Instead of jumping directly into
Rails and seeing your web service magically spring to life, we start with Rack.
This is not just some pedagogical theory, though. It has practical value.
Sufficiently complex Ruby web services are often split into multiple
sub-services. Rack is a specification designed to build modular web services
that can be composed. Whether it’s a simple web interface to view your
background job queue or a full blown service-oriented architecture, you’ll
encounter such services in the wild. They will almost certainly be Rack apps.
“Not Rails apps?” you ask. The wonderful thing is that Rails apps are Rack
apps, and so are Sinatra, Padrino and Lotus apps. It would be easier to note
exceptions than to compile a list. These days, it’s safe to assume that if it’s
serving up HTTP responses, and it’s written in Ruby, then it’s a Rack app.
Understanding Rack is essential to deeply understanding how a complex web service
written in Ruby works. We’re not training you to be able to complete the
cliché blog tutorial. We want you to go home armed with the knowledge needed to
contribute to the kind of projects we work on.
Change of Rack Maintainer
With such wide usage, it came as a bit of a shock when the Rack core team
announced that Rack is considered complete. Aaron
Patterson will step up to maintain point releases going forward, but the team
does not expect to release version 2.0 of Rack. I recommend reading the
announcement yourself for a fuller picture, but the gist of it is that Rack is
showing its age.
There’s a multitude of new protocols on the horizon, like WebSockets, HTTP2,
and Server-Sent Events, to name a few. Many implementations of the Ruby
language now have usable multi-threading. The world simply isn’t the same place
it was when the Rack specification was introduced.
The Future of Ruby Web Services
That said, for now, and a long time to come, you will still use Rack. It remains an
important part of the Ruby web stack and won’t be going anywhere for a while.
Even so, we need to be thinking about the future. Where will Ruby fit into
the event-driven, “real-time” future of the web? Does it have a place?
Whatever comes next needs to be designed for a world where resources can exist
not only as documents, but as streams. Our Chief Learning Officer Aaron Hillegass
talked about this at AltConf earlier this year.
I think that if there’s room for Ruby in the traditional web service space,
where Java is king, then there’s room in this new space. Go and Elixir may be
extremely well suited for the job, and I expect them to capture a significant
portion of the market. However, Ruby has a winning characteristic: its flexibility.
The ease with which you can kick off a project, iterate on the design and get
a working product out the door is unparallelled.
I share Aaron’s excitement for the future of WebSockets, Server-Sent Events
and the like. However, I think there’s reason to keep some stock in stateless
protocols like HTTP: the inherent unpredictability of mobile network
connectivity. WebSockets are awesome for broadcasting events to multiple
devices in near real-time, partly because they hold open a persistent
connection. However, when you lack the requisite, stable connection, that
characteristic is less exciting. As much as we all want
ubiquitous, reliable broadband, unreliable connectivity is, sadly, the state
of mobile internet for the foreseeable future. When you get off a plane in an unfamiliar city,
being able to send a request for a car from your favorite rideshare app under
sketchy network conditions will be of higher value than seeing real-time car
locations on a reliable connection.
Event sourcing application state over a streaming protocol will remain
unpractical for quite some time. Imagine downloading every change that ever
occurred to a Wikipedia page over a WebSocket just to get the end result.
Consequently, I believe we’ll see a proliferation of hybridized web services.
In between traditional request-response services and event sockets for
everything, there’s a whole world of practical applications where resources can
exist as documents or streams, like chat transcripts and real-time chat, or Wikipedia
pages and real-time, collaborative editing.
The building blocks for event-driven web services have been making their way
into the Ruby ecosystem for a few years now. Couple that with battle-tested,
traditional web service frameworks like Rails, and Ruby is in an excellent
position to continue being the language of choice for web developers.
ActionController::Live with version 4.0, although it feels
bolted on at best. Rails doesn’t have a first-class way of representing
resources as streams. Others have been researching ways to create hybrid
resourceful/eventful web services:
- Matt Thompson’s Rocket exposes
resources in a traditional RESTful manner, and as a stream using a non-standard
HTTP method (SUBSCRIBE) and Server-Sent Events.
- Faye is pub/sub
messaging system that can be mounted into a Rack application.
- Aaron Patterson
has done some research on a successor to Rack 1.0, but it’s still
very experimental. It may reduce the scope of Rack by dropping middleware, but
will hopefully be compatible with new streaming protocols.
What It Means for Ruby on the Server
For the foreseeable future, we’re still teaching Rack. It’s a stalwart of Ruby
web services, and isn’t going away any time soon. We believe that understanding
Rack is paramount for being able to tackle complex Ruby applications today, and
for a long time to come.
That said, things are changing. These are exciting times, and we’re making the most of them. Always learning,
we’re putting an increasing focus on evented protocols across all our
engineering divisions. We’re conducting internal experiments and doing awesome
work for clients.
What we learn, you’ll learn. Coming early next year, the Ruby on
the Server bootcamp will teach you to build evented web services as a first-class
topic. We’re excited about this unchartered territory, and seeing what will be
built in it.