If you want to write great Rails apps, there’s a lot you’ll need to know. Sometimes, it feels impossible to keep up. But if you don’t seek out new knowledge, you’ll fall behind.

You don’t have to dig for great Rails information, if it finds you. To help you write great Rails apps, I send new articles every single week to over 2,500+ Rails developers. Sign up, and you’ll learn how to speed up your apps, discover new Rails features, create more effective tests, write code more quickly, and become a better Rails developer.

I’ve also selected my most popular articles below for you to read. Keep scrolling to see my newest articles.

Most Popular:

For more articles written for developers like you, browse my full article archive.

Scopes are a great way to grab the right objects out of your database:

app/models/review.rb
1
2
3
class Review < ActiveRecord::Base
  scope :most_recent, -> (limit) { order("created_at desc").limit(limit) }
end

You’d use the scope like this:

app/models/homepage_controller.rb
1
@recent_reviews = Review.most_recent(5)

Calling that scope, though, looks exactly like calling a class method on Review. And it’s easy to build it as a class method, instead:

app/models/review.rb
1
2
3
def self.most_recent(limit)
  order("created_at desc").limit(limit)
end
app/models/homepage_controller.rb
1
@recent_reviews = Review.most_recent(5)

So why would you use a scope when you could use regular Ruby class methods? Is it worth keeping these totally seperate, but equivalent, concepts in your head? What if you run into weird bugs? Isn’t all this extra stuff the kind of thing that makes Rails harder to learn?

When would it make sense to use a scope instead of a class method?

Why use scopes when we already have class methods?

What if you wanted to grab all the reviews written after a specific date? But if no date was specified, you wanted all the reviews returned instead?

As a scope, that looks like this:

app/models/review.rb
1
scope :created_since, ->(time) { where("reviews.created_at > ?", time) if time.present? }

Easy enough, right? What about the class method?

app/models/review.rb
1
2
3
4
5
6
7
def self.created_since(time)
  if time.present?
    where("reviews.created_at > ?", time)
  else
    all
  end
end

It takes a little bit of extra work. Scopes prefer to return scopes, so they’re easy to chain together:

1
Review.positive.created_since(5.days.ago)

But to get the class method to work the same way, you have to specifically handle the case where time is nil. Otherwise, the caller would have to figure out whether it has a valid, chainable scope.

Methods that always return the same kind of object are really useful. You don’t have to worry as much about edge cases or errors. You can assume you’ll always be handed back an object you can use.

Here, it means you can chain scopes together, without having to worry about nil values coming back.

There are still ways you can break the assumption that you’d always get a scope back:

