Category Archives: Uncategorized

Why the text on my site isn’t full-width or centered

I’m often asked why the text in my site isn’t full-width or centered.

The reason the text isn’t full-width is because I believe that the wider a block of text is, the harder it is to follow the end of one line of text to the beginning of the next one.

The reason my text column isn’t centered is because I don’t think it would look very good.

How I approach software estimation

Software estimation is really hard. I’ve never encountered a programmer who’s good at it. I don’t think such a programmer exists. I myself am not good at estimation nor do I expect ever to be.

Here are two tactics that I use to deal with the challenge of estimation.

  1. Try to make estimation as irrelevant as possible
  2. Try to use historical data to make future estimates

Try to make estimation as irrelevant as possible

I figure if I’ll never be able to estimate accurately, at least I can try to make estimates a less important part of the picture. Probably my most successful tactic in this area is to try to only take on projects that last a matter of days. If a project will take more than a matter of days, then I try to break that project up and identify a sub-project that will only take a matter of days. That way, if I estimate that the project will take 2 days and it really takes 4, no one has “lost” very much and nobody’s too upset (especially if I let my stakeholder know that I have very low confidence in my estimate).

Try to use historical data to make future estimates

Obviously all estimates are based to an extent on historical data because you’re basing your estimates on past programming experiences, but there’s a little more to it than that. When I work on a project, I break the work into individual features. I have a sense for how long a feature will take on average. Even though some features take an hour and some features take three days, a feature takes some certain amount of time on average. If I think the average amount of time I take to build a feature is half a day and my I can see that my small project has 5 features, then I can estimate that my project will take 5 * 0.5 = 2.5 days. Obviously there’s a lot of room for inaccuracy in this methodology, hence tactic #1.

If you really want to go deep on estimation, I recommend Software Estimation: Demystifying the Black Art by Steve McConnell.

I’m renaming Rails with Jason to Code with Jason

I’ve decided to rename my podcast, formerly known as Rails with Jason, to Code with Jason.

Such a pivotal event in world history of course calls for some commentary. Here’s what you can expect to be different on the show, what you can expect to stay the same, and why I’ve decided to make this change.

What will change

As the name change implies, the scope of the podcast will no longer be limited to just Rails. This is actually less of a change of direction and more of an acknowledgement of existing reality. It’s already the case that probably half or more of my content is not Rails-specific.

One consequence of this change that I’m excited about is that I’ll be able to dramatically broaden the palette of guests that I can have on the show. When the podcast was explicitly Rails-focused, I had reservations about inviting “big names” from outside the Rails world on the show because I didn’t imagine that being on a Rails podcast would necessarily fit into their plans. Now that that limit is gone, I’ll be much more comfortable inviting any guest at all.

What will stay the same

The format of the show will still be the exact same. I’ll still have guests on for (hopefully) interesting technical conversations.

I’m still going to talk about Ruby on Rails. I myself am still a Rails developer and I expect to remain so indefinitely. If you’re a Rails developer and you’re wondering if the show will still be relevant to you, my hope and expectation is that it will.

Lastly, I’ll of course continue to charm you with my hilarious jokes and dazzle you with my towering intellect. As if I could stop if I wanted to.

Why I’m making this change

My motivation for expanding the scope of my podcast is pretty simple. I want to reach more people and broaden the possibilities for what the show can be. The more programmers I can help and the more I can help them, and the broader the field of topics that can be explored, the more fun and worthwhile of an endeavor this will be for me.

If you’re a listener of the podcast, thanks for listening so far. I hope you’ll join me in this next chapter of the show.

Active Record queries in views: when it’s bad, when it’s fine

“No Active Record queries in views”

Maybe you’ve heard the advice that you shouldn’t put Active Record queries (or other logic) in views, but you’re not sure exactly why, other than “separation of concerns”. Why exactly is separation of concerns good?

The rationale behind this advice is that mixing concerns (like query logic vs. presentation) makes the code harder to understand and change.

