Stac Blog

November 4th, 2015 by Josh

Case Study: Sky

Early in 2015 Sky made a commitment towards expanding its technology hub to the North. With this expansion came a new set of challenges regarding resourcing and training a dedicated team in the area.

We were approached by Sky to help draw up and deliver a bootcamp for Ruby developers during their initial recruitment drive. This involved authoring a set of materials and workshops that could be open sourced and built upon by their developers. We were also tasked with assisting new waves of developers joining the company in getting up to speed with Sky's architecture and processes.

Sky enlisted our help due to such rapid growth in Leeds and wanting to respond quickly and efficiently to on-boarding developers. With our experience of the best development practices — and more specifically Ruby — we were a good fit.

The initial bootcamps were held between June and September, 2015.

Sky Bootcamp on GitHub


The bootcamp’s curriculum followed this loose outline:

  • Exercises: Introductory tasks such as opening up an interactive Ruby shell and object oriented programming
  • Workshops: Face-to-face workshops with candidates, highlighting different features and patterns found in common Ruby applications
  • Final Project: An end of course project allowing candidates to put their learnings into practice within the context of a real world application
  • Handover: Migrating the candidate from the bootcamp into a production squad. Sky use a similar engineering culture to Spotify

However, this framework was in place more as a point of reference than a strict linear path. We found a more informal course to be more inviting and intuitive to candidates who already knew how they approached learning and problem solving.


Exercises were mostly unattended to allow time and mental space for candidates to discover a learning style that worked for them. Following each exercise they were also encouraged to request feedback and code reviews. We used industry standard tools such as GitHub to monitor and review candidates' progress. Forking from the main sky-uk/ruby-bootcamp repository allowed us to see work in progress, as well as providing a platform for us to review work in Pull Requests.

Workshops were more involved with us gathering candidates together for either live coding sessions or talks. These were always informal to encourage group discussion, and we found these to be the most effective tools for teaching candidates the "Ruby way" of doing things.

The final project was another useful tool for evaluating the sum knowledge from all exercises and workshops within the bootcamp. We found this to be a great talking point amongst candidates as well as a useful way to gauge who would work well in squads together.

DSL workshop on GitHub


We're incredibly proud of the work we did with Sky, and enjoyed helping them with their expansion to Leeds. We're excited about what it will do for the future of technology in the North.

The feedback we received from candidates was well balanced and positive, with Stac being praised for our support and expertise in teaching Ruby to newcomers and experienced developers in the language.

If you'd like to take advantage of the learning materials produced during this project, it's being actively developed over on GitHub.

May 15th, 2015 by Josh

Building a Slack slash command with Sinatra, Finch and Heroku

Slack is awesome. We use it on a daily basis to keep in touch with pretty much everyone. With all the positive press it's been having, we thought we'd see if we could create a simple bot which would respond to slash commands.


For the purpose of this post, we're going to write a bot which responds to questions about our Hey! events. Ideally, it will respond to the following sub-commands:

  • /hey when - When is the next event
  • /hey what - Who is speaking at the next event, and where can I find out more information on each talk
  • /hey unsupportedcommand - Respond to missing commands with a friendly error message


To achieve this we're going to use a few free tools:

  • Sinatra - A Ruby DSL for creating web applications
  • Finch - A great tool for exposing local sites to the Internet
  • Heroku - Cloud hosting platform, deployed to via Git

You can find the Sinatra code for this post on GitHub.


Firstly we're going to write a simple Sinatra application to respond to Slack requests. At its most basic, it will receive a question from Slack which it needs to then return a plain text response.

We'll create a Gemfile to tell Ruby about our dependencies:

source ''

gem 'rack'
gem 'sinatra'
gem 'foreman'

We've also added Foreman here which we'll want to use when we deploy the application to Heroku.

Next up we'll write a basic version of our application, we'll put the contents into a file called (a Rack config file).

require 'sinatra'

post '/' do
  text = params.fetch('text').strip

  case text
  when 'when'
  when 'what'

run Sinatra::Application

Right now, this takes the incoming text parameter (the command typed by the user that Slack sends), and responds with some placeholder text depending on the sub-command.

Now let's see if we can get Slack talking to this application. Run the application with the following command from the project directory:

bundle exec rackup

Assuming everything has worked correctly, you should see something like:

[2015-05-14 17:41:14] INFO  WEBrick 1.3.1
[2015-05-14 17:41:14] INFO  ruby 2.1.1 (2014-02-24) [x86_64-darwin14.0]
[2015-05-14 17:41:14] INFO  WEBrick::HTTPServer#start: pid=57001 port=9292

This is where Finch comes in. We need to expose this application to the Internet so Slack can talk to it.

Once Finch is installed, we'll tell it to forward your local application to an external URL which we can give to Slack:

> finch forward localhost:9292