app/models/review.rb
1
scope :broken, -> { "Hello!!!" }
1
2
irb(main):001:0> Review.broken.most_recent(5)
NoMethodError: undefined method `most_recent' for "Hello!!!":String

But I’ve never had that happen in real code.

The thing I love most about scopes is that they express intent. You’re telling the next person who reads your code, “This method can be chained, will eventually turn into a list of objects, and will help you select the right set of objects.” That’s a whole lot more than a generic class method says.

When should you use a class method instead of a scope?

Because scopes express intent, I use them whenever I’m chaining simple, built-in scopes (like where and limit) into more complicated scopes. Finding the right bunch of objects is what scopes were designed for.

There are two exceptions:

  1. When I need to preload scopes, I turn them into associations instead.
  2. When I do more than chain built-in scopes into larger scopes, I use class methods.

When your scope logic gets complicated, a class method feels like the right place to put it.

Inside a class method, you can easily mix Ruby code with database code. If you have sorting code that’s easier to write in Ruby, you could grab your objects in their default order, and use sort_by to put them in the right order.

Or, if you’re feeling particularly tricky, a class method could grab data from a few different places: your database, Redis, or an external API or service. Then, it could assemble it all into a collection of objects that feels like a scope that’s been turned into an array.

Even then, it’s still good to put your selecting, sorting, joining, and filtering code inside scopes. Then, use your scopes inside your class method. You’ll end up with a clearer class method, and scopes you can use throughout your app.


Scopes are one of my favorite Rails features. You can do some powerful stuff – read my article on sorting and filtering Rails models to see an especially useful scope example.

And there’s a really simple way to master using scopes: play with them inside tiny, focused apps. The free sample chapter of Practicing Rails will show you how. Check it out!

Why did Rails become so popular, so quickly?

The simplicity helped, especially if you came from the Java, XML, Enterprise world. It was also marketed incredibly well. But that’s not everything.

A lot of Rails’ success in the startup world came from a simple fact: The problems businesses have aren’t that unique. Rails was great at creating CRUD sites, while remaining flexible. And that’s really all a ton of businesses need. Especially at the beginning.

But this isn’t just true for businesses. A lot of the problems we face as software developers don’t change. Sure, our solutions evolve. They cycle. We get better. But the same solutions discovered by the last generation of developers can still help us today.

So, do you want to know the answers to the problems you’ll face in the future? The best thing you can do is look to the past.

Look to the past

On his website, Martin Fowler has an unbelievable collection of good solutions to common problems. Have you been hearing devs talk about Event Sourcing? He wrote the definitive article on it 10 years ago. Chasing performance and reliability problems with your new REST API or Service-Oriented Architecture? It’s his first law of distributed objects, from close to 15 years ago.

Avdi Grimm told me that “If you want to lead the technology curve, start investigating whatever Martin Fowler was writing about a decade ago.” That’s totally true. The time you spend reading through the patterns on his website will be a great investment in your programming future. And that’s not even mentioning the refactoring patterns.

Going further, just about any book or article written by the authors of the Agile Manifesto is worth reading – 15 years ago, they were working through the same software architecture problems we run into today.

You can find a lot of their discussions on the C2 Wiki. The debates we have about when TDD makes the most sense? They’re all there. And they’ve been there. The wiki has been around for a while, and it’s still a fantastic resource.

Books from the late 90’s to the early 2000’s are also helpful. I smiled all the way through Smalltalk Best Practice Patterns and Patterns of Enterprise Application Architecture (which was a huge influence on Rails), because they described problems I’ve had so well.


Just like design fashions, software development practices cycle. From distributed to centralized, from client side to server side, from dynamic to static.

Do you want to get ahead, understand what’s coming, and maybe even drive what comes next? Look to the past. Research the solutions to the problems that our current solutions will cause. And help bring the good practices of the last generation of software developers to the next.

Ruby conferences are awesome. There are so many people sharing so much knowledge, and you’ll take something away from almost every talk. And even if you can’t be there, new conferences mean lots of new talk videos.

But there’s a problem. Videos take time. Even at 1.5x, they’ll still last 20 or 30 minutes each. And that’s focused time that’s hard to find as often as I’d like.

Podcasts, though, have already found a place in my life. I start almost every commute by firing up Overcast and listening to a few episodes. And besides the commute, you can listen to them while you walk the dog, or do the dishes. You can hear them as you go off to sleep.

So, after conference videos are posted, I’d love to take some of the non-code-heavy talks and put them where I’ll naturally hear them: inside my podcast player. And it turns out there’s a pretty easy way to do just that.

Creating a personal podcast with Huffduffer

Huffduffer is a website that turns audio files you find anywhere on the web into your own personal podcast station. This is really cool! But there’s a problem when you try it with conference talks:

Most conference videos are conference videos.

So, before you can add a talk to Huffduffer, you have to grab just the audio out of it. And to do that, you have to find a way to download the video.

Fetching a video with youtube-dl

When you see a video on a site like Youtube, Vimeo, or Confreaks, and you’d rather have it on your machine, you can use a little tool called youtube-dl. On a Mac, it’s easy to install using Homebrew:

1
brew install youtube-dl

(You can install it on other systems using the instructions on the site).

Once it’s installed, if you wanted to download Kylie Stradley’s great RailsConf 2015 talk so you could watch it offline, run:

1
youtube-dl http://confreaks.tv/videos/railsconf2015-amelia-bedelia-learns-to-code

This is close to what we want. But to put it in a podcast, you only need the audio. youtube-dl supports that with the -x flag, but you have to install ffmpeg first:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ brew install ffmpeg
$ youtube-dl -x http://confreaks.tv/videos/railsconf2015-amelia-bedelia-learns-to-code

[generic] railsconf2015-amelia-bedelia-learns-to-code: Requesting header
WARNING: Falling back on generic information extractor.
[generic] railsconf2015-amelia-bedelia-learns-to-code: Downloading webpage
[generic] railsconf2015-amelia-bedelia-learns-to-code: Extracting information
[download] Downloading playlist: Confreaks TV | Amelia Bedelia Learns to Code - RailsConf 2015
[generic] playlist Confreaks TV | Amelia Bedelia Learns to Code - RailsConf 2015: Collected 1 video ids (downloading 1 of them)
[download] Downloading video 1 of 1
[youtube] bSbla50tqZE: Downloading webpage
[youtube] bSbla50tqZE: Extracting video information
[download] Destination: RailsConf 2015 - Amelia Bedelia Learns to Code-bSbla50tqZE.m4a
[download] 100% of 31.88MiB in 00:05
[ffmpeg] Correcting container in "RailsConf 2015 - Amelia Bedelia Learns to Code-bSbla50tqZE.m4a"
[youtube] Post-process file RailsConf 2015 - Amelia Bedelia Learns to Code-bSbla50tqZE.m4a exists, skipping

Then, in Huffduffer, click the “Huffduff it” link in the header, and you’ll run into the last hoop you have to jump through.

Uploading the audio with Dropbox

You can’t upload your new audio file to Huffduffer, because Huffduffer wants a link to the file, not the file itself.

If you’re a Dropbox user, you can easily get the file onto the internet if you drop it into Dropbox’s Public/ folder. Then, you can right click and “Copy Public Link” to get the link you’ll use on Huffduffer.

Finally, use the “RSS” link on Huffduffer to get your podcast into your favorite podcast player.

Sadly, as a podcast, you miss out on the (frankly awesome) pictures in this talk. And it doesn’t work well with code- or demo-heavy talks (though you might still be able to get the gist of it).

But sometimes, it’s not a choice between listening to a talk or watching a talk. It’s between listening to a talk and not experiencing it at all. If those are your options, audio-only seems like a decent compromise.

Putting it all together

So, here’s that process again:

  1. Sign up for a free Huffduffer account.
  2. Install youtube-dl.
  3. Install ffmpeg.
  4. Download the talk’s audio with youtube-dl -x <url_to_talk_video>.
  5. Toss the audio file into ~/Dropbox/Public, or somewhere else that’s publicly accessible.
  6. Click “Huffduff it,” and paste the link to your new audio file.
  7. Listen to the new episode of your very own conference podcast!

If you’re a fan of podcasts, give this a try. It’s really nice to have conference talks pop up where you’re already listening.

When you research how to deploy your Rails app, you’ll see a lot of names: Apache, Unicorn, Puma, Phusion Passenger, Nginx, Rainbows, and many more. They all seem to fit under the “deploying Rails” category of software, but there’s a key difference between them. Some are “web servers,” and others are “app servers.”

Once you understand which is which, and where each category fits in your system, deployment will make a lot more sense. But the categories aren’t always clear.

What’s a web server, and how is it different than an app server? Can you use one without the other? And where does Rack fit in?

What’s a web server?

A web server is a program that takes a request to your website from a user and does some processing on it. Then, it might give the request to your Rails app. Nginx and Apache are the two big web servers you’ll run into.

If the request is for something that doesn’t change often, like CSS, JavaScript, or images, your Rails app probably doesn’t need to see it. The web server can handle the request itself, without even talking to your app. It’ll usually be faster that way.

Web servers can handle SSL requests, serve static files and assets, compress requests, and do lots of other things that almost every website needs. And if your Rails app does need to handle a request, the web server will pass it on to your app server.

What’s an app server?

An app server is the thing that actually runs your Rails app. Your app server loads your code and keeps your app in memory. When your app server gets a request from your web server, it tells your Rails app about it. After your app is done handling the request, the app server sends the response back to the web server (and eventually to the user).

You can run most app servers by themselves, without a web server in front of it. That’s probably what you do in development mode! In production, though, you’ll usually have a web server in front. It’ll handle multiple apps at once, render your assets faster, and deal with a lot of the processing you’ll do on every request.

There are a ton of app servers for Rails apps, including Mongrel (which isn’t used much anymore), Unicorn, Thin, Rainbows, and Puma. Each has different advantages and different philosophies. But in the end, they all accomplish the same thing – keeping your Rails app running and handling requests.

What about Passenger?

Phusion Passenger is a little unique. In “standalone mode,” it can act just like an app server. But it can also be built right into a web server, so you don’t need a separate app server to run your Rails apps.

This can be really convenient. Especially if you’re planning to run a bunch of apps and don’t want to spend time setting up an app server for each one. After installing Passenger, you just point the web server directly at your Rails app (instead of an app server), and your Rails app will start handling requests!

Passenger is a nice option, but having a separate app server can be still be good. Keeping the app server separate gives you the flexibility to choose an app server that best fits your needs, and you can run and scale it on its own. Still, I’m going to try it again the next time I deploy a new small app. I’m hoping it’ll make it easier to deploy future apps to the same server.

What about Rack?

Rack is the magic that lets any of these app servers run your Rails app. (Or Sinatra app, or Padrino app, or…)

You can think of Rack as a common language that Ruby web frameworks (like Rails) and app servers both speak. Because each side knows the same language, it means Rails can talk to Unicorn and Unicorn to Rails, without having either Rails or Unicorn know anything about the other.

How do they relate?

So, how does this all fit together?

Out of these pieces, a web request will hit your web server first. If the request is something Rails can handle, the web server will do some processing on the request, and hand it off to the app server. The app server uses Rack to talk to your Rails app. When your app is done with the request, your Rails app sends the response back through the app server and the web server to the person using your app.

More specifically, Nginx might pass a request to Unicorn. Unicorn gives the request to Rack, which gives it to the Rails router, which gives it to the right controller. Then, your response just goes back through the other way.


This overview might be simplified. But even just knowing these categories will help you put the software you run into into the right mental buckets.

After you understand how app servers and web servers fit together, it’ll be a lot easier to debug server problems when you have them. You’ll know all the different places you could look, and how they interact. And once the next interesting app server arrives, it’ll be even easier for you to swap it in!

Thom Parkin made a great point in the comments of an earlier article of mine:

Great advice. But you missed one very important [final] point. Since this is Open Source, once you have figured out the details of that feature/function where the documentation is a bit light, YOU SHOULD UPDATE THE DOCS AND SUBMIT A PULL REQUEST. In that way the entire community benefits, and you can even gain some “coder cred” for your participation!

I’m happy Thom mentioned this, because it’s so important. Fixing documentation is the easiest way to start contributing back to the projects you use and love.

My first contributions to projects like Rails, Rubinius, and Elixir have all been doc fixes. I’ve made small tweaks to make things clearer, explained some things that you could only discover by reading the code, even just fixed broken formatting. These have all been quick, easy ways to help out some big open source projects. Even when they’re my only contributions to a project, they’ve still helped future users, and Future Me. And that’s what open source is all about.

Why documentation fixes are such a great way to get started

Doc fixes are the least intimidating way to contribute to a big project like Rails:

  • You don’t have to set up the project in order to fix the bug. Since you’re just updating the documentation, you don’t have to get the tests or the app running. Sometimes, you won’t even have to clone the project to your machine – you can make your change right on GitHub!

  • If the maintainer asks you to make changes to your pull request, they’re usually a matter of wording or taste. Those kind of changes can be easier to stomach than criticism of your code. And it’s easier for you to make those changes, because you don’t have to update tests or code, just words.

  • Documentation is hard for a project maintainer, so updates are appreciated. Often, authors are too close to the code to understand where the confusing parts are. They need other, newer developers to tell them where the docs need help. It takes practice to see your project as a beginner would, and not everyone has built that skill.

  • Finally, you’re starting to build a relationship with the maintainer, with a low-impact change. You’re not changing the direction of the project, like you would if you were contributing an entire feature. So your change is easier for a maintainer to review, and they’ll usually respond to you more quickly. Your merge request won’t get stuck in the “Is this a good idea?” phase.

As you keep building that relationship, you’ll start to be seen as a reliable contributor. Your pull requests will get reviewed faster, and it’ll be easier for both of you to talk through more complicated feature requests and bug fixes.

They’re easier to start, they’re easier to do, and they tend to get merged more quickly. So why wouldn’t your first contribution be a doc fix?

How to start contributing back updated documentation

There’s an important way contributing doc updates is like fixing bugs: They both rely on being sensitive to things that feel wrong. You have to pay attention.

When you run into behavior you didn’t expect, it might be time to update the docs. If you have to dive into the code to solve a problem, you might also want to tell other people about it. You should even be sensitive to broken formatting and typos in the documentation you read. If you’re not going to fix it, who will?

Once you have a good idea of where to make the change and how you want to word it, make your change and send a pull request through GitHub.

If you’re still trying to decide on the best way to update the docs, open an issue on GitHub. It can be something like this:

“Hey, this was confusing to me. I was thinking of updating it to look something like this: … What do you think? Anything else I should mention?” Together, you can come up with wording that satisfies everyone.

Finally, don’t be discouraged if you don’t get a response. Big projects have a lot going on, so it’s easy for your contribution to fall through the cracks. In a week or so, if you still don’t hear from anyone, ask the maintainer again.

Documentation is often the first thing you encounter when you work with a library, so it’s important that it’s detailed and clear.

So when you’re confused about the code you use, or have to dive into the source, make it easier for the next person. Write a quick update, and contribute it back. It’s the easiest way I know of to become an open source contributor.

This article was originally sent to the people on my list. To read more like it, sign up here!

After you pick up the Rails basics, you still have a lot to learn. You have to understand gems, DSLs, refactoring, testing, and the deeper parts of Rails itself.

With the Ruby Book Bundle, launching on Monday, July 6, you can kickstart your Rails education with Practicing Rails and 5 other great Ruby books at a huge discount. Sign up to get a reminder when the bundle sale starts!


Imagine a question that can be either “pending”, “approved”, or “flagged”. Or a phone number that’s a “home”, “office”, “mobile”, or “fax” (if it’s 1982).

Some models call for this kind of data. An attribute that can have only one of a few different values. And that set of values almost never changes.

It’s a situation where, if it were plain Ruby, you’d just use a symbol.

You could create a PhoneNumberType or QuestionStatus model and a belongs_to relationship to hold these values, but that doesn’t seem worth it. You could stuff them in a yaml file, but now you have to look in a totally different place to figure out what your object can do.

In 4.1, Rails took a stab at solving this problem with ActiveRecord enums.

A few values, in the model

ActiveRecord enums are pretty easy. You give your model an integer column:

1
bin/rails g model phone number:string phone_number_type:integer

List the values that attribute can take:

app/models/phone.rb
1
2
3
class Phone < ActiveRecord::Base
  enum phone_number_type: [:home, :office, :mobile, :fax]
end

And now you can deal with strings instead of numbers.

Instead of this:

1
2
irb(main):001:0> Phone.first.phone_number_type
=> 3

You’ll see this:

1
2
irb(main):002:0> Phone.first.phone_number_type
=> "fax"

You can change that attribute using either strings or ints:

1
2
3
4
irb(main):003:0> phone.phone_number_type = 1; phone.phone_number_type
=> "office"
irb(main):004:0> phone.phone_number_type = "mobile"; phone.phone_number_type
=> "mobile"

Or even using a bang method:

1
2
3
4
irb(main):005:0> phone.office!
=> true
irb(main):006:0> phone.phone_number_type
=> "office"

You get methods for asking if your attribute has some specific value:

1
2
irb(main):007:0> phone.office?
=> true

And you can find all objects with the value you’re looking for:

1
2
irb(main):008:0> Phone.office
  Phone Load (0.3ms)  SELECT "phones".* FROM "phones" WHERE "phones"."phone_number_type" = ?  [["phone_number_type", 1]]

If you want to see all the different values you can use, along with the numbers they’re associated with, use the phone_number_types class method:

1
2
irb(main):009:0> Phone.phone_number_types
=> {"home"=>0, "office"=>1, "mobile"=>2, "fax"=>3}

Which makes them easy to put into an HTML form:

app/views/phones/_form.html.erb
1
2
3
4
<div class="field">
  <%= f.label :phone_number_type %><br>
  <%= f.select :phone_number_type, Phone.phone_number_types.keys %>
</div>

An enum in a form

A few things to watch for

Enums aren’t without their problems, though. You have to keep a few things in mind if you don’t want to run into trouble later on.

When you define an enum, order matters. So if you go back to your code and decide that those values should really be in alphabetical order:

app/models/phone.rb
1
2
3
class Phone < ActiveRecord::Base
  enum phone_number_type: [:fax, :home, :mobile, :office]
end

Your phones won’t have the right types anymore. You can get around this by telling enum which number goes with which value:

app/models/phone.rb
1
2
3
class Phone < ActiveRecord::Base
  enum phone_number_type: {fax: 3, home: 0, mobile: 2, office: 1}
end

But really, your best option is to keep the order consistent.

A bigger problem is what to do outside the Rails world. Even though Rails sees these enum values as strings, they’re just numbers inside your database. So someone looking at your raw data will have no idea what those numbers mean. This also means that every app that reads that database will have to know that enum mapping.

You could dump your enum mapping to the database or a yaml file if you really needed other people to see them. But that’s not DRY, because now you’re defining your enum in two places. And if you’re going that far, it might be better to do what we were avoiding in the beginning: create a totally separate model and association, so that a Phone would belong_to a PhoneNumberType.

But if you’re keeping it simple, enums are a great way to start.

P.S. In case you missed it, Practicing Rails is going to be included in the Ruby Book Bundle, launching on Monday, July 6. Get it and 5 other great Ruby books at a huge discount!

Rails’ scopes make it easy to find the records you want:

app/models/review.rb
1
2
3
4
5
class Review < ActiveRecord::Base
  belongs_to :restaurant

  scope :positive, -> { where("rating > 3.0") }
end
1
2
3
4
irb(main):001:0> Restaurant.first.reviews.positive.count
  Restaurant Load (0.4ms)  SELECT  `restaurants`.* FROM `restaurants`  ORDER BY `restaurants`.`id` ASC LIMIT 1
   (0.6ms)  SELECT COUNT(*) FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0)
=> 5

But if you’re not careful with them, you’ll seriously hurt your app’s performance.

Why? You can’t really preload a scope. So if you tried to show a few restaurants with their positive reviews:

1
2
3
4
5
6
7
8
9
10
irb(main):001:0> restauraunts = Restaurant.first(5)
irb(main):002:0> restauraunts.map do |restaurant|
irb(main):003:1*   "#{restaurant.name}: #{restaurant.reviews.positive.length} positive reviews."
irb(main):004:1> end
  Review Load (0.6ms)  SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0)
  Review Load (0.5ms)  SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 2 AND (rating > 3.0)
  Review Load (0.7ms)  SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 3 AND (rating > 3.0)
  Review Load (0.7ms)  SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 4 AND (rating > 3.0)
  Review Load (0.7ms)  SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`restaurant_id` = 5 AND (rating > 3.0)
=> ["Judd's Pub: 5 positive reviews.", "Felix's Nightclub: 6 positive reviews.", "Mabel's Burrito Shack: 7 positive reviews.", "Kendall's Burrito Shack: 2 positive reviews.", "Elisabeth's Deli: 15 positive reviews."]

Yep, that’s an N+1 query. The biggest cause of slow Rails apps.

You can fix this pretty easily, though, if you think about the relationship in a different way.

Convert scopes to associations

When you use the Rails association methods, like belongs_to and has_many, your model usually looks like this:

app/models/restaurant.rb
1
2
3
class Restaurant < ActiveRecord::Base
  has_many :reviews
end

But if you check out the documentation, you’ll see that they can do more. You can pass other parameters to those methods and change how they work.

scope is one of the most useful. It works just like the scope from earlier:

app/models/restaurant.rb
1
2
3
4
class Restaurant < ActiveRecord::Base
  has_many :reviews
  has_many :positive_reviews, -> { where("rating > 3.0") }, class_name: "Review"
end
1
2
3
4
irb(main):001:0> Restaurant.first.positive_reviews.count
  Restaurant Load (0.2ms)  SELECT  `restaurants`.* FROM `restaurants`  ORDER BY `restaurants`.`id` ASC LIMIT 1
   (0.4ms)  SELECT COUNT(*) FROM `reviews` WHERE `reviews`.`restaurant_id` = 1 AND (rating > 3.0)
=> 5

Now, you can preload your new association with includes:

1
2
3
4
5
6
7
irb(main):001:0> restauraunts = Restaurant.includes(:positive_reviews).first(5)
  Restaurant Load (0.3ms)  SELECT  `restaurants`.* FROM `restaurants`  ORDER BY `restaurants`.`id` ASC LIMIT 5
  Review Load (1.2ms)  SELECT `reviews`.* FROM `reviews` WHERE (rating > 3.0) AND `reviews`.`restaurant_id` IN (1, 2, 3, 4, 5)
irb(main):002:0> restauraunts.map do |restaurant|
irb(main):003:1*   "#{restaurant.name}: #{restaurant.positive_reviews.length} positive reviews."
irb(main):004:1> end
=> ["Judd's Pub: 5 positive reviews.", "Felix's Nightclub: 6 positive reviews.", "Mabel's Burrito Shack: 7 positive reviews.", "Kendall's Burrito Shack: 2 positive reviews.", "Elisabeth's Deli: 15 positive reviews."]

Instead of 6 SQL calls, we only did two.

(Using class_name, you can have multiple associations to the same object. This comes in handy pretty often.)

What about duplication?

There still might be a problem here. The where("rating > 3.0") is now on your Restaurant class. If you later changed positive reviews to rating > 3.5, you’d have to update it twice!

It gets worse: If you also wanted to grab all the positive reviews a person has ever left, you’d have to duplicate that scope over on the User class, too:

app/models/user.rb
1
2
3
4
class User < ActiveRecord::Base
  has_many :reviews
  has_many :positive_reviews, -> { where("rating > 3.0") }, class_name: "Review"
end

It’s not very DRY.

There’s an easy way around this, though. Inside of where, you can use the positive scope you added to the Review class:

app/models/restaurant.rb
1
2
3
4
class Restaurant < ActiveRecord::Base
  has_many :reviews
  has_many :positive_reviews, -> { positive }, class_name: "Review"
end

That way, the idea of what makes a review a positive review is still only in one place.


Scopes are great. In the right place, they can make querying your data easy and fun. But if you want to avoid N+1 queries, you have to be careful with them.

So, if a scope starts to cause you trouble, wrap it in an association and preload it. It’s not much more work, and it’ll save you a bunch of SQL calls.

There are a ton of books, videos, podcasts, and courses for learning Rails. There’s no way you’d have time to go through them all! So what’s the best way for an absolute beginner to learn Ruby and Rails? Which resources should you start with, and when?

Books and websites

If you’re totally new to programming, the best place to start is Learn to Program, by Chris Pine. It’s an intro to the core programming ideas you’ll need to know. If you’re planning to learn Ruby and Rails, it’s especially great, because it uses Ruby for all of the examples.

After that, Daniel Kehoe’s Learn Ruby on Rails is a gentle introduction to Rails. It teaches you a small part of Rails that will prepare you to take on the harder resources.

If you already know a few other languages or frameworks, check out the free Getting Started with Rails guide. It’s a good, short intro to Rails, that will teach you Rails’ concepts and core ideas.

Once you know the basics, there are two bigger books that will fill out your Rails knowledge.

Agile Web Development with Rails is my favorite general Rails book. It does a good job of teaching first by example, and then by reference. We use it at work to teach devs without Rails experience, and like most of the rest of the Pragmatic Bookshelf books, it’s very good.

The Ruby on Rails Tutorial is the other big Rails resource. It walks you through most of what you need to know to build a fully functional example app. I know a lot of great Rails developers who got started with the Rails Tutorial. And the web version is free, so you can see if it’s your style before you commit to it. If you put in the effort, you’ll get a lot out of it.

Once you’ve gone through one or two of these books, it’s pretty normal to feel confused and frustrated. Especially when you try to put everything together and build your own apps. My book, Practicing Rails, will help you solve the most painful problems you’ll run into as you start your programming career. In Practicing Rails, you’ll learn how to debug your code when it breaks, pick up some processes you can follow to turn the ideas in your head into real features, and discover how to write tests without getting stuck.

While you build your own apps, there are two resources you’ll use more than any others:

The Rails Guides will teach you the most important parts of Rails with documentation and examples. I go back to these all the time. And they’re always up to date.

When you want to know how to call a Rails method, or even whether a method exists to do what you want to do, you’ll need the official Rails API documentation.

(There are much better ways of browsing the API documentation, though, and I talk through a few of them in one of the lessons in my free email course).

You can start building simple apps without knowing a whole lot of Ruby, but spending more time learning Ruby will become important, quickly. And Programming Ruby is the best book I’ve found to get comfortable with the language.

Videos and guided courses

Books and websites are my favorite way to learn new things about Ruby and Rails. But if you prefer watching to reading, there are lots of great screencasts and courses you can check out, too.

If you want a video course to teach you Ruby and Rails, I’ve heard lots of praise for the Pragmatic Studio courses. They sound like a great place to start.

The RailsCasts haven’t been updated in a few years, but they’ll still show you great answers to common web problems. The APIs might have changed, but the ideas have stayed pretty much the same. They’re definitely worth watching.

Avdi Grimm’s Ruby Tapas screencasts will show you fun Ruby code in 5-10 minute videos. They’re Ruby-focused (rather than Rails-focused), but I always learn a lot from them. You can find a few free sample videos on the site, but they’re all great. It’s really worth subscribing to.

The Destroy All Software screencasts aren’t specifically about Ruby and Rails, but watching them will make you a better developer, whatever your language.

Finally, bloc.io is an online bootcamp some readers have recommended. They pair you with a mentor who can help you with your specific problems when you get stuck.

One-on-one help is great – it can be exactly what you need while you’re learning. If you can’t find a friend or mentor to help you out, I wrote an email to my list about where you should look. (By the way, you can sign up here to get helpful emails like that every Friday).

What do I recommend?

I know, that’s still a whole lot of stuff! My recommendation, if you like reading and already know the programming basics, is to start with Programming Ruby and Agile Web Development with Rails. While you read, build some tiny sample apps to try out the things you learn. (You’ll learn more about how to do that in the free sample chapter of Practicing Rails).

Do you have any other recommendations for resources that helped you out? Anything you can’t believe I missed? Comment and tell us all about them!

This article was inspired by a question from James on my advice page. If you’re stuck on questions about Ruby and Rails, and need some help or advice, ask me there!

You’re confident about the core ideas behind Rails. You can write working code, no problem. And you’re learning more about code quality, refactoring, writing great tests, and object-oriented design.

By this point, you’re starting to feel like you’re getting it, that you’re on the path to becoming an expert. When you look backwards, you see just how far you’ve come, and you’re pretty happy with your progress.

So why do you feel so slow? Now that you care about testing, maintainability, and design, it feels like it takes you way more time to ship anything!

Is it even possible to ship high quality code quickly?

It’s all part of the process

This feeling is incredibly common, no matter what you’re learning.

Now that you’re no longer a beginner, you’re starting to see all the different shapes that your code could have. You have more alternatives to think through whenever you put down a line of code. You have to test edge cases you never recognized before.

You’ve learned lots of helpful skills. But right now, they still take a lot of thought. You have to weigh every decision you make, so you feel comfortable that you’re making the right decision based on the things you’ve learned.

It will get faster, though. The skills you’ve learned will become more automatic. You’ll build intuition. And you’ll be able to make better decisions more quickly.

Which is nice to know, but it doesn’t help you right now. So what can you do now, to finish things faster?

Take it in stages

If you’re obsessed with writing perfect, high-quality, highly-maintainable code every time you put your fingers on the keyboard, you’ll never get anything done.

When I get stuck, I write code the same way I write articles. You’d start with a rough draft. Maybe sketch out some tests, code, or comments. Or even write some ideas out on paper. At this point, you wouldn’t worry about structure, you’re just using code to clear up the vague ideas you have in your head.

Then, I turn those ideas into a straightforward implementation. What you might call “The simplest thing that could possibly work.” It’s not perfect, and not even close. But don’t worry about it. Because once the code works, you’ll do a tidying pass. TDD edge cases, refactor obviously bad code, or make names clearer.

These “refined drafts” are usually good enough to ship. But I’ll usually do a few more passes. Not too many, though – you’ll soon start to see diminishing returns. You’ll spend more time cleaning up the code than it’s worth.

Then, if you really want to end up with the cleanest possible code, let it settle for a while. Come back to it in a few weeks or months, and do another pass at it. By that time, you’ll know more about your system, and you’ll have learned more about how to write great, highly-maintainable code. So you’ll do an even better job.

Just like writing, that process is:

  1. Sketch out a rough outline, draft, or prototype.
  2. Write a simple, unedited, straightforward implementation (often guided by TDD, or written along with tests).
  3. Refine, refactor, and clean up that implementation a little bit.
  4. Let it settle.
  5. Come back to it, and do one more pass.

It sounds like a lot more work. But when you go in stages like this, you’ll move faster, without always second-guessing yourself. And you won’t end up overthinking decisions between a few just-as-good options.

This article was inspired by a question from Topher on my advice page. If you’re stuck on questions about Ruby and Rails, and need some help or advice, ask me there!

When you use Ruby to wrap an API, you have to have a way to configure it. Maybe the wrapper needs a username and secret key, or maybe just a host.

There are a few different ways to handle this. So which one should you choose?

The easy, global way

You might want your service to act like it’s always around. No matter where you are in your app, you’d have it ready to use. Otherwise, you’ll spend three lines of configuring it for every line of using it!

You could make the configuration global, using constants or class attributes:

config/initializers/product_api.rb
1
2
3
ProductApi.root = "https://staging-host.example.com/"
ProductApi.user = "justin"
ProductApi.secret = "mysecret123"
app/controllers/products_controller.rb
1
2
3
def show
  @product = ProductApi.find(params[:id])
end

Lots of gems use this pattern. It’s pretty easy to write, and really easy to use. But it has some big problems:

  • You can only have one ProductApi.

    If you want to use the Product API as two different users, or hit different servers from a single app, you’re out of luck.

  • ProductApi has global data that’s easy to accidentally change.

    If a thread or a part of your app changed ProductApi.user, everything else using ProductApi would break. And those are painful bugs to track down.

So, class variables have some problems. What if you configured instances of your Product API class, instead?

What would it look like with #initialize?

If you used instances, you’d create and configure your API wrapper when you need it:

app/controllers/products_controller.rb
1
2
3
4
5
6
7
def show
  product_api = ProductApi.new(
    root: "https://staging-host.example.com/",
    user: "justin",
    secret: "mysecret123")
  @product = product_api.find(params[:id])
end

Now, you can pass different details to your API whenever you use it. No other methods or threads are using your instance, so you don’t have to worry about it changing without you knowing it.

This seems better. But it’s still not as easy as it should be. Because you have to configure your API every time you use it.

Most of the time you don’t care how the API is set up, you just want to use it with sane options. But when you’re working with instances, every part of your app that uses the API has to know how to configure it.

But there’s a way to get the convenience of global access, using good defaults, while still being able to change it if you need to.

And this pattern shows up all the time in an interesting place: OS X and iOS development.

How do you get good defaults and flexibility?

What if you could configure each instance of your API wrapper, but you also had a global “default” instance when you just didn’t care?

You’ll see this “defaultSomething” or “sharedWhatever” pattern all over the iOS and Mac OS SDKs:

1
2
3
[[NSURLSession sharedSession] downloadTaskWithURL:@"http://www.google.com"];

[[NSFileManager defaultManager] removeItemAtPath:...];

And you can still ask for instances of these classes if you need more than what the default gives you:

1
2
3
NSURLSession *session = [NSURLSession sessionWithConfiguration:...];

NSFileManager fileManager = [[NSFileManager alloc] init];

You could build something like that in Ruby, with a default_api class method:

app/controllers/products_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
def show
  @product = ProductApi.default_product_api.find(params[:id])
end

...

def show_special
  special_product_api = ProductApi.new(
    root: "https://special-product-host.example.com/"
    user: "justin"
    secret: "mysecret123")
  @special_product = special_product_api.find(params[:id])
end

And the implementation might look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ProductApi
  def initialize(root:, user:, secret:)
    @root, @user, @secret = root, user, secret
  end

  def self.default_api
    @default_api ||= new(
      root: ENV['PRODUCT_API_ROOT'],
      user: ENV['PRODUCT_API_USER'],
      secret: ENV['PRODUCT_API_SECRET'])
  end

  def find(product_id)
    ...
  end
end

Here, I used environment variables in default_api, but you could also use config files. And you could switch the ||= to use thread- or request-local storage instead.

But this is a decent start.


Most gems I’ve seen, like the Twitter gem, will have you configure and create each API object when you need them. This is an OK solution (though I usually see people assigning these to globals anyway).

But if you go one step further, and also use a pre-configured default object, you’ll have a much more comfortable time.