Another way to think about this is to think about what kinds of things tend to change together.

Related changes

Even though many changes require touches at multiple levels in order for the change to be complete (model, controller, view)​, some changes are more closely related than others.

A change to the SQL in a query is more likely to call for other SQL changes than it is to call for a CSS change. For this reason, it usually makes sense to put query code next to other query code so that all the query code can be noticed and considered and worked with at the same time.

Sometimes queries in views is fine

Having said that, I don’t dogmatically follow a rule of “no queries in views”. If I for example have a select input and it needs to contain all categories, I’ll unashamedly put Category.all right into my view code. The alternative to this is to clutter up my controller with instance variables and before_actions.

The reason I don’t feel bad about this is that Category.all is unlikely to ever influence or be influenced by some other model change. And in the unlikely event that I’m wrong about that, I can easily move that query out of the view when I need to. But I’m hardly ever wrong about that. (I never put complex queries in my views though.)

Takeaway

Keeping logic code out of views tends to help make your code easier to change and understand. It’s generally good to keep Active Record queries out of views, but putting Active Record queries in views is typically harmless when the query is very unlikely to influence or be influenced by anything else.

Writing software isn’t like building a house, it’s like writing a novel

It’s common to analogize writing software with building a house.

I think it’s a lot more like writing a novel.

With a house, you can add an addition and not necessarily have to change much. But with a novel, everything in it has to reconcile.

The father becomes a mother

Imagine a novel about father who has a troubled relationship with his son because the father spends too much time at the bar, getting in fights and getting fired from a string of jobs due to his irresponsibility. In the end the father dies in a drunken car crash and, fast forward, the son grows up to be just like his father. (Sorry, didn’t mean to make it so dark!)

But then imagine “the requirements change” somehow and the father character needs to be a mother instead.

We can’t just search-and-replace “dad” with “mom”. All sorts of other things need to change as well if the whole thing is going to square up.

If the tragedy of the story is that the son turns out to be just like his father, then maybe a mother-son thing doesn’t really make much sense anymore. Maybe the son has to be a daughter instead. A mother can just as plausibly be an alcoholic as a father of course, but the part about the constant fist fights makes a little less sense now. That part will probably either have to be eliminated or changed to something else.

Every codebase is a novel

Software is of course the same way. Some changes are isolated sometimes, but quite a lot of changes have ripple effects throughout the whole system. And the bigger a codebase gets, the more challenging and time-consuming it is to keep everything self-consistent.

This is why the construction analogy doesn’t really fit all that well. I think the novel analogy is better.

How to install nginx and Passenger on an EC2 instance for Rails hosting

This is part 2 of my series on how to deploy a Ruby on Rails application to AWS. If you found this page via search, I recommend starting from the beginning.

Recap of last step and overview of this step

In the previous step we launched an EC2 instance.

In this step we’re going to install some useful software on our new EC2 instance, specifically web server software.

A note before diving in: I must give credit to Passenger docs, from which some of this is directly lifted.

1. Install nginx

The very first step is to install nginx, which luckily involves very few steps.

As a reminder, these commands and all commands that follow are meant to be run on your new EC2 instance. Instructions for how to SSH into your EC2 instance can be found near the end of the previous step.

sudo apt-get update
sudo apt-get install -y nginx
sudo service nginx restart

2. Install Passenger

I recommend executing each of the following groups of commands separately, one at a time. That way it’s easier to tell whether each group of commands was successful or not.

sudo apt-get install -y dirmngr gnupg
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt-get install -y apt-transport-https ca-certificates

sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bionic main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update

sudo apt-get install -y libnginx-mod-http-passenger

The following step verifies that the config files do in fact exist at /etc/nginx/conf.d/mod-http-passenger.conf. The result of the ls command is supposed to be the file path, printed back out to you (/etc/nginx/conf.d/mod-http-passenger.conf). If it’s not, there’s a problem.