→ Requesting connection... ✔
→ Establishing secure connection... ✔

The following sites are now being forwarded. Press CTRL+C at any
time to end your session:

| Public URL                         | Private URL           |
|   | http://localhost:9292 |

Great, we're all set to configure Slack. Under your own Slack account, visit /services/new/slash-commands to add a new command, and configure it as below.

Setting up a Slack integration

When that's all saved, you should be able to test out your slash command integration! Try typing the following into any slack channel:

/hey when

And you should get back TODO. It works! Let's improve our application a little further.

require 'sinatra'

InvalidTokenError =

post '/' do
  raise(InvalidTokenError) unless params[:token] == ENV['SLACK_TOKEN']

  user = params.fetch('user_name')
  text = params.fetch('text').strip

  case text
  when 'when'

The next Hey! event will be held on the 20th May from 7:30pm at The Belgrave in central Leeds.

Hopefully see you then #{user}!

  when 'what'

The next Hey! event has two lectures planned. The first one is with Rich Fiddaman discussing everything hospitality. The second is with Matt Dix discussing Leeds Indie Food Festival.


    'Unknown command :cry:'


run Sinatra::Application

We've added a few things here:

  • Some real copy for the when and what sub-commands
  • We're raising a custom error if the request isn't coming from Slack. We can verify this by checking the request contains a private token that only you and Slack know about
  • We're also dealing with missing commands by falling back to a friendlier error message

Now when you type /hey when you should see something like this:

Working slash command

And if you mistype a command:

Missing command

Deploying to Heroku

Now we've got our application working and tested, we need to push it to Heroku. First create a Procfile so Heroku knows how to run the application:

echo 'web: rackup' > Procfile

Then add everything to Git and push it:

git init
git add -A
git commit -m "Initial commit"
heroku create
git push heroku

The heroku create command should return the URL your application is available at. Now your application is hosted! All that's left to do is change the URL in the Slack slash command settings and you're good to go.

Future Improvements

A few potential improvements to this application could be:

  • Remove the hard-coded event information. This would ideally pull from a Hey! API
  • Embed more information about the events in the what command
  • Add another sub-command to subscribe to the Hey! mailing list directly from Slack

We hope you've found this brief tutorial useful, let us know how you're using slash commands in the comments.

November 25th, 2014 by Josh

Log tagging in Rails

Sometimes when debugging issues in a live application, it can be hard to pair up log entries with application requests. The water can become even murkier when you've got many application processes accepting requests from multiple entry points (such as a load balancer).

One way of dealing with this is to tag each request with a unique ID, and use that ID to trace the request throughout its lifespan. Heroku has a great article on HTTP request IDs over here.

We needed to do this recently whilst deploying a large application to the Heroku platform, so we decided to look into log tags within Rails.

It's quite simple to get tags showing up in your Rails logs. Say we want to show the current request ID against each log entry, all we need to do is configure the log_tags setting in an initializer:

# config/initializers/log_tags.rb

My::Application.config.log_tags = [ :uuid ]

Now you can filter the log content by a particular request ID to see all output related to a single request (including any requests to assets if you are using Rails to serve static assets). Some services let you search for keywords in logs (such as PaperTrail) which can make this process easier.

For example, a controller request before tagging might look like this:

Started GET "/dashboard" for at 2014-11-24 15:48:30 +0000

And after:

[a00c54e0-874f-4358-a7b9-accef0c407c6] Started GET "/dashboard" for at 2014-11-24 15:48:30 +0000

This is particularly useful on Heroku, as they set X-Request-ID at the routing layer, meaning we can trace the request from the very start when the request gets accepted by the router (before it hits any of your application dynos).

It's worth noting that if X-Request-ID is not set, Rails will generate a unique ID for the request itself, meaning you can still use this feature.

As well as :uuid there are many other symbols you can use to provide more useful tags in your logs such as :host and :remote_ip. You can also provide a lambda/proc as an item in the settings array should you need to define more custom behaviour.

July 25th, 2014 by Josh

Hey!Stac Relaunched


Since we launched Hey!Stac a year ago, we've put on 12 events, had 35 talks and scoffed 704 brownies. Following a successful year we wanted to take stock of what the brand had become and where we wanted to take it in the future.

The end result was a new brand and site which presents the content in a way which allows it to be explored, and a new event format which we're launching in August.

You can read more about our plans for the future over here.

July 11th, 2014 by Josh

Case Study: NHSx

It's not often that you get a call from the NHS asking you to build a learning platform from scratch, using the latest technologies and delivered using agile management practices, but one February morning we were faced with exactly that.

