After you finish the Rails tutorials and start your own app, things get confusing. Like where does your non-CRUD, general logic go? How does grabbing followers from Twitter fit into MVC? Ask two people, and you get four answers. Or your thread devolves into a bunch of smart people insulting each other for hours, while you beat your head against the desk. Either way, you’re left with a headache.

You can’t build the app you’ve been dreaming of without some general, non-Rails logic. So where do you put your code, and still keep things simple?

The easy place to start

When I have logic that feels related to an existing ActiveRecord model, I’ll start by putting it into that model. For example, if I had a Game model and I wanted to import a bunch of games from CSV files, I’d put that method right onto the Game class:

app/models/game.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Game < ActiveRecord::Base
  def self.parse_from_csv(csv_string)
    games = []
    CSV.parse(csv_string, quote_char: "'") do |row|
      games << Game.from_csv_row(row) if (row[0] == 'G')
    end
    games
  end

  def self.from_csv_row(row)
    Game.new({
      dgs_game_id: row[1],
      opponent_name: row[2],
      created_at: row[4],
      updated_at: row[4],
    })
  end
end

You have all the information your methods need right at hand. It’s easily testable. And it’s probably where a new contributor would look for that logic first.

But if you keep adding and changing that model, it’ll get big and complicated. Different parts of the model will interact in strange ways. The more you change it, the harder it will be to change.

In that case, you’d probably want to refactor that code out to a non-ActiveRecord model.

Non-ActiveRecord models

Just because it’s in a Rails app, doesn’t mean it has to inherit from Active/Action-whatever.

You can write your own Ruby code, in plain Ruby objects, and use them in your Rails app. These objects can still be called models, because they’re modeling part of your problem. They just don’t have an ActiveRecord database storing their data.

The next time I worked on that game CSV parser, the Game class was getting a little too big. So I moved the parser logic into its own GameCSVParser class.

The whole commit is here, but this is what the non-ActiveRecord class looks like:

app/models/game_csv_parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class GameCSVParser

  def initialize(csv_string)
    @rows = CSV.parse(csv_string, quote_char: "'")
  end

  def games
    game_rows.map { |row| Game.new(game_attributes(row)) }
  end

  private

  def game_rows
    @rows.select { |row| is_game_row?(row) }
  end

  def game_attributes(row)
    {
      dgs_game_id: row[1],
      opponent_name: row[2],
      created_at: row[4],
      updated_at: row[4],
    }
  end

  def is_game_row?(row)
    row[0] == 'G'
  end
end

I’ll go right to creating a new plain Ruby object if the logic I’m adding doesn’t feel related to any specific ActiveRecord model. Or if the code seems like it should be a part of a thing that doesn’t exist yet in the app. Otherwise, they mostly pop up through refactoring.

With plain Ruby objects, you can write anything. But knowing you can write anything doesn’t help you with direction. What methods do you need? How will all your new objects interact?

A lot of Rails apps use the same categories of plain Ruby objects. These categories are patterns you can follow to write code that other developers would recognize. You might have heard of a few of them already.

Service objects, presenters, and jobs

There’s nothing special about service objects, presenters, and jobs. They’re just plain Ruby objects that act in a particular recognizable way.

For example, a Resque job is a plain Ruby class that has a perform method and a @queue:

app/workers/fetch_games_for_player.rb
1
2
3
4
5
6
7
8
class FetchGamesForPlayer
  @queue = :default

  def self.perform(player_id)
    player = Player.scoped_by_id(player_id).ready_for_fetching.first
    player && player.fetch_new_games!
  end
end

perform is called when the job is run.

A presenter is a plain Ruby object with code that only makes sense inside a view:

app/presenters/user_presenter.rb
1
2
3
4
5
class UserPresenter
  def show_related_users?
    @user.related.count > 3
  end
end

It might also include Rails’ view helpers, or take a few different objects and treat them as one unified object for the view’s convenience.

A service object is a plain Ruby object that represents a process you want to perform. For example, writing a comment on a post could:

  1. Leave the comment.
  2. Send a notification mail to the author of the post.

A service object could do both, and keep that logic out of your controller.

There’s a great take on service objects here. It’s full of examples.

For simple processes, I don’t bother with service objects. But if the controller starts getting too heavy, they’re a good place to put that extra logic.

You can use these patterns to organize your own business logic. They’re just plain Ruby objects, but they’re Ruby objects that share a certain flavor, that have a name, and that you can talk to other developers about.

Where do you start?