if [ ! -f /etc/nginx/modules-enabled/50-mod-http-passenger.conf ]; then sudo ln -s /usr/share/nginx/modules-available/mod-http-passenger.load /etc/nginx/modules-enabled/50-mod-http-passenger.conf ; fi
sudo ls /etc/nginx/conf.d/mod-http-passenger.conf

Now we’ll restart nginx to make our changes take effect.

sudo service nginx restart

This step validates the Passenger installation.

sudo /usr/bin/passenger-config validate-install

3. Configure nginx/Passenger to know about Ruby

What follows in this step is roughly copied from this page. If you have trouble or want clarification, I recommend visiting that page to get the info directly from its original source.

The first thing we need to do is find out our Ruby path. Running the following command will tell us. You’ll probably have to look kind of hard because the output of the command is “noisy”. The Ruby path is there but it’s kind of obscured by some other stuff.

passenger-config about ruby-command

Once you’ve found the Ruby path in the output of that command, copy it. We now need to edit /etc/nginx/sites-enabled/default. I use Vim but you can of course use whatever editor you want.

sudo vi /etc/nginx/sites-enabled/default

We’ll need to add the following two lines inside the server block. I don’t believe it matters exactly where these two lines go as long as they’re between the two braces of the server block.


passenger_enabled on;
passenger_ruby /usr/bin/ruby2.5; # Note: your Ruby path may be different

If it helps, here’s what my complete /etc/nginx/sites-enabled/default looks like (with comments removed for brevity):

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        index index.html index.htm index.nginx-debian.html;

        server_name _;

        # Important: delete the following 3 lines
        # location / {
        #         try_files $uri $uri/ =404;
        # }

        passenger_enabled on;
        passenger_ruby /usr/bin/ruby2.5;
}

Now we’ll restart nginx to make our changes take effect.

sudo service nginx restart

4. Enable port 80 to allow web traffic

Our server is now ready to be visited in the browser, except by default AWS doesn’t have port 80 open, the port for HTTP traffic. Let’s open port 80.

The way we do this is by adding a rule for port 80 to our EC2 instance’s security group.

To do this, first go to to the AWS console, click the EC2 instance, make sure you’re on the Description tab, then click the first link under Security groups.

Then, under the Inbound tab, click Edit.

Click Add Rule, select HTTP from the list, then click Save. The change will take effect right away and HTTP traffic will be allowed starting immediately.

5. Visit the server in the browser

Enter your EC2 instance’s public DNS into your browser. As a reminder, this can be done by going to the EC2 Dashboard, right-clicking your instance, and clicking Connect.

When you visit your server you should see the following page. This means nginx is running!

Now we can move onto the next step, connecting Rails with nginx.

Exosuit demo video #2: launching an EC2 instance from Exosuit’s web UI

Exosuit is a tool I’ve been working on to make Rails-AWS deployments almost as easy as Rails-Heroku deployments.

Back in late September 2019, I coded up an initial version of Exosuit and released a demo video of what I had built.

Since then a lot has changed, including my conception of what Exosuit even is.

My original thought was that Exosuit would be mainly a command-line tool, with a web UI in a supporting role. Now my thinking is that Exosuit will be mainly a web UI tool, with a command-line tool in a supporting role.

Here’s what I’m currently imagining the launch process to look like, roughly:

  1. Create an Exosuit account
  2. Connect Exosuit with your AWS account and let Exosuit launch an EC2 instance
  3. Run git push exosuit master to deploy your Rails application to your new EC2 instance

So far I have steps 1 and 2 complete. It might not sound like a lot, but it took me over a month of work!

Below is a demo video of what Exosuit can do so far.

If you’d like to get real-time updates on my progress with Exosuit, you can sign up for my email list below or follow me on Twitter.

Capybara: expect field to have value

I commonly find myself wanting to assert that a certain field contains a certain value. The way to do this with Capybara is documented on StackOverflow but, unfortunately, the answer there is buried in a little too much noise. I decided to create my own tiny noise-free blog post that contains the answer. Here it is:

