Posts
-
A Look Through the Changelog.com Source Code
Changelog recently open sourced the Phoenix application that provides the backend for their website and podcast publishing platform. They published an announcement post along with the source code on Github.
This was a good oppurtunity for me to take a look at someone else’s Phoenix application, to see how they do things. Below you can find the notes I made while looking through the source.
The Basics
- Phoenix 1.2
- Elixir 1.3
- Ecto 3.0
- Webpack 2.0
Dependencies
The following dependencies were ones I didn’t recognise or found interesting:
- timex - Full-featured Elixir Time Library
- ex_machina - Test data generator
- scrivener - Pagination
- cmark - Markdown rendering
- arc - File upload
- hashids - Reversible non-numerical IDs
- bamboo - Transactional email
- ecto_enum - Enums for Ecto models
- con_cache - Key-Value store
- credo - Elixir Static Analysis
Routes
- Separate
admin
andpublic
pipelines. admin
pipeline sets layout, requires admin.auth
pipeline looks for current user.public
pipeline usesLoadPodcasts
plug to pre-load podcasts.- Most paths are served by
PageController
, which loads a template based on the action name. /weekly
and/nightly
routes are for mailing list subscriptions.- Sub-paths for subscribe, confirm, unsubscribe, etc.
Lib
ConCache
is a worker child of the ChangeLog application./uploads
directory is setup to be served statically for dev only inEndpoint
./lib/changelog/enums.ex
defines a custom column type for the podcast status. This could be used in multiple models./lib/changelog/factory.ex
is a collection of factories for the various models, usingex_machina
./lib/changelog/hashid.ex
sets up the encode/decode for the hashed IDs. Salt also set here.- Commonly used regular expressions are defined in a
Regexp
module. Scrivener
default page size is setup inRepo
.- Page
<title>
set viaMeta.Title
andMeta.AdminTitle
. Imported inLayoutView
. - Other metadata (twitter, images, feeds, description) set by additional Meta modules.
- craisin is the name of the application that handles Campaign Monitor access. Is based on HTTPoison with multiple resources as sub-modules. All mailing list alterations done over API, no local DB records for this.
Models
- Channels are not currently exposed in the public interface. They are playlists for episodes from different podcasts.
- Not all the models are
Ecto
backed.Newsletter
for example. - Use of
Ecto.get_change
to delete records where thedelete
key has been set in a changeset. Pattern is shown inEcto.Changeset
documentation. Uses a virtual delete field to remove nested records. Untested. (1) Episode.with_numbered_slug
is used to scope episodes using a regex.- Episode
slug
is a string. Episodes with numeric-only slugs are “numbered episodes”. Episodes with any non-numeric characters are bonus content. Episode.extract_duration_seconds
uses FFMPEG viaSystem.cmd
to get the episode duration.
Controllers
- There is a lot of application logic in the controllers. (2)
scrub_params
is used to covert empty strings in changeset values to nil.- Slack integration for listing upcoming episodes with a countdown.
Helpers
ViewHelpers.no_widowed_words
prevents an overflowed string from only having a single word on the final line. Inserts a
between the last two words.Viewhelpers.tweet_url
has multipledefs
fortweet_url
, with a default AND a guard. Header w. default, header w. guard, other headers as usual.
File Uploads
- Uses Arc.
- Uploadables defined in web/uploaders/
- Arc provides a way to run transformations using system binaries, without the user invoking
System.run
directly. cast_attachments
is used in model changesets to handle the attachment.
Views/Templates
- Nested models supported using
inputs_for
. Models handle these fields withcast_assoc
.
Javascript & CSS
- Switched from Brunch to Webpack in 935b7c5.
- Turbolinks to do page transitions. Fast page loads, and additionally allows player to keep playing between page loads? (3)
- Semantic UI for admin area CSS framework.
- Separate assets pipelines for main site and admin area.
- CSS is SASS
- Javascript is ECMA 2015 (ES6.0).
- Uses Umbrella.js for DOM/events/AJAX
- ES6.0 JS classes are used to describe domain objects and encapsulate their functionality. Episode and Player for example.
Search
- Admin-only at present.
- Uses
LIKE
SQL queries. - Multiple or single result type (People, Episodes, etc)
- Serviced via AJAX.
Transactional Email:
- Uses Bamboo.
- SMTP provider is Campaign Monitor.
- Username and password configured in config as ENV variables.
- Config picks up environment variables using e.g.:
password: {:system, "CM_SMTP_TOKEN”}
. auth_view
used to generate URLs in emails, passing in the application endpoint instead of a current connection.
Passwordless Logins
- User visits
/in
to enter their email and be sent a login email GET /in
displays the formPOST /in
processes the form. Two function definitions, with one being pattern matched to look foremail
param.- Token and expiry set on user in controller action.
- Error if user not found, user being shown a 404.
- When in dev environment it gives a login link in the response page, and skips sending the email.
- Response page checks for
@person
instance variable, shows confirmation message. - 15 minute expiry. Checked after retrieving user, not part of query.
- Auth token in URL is a Base16 encoded email and random token with a separator,
|
. GET /in/:token
decodes the auth token, checks for user with email and matching random token.- One-time-use. Resets the token and expiry on successful login.
Did I get something wrong? Get in touch with me on Twitter.
Followup
Added on 2016-11-16.
- I actually mistook this as something that was unused. I created a pull request doing so. Jerod Santo kindly showed me where it was used.
- Jerod Santo asked what I meant by this. See my replies there, and also my How I Put Rails Models on a Diet post.
- Confirmed. I’m a big fan of Turbolinks.js, even the statically generated Pincount Podcast site uses it.
-
How I Put Rails Models on a Diet
Photo by Antoine Beauvillain on Unsplash.
Improving my Rails applications with a Service Layer.
I first discovered Rails in 2005. I’ve been developing web applications in Rails since 2006. It’s fair to say that the majority of my income since graduating from University has been Rails related work.
Slowly, Rails projects became less enjoyable. Multi-person greenfield projects would start off great, but would often end up as being difficult to understand, modify, and collaborate on. Brownfield projects were worse: fat controllers; fat models; and tests that were minimal, brittle, and frustratingly slow.
Jamis Buck’s Skinny Controller, Fat Model pattern did a lot to improve things, though for the most part it was ignored in the projects I had the chance to work on. I liked that the application logic was in the model, where testing it didn’t involve the controller lifecycle. Still, fat models were now the burden, the logic being closely coupled to the persistence layer. Could the application logic go elsewhere?
The late James Golick had the solution I was looking for: Services. Instead of packing all the logic into the models, it could exist in its own Ruby classes. Free from the shackles of persistence, services are just Plain Old Objects, where their purpose was clear, and testing fast due to their focussed purpose.
Time for an example! We have an e-commerce application, and wish to create an order from a request, calculate the tax on that order, and persist the order.
The Controller
Below is an example of a controller action which would create an order:
The controller only deals with passing the parameters to the service (or session information if required), and carrying out HTTP actions on the response. It makes no decisions on it’s own. The double-assignment isn’t the neatest (I’ll perhaps blog about different patterns I have tried for this in a future post), but it’s clear and understandable.
A Service
The
OrderCreator
service is what I would categorise as an Orchestrator; it mediates between the controller and the rest of the application. This, along with other services, would go in theapp/services
directory at the root of a Rails application.The first thing to note is the
initialize
method. Yes, that is dependency injection. No, you are not reading Java code from 1998. The use of DI here allows us to swap out the classes for testing purposes, so we can isolate the service and test it on it’s own. If you’d like to see how this works in practice, check out the James Golick post linked above. Whilst passing arguments toinitialize
works well, I like to use Brandon Keepers’ Morphine gem, which provides a nice API for doing simple dependency injection.The second thing is that this service calls another service. Each service should be as simple as necessary, while allowing the services to be composed and re-used. It’s likely that sales tax would need to be re-calculated when editing an order, so extracting that functionality to a separate service makes sense.
Thirdly, we have the response. Depending on whether the order is persisted successfully, we pass back a symbol communicating the success state, and the order itself.
The Auxiliary Service
Lastly, we have a service for calculating tax on our order.
The
TaxCalculator
service calculates the sales tax, assigns the relevant attributes, and passes the order back. The order doesn’t even have to be an ActiveRecord instance, it could be any Struct or Object which responds tosubtotal
,tax
,tax=
andtotal=
. Indeed, this is how this service would be tested, without instantiating a model, or even loading the Rails stack. The statelessness of this service removes side-effects, and allows for fast testing and easy debugging.This is the sort of code that would previous have been encapsulated in a model callback or class method. Where the service becomes really adventagous is when tax gets more complicated, being related to geography, different rates of tax, etc. (Shout out to VAT MOSS!). The model no longer requires logic implementing these things, and mudding it’s persistence role.
The Model
So what is left in a model? Not much. The following is what I put in models:
- ActiveRecord Relationships
- Validations
- Class methods which wrap ActiveRecord API methods.
- Instance methods which modify the state of the instance without any application logic.
What is out?
- No public scopes. Wrap these.
- No using ActiveRecord API methods outside of the model.
- No display methods (example: a
full_name()
instance method which concatenatesfirst_name
andlast_name
attributes). This is a view concern. Either use a helper method, or use the Decorator/Presenter pattern to wrap the model instance for display. - No callbacks. Samuel Mullen has written about this, but prescribes a less aggressive callback prohibition than I follow.
The Result
The core functionality of the the Distrify application is now easier to understand. No longer does debugging involve following chains of callbacks in the model, or other logic tied to the persistence. This speeds up the development of new features, as the risk of unintended regressions to existing features is much reduced.
Isolated testing of the services comprising the main logic of the application allows them to be run exceptionally fast, reducing developer downtime during development. Currently, the Distrify application has 34 controllers, 44 models (many of these are non-ActiveRecord models), and 130 services. There are 1869 Spec examples, which run in 1.58 seconds (plus 4.07 seconds for the test suite to load) on my late 2013 dual-core Macbook Pro. That test runtime is not a typo.
I should note that reduced test runtime was not a goal of using the service pattern. Increased understandability, reduced side-effects, and clearer ownership of functionality were the original goals. The tests running in single-digit seconds was just a nice side effect.
This started out as an experiment, but after more than a year productivity still seems to be high, and we are very pleased with how this has turned out.
Further Reading
Not so much reading, but I can highly recommend Gary Bernhardt’s Destroy All Software screencasts. Season 4 covers a lot of what I’ve talked about in great detail, plus you’ll learn a bunch of other stuff too.
TLDR
Controllers do HTTP, models do persistence, decorators provide logic to views, services do everything else.
This post was also published on Medium. Thanks to Kieran Masterton for proofreading and guidance on the usage of Medium.
-
A New Distrify Player
Over the last six months I’ve been working on a complete rewrite of the Distrify player and backend infrastructure. Yesterday we migrated the first large batch of content-owners to this new player, so despite using it in production on a small scale for several months now, this was the first time it would be seen by a large number of people.
The player was conceived, designed, and built from the ground up with user experience in mind. The player has a fantastic design by Mike Kus; the frontend in React, initially built by Neil Kinnish; with a Rails backend by Kieran Masterton and myself. The play and purchase experiences are fast, but we’re working hard to make them even faster and easier to use. I plan to write more about the technology choices that were made along the way.
The response so far has been fantastic, I’m incredibly proud of the whole Distrify team.
-
SXC 2015 Round 2 - Dalbeattie
2015 is a year of change for me, at least as far as the bike goes. The little training I do manage (bother!) to do has been focused almost completely on Enduro. I’ve not ridden a road bike since last August, and sessions involve a lot more time doing weights, strength work, sprints, and skills sessions. I planned to enter the handful of Scottish Cross Country rounds which did not clash with Enduro races, but there wasn’t enough to make a good go at the overall title, so the races were to be for training only. This more relaxed approach to XC seems to be working well, and despite the gleeful comments about my hairy legs on the start line, I pulled off a surprise third place in the first round of the SXC at Cathkin Braes.
Round two was to be at Dalbeattie, and with a slightly shorter course to last year, which retained it’s technical character, I was sure I could equal the second place I had here in 2014. I started hard from the gun, making sure to get into the first tight section of boardwalk without getting involved in the melee of the big group. Jack Ravenscroft had a similar idea, cruising past me on the first forestry road. I tucked in behind, and when we got to the next section of forestry road I had a look to see who was around. Rab Wardell and Andy Barlow of Dirt School were both close at hand, and despite riding their trail bikes took good pace into the next section of climb. I knew I had to get 15-20 seconds on them for the descent, so followed Paul Carmichael as he pushed on towards the top of the climb. I got the gap I wanted, with Andy and Rab catching me up as things got flat again.
For the second lap I was mostly on my own, with a bit more of a gap at the bottom of the descent. Apart from dropping my chain towards the end of the gap due to a botched doubling-up of two rock sections, it was fairly uneventful. On lap three three I seemed to ease off a bit, and while I was going slower, Rab went fast and was right behind me going into the fourth lap. Paul Newnham told us that Jack had punctured and withdrawn, so we were now one and two. Again I knew I had to get a gap for the descent, so raised the pace going up the climb to the point where I wondered if I could maintain this pace for a lap and a half. I knocked 50 seconds off my previous lap time, definitely the negative split I would look for at this point in a race.
Going into lap five I knew there was a small gap back to Rab, but not big enough that I could ease off. I kept the pressure on, and apart from the stress of catching back markers in the tight sections, I matched my lap four split time. I crossed the line first, with Rab at 1m 16s, and James Fraser-Moodie at 3m 34s. I am of course very pleased to win, it’s only taken eleven seasons of podium appearances and other good results to get to the top of the box.
It was very interesting to see Rab run me so close on a trail bike that is nearly identical to the one I race Enduro on (29er, carbon, medium travel). While I wonder if he would have been closer with a change to proper XC tyres, it does drive home that modern trail bikes are fantastically versatile. I get the definite feeling that the “I don’t have an XC bike” excuse is redundant. Hopefully we can all convince a few of our Enduro-racing friends to come and give a Scottish XC a go.
Thanks to Emma (who was first in senior women, yah!) for doing my bottles, Steve at I-Cycles for the ongoing support, and all the other people who cheered me on and sent me their congratulations. And thanks to the Morven, Steve Brown, and all the other folks who make these races happen.
Finally, I found out a few hours after the race that my Aunt Dianne had passed away, so this race win is dedicated to her.
Related Stuff:
-
SXC 2014 Round 1 - Forfar
The first round of the Scottish Cross Country Series was held just outside Forfar, with a course making fantastic use of woodland borders and disused quarry workings.
2013 had been a very wet and slow affair, making me a bit worried when it looked like the course was to be longer than last year. Thankfully conditions were dry and super fast, making for some nice fast sub-19 minute laps.
I got a decent start, following Rob Friel into the first singletrack. I let Gareth Montgomerie past on one of the early climbs, thinking there was no point in holding him up as he would likely ride away from me. I kept going steady, getting a good gap in the first lap to James Fraser Moodie. Sadly I tore a tyre on an embedded rock, so had to put a tube in. I was carrying my trusty pump, which although it is near-guaranteed to work better than an air canister, took several minutes to pump the tyre back up again. I lost about four and half minutes, dropping from third to sixth.
It took another lap to get back up to fourth, but I could see James about four minutes ahead on the twisty course, there was no chance of catching him in the remaining two laps. I rolled in for fourth, disappointed by the puncture but pleased with my early season form.
Thanks to the SXC and the chaps from Forfar for a great event. Full results can be found on MyLaps.
-
Scottish Enduro Series 2014 Round 1 - Fort William
An Enduro, in February, in Scotland? I wondered about this, especially when standing in a rainy carpark knowing that my B&B roommate had decided to spend another few weeks in Spain. Apparently it was warmer there.
The Scottish Enduro Series is a new endevour brought by No Fuss Events and Innerleithen MTB Racing. Six rounds, some classic Scottish riding locations, and as on-trend as you like! I entered the whole series as soon as I could, sure that I could progress towards the upper echelons of mediocrity by the end of the season.
So back to the first round, in Fort William, where it was raining on practice day. Stage one used the top part of the XC World Championships course, twisting down with lots of pedalling and speed to be carried through tight hairpin bends. The straightforwardness made me slightly worried about the rest of the stages.
Not to worry, stage two went down Blue Crane, with some small detours, then into the Stump Alley descent as previously used on World Cups and Scottish Cross Country racing. Steep and with big holes, a few years of fallen trees meant that only the main line was rideable, leading to a luge-like trench appearing. After this there was some mixed rooty sections and a few steep faces, great fun.
Stage 3 was down the final sections before Nessie, including a bus stop and a line over the top of a rock, then a sprint from the foot of Nessie to the far reaches of the 10 Under the Ben course.
Stage 4 took in part of the World Cup Downhill track, then down the XC World Championships climb with some rough sections pedally sections in new growth trees.
On race day things went about as expected for me. Stage 1 was lots of sprinting, stage two rode easier than it did on race day, despite the mud. Due to a late start the top of stage 3 was barely recognisable, with a few fallen bodies to be negotiated. Stage 4 was cut short due to rainfall swelling a burn crossing to waist-deep. In the end I was 40th of 83 seniors, within my target of top-half for the first round, so I was reasonably happy, but I know I have work to do.
Next up, Innerleithen for some steeper stuff, and hopefully some more banter with a fantastic group of competitors and organisers!
-
SXC 2012 Round 1 - Kirroughtree
The first round of the 2012 Scottish Cross Country took place at Kirroughtree. The course used parts from previous races there, but was an all-new arrangement. The usual singletrack and fireroad to start, followed by a long natural climb, into an undulating rocky section, then some fast natural descending before a forestry road drag. A few pieces of natural singletrack dropped you into the finish of the Red route, back to the arena to start it all again.
There was a pretty good turnout for the first round, so the racing was going to be fast. On the first lap I tried not to go to wild chasing the elite guys, they were off to do their own battle. Weirdly on the first lap there were five elites up front, then the expert racers including myself fairly close together behind. It was at this point I realised I could have quite a good battle with Hamish Fletcher-Cooney, a fellow expert who I’d raced against a few times last year.
At the end of the first lap he had about 29 seconds on me, but I noticed as we did the first half of the lap that I could take him back fairly quickly on the climb and natural sections. I overtook on the natural climb, and pressed on a little bit to see what would happen. On the forestry road drag I lost some time, and we crossed the line at the end of the second lap with only a few seconds between us.
This status-quo continued on the next lap, with the gap over the line again being only a few seconds. For the last lap I knew I had to put a big effort in on the climbs to make sure he couldn’t close the gap on the flatter sections. I properly turned myself inside out on the first half of the course, then did my best to keep the speed up for the rest of the lap, resisting the temptation to look behind.
I crossed the line in sixth position, first expert, and held Hamish off my 18s. The course really is well suited to differing types of rider, I’m really looking forward to racing Kirroughtree again in June when the British XC Series finally comes back to Scotland.
Thanks to the SXC and the girls at The Breakpad for the awesome course.
Full results are available on the SXC website.
-
BMBS 2012 Round 1 - Sherwood Pines
This year Sherwood had a mostly new course on offer for the first round of the British series. Unfortunately it was as flat as the old courses, with minimal technical sections to separate riders, resulting in some very close racing. After the race I was told there was caution arrows on some sections, I never saw these and still think my leg is being pulled.
I was gridded first, so was in the front row with a good chance of staying out of any trouble. Unfortunately there was a big crash in the row behind as the barriers narrowed in the start straight, ending many people’s races very early and resulting in Wheelbase’s Joe Richards having a helicopter ride to the hospital to be checked out (he’s OK, it was just precautionary).
The first section of singletrack came pretty quickly, by which time I was probably down in about 20th due to my lack of power for the start. I sat steady, laughing at riders being too keen to make a pass in inappropriate places, and at those who were now regretting their seriously-slick tyre choices. Once the second lap came round I started to move up places, blasting past people on the one short-step climb on the course, and drafting riders on the forestry roads before sprinting past into the singletrack.
On the last lap I was still making up places, but struggling with some of the elite back markers who were riding some sections a lot slower than I wanted to, especially frustrating with the narrow tree-lined singletrack that makes up the majority of the Sherwood course. The run-in to the finish was tight, with some rooty singletrack and right-angles to negotiate. I managed to pass some more elites on get on the back of a group of three other expert riders but I was outgunned in the sprint by all of them and came in for a rather pleasing tenth place. Not bad for a course that’s not supposed to suit me.
-
Scottish Cyclocross Season Roundup
Scottish Cyclocross is now bigger than ever, some of the rounds had almost 300 people turning up. Great courses and great people, I look forward to more of this in 2012.
SCX Round 1 – Irvine
I’d never ridden the cyclocross course at Irvine before, despite it appearing twice in the past, once as an SCX round in 2009, and as the delayed 2010 champs in January 2011. Famous for it’s sand-trap, a long stretch in the dunes at the back of the beach, I was keen to see this was a gimmick or something worth using as part of the course.
The course has two runups, one short up a set of steps, the other a 25m steep grass section. The sand-trap is about 100m long, and is an awesome addition to the course. It takes more grunt than skill to ride it, though things are much easier when you realise you can skirt along the margins out of the really soft stuff, though you risk getting stuck in some of the larger ruts.
As for the racing, I had a horrible first couple of laps, going backwards after the initial fast start it took me a while to get into the swing of things. For the second half of the race I had Rapha’s James McCallum in sight, allowing me to keep my lap times sensible even though I was feeling a bit horrible. I put in a big effort on the last few laps, but didn’t make the catch by the end.
13th place, an improvement on my first CX race last year. Full results on the SCX website.
SCX Round 2 – Plean
A bit of a classic course remixed for 2011. Gone was the large climb at the back of the course, replaced with two new grassy sections. Loads of people complained about this course, but despite only having the one bike I had little issue with the bike clogging up. Definitely a course for the more powerful and skilled riders.
I got into fourth wheel into the first singletrack, then had to stop because my brake hanger cable was rubbing on the tyre. Almost as soon as I remounted I jammed my too-short chain on the big-ring, big-sprocket combination. My fault, fixed that then remounted. I was down in about 30th at this point. My disaster lap continues as I go some course tape caught in my cassette.
After this things started to come together, I was making up lots of places by riding sections others with running, and taking risks on some of the fast muddy descents. I did manage to drop my bike about halfway through as I hopped the hurdles, resulting in twisted bars and a bent STI. With no tools I just had to ride it like that.
I ended up 10th, which I was very pleased with given the troubles I had. Full results on the SCX website.
SCX Round 3 – Mugdock
Another classic course, this time without the crazy start of last year which resulted in lots of pileups. I got a good start and started to pick people off quite early. On the third lap I thought I felt my front tubeless tyre burping some air when I slammed it into some off-camber ruts. The next lap at the same point I was sure it was happening, and now had a very low front tyre. I kept riding it, hoping to make the pits where I could borrow a pump. Alas it burped the remaining air on a fast gravel corner, I luckily managed to step off the bike as it happened, with no injury. I ran round to the start-finish area to see what the time was like, then posted my DNF, my first of the year. Spectating was great fun after this, though I think some people were a little shocked by my enthusiastic heckling.
Hallocross
Organised by the Tri Centre on the same course as the Edinburgh 48 races, Hallocross was night-time cyclocross, in fancy dress, with cider. 60 people turned out for it, very impressive for a midweek event that required lights. Even knowing the course very well it was pretty frightening at times keeping the ’cross bike upright on the gravel corners and going over some of the blind drops. The racing was close and fast, with lots of mini battles to be had. Results were only down to third, due to the technical difficulties of reading numbers in the dark. I think I was seventh or eighth, but had fantastic fun whatever the result.
SCX Round 4 – Ballater
Ballater isn’t exactly close, but some nice weather meant the drive north of the Lecht was one to remember. The Ballater course was very non-traditional ’cross, with some fast rocky tracks interspersed with forestry road. A few technical sections, punchy climbs and a horrible set of steps made it a tough one though. My only issue with the course was a rocky burn crossing which was very hard to cross without kissing the rims against the rocks.
I had a good start here too, and picked off places as people dropped chains and punctured due to the rocks. The climbs were really suiting me, with the descents allowing some recovery time.
I ended up 6th, my best result so far. Full results on the SCX website.
SCX Round 5 – Strathclyde Country Park
One of my favourite courses from last year, it had been changed slightly with one of the grassy climbs replaced with hardpack, and one of the descents on a gravel path. It was super muddy, with the field section being calve-deep mud. More than 30 people sheared their rear mechs off due to the small stones on the descent getting dragged into the mech by the mud. I joined them on the third lap, my mech sheared clean through, with the hanger being left completely perfect. Bah. The chain needed replaced too, only having been on for three races prior.
SCX Round 6 – Meadowmill
Another redesigned course for 2011, with lots of flat out fast sections, the usual awesome singletrack, and some horrible headwind sections due to gale force winds all day. It was nice to race on a dry mud-free course after the previous round. The course wasn’t really for me, there was no rest on it so I had to ride at a pace I could sustain for the whole hour, rather than just a few minutes at a time.
Despite this I really enjoyed the high pace all the way round, and the interesting technical sections. I had a near-miss with a spectator on the course, unfortunately Davie Lines didn’t manage to swerve and was on the ground and out of the race instantly.
I ended up 15th. Full results on the SCX website.
Scottish Cyclo-Cross Championships
Made it to within a mile of this race when I crashed the car due to slippy conditions. No race! I don’t think I’ve actually ridden the champs since I won them as a junior in 2002. Will have to make it next year for the 10th anniversary.
Callendar Christmas Cross
A new event for 2011, run by Franco Porco and Davie lines around the spectacular venue of Callendar House and the Antonine Wall. The course was fantastic, with steep run-ups, long off-camber sections and slippy climbs. Those who were technically inclined had no running at all. It rained for almost the entire day before the race, meaning there was lots of sloppy mud to be had once the grass was chewed up. This was good, certainly better than the sticky mud we had seen at other venues.
The start was along a fast section of tarmac. I hung back so as to avoid those weaving side-to-side as they tested their VO2 maxes. On the first steep run-up and muddy corner I went from 25th to 10th by virtue of riding it then going round the inside near the apex. I then stormed up the first climb to find myself in fourth position for the rest of the lap. Myself and the other mountainbikers were definitely at a big advantage on this course. I couldn’t hold my position on the flat sections of the following lap, and was riding round with Paul McInally and junior rider Calum Foster. I only made two mistakes the whole race, one being losing my line on a long off-camber section and losing about 20s, and the other crashing on an off-camber descent where I lost very little time.
Calum started to make some mistakes about halfway through, and I took full-advantage of him losing his line on the section I lost time on, by putting the hammer down as soon as I saw him veer. Paul was yo-yoing back and forth, making lots of time up on the fast sections round the house and one muddy section that had become a run, and losing it as I took risks on the back-side of the course. On the last two laps I put in the big efforts on the climbs and the running section, eeking out enough of a gap to take 7th overall and 5th senior. Paul was 8th a few seconds back, and Calum finished an impressive ride to take 9th,
A great result to end the year, especially after a few weeks of zone-2 riding and a complete lack of intervals in December.
Full results on the SCX website.
-
No Fuss Tour De Ben Nevis 2011
I missed out on this event in 2010, a lack of enthusiasm at the end of the season meant I just wasn’t up for it though. Innerleithen MTB Racing was well represented though, with I-Cycles own Steve Deas just missing out on the podium, and taking No Fuss’ Best All-Round Mountainbiker prize. Steve raved about the event, adamant that I should do it in 2011.
This year I was much more enthusiastic. Not racing for most of June and July, and not training properly in months meant I was mentally fresh and ready for this big day out in the hills.
On the Friday night I stayed in a bunkhouse with Marty, Niall, Dave, Dave and Colin. Only some beer was drunk by me, and we were in bed by midnight. Up early, and at the start venue for 8:30, we had to wait for a while to dib in. While we were waiting in the road to start there were heavy showers which only lasted a few minutes at a time. This did not bode well for four plus hours in the big hills. We were led by a police car to the High Street, where the official start was to be. Pipers piped us down the high street at slow march, with us riding along very slowly behind (no dabs!). Once onto the main road we were off.
Up the first climb I was in the first couple of riders, looking for James Shirley and Rauri Watt who had performed well last year. A couple of roadie-looking guys were pushing good pace, but I wasn’t wanting to blow myself up in the first couple of miles as I had no idea how fit I really was. Nic Smith slowly pulled away towards the top, and left a small group of us wondering whether to chase him or not on the rolling roads. I worked with James, Rauri and a few other guys on the road, then it was every man for himself on the first part of the West Highland Way.
Rauri pulled out a little gap here, again I was content not to chase. After about ten miles we got to the Kinlochleven descent. Saddle down, dibbed in, and off! After only a few hundred yards a rock struck me on the shin, the pain rolling up and down my leg as I tried to keep the speed up. I didn’t know the descent to start with, and the pain wasn’t helping things. I got down in one piece, no punctures on the huge drainage channels due to following Steve’s advice and jumping them. I was 17th on this, the first, special stage.
Up the climb to Mamore lodge I was caught Ben Arnott. He’d managed to land on his face during the descent, and had broken a finger. I rolled on, hoping to get a good result in this special stage. I almost caught James Shirley who had got a gap on me before the previous descent, and was struggling a little with his single ring. I was 4th on the climb.
Next up we rolled along the side of some lochs, splashing through huge deep puddles. I made good pace along here, aware that there were a few people with me as we had bunched up after the previous special stage. Right before the river crossing I dismounted to avoid what looked like an especially deep puddle, only to discover the water at the sides was also waist deep. After that the river crossing was an anti-climax, being only knee deep at it’s deepest.
At the other side the path was punctuated by ditches every few meters, so it was quicker to run. After about half a kilometer I met James coming the other way: we’d both missed the dibber after the river crossing. Rubbish. I ditched my bike and bag and joined James on the run back along the riverbank to the dibber, then back to the bikes. This special stage was pretty much a 40 minute walk/carry up a steep mountain path. We made good time up here, eventually dropping other riders who looked like they were making good pace on the bottom section. The end dibber was at the Lairig bothy. I was 6th on that stage.
As I had been descending the section to the bothy I noticed that there was a rattling coming from the backend of the bike. I suspected it was loose bushings as I’d had them apart a few days before to clean them. After getting my allen keys out of my bag I realised it was the rear wheel that was loose in the frame, rattling in the dropouts. The skewer-nut was seized onto it’s thread, so there was no way for me to tighten it up. I left it out, confident that the wheel wouldn’t be pulled out even under heavy load.
The descent down towards Spean Bridge is a cracker, full-on 30-40mph snaking forestry road for several miles. At the bottom James had a puncture, so I kept on trucking, hoping I might catch some of the four guys up ahead. I passed the 20km to go sign, feeling my legs weakening on the rather dull trails and forestry road we were faced with at this section. I necked my remaining gels, all three of them, within about 15 minutes. Shortly after I felt better again, knowing I just had to keep it rolling. As soon as I recognised some of the trails and knew where I was, it was like someone turning on the nitrous. I took a gulp from the bottle on my frame, then emptied the rest onto the ground as I knew I wouldn’t be needing it. I was flying up the final climb, knowing it well from many races in the past.
The final descent was the Blue Crane down to the top of Nessie. I knew this descent well, so was confident of doing well. In my tiredness I made a mistake and lowered my saddle. This was great for the first section, but the middle section is a fast forestry road where you need to pedal all the time. Having the saddle down here was not good for my tired legs, but I wasn’t convinced I would make any more time up by stopping and raising the saddle. It was great fun anyway, especially as I hadn’t ridden these trails this year. I was 16th on this stage.
The final little tarmac section to the start-finish was over pretty quickly, taking turns in front with James who had caught me up at the bottom of Nessie. My legs collapsed within sight of the end, and I finished in 6th, a few seconds down on James.
Oddly at this event, the positions rather than time on the special stages were what mattered. This meant I was 4th, which was a pretty pleasing result all things considered. I am already looking forward to next year.
Full results are available from Sportident.