There are a lot of different places your non-Rails business logic could go. It might be hard to choose. So here’s what I do:

  1. If the logic is mostly related to an existing class, even if it’s an ActiveRecord model, I put it in that class.
  2. If it doesn’t fit an existing class, I create a new plain Ruby class to hold the logic.
  3. If it feels like the logic should be part of something that doesn’t exist yet, I create a new plain Ruby class for it.
  4. If I come back to the code later, and the model is getting too complicated, or the code doesn’t make sense in that model anymore, I’ll refactor it into its own plain Ruby class.
  5. If the code only makes sense in a view, I’ll add it to a helper or create a presenter.
  6. If the code doesn’t need to run during an HTTP request, or has to run in the background, it goes in a job.
  7. If I’m juggling several different models or stages of a process, and it’s making the controller too hard to understand, I’ll put it into a service object.

How about you? Where does your code go? And do you have any patterns besides these that you’ve found helpful? Leave a comment and let me know.

And if you don’t have a process yet, try mine. See how it fits you. There’s no perfect way to write code, but when you get stuck, a process like this will help you get started.

(This post is based off of one I sent to my list a few months ago. To read more like it every week, join up here!)

In Using a Little Bit of Convenience to Save Your Programming Flow, I talked about how the simplest abstractions can make your codebase more fun to work with.

But what about when you have a bad abstraction?

You dig out the API reference every time to understand what that method that clearly should have been named leaderboard is actually called. You try to refactor around it, but one part of the code hands you structured data and the other part gives you raw lines of text. And every time you touch the code, something breaks, and you blow the rest of your day trying to debug it. Because you tweaked position, but didn’t update score at the same time.

So how do you build good abstractions, while staying far away from the bad?

Using good metaphors to write clearer code

Good abstractions come from good metaphors.

A metaphor describes something in your system by relating it to a concept that’s already in your head. For example:

  • Many command lines use the metaphor of a pipe.

    You put data in one end of the pipe, and it comes out the other end. Easy to imagine and easy to use.

  • In concurrent programming, a lock is a good metaphor.

    Without knowing anything about how locks work internally, you know that when a resource is locked up, you can’t use it. You have to wait until it’s unlocked.

  • In Object-Oriented Programming, message passing triggers a specific mental image: An object passes another object a message. The second object can do something with the message or pass it to someone else.

    You don’t need to know anything about the implementation in order to get the idea (and it makes things like the proxy pattern much easier to understand).

A good metaphor is critical. If you see an abstraction based on a good metaphor, you’ll rarely have to read the documentation or go source diving to understand the code. The better the metaphors you come up with, the easier it will be to describe your system to someone else, and the easier it’ll be to work on your system later on.

How do you come up with good metaphors?

A good metaphor is specific, self-contained, and creates a vivid mental image of the thing it describes. It doesn’t leave room for misunderstanding, and it matches the code’s behavior as closely as possible. If someone makes assumptions about the code based on their understanding of the metaphor, those assumptions should be valid.

Coming up with good metaphors is hard. You’ll often go through a few leaky metaphors before you can find the right one, and that’s OK! It will get easier with practice. But here’s a process that’s helped me:

Think about what a bit of code does, without thinking about how it does it. What image comes up in your mind? How does other code use it? If you had to describe it in a word or two, which words would you use? Write that down.

Then, think about that image. Does it fit how that code works? Are there edge cases that leak through the metaphor? Is there anything besides the metaphor a new contributor would have to understand before they could use the code? When you think about your metaphor, do you get a clear picture in your mind, or is it fuzzy?

These are indicators that your metaphor doesn’t match your code closely enough. But the closer you are to a good metaphor, the less of a leap you’ll have to make to get there.

Finally, use it in a sentence. “This code is a (something), because…” Could you explain your metaphor to someone without a technical background, and have them understand what it does? The less background someone needs to understand the metaphor, the more helpful your metaphor will be.

If you’re close, but not quite there, take a look in a thesaurus. Subtle differences between similar words can mean the difference between an OK metaphor and a perfect one.

Metaphors and OOP

Object-Oriented Programming is fundamentally based on metaphor. That’s where it gets its power! Well-designed classes don’t just hide their implementations from other classes, they hide their implementations from you.

With a great metaphor, you should be able to tell just from the class name how to use your objects. If your classes are named well, and they cause the right images to appear in your mind, you shouldn’t have to dive into their implementation to understand them.

So now, I’d like you to think about the classes in the last code you worked with. Can you think of any that have particularly clear metaphors? Which classes do you feel like you work with, rather than work against? How often do you go digging into them to figure out how to use them?

I’d love to hear what you find out. Leave a comment, and let me know.

To become a great software developer quickly, you have to consciously think about the code you’re writing and the processes you’re following. And I can help you.

