Josh Thompson     about     archive     tags

The Complete Guide to Rails Performance: basic setup

You know the feeling.

You are excited to start a guide or a tutorial. You buy it, crack it open, and start working through the environment setup.

Then… something goes wrong. Next thing you know, you’ve spent two three too many hours debugging random crap, and you’re not even done with the introduction to the dang thing.

Oh, this has never happened to you? Must be nice.

I’m working through The Complete Guide to Rails Performance, and I’m thrilled to get learning underway.

I’ve hit a few hiccups, though. I’m not the most sophisticated user out there, so here’s a mess of problems I ran into, and the solutions I did.

All of my struggles were with ElasticSearch. I’ve never used it before, so this isn’t surprising.

The RubyGems docs recommend the following:

Install Elastic Search:

  • Pull ElasticSearch 5.1.2 : docker pull
  • Running Elasticsearch from the command line:
    docker run -p 9200:9200 -e "" -e ""
>> Read more

Growing in your first software development job

I started my first software developer role a year ago. (November 2017)

This is tremendously exciting, of course, but introduces its own set of challenges, like:

I finished Turing and I’ve got a job! Oh snap. I just finished a grueling program, and my reward is I’m fit to sit at the same table with people who know so much more than me.

I have to learn a whole new codebase. Or four.

I have to meet the standards of an inexperienced-but-competent professional, which are higher than “eager student”.

So, I’ve been thinking a lot about how to grow as a developer in my job.

What does “grow as a developer” mean?

Part of growing in anything means having goals. I have career goals that may be 5+ years out, but for the next year or two, these are the goals I’m using to drive me towards my goal of being “an experienced developer””

  • Build deep competency with the “standard” Rails framework. I think Rails scales just fine, and I don’t want to toss a JS-heavy front-end on our application. (I’m secretly pulling for Turbolinks and Stimulus…)
  • Help guide our product through a few big changes in the coming year, and help drive decisions around those changes
  • Support other teams within the company
  • Put up a lot of PRs, close a lot of tickets. Do a lot of “work”
  • ???

These are not great goals, as far as good goal-setting goes, but I am not worrying too much about it, because good habits tend to be more important than good goals. And I’ve got good habits!


Here are some constraints I’m operating within:

  • I work on a 100% distributed team of developers, but most of the rest of the offices works in-office in Pittsburgh. (Project/Product Management, Quality Assurance, DevOps, Support, Managed Services, Sales)
  • My immediate team is a group of three other developers. Myself and one other dev started at the same time.
  • The other two developers have been on the team for about three years.
  • The individuals who built most of the application is no longer on the team.
  • there is an extreme level of trust passed to all on the team. No one is required to pair with me, or checks in with me every day to make sure I’ve committed X code or fixed Y bugs.
  • We’re currently without an immediate manager.
  • I live a balanced life. I spend time with my wife, I rock climb a lot, I’ve gotten back into running, I read a lot. I won’t spend 20 hours a week on top of my job, trying to become a better developer.
>> Read more

Primitive Obsession & Exceptional Values

I’ve been working through Avdi Grimes’ Mastering the Object Oriented Mindset course.

One of the topics was using “whole values”, instead of being “primative obsessed”. The example Avdi gave was clear as day.

He used a course with a duration attribute to show the problem.

=> 3

3 what? weeks? days? months?

Of course, you could write a method like:

=> 3

But now you’ll have trouble rendering this all over the place. You’d have conditionals every time you wanted to render courses in weeks (if it makes sense), or in months (if appropriate), or of course, days.

So, the solution is to use “Whole values”. This means an attribute should be a complete unit, in and of itself, and should need no further refining to be usable.

So, you should be able to do something like this:

=> Months[3]
=> Weeks[5]
>> Read more

`ls` command to show directory contents

I like to use the tree command on my local machine when trying to peek into the structure and contents of a given directory.

tree -L 2

will [L]ist recursively everything [2] levels deep from your current directory. The output is nicely formatted like this:

> tree -L 2
├── cargo
│   ├──
│   ├──
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├──
│   ├── appveyor.yml
│   ├── rustfmt.toml
│   ├── src
│   ├── target
│   └── tests
├── fastly
│   └── fastly-test-blog
├── learning_aws
├── learning_elixir
│   ├── hellow
│   ├── sample01.exs
│   └── sling_clone
├── learning_over_the_wire
│   ├── bandit
│   └── leviathan
├── learning_react
│   └── react_tutorial
├── learning_ruby_rails
│   ├── InstaClone
│   ├── blocks_practice.rb
│   ├── chris_pine_ruby_lessons
│   ├── eloquent_ruby
│   ├── email_sender

If you’ve SSHed into a linux box, however, and you’re trying to look around a bit, you won’t have tree available to you. How can you list out the contents of directories?

Easy. The good ‘ol ls command:

>> Read more

Rails Migration: When you can't add a uniqueness constraint because you already have duplicates

I get to occasionally contribute to the Wombat Security dev blog. I wrote the following for

This post has been updated to reflect some lessons learned while running this migration in production. Don’t leave a column without an index at any point in the migration. skip to section

For work, I picked up a bug where a CSV export was creating duplicate rows when it shouldn’t have been.

We generate the CSV export with a big ol’ SQL statement in some Elixir workers, and got the bug reproduced and found the problem was with how we did some joins on other columns.

We had something in the statement like this:

LEFT OUTER JOIN `reports` ON `reports`.`id` = `people`.`report_id`
LEFT JOIN `addresses` ON `addresses`.`people_id` = `people`.`id`
LEFT JOIN `favorite_colors` ON `favorite_colors`.`people_id` = ``

In this highly contrived example, I found out that we’re expecting a single row in the favorite_colors table for each person, but we were getting multiple favorite_color rows.

Every time we had a duplicate row on that joined table, the LEFT JOIN created two rows in the export, even though there should have been one.

>> Read more