Alongside good friend Harry Roberts (who's also done a nice write up of the project here) we met Jason, the NHS Leadership Academy’s Programme Lead, and after a short discussion we agreed this was definitely a project we'd like to be involved in.



The aim of the project was to build a learning platform that could be used to distribute educational content to anyone, at any level within the NHS. Whether they're a nurse or an executive, the platform needed to provide a place for them to take part in online programmes and report their progress back to coaches and programme leads.

On top of this, we also needed to make sure that the content packages were easy to author and manipulate. The platform needed to satisfy the users who administered the programme content just as much as the participants, as the quality of the content was just as important. There were already systems out there that supported a variant of what we needed, but they didn't fit the delivery model we had in mind, so we worked with the authors to build something more suitable for the platform. This resulted in a custom package format that meant authors could create learning content, add resources such as videos and images, and bundle it all up into a single upload to publish on the platform.


One of the most refreshing aspects to this project was how it was run and delivered. IT projects in the public sector are mostly publicised for being monolithic beasts resulting in bloated software and off-the-mark deliverables, but I'm glad to say that this project couldn't have been more different. It's a huge credit to Jason and his team that the project was delivered on time and to the specification.

On top of that, it was all done in an agile manner. We used tools like Trello and Slack to keep communication tight, and GitHub to keep conversations around code focused and relevant. During a series of 14 sprints we took the project from MVP to final deliverable. We used a staging server to preview code before production releases to ensure internally we were happy with how things worked, and we used automated deployment processes to push code live.

It was made even more enjoyable by Jason allowing the development team to just "get things done" without too much bike-shedding about how we were doing things, with the knowledge that we had the experience to deliver what was asked of us.


The main platform project was build in Rails 4, using a small handful of gems to speed up development of some common features. Alongside this, Harry worked on a UI Toolkit written in Sass. We worked on the functional and presentational sides of the application in separate branches (using Git), until we were ready to pair the work up.

A bit more detail about the technology used on this project:

  • To run the app itself we used Foreman and Unicorn. Using Unicorn allowed us to deploy the app with zero downtime using rolling restarts
  • Dragonfly was used a lot, not only for image uploads, but storing assets and content packages, and post-processing assets into cloud storage
  • App Signal meant we were notified of any production errors or performance regressions
  • Rack Cache helped us tune some heavy page requests and dragonfly downloads
  • Ember.js allowed us to create mini applications that we could embed into certain parts of the site which required richer features (such as private user portfolios)
  • jBuilder helped us build a more consistent API for the JavaScript applications by treating our JSON views just like any other Rails view
  • Capybara and Site Prism allowed us to thoroughly test the entire stack, along with the usual unit and controller specs

Alongside the technologies listed above we also created some private gems to support some more bespoke features of the platform such as content delivery (which used our custom package format), application permissions, and feature flags so we could easily enable features for certain participants.


It was a pleasure to be a part of such an agile team, especially on a project with such a large impact on its user base. We can't wait to see how the project evolves and matures as more learning content gets added, and we look forward to seeing the Leadership Academy continue to improve the jobs and lives of people who have used the platform, delivered by a small team in just a few months.

April 15th, 2014 by Josh

Action Mailer Interceptors

There's a little known feature in ActionMailer called Interceptors. If you've ever wanted to conditionally alter an outgoing email within a Rails application, Interceptors are what you're looking for.

Interceptors allow you to do exactly that, intercept an outgoing email. It's at this point you can choose to alter the to address, add a BCC address, or stop the mail from sending altogether.


Let's look at how Interceptors work. Firstly, define a class which responds to the .delivering_email class method. This will accept a single argument, the mail object:

class RedirectOutgoingMails
  class << self

    def delivering_email(mail) = ''


In the above Interceptor, we're overriding the to address to only send to regardless of who the mail was meant to go to.

Now the Interceptor needs registering with ActionMailer:


Once registered, this will intercept all mails. This might not be what you want, so let's look at adding it only for certain environments:

if %w( development staging ).include?(Rails.env)

Now we'll only have the mails intercepted in our development or staging environments. This can be particularly useful if you use sample data from production on staging, and don't want to accidentally email real users (although we wouldn't recommend directly using live data on staging).

Other Uses

As we have access to the entire mail object, we can do more than just alter the to address. We can, for example, stop delivery of the mail altogether:

class HaltMailDelivery
  class << self

    def delivering_email(mail)
      mail.perform_deliveries = false


Or we could BCC in all admin users to all emails:

class BccAdminsToAllMails
  class << self

    def delivering_email(mail)
      mail.bcc = User.where('admin = ?', true).pluck(:email)



One slight improvement we could make to the original example is to source the override email addresses from the ENV constant, so we don't need to make code changes when we want to change the to addresses:

class RedirectOutgoingMails
  class << self

    def delivering_email(mail) = to_addresses

    def to_addresses


Now all we need to do is change the config value in MAIL_INTERCEPT_ADDRESSES and restart our application and the changes will take effect.