Download my free 33-page sample of Practicing Rails, and learn how to try ideas like this on a small scale, without getting overwhelmed.

Generally, global variables are bad. But sometimes, a global in the right place can make your code a lot simpler.

In Rails, you might set data once during a request, but use it in every layer of your app. Which user is making the request? What permissions do they have? Which database connection should be used?

This information should be available throughout your code, so passing it everywhere would just be a bunch of noise. But using a Ruby global variable, or setting a class variable, will cause its own problems. Multiple threads could overwrite it, and you’d end up with a huge mess, and maybe unrecoverably bad data.

You need something that’s global, but for just your request.

The plain Ruby way

Usually, you’ll see this handled with Thread.current[]. It looks like this:

1
Thread.current[:current_user] = user

This is simple enough. It’s a decent solution. But it has two big drawbacks:

  1. Someone could accidentally overwrite your data.

    What if two people picked the same key? You’d stomp on each other’s data. And if you’re storing something like users, that would be seriously bad. In your own apps, this probably won’t be a problem. But if you’re writing gems, or your Rails app is big and messy, it’s something you need to think about.

  2. It’s not well-structured.

    Thread.current[] is just a big bag of data. You can’t easily document it. If you want to know what you can take out of it, you have to search for what you put into it.

    Of course, if you’re putting away enough global data that this is a problem, you have more to worry about than Thread.current[]’s lack of structure. But it’s still a point to keep in mind.

So, is there a better solution than Thread.current[]? As you might imagine, Rails itself manages a lot of request-local data. And the box of goodies that is ActiveSupport has a different pattern to follow.

The Rails way

If you dig through ActiveSupport, you might run into ActiveSupport::PerThreadRegistry. You can probably tell from the name that this is exactly what we’re looking for.

With ActiveSupport::PerThreadRegistry, the earlier example would look like this:

1
2
3
4
5
6
7
8
class RequestRegistry
  extend ActiveSupport::PerThreadRegistry

  attr_accessor :current_user, :current_permissions
end

RequestRegistry.current_user = user
RequestRegistry.current_user # => user

It’s a tiny bit more work. But with ActiveSupport::PerThreadRegistry:

  • You have a place to put documentation. Anyone looking at your class will know exactly what global data you’re expecting, and what global data they can use.

  • You get an API that looks good. In fact, it looks like you’re just setting class variables. That’s probably what you’d be doing if you didn’t have to worry about threads.

  • Any data you set on the class will be namespaced. You don’t have to worry about RequestRegistry.current_user colliding with PhoneNumberApiRegistry.current_user, they’re treated totally separately.

Rails uses ActiveSupport::PerThreadRegistry internally, for things like ActiveRecord connection handling, storing EXPLAIN queries, and ActiveSupport::Notifications. So if you’re looking for more good examples of the power of PerThreadRegistry, Rails itself is a great place to start.

When threads and requests don’t match

For some Rails servers, a single thread handles multiple requests. This means anything you put into a PerThreadRegistry will stick around for the next request. This is probably not what you want.

You could do what Rails does, and clean up the things you put into the PerThreadRegistry after you’re done with them. Depending on what you put in there, you might be doing this anyway.

In the comments, MattB points to an easier solution: request_store. It acts like Thread.current[], but clears itself after each request.

This leaves the door wide open for someone to create a PerRequestRegistry, which combines the safety of request_store with the API of PerThreadRegistry. If someone’s done this already, I’d love to hear about it!

Try it out

Global data can be bad. Too many globals can quickly lead to unmaintainable code.

But if it makes sense to keep data in a central place for an entire request, go beyond Thread.current[]. Give ActiveSupport::PerThreadRegistry or request_store a shot. If nothing else, it’ll make dealing with global data a little less risky.

I love each, but I have a problem with it. What happens when you have an empty collection?

If you call [].each, nothing will happen and [] will be returned. Sometimes, that’s what you want. But more often, especially when you’re building UI, you’ll want to handle empty lists in a special way. For example, I usually want to show a different message when I don’t have any data.

But since [].each returns [], not nil, you’re stuck writing something like this:

app/views/users/index.html.erb
1
2
3
4
5
6
7
<% if @users.empty? -%>
  <p>You don't have any users. <%= link_to "Add one!", new_user_path %></p>
<% else -%>
  <% @users.each do |user| -%>
      <p><%= user.name %></p>
  <% end -%>
<% end -%>

That works, but it feels awkward. I’d rather say, “Do this thing to each item in this collection, unless there’s nothing in it, in which case do this other thing entirely.” I want something like each, with an “or else.”