expect(page).to have_field('Name', with: 'Abraham Lincoln')

Reader Q&A: Kaemon’s question about test-first vs. test-after

Recently reader Kaemon L wrote me with the following question:

“As a beginner, is it better to write tests before you code to make it pass? or is it better to code first, write tests for the code to pass, and then add more tests as you come across bugs? In my experience so far learning RSpec, I’ve found it easier to code first and then write tests afterwards. Only because when I would try to write tests first I wasn’t exactly sure what needed to be tested, or how I was planning to write the code.

This is a great question. In addressing this question I find it useful to realize that when you’re learning testing you’re actually embarking on two parallel endeavors:

1. Writing tests (outcome)
2. Learning how to write tests (education)

I think it’s useful to make the distinction between these two parts of the work. If you make the realization that achieving the desired outcome is only half your job, and the other half is learning, then it frees you up to do things “incorrectly” for the sake of moving forward.

With that out of the way, what’s actually better? Writing tests first or after?

I’m not sure that it makes sense to frame this question in terms of “better” or “worse”. When I think of test-driven development, I don’t think of it as “better” than test-after in all situations, I think of TDD as having certainadvantages in certain scenarios.

What are the advantages of test-driven development?

TDD can separate the what from the how. If I write the test first, I can momentarily focus on what I want to accomplish and relieve my mind of the chore of thinking of how. Then, once I switch from writing the test to writing the implementation, I can free my mind of thinking about everything the feature needs to do and just focus on making the feature work.

TDD increases the chances that every single thing I’ve written is covered by a test. The “golden rule” of TDD (which I don’t always follow) is said to be “never write any new code without a failing test first”. If I follow that, I’m virtually guaranteed 100% test coverage.

TDD forces me to write easily-testable code. If I write the test first and the code after, I’m forced to write code that can be tested. There’s no other way. If I write the code first and try to test it afterward, I might find myself in a pickle. As a happy side benefit, code that’s easily testable happens to also usually be easy to understand and to work with.

TDD forces me to have a tight feedback loop. I write a test, I write some code. I write another test, I write some more code. When I write my tests after, I’m not forced to have such a fast feedback loop. There’s nothing stopping me from coding for hours before I stop myself and write a test.

If I choose to write my tests after my application code instead of before, I’m giving up the above benefits. But that doesn’t mean that test-after is automatically an inferior workflow in all situations.

Let’s go back to the two parallel endeavors listed above: writing tests and learning how to write tests. If I’m trying to write tests as I’m writing features and I just can’t figure out how to write the test first, then I have the following options:
1. Try to plow through and somehow write the test first anyway
2. Give up and don’t write any tests
3. Write the tests after

If #1 is too hard and I’m just hopelessly stuck, then #3 is a much better option than #2. Especially if I make a mental shift and switch from saying “I’m trying to write a test” to saying “I’m trying to learn how to write tests”. If all I’m trying to do is learn how to write tests, then anything goes. There’s literally nothing at all I could do wrong as part of my learning process, because the learning process is a separate job from producing results.

Lastly, what if I get to the stage in my career where I’m fully comfortable with testing? Is TDD better than test-after? I would personally consider myself fully comfortable with testing at this stage in my career (although of course no one is ever “done” learning). I deliberately do not practice TDD 100% of the time. Sometimes I just find it too hard to write the test first. In these cases sometimes I’ll do a “spike” where I write some throwaway code just to get a feel for what the path forward might look like. Then I’ll discard my throwaway code afterward and start over now that I’m smarter. Other times I’ll just begin with the implementation and keep a list of notes like “write test for case X, write test for case Y”.

To sum it all up: I’m not of the opinion that TDD is a universally superior workflow to non-TDD. I don’t think it’s important to hold oneself to TDD practices when learning testing. But once a person does reach a point of being comfortable with testing, TDD is an extremely valuable methodology to follow.