30 Mar 2020
In this post I want to share a Ruby gem that is so good it’s crossed over into Python.
VCR allows you to record your test suite’s HTTP interactions and replay them during future test runs for fast,
deterministic and accurate tests.
Hello Old Friend
I’ve recently changed jobs and with this change came a new language (Python) and some new challenges.
One thing that hasn’t changed though is the need to interact with APIs, on my very first ticket I was working with a REST API.
Building APIs and testing them has been a core part of my job for years now, but that was with Ruby.
As I began to design a client for this API I was also searching Google for the “Python way” to design and test an API client.
My heart sank as I saw examples of people mocking APIs, I really didn’t want lose time messing around with mocks.
On a whim I Googled “VCR for Python” and boom up comes vcrpy
the Python version of my old friend vcr.
Install, Record and Replay
Installing VCR is simply pip install vcrpy
or pip3 install vcrpy
if you’re using Python3.
OK so lets say for example you’re working on a client for an API like Github, a basic version would look something like this.
Now we can use our client to fetch data about the user, lets take a simple use case and just get my name.
So far we’ve got a function using our client class to fetch the username value, but no tests.
Someone could be working on the Github client class in a few weeks time, make some changes and now my get_my_name()
function is broken. We can’t have that, so we’ll have to add a test.
Now we have a test it’s job done right? Well not quite…
Lets say our suite of tests is running on Jenkins or Gitlab a week from now and there’s a failure,
the build is broken and people are losing their minds.
It’s get_my_name_test()
that’s broken the build, but nobody knows how. Then you hear someone say the famous words:
Must be networking issues because it’s passing now.
You even catch yourself muttering:
But it ran fine on my machine….
The problem could well be due to networking issues, but networking shouldn’t affect your unit tests
, they should be able to run and pass offline on any machine.
This is where VCR comes in, with only one extra line of code, we add a vcr.use_cassette
block.
So when get_my_name()
uses our Client
class to make a request to Github’s API, all the HTTP request and response will be recorded.
This means that the VCR cassette will record and replay all HTTP interactions that happen within the execution of the with
block.
After the first run of this test, VCR will create a YAML file at the path we’ve provided, this is the VCR cassette.
This cassette has captured all HTTP interactions and can be used to replay them for future runs of this test.
As you can see in the example below, the cassette captures all details of the request and response such as: headers,
authorization, response codes and server details.
Where’s my Walkman?
So hopefully by now you’ve now seen how amazing VCR is and why the Ruby gem crossed over into the Python world.
I think it’s an incredible testing tool and highly recommend every developer use it when testing code that has HTTP interactions.
That’s all folks, as always I hope you enjoyed this post and if you’ve any questions feel free to leave me a comment below.
05 Mar 2019
The goal of this post is to share a flexible way of supporting multiple Bootstrap4 themes, using webpacker.
If you hate reading blog posts or just want to jump straight in to the code, I’ve created a demo app you can pull from Github here.
From Sprockets to Webpacker
Recently I began the process of migrating a Rails app from sprockets to webpacker.
I hit many snags along the way, but one of the most awkward ones was supporting multiple themes.
The Rails application I was working on had a “default” theme and a “dark” theme.
Both were compiled and served with some “Rails magic” and I did’nt really have to worry too much about how sprockets worked behind the scenes.
As the application grew, our dev team decided to move to webpacker, so we could take advantage of JS libraries like React.
I figured that since Bootstrap 4 uses SCSS and variable overriding, it’d be a pretty simple aspect of the migration.
Needless to say I was wrong.
If you’re a Rails developer who’s grown very used to the “Rails way” of doing things, webpacker and it’s configuration can seem a little daunting.
Sprockets handles the asset pipeline with little to no configuration. Webpacker does require some basic configuration and understanding of javascript importing, but it’s worth it in the long haul.
Getting started
The first thing you’ll need to do is change how your application loads in javascript and stylesheets.
So here we’re telling our application to use the webpacker helpers: javascript_pack_tag
and stylesheet_pack_tag
to load our assets or ‘packs’.
The current_theme
variable needs to return a theme string, for example: 'cerulean'
or 'darkly'
. This will be the name of our theme’s pack.
A good idea for current_theme
is to add a string column to your uses table called ‘theme’, where users theme selection can be saved.
Then write a UserHelper method to access this in the view for the current_user.
In the demo app I’ve just stored the variable as a simple cookie.
The next place we need to look is app/javascript/packs/application.js
. This is the default entry point for webpacker when it is compiling your assets.
So what does that mean? Basically everything that you want webpacker to compile must be imported here, this is fairly new to sprockets veterans.
In my application.js
I’m importing some standard libraries like bootstrap, then I’m importing all of my themes.
Structure is Key
An important thing to note here is my directory structure, it’s very important to keep your packs clearly separated from an early stage.
This will allow us to dynamically request a specific theme in our view code.
Lets focus on the theme app/javascript/packs/cerulean
, this theme contains a index.js file that you can use to import scss files.
Then in our cerulean.scss file we can import our custom theme variables, bootstrap and any other styles needed for our theme.
The most important thing to note here is the order of the imports. Here we take advantage of Bootstrap4 using SCSS, by importing our variables first to overwrite the bootstrap default variables.
This is what allows us to have custom colors, fonts etc.
Creating your own theme
As you can see the rest of our theme’s packs have exactly the same structure and exactly the same importing strategy.
This gives us a consistent and predictable folder structure for our code, but also allows fully flexible theming.
With this approach you can add a new theme in minutes!
So now all you have to do is create a _variables.scss
and override bootstrap to your liking.
If you’re like me and don’t have time to come up with a totally unique theme by yourself there’s lots of places online where you can buy themes, or just download free ones.
For my demo app, I used BootSwatch themes, you should check them out for ideas and color schemes.
11 Aug 2017
Recently my team was tasked with building an in house Kanban Ticketing system, similar to JIRA.
At it’s core the system would create and manage tickets, which are assigned to people to work on.
We needed to support several different types of tickets, using the JIRA example you could have: story, defect, request or epic tickets.
It became apparent to the team early on that all these tickets would have the exact same database structure, but would need to behave differently.
When to use Single Table Inheritance
Before diving into how to implement STI, I want to point out that this design choice only makes sense in certain circumstances.
You should ask yourself the following questions:
- Does your application have several sub-models that inherit from a parent model class?
- Do the sub-models all have the same attributes and database columns as each other?
- Do the sub-models need to behave differently from the parent model class?
If you answered yes to all of the above, then you’ve come to the right place.
If not you may need to consider another design like polymorphism, or even separate tables for each model.
Having attributes that are not used by all sub-models can lead to a tonne of nulls in your database.
Remember that STI is a great way of DRYing up models that share the same attributes, OO characteristics and database structure.
A real world example
I’m going to stick with the JIRA example given above, so the first thing we’ll do is generate a migration to create our ticket table.
Here’s an example migration for creating the ticket table.
The type
column we’ve defined is the default column used by STI, to store the sub-model name.
If you want to use a different column you just need to declare it your base model.
self.inheritance_column = :my_cool_column
Next we’ll need to define our Ticket model and it’s sub-models.
A simple Ticket model will look like this.
So we’ve defined our base Ticket model with a few validations and an after_create action.
Notice that we have not defined the method set_default_priority
yet, this will be done in the sub-models.
All of the sub-models we’ve defined have a unique implementation of the set_default_priority
function.
This is to illustrate that by using STI we can have sub-models share the same database table, yet have behave differently.
Using the rails console we can test that STI is working as expected.
Now we know STI is working as expected, we can begin to build our ticketing system on our ticket model.
We can add our routes and some controller actions.
Wrapping up
Through the use of Single Table Inheritance we’ve been able to design our sub-models to be flexible on a code level, while sharing the same database table.
I hope this post has given you a good understanding of how and when to implement Single Table Inheritance.
I’ve created a simple toy app with all the code shown above that you can find here on Github.
Feel free to clone it and experiment yourself!