Rendering Rails Collections

Inside your views, Rails can help. It’s great at rendering collections of things:

app/views/users/index.html.erb
1
<%= render @users %>
app/views/users/_user.html.erb
1
<p><%= user.name %></p>

When render is passed @users, it renders _user.html.erb once for each user inside @users. You can skip the each entirely.

As a bonus, if @users is empty, render returns nil, just like we want! So you can write this, and get the same output as the original version:

app/views/users/index.html.erb
1
<%= render(@users) || render('empty') %>
app/views/users/_user.html.erb
1
<p><%= user.name %></p>
app/views/users/_empty.html.erb
1
<p>You don't have any users. <%= link_to "Add one!", new_user_path %></p>

It’s a lot more direct, once you understand Rails’ conventions.

What about outside of a view?

If you follow Rails, render with a collection is a fast, powerful way to render collections of objects.

But sometimes you won’t want to deal with an extra partial to render each item. Or render won’t support your design. Or you won’t even be inside a view.

The best solution I’ve found so far is presence.

list.presence is the same as:

1
2
3
4
5
if list.present?
  list
else
  nil
end

That is, you’ll get the list back if it has anything in it, and nil if it’s empty.

With presence, you could write:

1
2
3
@users.each do |user|
  puts user.name
end.presence || puts("You don't have any users.")

This prints each name if there are users in @users, or You don't have any users otherwise.

Still, I could do without the presence. It feels like a hack, because it is one. If it was supported, something like this might be better:

1
2
3
@users.each do |user|
  puts user.name
end || puts("You don't have any users.")

or the Smalltalk-ish:

1
2
3
@users.each(if_empty: lambda { puts "You don't have any users." }) do |user|
  puts user.name
end

or even (gasp!):

1
2
3
4
5
for user in @users
  puts user.name
else
  puts "You don't have any users."
end

For now, though, I usually just go with presence or the basic if blank?; else each pattern.

Which do you think is better? How do you handle empty lists? Have you found a better way? If so, tell me about it!

There are a lot of ways to launch a Ruby or Rails console: irb, bundle exec irb, bundle console, and rails console are some of the most common. They seem similar, but they each work a little bit differently.

If you don’t know what those differences are, you’ll have some problems. Maybe you won’t be able to get your ActiveRecord models connected to the database. Or you’ll require a file and get the wrong version. Or a library you thought would be avaliable, wasn’t.

How do you make sure you’re using the right console at the right time?

Bundler vs non-Bundler

irb is just a plain Ruby console. It doesn’t care about your Gemfile. It doesn’t load anything but the core Ruby libraries. Anything else you want, you have to require.

If you install a gem using gem install, you can require it inside irb. If you used bundle install, you might be able to require it, depending on where Bundler put it. (Bundler will sometimes put gems outside of Ruby’s gem path, if you run something like bundle install --path or bundle install --deployment).

Since irb ignores your Gemfile, the versions inside your Gemfile.lock don’t matter. irb will load the newest version of a gem it can find:

1
2
3
4
5
6
7
8
9
10
11
12
13
~/Source/testapps/consoles[master *] jweiss$ gem list rails

*** LOCAL GEMS ***
rails (4.2.0.beta2, 4.2.0.beta1, 4.1.5, 4.1.1)

~/Source/testapps/consoles jweiss$ cat Gemfile | grep rails
gem 'rails', '4.1.5'

~/Source/testapps/consoles jweiss$ irb
irb(main):001:0> require 'rails'
=> true
irb(main):002:0> Rails.version
=> "4.2.0.beta2"

This can cause really weird problems with your code, if you’re not expecting it.

irb is great if you’re messing with core Ruby files. It’s fast, and doesn’t need any setup.

But if you want to use your Gemfile when you run a console, run bundle exec irb instead. The bundle exec allows irb to load the gems that Bundler knows about, and only the gems Bundler knows about:

1
2
3
4
5
~/Source/testapps/consoles jweiss$ bundle exec irb
irb(main):001:0> require 'rails'
=> true
irb(main):002:0> Rails.version
=> "4.1.5"

We got exactly the Rails version we were looking for.

bundler/setup vs Bundler.require

When would you run bundle console instead of bundle exec irb?

bundle exec irb sets things up so you can only require the gems in your Gemfile.lock.

bundle console goes one step further. When you run bundle console, you don’t even need to require the gems in your Gemfile. They’re already required for you:

