ryanbigg

The 2018 MacBook Pro Keyboard Drives Me Crazy

I recently upgraded from a 2015 MacBook Pro to a 2018 MacBook Pro. And by "recently", I mean back at the start of June. I wanted a new MacBook Pro because of the faster performance that a new computer would give me. Work (Culture Amp) was also upgrading their fleet of Macs and I was one of the lucky people to get a new one. So I've been using this computer as a work computer for almost 3 months now and, my god, the keyboard drives me mental. Even writing this blog post now on the train and there's: duplicated "o's" that...

ryanbigg

Culture Amp Junior Engineering Program Discontinued

For the past two years, I have ran not one but two successful Junior Engineering Programs (JEPs) at Culture Amp. The official number of developers that I have trained there is 19. But I trained a bunch more developers from time-to-time as well. So the proper total would probably be in the range of 30-40 developers at Culture Amp that I have helped train, support and grow over the past two years. I am really proud of this work that I have done and I have really enjoyed my time doing it. Unfortunately, Culture Amp has decided not to run the JEP...

ryanbigg

Polymorphic Routes

Really early on in Rails, you would write routes like this: redirect_to :controller => "posts", :action => "show", :id => @post.id What this would do is dutifully redirect to the show action inside the PostsController and pass along the id parameter with a value of whatever @post.id returns. Typical 302 response. Then Rails 1.2 came along and allowed you to use routing helpers, like this: redirect_to post_path(@post) And the people rejoiced. This would do effectively the same thing. post_path here would build a route...

ryanbigg

Working Towards Integration Testing Duolithic Applications

I've been revisiting Twist v2 recently. It's my book review tool that I've rebuilt multiple times over the past 8 years. Its latest incarnation is what I'm calling a "duolith": a very light Hanami backend application with a GraphQL API, and a frontend built with React and Apollo. The backend and the frontend codebases are kept in separate directories in the same codebase. This allows for separation between the Ruby and JavaScript code, but also the ability to commit changes to both at the same time. The frontend knows how to...

ryanbigg

Junior Engineering Program: Resources

This post is part of a series of posts about the first cohort of the Culture Amp Junior Engineering Program (JEP). You can read the first two posts here: Junior Engineering Program: Launch Junior Engineering Program: Onboarding In the last post I covered the process of what we did in the weeks immediately following the juniors starting, but didn't talk too much about what we taught them during those or subsequent weeks. That is what this post is going to talk about: what we taught our juniors over the 26 weeks of the Junior Engineering...

ryanbigg

Culture Amp Junior Engineering Program: Retrospective

This post is a short summary of the Culture Amp Junior Engineering Program (JEP) that I ran from November last year until June this year. If you're keen to apply for the 2nd cohort then you can do that here: Apply here for the Culture Amp Junior Engineering Program's second cohort This post is the first in a series of four blog posts which will go into detail about how the last JEP operated, with the aim of giving potential future cohort applicants and the general public a taste of what a Culture Amp JEP looks like. Our first Junior...

ryanbigg

Joy of Elixir - Progress Update

I started writing Joy of Elixir near the end of July last year. I wrote a large amount of the book in a relatively short time and I've been quietly updating it (slowly) ever since. I took time away from Joy of Elixir to publish Exploding Rails (which is doing very well!) and then took a little writing break to "recover". Recently, I received an email from someone called Svetlana Rosemond. She said: Hello Ryan, I'm currently working my way through Joy of Elixir. Well done! When will you complete chapter 11? Working with Files. I'm...

ryanbigg

Web Directions Code Leaders: Hiring Juniors

Here are my raw speaker notes for my Web Directions Code Leaders talk, titled "Hiring Juniors". The video will be online later. The slides for this talk are available here on Speakerdeck Intro [slide] Hi, I'm Ryan. You know that part already. What you might not know is that I've been mentoring juniors on-and-off for close to a decade now and I've had varying rates of success. I've mentored juniors who have gone on to become lead developers at tech companies you'd probably know about. But, at the same time, I've also mentored juniors...

ryanbigg

Making Tests Go Faster

At Culture Amp, we have a large Rails app that we’ve been building since 2011. This app has about 150k LOC and an extensive test suite that uses Rubocop, RSpec, Capybara, Cucumber and FactoryBot. We run these tests for the application on Buildkite and currently they take about 16 minutes to run end-to-end. This is 16 minutes that developers are waiting to get feedback on whether their build passed or failed. While this is not unacceptably high, we could do better. Developers could ship things faster, or respond quicker to build failures,...

ryanbigg

My thoughts on Hanami

(This was originally posted as a comment on Reddit) This blog post has been translated into Japanese, thanks to @hachi8833! I've been toying around with Hanami for a few weeks now and imo it feels better than Rails. If you want to see some code rather than text, here's my little example app I've been building with Hanami. Here are the top three things that I like about Hanami, in long form: Repository pattern instead of Active Record Documentation link: Hanami | Guides - Models Overview The Active Record pattern encourages you to throw...

ryanbigg

How require loads a gem

In modern versions of Ruby, you can use the good old require method to load a gem. For instance, if you've got the gem activesupport installed, you can require everything inside of activesupport (including the kitchen sink) with this line: require 'active_support/all' You might've just tried to open up irb and run that line, and it might've worked for you... assuming you have activesupport actually installed. It works on my machine, at least. But how does require know where to find gems' files in Ruby? Wouldn't those files need to be on the...

ryanbigg

Rails' CurrentAttributes considered harmful

This blog post has been translated into Japanese, thanks to @hachi8833! I was made aware of this commit recently (thanks to Rebecca Skinner) to Rails which introduces what is effectively a global state to Rails applications. Rather than writing why global state in-general is a bad thing myself, I will instead link you to this excellent question + answer on the Software Engineering Stack Exchange. Very briefly, it makes program state unpredictable. To elaborate, imagine you have a couple of objects that both use the same global variable....

ryanbigg

Rails 5 in Action

I have been asked a few times since Rails 5 was released when Rails 5 in Action (an update to Rails 4 in Action) will be published. The short answer is that it won't be. After Rails 4 in Action, I cut ties with Manning due to problems I've outlined in many previous posts. Most recently "My self-publishing success story". It just isn't worth any more energy/time to continue to work with that particular publisher. Since they are the ones that own the rights to the Rails * in Action series and the IP of the book, working on an update to...

ryanbigg

Validating nested JSON data with ex_json_schema

I've been working on an Elixir service which reads events from a JSON API and then processes those events. The code to deserialize the events runs a little like this: defmodule MyApp.Event do def deserialize(event_module, data) do %{"id" => id, "type" => type, "body" => body} = data %__MODULE__{ id: id, type: type, body: body |> event_module.deserialize, } end end It's invoked like Event.deserialize(Response, data), where data looks something like: %{ "id" =>...

ryanbigg

Elixir Tip: Enum.any? + match?

I recently found out about the match?/2 function in Elixir through the #elixir-lang IRC channel on Freenode. What this function allows you to do is to determine if a given pattern matches a given expression. For instance, if you wanted to know if a list of maps contained a particular key + value combination, you could do this: people = [%{name: "John"}, %{name: "Jane"}] Enum.any?(people, fn (person) -> match?(%{name: "John"}, person) end) This code will get Elixir to tell you if any of the people have the name...