1
2
3
4
5
6
7
8
9
~/Source/testapps/consoles jweiss$ bundle exec irb
irb(main):001:0> Rails.version
NameError: uninitialized constant Rails
  from (irb):1
  from /usr/local/bin/irb:11:in `<main>'

~/Source/testapps/consoles jweiss$ bundle console
irb(main):001:0> Rails.version
=> "4.1.5"

You could also get this behavior if you called Bundler.require inside your bundle exec irb console. Any gem in your Gemfile that isn’t marked require: false will be automatically required, and you’ll be able to use it without any extra work. When you’re working on projects with a Gemfile, that’s incredibly convenient.

Accessing Rails

There’s still one difference to think about: bundle console and rails console.

1
2
3
4
5
6
7
8
~/Source/testapps/consoles jweiss$ bundle console
irb(main):001:0> Rails.application
=> nil

~/Source/testapps/consoles jweiss$ rails console
Loading development environment (Rails 4.1.5)
irb(main):001:0> Rails.application
=> #<Consoles::Application:0x007f8db4d5ab30 @_all_autoload_paths=["/Users/jweiss...

bundle console just requires a bunch of gems. rails console requires those gems, but it will also load your entire Rails environment, set up autoloading, initialize your application, and give you a full Rails environment to play around in.

You can get something like the Rails console from bundle console if you require config/environment.rb:

1
2
3
4
5
6
7
~/Source/testapps/consoles jweiss$ bundle console
irb(main):001:0> Rails.application
=> nil
irb(main):002:0> require_relative 'config/environment.rb'
=> true
irb(main):003:0> Rails.application
=> #<Consoles::Application:0x007fd264f0b7c8 @_all_autoload_paths=["/Users/jweiss...

Each one, just a little more complicated

So, to recap:

  • irb is the basic Ruby console. It ignores your Gemfile, and only core Ruby classes are accessible without require-ing them. It can’t easily load gems that Bundler installs outside of RubyGems’ load path.

  • bundle exec irb is like irb, if you also required bundler/setup. You can only easily require gems that are in your Gemfile.lock, but you can load those gems no matter where Bundler put them.

  • bundle console is like bundle exec irb, if you also called Bundler.require. All of the gems in your Gemfile, except the ones marked require: false, can be used without requiring them. It’s really convenient when you’re writing your own gems, or working on non-Rails code.

  • rails console is like running bundle console inside a Rails app, if you also required config/environment.rb. You can play with your entire Rails app, autoloads and database connections work, and everything’s hooked up the way you’d expect. If you’re working in a Rails app, this is the most helpful kind of console.

There aren’t too many differences between these consoles. And while most of those differences won’t be too big (Oh, this file isn’t required? Better require it!), others will be totally infuriating if you don’t know what’s going on. (WHY IS THIS LOADING THE WRONG VERSION OF RAKE AGAIN!?)

But if you know the idea behind each of these consoles, you’ll be able to use the right kind of console at the right time. And all the libraries you need will be close by when you need them.

Have you ever wanted to pass a method to a function that only takes a block? Or figure out which of your object’s superclasses broke the method you’re trying to call?

Those things are easy to do with the method method. Use it well, and you can learn about your dependencies, save yourself hours of debugging, and get your code to the places it needs to be.

Methods as easy as lambdas

Lots of Ruby methods take blocks or lambdas. But you can’t directly pass a method to another method, the way you would with a lambda. You have to use method first:

1
2
3
4
irb(main):001:0> sin_method = Math.method(:sin)
=> #<Method: Math.sin>
irb(main):002:0> (1..10).map(&sin_method)
=> [0.8414709848078965, 0.9092974268256817, 0.1411200080598672, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891, 0.9893582466233818, 0.4121184852417566, -0.5440211108893699]

So, what’s happening here?

The first line turns the method Math.sin into a Method object. Just like lambdas, Method objects respond to call. Method objects respond to to_proc (Thanks, Benoit). So they can be used in the same places you’d use a lambda:

1
2
3
4
irb(main):004:0> sin_method = -> (x) { Math.sin(x) }
=> #<Proc:0x007fe9f90a9bd8@(irb):4 (lambda)>
irb(main):005:0> (1..10).map(&sin_method)
=> [0.8414709848078965, 0.9092974268256817, 0.1411200080598672, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891, 0.9893582466233818, 0.4121184852417566, -0.5440211108893699]

Take a look at the first line again. This code, using a lambda, works the same way as the earlier code, using method.

Depending on how you’ve written your code, getting ahold of a Method object can be a lot easier than wrapping it in a lambda. So when you need a lambda and all you have is a method, remember the method method.

Where did that method come from?

You just called a method on your object, and it does something you didn’t expect. Maybe someone overrode it or monkey-patched it. How do you figure this out?

You could dig through the source code for a few hours. But Method has two methods that can speed things up.

To figure out which class defined the method you’re calling, use owner:

1
2
irb(main):003:0> Task.new.method(:valid?).owner
=> ActiveRecord::Validations

When you want to go a little deeper and figure out exactly where the method was defined, use source_location:

1
2
irb(main):004:0> Task.new.method(:valid?).source_location
=> ["/usr/local/lib/ruby/gems/2.1.0/gems/activerecord-4.2.0.beta2/lib/active_record/validations.rb", 55]

source_location returns an array. The first element is the path to the file where the method was defined, and the second element is the line number. With those, you know exactly where to look next.

Reading the source (without having to dig)

Once you can figure out where a method was defined, you might want to see how it’s defined.

Method can’t do that by itself. But if you install the method_source gem, you can see the source code for many methods right from your console:

1
2
3
4
5
6
7
irb(main):002:0> puts Task.new.method(:valid?).source
    def valid?(context = nil)
      context ||= (new_record? ? :create : :update)
      output = super(context)
      errors.empty? && output
    end
=> nil

You can even see the comments:

1
2
3
4
5
6
7
8
9
10
11
12
irb(main):003:0> puts Task.new.method(:valid?).comment
# Runs all the validations within the specified context. Returns +true+ if
# no errors are found, +false+ otherwise.
#
# Aliased as validate.
#
# If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
# <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not.
#
# Validations with no <tt>:on</tt> option will run no matter the context. Validations with
# some <tt>:on</tt> option will only run in the specified context.
=> nil

Pretty awesome, right? Your documentation is right in the console!

Introspection is awesome

Some of my favorite Ruby classes are those that let you inspect your code from within your code. Classes like Class, Module, and Method. With these, you can learn a ton about your code as it runs, and modify it on the fly. Learn these classes well, study their API, and you’ll be able to do amazing things with Ruby.

When you generate a scaffold in Rails, you’ll see the usual respond_to blocks:

app/controllers/tasks_controller.rb
1
2
3
4
5
6
7
  def destroy
    @task.destroy
    respond_to do |format|
      format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

But some of your actions, like index, don’t have them!

app/controllers/tasks_controller.rb
1
2
3
4
5
  # GET /tasks
  # GET /tasks.json
  def index
    @tasks = Task.all
  end

This is bad. Why? If you hit /tasks.txt, and txt isn’t supported by your app, you’ll get the wrong error:

1
ActionView::MissingTemplate (Missing template tasks/index, application/index with {:locale=>[:en], :formats=>[:text], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}

This isn’t quite right. You should be telling the client that they’re requesting a format you don’t support, not that you can’t find the right file.

If this was a UnknownFormat error, you could return a better response code. Instead, these errors will get mixed together with other, unrelated errors, and it’ll be really hard to handle them.

You could add a respond_to block to your index action:

app/controllers/tasks_controller.rb
1
2
3
4
5
6
7
8
9
  # GET /tasks
  # GET /tasks.json
  def index
    @tasks = Task.all
    respond_to do |format|
      format.html
      format.json
    end
  end

Then, you’d get the exception and error code you’d expect:

1
2
3
4
5
6
Started GET "/tasks.txt" for 127.0.0.1 at 2014-11-03 22:05:12 -0800
Processing by TasksController#index as TEXT
Completed 406 Not Acceptable in 21ms

ActionController::UnknownFormat (ActionController::UnknownFormat):
  app/controllers/tasks_controller.rb:8:in `index'

Much better. But littering all your controllers with respond_to is crazy. It feels un-Rails-ish. It violates DRY. And it distracts you from the work your controller is actually doing.

You still want to handle bad formats correctly. So what do you do?

A respond_to shortcut

If you’re not doing anything special to render your objects, you can take a shortcut. If you write:

app/controllers/tasks_controller.rb
1
2
3
4
def index
  @tasks = Task.all
  respond_to :html, :json
end

it works the same way as writing the full respond_to block in index. It’s a short way to tell Rails about all the formats your action knows about. And if different actions support different formats, this is a good way to handle those differences without much code.

Handle formats at the controller level

Usually, though, each action in your controller will work with the same formats. If index responds to json, so will new, and create, and everything else. So it’d be nice if you could have a respond_to that would affect the entire controller:

app/controllers/tasks_controller.rb
1
2
3
4
5
6
7
8
9
class TasksController < ApplicationController
  before_action :set_task, only: [:show, :edit, :update, :destroy]
  respond_to :html, :json

  # GET /tasks
  # GET /tasks.json
  def index
    @tasks = Task.all
  end

And this actually works:

app/controllers/tasks_controller.rb
1
2
3
4
5
6
Started GET "/tasks.txt" for 127.0.0.1 at 2014-11-03 22:17:37 -0800
Processing by TasksController#index as TEXT
Completed 406 Not Acceptable in 7ms

ActionController::UnknownFormat (ActionController::UnknownFormat):
  app/controllers/tasks_controller.rb:8:in `index'

Exactly the kind of error we were hoping to get! And you didn’t have to mess with each action to do it.

Sometimes you’ll want to do different things depending on the state of a model. For instance, for create, you’d either redirect or re-render the form, depending on whether or not the model is valid.

Rails can handle this. But you still have to tell it which object you want it to check, with respond_with. So instead of:

app/controllers/tasks_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
  def create
    @task = Task.new(task_params)

    respond_to do |format|
      if @task.save
        format.html { redirect_to @task, notice: 'Task was successfully created.' }
        format.json { render :show, status: :created, location: @task }
      else
        format.html { render :new }
        format.json { render json: @task.errors, status: :unprocessable_entity }
      end
    end
  end

you can write:

app/controllers/tasks_controller.rb
1
2
3
4
5
  def create
    @task = Task.new(task_params)
    flash[:notice] = "Task was successfully created." if @task.save
    respond_with(@task)
  end

This way, you separate your code from the formats you respond to. You can tell Rails once which formats you want to handle. You don’t have to repeat them in every action.

The responders gem

In Rails 4.2, there’s a catch: respond_with is no longer included. But you can get it back if you install the responders gem. And the responders gem brings some other nice features with it.

You can set flash messages in respond_with by including responders :flash at the top of your controller:

app/controllers/tasks_controller.rb
1
2
class TasksController < ApplicationController
  responders :flash

Conveniently, you can set defaults for these flash messages in your locale files.

Also, if you have the responders gem in your Gemfile and you generate a Rails scaffold, the generator will create controllers using respond_with instead of respond_to:

app/controllers/tasks_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class TasksController < ApplicationController
  before_action :set_task, only: [:show, :edit, :update, :destroy]
  respond_to :html, :json

  def index
    @tasks = Task.all
    respond_with(@tasks)
  end

  def show
    respond_with(@task)
  end

  # ...

This is a lot cleaner than the scaffolds Rails comes with.

respond_with or respond_to?

If you want to return different information for different formats, you have a few options. The controller-level respond_to combined with respond_with is a great way to get short controllers. But it tends to help the most when all of your controller actions respond to the same format, and act in the way Rails expects them to.

Sometimes, though, you want to be able to have a few actions that act differently. The one-liner respond_to is great for handling that situation.

If you need more control, use the full respond_to with a block, and you can handle each format however you want.

With any of these, requests for formats you don’t support will get the right error. And both your app and its clients will be a lot less confused.

You’re working with a brand new library or feature, and you just can’t understand the documentation. Maybe it’s hard to get set up, so you have to bounce between RDocs until you learn how everything fits together. Maybe the documentation doesn’t even exist. Or maybe you just learn best by seeing lots of examples.

You need some help. But where do you learn how to use a feature, if not its documentation?

One of my favorite GitHub features

When you want to go beyond the documentation and see real-world uses of a library or feature, use GitHub’s code search.

For example, say I just read the Rails guide on Conditional GET Support. I feel like I understand it, but I want to see some more examples before I use it for real.

I could hop onto GitHub search, and look for "if stale?". Then, in the sidebar, pick code and Ruby:

And now I have tons of great examples of how stale? could be used.

Not all of the examples are interesting. But in one listing, I notice the author using Post.maximum:

app/controllers/archives_controller.rb
1
2
3
4
5
6
7
class ArchivesController < ApplicationController
  def index
    if stale?(last_modified: (Post.maximum(:updated_at) || EPOCH).utc, public: true)
      @months = Post.find_all_grouped_by_month
    end
  end
end

That seems like a great way to use stale?. And if I hadn’t seen this example, I might not have thought to try it.

How should you use what you find?

When you search open-source code, you get hundreds of examples for nearly any feature. You’ll notice where the documentation makes sense, and where it’s over-simplified. And you’ll see objects working together in real code. That will teach you more about how classes are connected than any RDoc can.

Still, use the examples to learn new things, not to cargo cult into your own project. Using code without understanding it is the fastest way to a poorly designed system.

In my example, maximum might not be the right thing to do in my project. I shouldn’t copy the line without learning more about it. Without understanding when it makes sense to use. But examples can teach you things you didn’t know before. And they’re a great way to decide what to learn about next.

Like any search, it’ll take some practice to get good results. But I’ve learned a lot from the code I’ve found, and I know you will too.

When I was first learning the board game Go, I bought and read a few introductory books. They taught me the rules, and some basic strategy. I knew that there was a fun game there. But I just wasn’t seeing it.

When it came time to play my own games, I was confused and stressed out. There were 361 possible moves I could make, but which of those was the best one? Not even that, which of those were even acceptable? Using the information I got from the first books, I could maybe narrow decent moves down to about a hundred, but I still had trouble knowing where to start, and what to do. And it just wasn’t fun to me.

I felt like I couldn’t even play the game unless I studied everything first.

So, on a friend’s recommendation, I picked up another book. The book was called “The Second Book of Go.” It had short chapters, each on a specific topic that beginners tend to struggle with. And it gave me some processes I could follow, so I could know that I wasn’t making insane moves.

It taught me the reason behind crazy-looking strategies, and it taught me tricks to make better decisions and evaluate my own moves. And it showed me that even wrong moves had value.

When I started playing again, I began to have fun.

As long as I’ve written here, I’ve heard from people learning Rails that were in the same boat as I was learning Go. They heard it was supposed to be fun, but it was actually just frustrating. They didn’t know where to start. The things they learned didn’t stick with them. They couldn’t spend time learning consistently enough to grow as a Rails developer. Most of all, they were overwhelmed, because the space of possibilities in front of them seemed too big.

If this sounds familiar, I wrote a book for you. It’s meant to bring the joy of Ruby and Rails to those who were about to give up. To show that with a little structure, a little practice, and a little curiosity, you can write your own Rails applications, and have fun doing it.

It’s available for pre-sale, starting today. It’s 25% off until it’s finished. And when you buy it, you’ll get today’s draft immediately, and updates to it from here on out.

I hope you enjoy it.

(This is a short excerpt from Practicing Rails. Sign up here to get the first chapter free!)

So, you’re working on a new app, and Rails just generated a test for you:

test/models/bug_test.rb
1
2
3
4
5
6
7
require 'test_helper'

class BugTest < ActiveSupport::TestCase
  # test "the truth" do
  #   assert true
  # end
end

You uncomment it, come up with a name, and you’re ready to write your test, right? But then what? What do you write first? What should your test code look like?

If you follow a simple pattern, you’ll turn those stubbed out lines of code into clear, well-structured test cases.

The three-phase test pattern

Your test cases should work in three phases:

  1. First, you set some stuff up (“Arrange”)
  2. Then, you do something (“Act”)
  3. Then, you make sure that what you expected to happen, actually happened. (“Assert”)

For instance, imagine you were testing a method on an array in Ruby. Following this pattern, your test could look like:

1
2
3
4
5
6
7
8
9
10
test "Array#sort will sort an array of numbers" do
  # arrange
  unsorted_array = [7, 4, 2, 3]

  # act
  sorted_array = unsorted_array.sort

  # assert
  assert_equal [2, 3, 4, 7], sorted_array
end

Simple enough. But every part of the test has a place to go, and each stage of the test almost tells you how to write it.

Sometimes, you won’t need an Arrange phase, or the Act and Assert phases will be combined. But it still helps to think about all three phases as you write your tests.

The Assert phase gotcha

There’s a trick to the Assert phase: you shouldn’t use the same logic that the Act phase used in the Assert phase. You should always take two paths to the same answer. Otherwise, you won’t notice bugs in the code you’re calling, because it’s just getting called again in the Assert phase.

For example, if you’re doing some math:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
test "average returns the average of a set of numbers" do
  # arrange
  numbers = [1, 2, 3, 4]

  # act
  average = numbers.average

  # assert

  # this is bad
  assert_equal [1, 2, 3, 4].average, average

  # this is better
  assert_equal 2.5, average
end

Calling [1, 2, 3, 4].average again in the Assert phase is bad, because average could return almost anything and that assertion would still pass.

Here, that’s pretty clear. But even when things get more complicated, make sure you’re not just running the same code twice. Otherwise you’re only verifying that your method was called, not that it worked the way you expect it to.

Usually, the easiest way to take a second path to the answer is to find the answer by hand and hardcode it. It can be brittle, but it’s better than your tests breaking without you realizing it.

Why three phases?

If you split your tests into those three phases, you have simpler questions to answer. Instead of “How should I write this test?”, you can focus on each phase: “How should I set this test up?”, “What am I testing?”, “What should the answer look like?”

These questions still might not have easy answers, but the answers will be a lot easier than thinking about the entire test at once. And if you’re lucky, you can even share phases between related tests, making your next test much less painful to write.