Browse through the showcased feeds, or enter a feed URL below.
A feed by Justin Weiss
Permalink - Posted on 2017-08-22 04:40
Maybe fixing a bug just spawned a dozen new ones. Or your code breaks in such a weird way that you wonder if you really understand it at all. You think it’s time for a deep dive.
But knowing you need to dive deeply into a topic? That’s only step 1. How do you actually learn a topic down to its fundamentals? How do you learn enough that it comes naturally to you?
There are a lot of places you could start your learning. But when I need to learn a lot about a topic quickly, books are my favorite place to start. For example, if you’re doing a deep dive into git, a book called Pro Git is probably exactly what you’re looking for.
Books are great for deep dives because they’re comprehensive: Most medium-sized topics are pretty well covered by a 200–400 page book. At the end, you might not be an expert, but you’ll have a pretty good understanding and solid fundamentals to grow from. That’ll help if you decide to move on to reading source code or specs.
But maybe you don’t want to buy a book. Or a book on your topic doesn’t even exist. When that happens, where else can you look?
Official documentation is a good alternative. If you’re doing a deep dive into a single part of a framework like Rails, or a web technology like OAuth, official docs are an especially good match.
For projects and frameworks, something named “The X Guide(s)” is your best bet for starting. For example, I often recommend the Rails Guides for new Rails developers, and the Elixir Guides are a great place to learn how to write Elixir code.
But while guides are more comprehensive than, say, a blog post, they aren’t totally comprehensive. Instead, you can use the guide as a jumping-off point to the reference documentation, like RDoc.
Reference material is hard to understand if you don’t have a way to put all those methods and classes into context. It’s just a mess of details with no real structure. So I find that references work best when you pair them with guides or books.
I say “almost nothing”, because there is one thing more comprehensive than reading official docs: Reading the source code. But reading source code isn’t like reading a book: it takes experience, practice, and guidance. So even though it will give you the most detail, it’s not where you should go first.
After deep diving through all this written material, you’ll have some open questions. So, ask them! The author of a library will usually have a better mental model of it than anyone else, and can walk through their thought process to help you out. Many authors of open source projects and frameworks make themselves available through Slack or IRC. You can usually find details on project pages.
If you don’t have access to those people? You can still ask. Ask your colleagues, or more senior devs. I’m surprised at how often asking a single unanswered question to a friend will make everything else click into place.
Once you know you have to do a deep dive, there are a few places you can start. Here’s the order I’ll usually follow:
And I’ll fill the gaps by asking questions. It’s not the fastest process, but it’s the best combination of breadth and depth that I’ve found so far.
Do you regularly do deep dives? If so, I’d love to know what resources you’ve found most helpful. Leave a comment and let me know!
Permalink - Posted on 2017-08-15 04:40
Have you ever found a Rails topic that didn’t make any sense to you?
Like, you thought you knew it, so you wrote some code, and something completely different happened?
Or you know you don’t understand, but you kind of know enough to get by, except you spend so much time fighting edge cases that you could have been an expert in it by the time you were done?
Well, what if it didn’t have to be that way? Wouldn’t it better to just know how things worked? To have a solid mental model of the problem in front of you? So you could just make the right decisions, and write the right code?
When I was first learning web development, sessions were That Thing: I thought I kind of knew them, but I didn’t. And my misunderstanding of sessions caused so many bugs that I was criticized, a lot, for the problems I created.
Soon, I realized I had to take time to actually understand how sessions worked. To demystify them, to make them not scary or weird. And eventually, to be able to guess how they’d behave – and to be right.
“Sessions” isn’t the only topic I’ve done a deep dive into. Data modeling, caching, metaprogramming, they’re all confusing things that are really easy to get to kind of work. But you’ll run into eternally hard debugging problems if you don’t understand them.
In Practicing Rails, I wrote about T-Shaped learning: When you have good baseline knowledge, but push much further into specific topics as you need to. Those pushes are deep dives, and they’ll help you solve huge problems over the course of your programming career.
So how do you know when it’s time for a deep dive?
First, to do a deep dive, you have to know what you’re diving into.
Deep dives are most helpful when you’re dealing with a single topic. A specific thing you can describe in a word or a short phrase. SQL query performance. Sessions. HTTP Caching. Too specific, and you miss the interactions that make a topic so complicated. Too general, and you’re doing a deep dive into “Programming.” Which, I guess you kind of are, but that’s a deep dive you’ll spend your whole career on.
Next, you should do a deep dive in one of two situations:
You think you know what you’re doing, but something totally unexpected happens. You know in your heart that pushing that green button turns the hallway light on, but you push it, and the room collapses instead.
You know you don’t really understand something, and that’s been OK… But now, you’re fixing a bug, and everything you try causes more problems than you’re solving, creating new bugs as quickly as you’re fixing old ones.
These situations have something in common: You’ve just started to notice that you’re going in the wrong direction. And even though you hope you’ll turn things around, you’re starting to realize you’ll waste a lot of time struggling.
They’re both ways to help you sense, early on, that the way you’re doing things isn’t working.
So, the next time you run around in circles, battling edge cases to fix a bug, or the next time you’re floored by code you wrote doing something completely different than what you expected, remember the feeling you have. Get sensitive to it. That’s the feeling that’ll tell you it’s time to pause. To collect yourself. And to learn, deeply, that thing you now know you don’t understand.
Permalink - Posted on 2017-05-09 04:40
In my most recent article, I mentioned a great new feature in Rails 5.1,
delegate_missing_to, any method that you can’t find on one object is called on another object, instead:
But, like Gavin mentioned in the comments, this seems like an odd way to avoid inheritance. Why not just use a subclass? You’d get the same effect, and you don’t have to add a whole new feature. It seems like a weird thing to add.
There must be a reason
delegate_missing_to was added, though. And for Rails features, pull requests are a great way to find those reasons. In this pull request, DHH mentioned why he suggested the feature:
Here’s a common pattern if you want to build a decorator:
That seems like a pretty good place to start digging.
When you build a decorator, you’re changing the way an object acts, without creating a new subclass. For example, in the code from earlier:
You’d say that “Player decorates user,” because a Player almost acts like a User, but has an extra method,
points. And it does this without inheritance.
Why would you need something like this? That’s a tough question to answer, because like many design patterns, it’s not always clear where you’d want to use it instead of something else.
Decorators could just be a more complicated way to do inheritance. I mean, which of these two lines of code is better?
Clearly the second one, right? Here, creating Player as a decorator instead of a subclass is just a waste of code.
But sometimes, you want to add functionality to an object later on, far away from where you created the object. For example, what if you had code like this?
Now, you can create the user however you want, in whatever method you want. The code that creates the User object doesn’t know or care that a Player class even exists. And you can still use the original User object if you don’t want those extra methods anymore.
This helps you separate behavior into different classes. Each class can focus on how the User object would be used in a specific situation – a Player, an Employee, a Developer. With inheritance, it’s easy for all this stuff to get jumbled together.
When you decorate an object, you can only call the public methods on that object. When you subclass, you can call any method, even private ones. That can make subclasses break more frequently, because they can accidentally rely on their parents’ implementation details. Those details will usually change more often than the public methods.
Decorators can be especially useful when you’re breaking apart large classes. With decorators, it’s easier to follow the Single-Responsibility Principle – each decorator can do one thing and do it well, and you can combine decorators to get more complex behavior.
There are a lot of ways to share behavior in Ruby. You can subclass, you can combine modules, you can even grab methods off one class and attach them to another if you want to. The decorator pattern, though, gives you something a little different. You’re just using instance variables and method calls, the building blocks of any object-oriented language. From those fundamentals, you can have flexible behavior while your app is running – all without overcomplicating your code.
Permalink - Posted on 2017-05-02 05:49
Last week, during RailsConf 2017, Rails 5.1 shipped.
form_tag, and replacing it with
form_with. I can’t wait to try it.
But the reason I love Rails isn’t the big new features. It’s the little, constant improvements. It’s those quality-of-life changes that make me happier when I’m writing Rails apps. And Rails 5.1 is full of them.
Have you used Rails’ tag helpers, like
Use calls like
tag.br, and you can stop worrying about parameter order and juggling two different methods:
These new tag helpers support HTML5 by default, and even let you create your own elements:
assert_difference, I spent way too much time juggling local variables in tests:
assert_difference, it’s much clearer what you’re trying to do:
assert_difference only checks changes in count. But
assert_changes can check non-numerical changes, like changes between two strings, or between nil and something else:
Instead of a string, you can give it a lambda:
to: can be anything that compares with ===. That’s nice when you know something about the value, but don’t know what it is, specifically:
In some Rails code, you’ll see the
delegate method used. Delegation is helpful when you want to add behavior on top of another class, without inheriting from it:
But sometimes you want to forward everything to the class you’re wrapping.
There are a few ways to do this with Ruby, using
SimpleDelegator. But to better match the
delegate_missing_to was added to Rails 5.1. It does exactly what it says:
Now, any call to a method that’s not in the Player class will search on
And as of Rails 5.1,
alias_method_chain is now officially gone – replaced with prepend.
New versions of Rails are always exciting. But it’s the details that give Rails its beauty. The small changes that make you happier with the code you write every day.
How do you find those changes? Dive into the changelogs. Take a look at interesting pull requests. See which of the new, small, 5.1 features will make your life that little bit easier.
And when you find some cool stuff, don’t keep it to yourself. Share it here, so we can all learn something new!
Permalink - Posted on 2017-03-01 05:05
What code of yours isn’t tested? Is it code that deals with complicated situations that you don’t control? Threads, running commands, git, networking, or UI?
Our apps are most interesting when they’re complicated. They’re also most dangerous. And that’s why code that’s hard to test is exactly the kind of code that needs to be tested well. That doesn’t always happen.
Instead, every time you touch that code, you touch lightly. You tread carefully. Maybe you do some manual testing. And when you send the pull request, you hope your teammates don’t realize those tests don’t exist.
But that won’t make things better. You’ll run into the same problems, the same bugs, the same stress next time – and every time after that. How can you finally make those challenging tests something you can rely on?
The most frustrating thing about these tests? It’s going to take ten times as long to write it as it feels like it should. If you estimate the time the test saves you against the time you spend writing the test, it just doesn’t seem worth it.
But it’s not just about this test. It’s about all your future tests.
Most of the best-tested code I’ve seen has a lot of support. It’s not just the code in
test/models. Extremely well-tested code has fakes, it has mocks, it has a good set of test fixtures, it has configuration options specifically for the tests.
All that takes time to write and put together.
But once you have it, it feels so good. You can come up with test after test, feeling comfortable about your code, and confident in quickly you can move after the investment you’ve made.
You can rely on the work you’ve already done.
So it’s not just about preventing bugs in complicated code. It’s also about making future code easier to test, piece by piece.
Sometimes, though, it’s not about understanding the value – I get it. Instead, I just get stuck because I can’t figure out how to write a small, fast, unit test.
How do you know you’re running the right git commands in your deployment tool, without actually running
git? How do you make sure you’re sending a remote server the right headers?
With enough time, you can build a quality fake for your tests to rely on.
But when that seems like too much to think about, there’s something else you can try. Break testing apart into two separate steps: “test the code” and “write the mock.”
Just call that server. Just run that command. Why?
You probably don’t want to keep these tests around forever, though:
So, writing your test as a real-world integration test isn’t a permanent solution, or even a long-term one. But even with all those drawbacks, it’s still helpful. And after you replace it, you can still keep the integration test around, in a separate suite. That way, you can always check my code against reality, not just your assumptions.
Some code is just hard to test. It takes a while to build up the infrastructure you need to write reliable tests quickly. And a lot of the time, it doesn’t seem worth it.
But when you stop thinking about that single test, and think about the value of making all your future tests easier, testing complicated code becomes a lot more motivating. And once the first test goes down, the rest of them seem to magically become so much easier to write.
Sometimes, though, that’s not enough. What if you know how to make sure your code works in the real world, but just can’t figure out how to test it?
When that happens, stop looking at the test as something you need to keep pure and isolated. Instead, see it as a way to automatically do what you’re already doing manually.
It’s not perfect, and you should replace it as soon as you can. But those tests can give you the confidence you need to write and change complicated code quickly.
Permalink - Posted on 2017-02-14 06:08
Have you ever wanted to import a bunch of data into your app from a CSV file? Or maybe you need to fix badly encoded characters in some of your customer reviews. Or you changed your mind about how you wanted to store data in Redis, and had to move everything from the old format to the new one.
At Avvo, we called these “ad-hoc tasks.” As in, you probably only need to run them once. So what’s the best way to handle an ad-hoc task in Rails?
A migration works well if you need to change the structure of the data in your database. It tracks whether the task was run, it carries over changes to other environments – it’s what migrations were built for. It’s also what you’re probably already using them for.
If you’re changing data at the same time, a migration might work well. But there are some things to watch out for.
Calling something like
Permissions.create(...) in your migration can cause you trouble. If the model has changed, your migration might break, because your model might not be available when the migration runs. Or your model might have changed between the time you wrote the migration and when it ran. There are ways to get around this, but they’re error-prone and can fail in weird ways.
Migrations are also less useful if your task doesn’t involve ActiveRecord.
These aren’t deal-breakers. But I tend not to import or change much data in migrations. There are better options.
You have a task. You probably only want to run it once. And you want to be able to test it on your machine and run it in production.
Rake tasks work really well for this. Rails can even generate rake tasks for you:
This creates a file for you to stash your code into:
task block, you can use all your models and the rest of the code in your Rails app. It’s easy to import and change data, because you can write your code just like you were sitting at a Rails console.
Once you’ve written your task, you can run it with
rake locations:import. If you’re using Heroku, you can run it with
heroku run rake locations:import. If you’re using Capistrano, you can use the capistrano-rake gem to run your task. You might have an even better option, though.
Most of these background job processors can schedule jobs to run later. In Sidekiq, for example, there’s the sidekiq-scheduler gem. And with sidekiq-scheduler, there’s a trick you can do.
What if you had a job that never automatically scheduled itself, but let you manually schedule it whenever you wanted? That would work great for “one-off” jobs that you might want to run again later, or that you’d rather run using a UI.
In sidekiq-scheduler, you can schedule the job far in the future, and set the job to disabled:
Then, when you visit sidekiq-web, you’ll see a button to manually enqueue the job:
With this, you can run your job whenever you’re ready, in both development and production. And if you ever need to run it again, it’s right there in the UI.
This isn’t the best option if your job is dangerous. It’s too easy to accidentally click that button. And it’s also not great if the job takes a while to complete, because Sidekiq works best if jobs finish quickly. Your job will take over a worker, and you won’t be able to safely restart Sidekiq until your job finishes. But if your job is fast, and can run safely more than once, this works well. If it’s a cleanup kind of task, you might decide you want to run it regularly.
If you only want to focus on scheduling and triggering, or need more flexibility to set params in your one-time scripts, a reader, Dmitry, pointed me at sidekiq-enqueuer. With sidekiq-enqueuer, you can schedule jobs and set params, all through the Sidekiq web interface.
I’ve used all of these ways to run one-off tasks. But I’ll usually go for a rake task first. It works, it’s hard to run accidentally, and it’s easy to get rid of when you’re done with it. I don’t choose rake tasks every time, though.
I might choose a migration if:
I might choose a Sidekiq job if:
How about you? Do you have any other options, or make different choices? Leave a comment and let me know!
Permalink - Posted on 2015-09-22 06:35
In last week’s article, you learned a short process that solves most encoding problems. But there’s one encoding problem that’s much harder to solve.
I know you’ve seen it. (Or maybe youâ€™ve seen it?) It’s when a curly quote turns into â€™, or an em-dash turns into â€”. It’ll make you think you’ve gone crazy. It should just work!
You could create a giant table, so you could find bad characters and replace them with good ones:
But there’s an easier, more reliable way to fix those broken characters.
Last week, you learned that an encoding is just a way to turn groups of meaningless bytes into displayable characters. Not every character can be represented in a single byte, because there are more than 256 possible characters. So some characters, like the curly quote
’, are represented with more than one byte:
Even though the string only has 7 characters, they’re represented by 9 bytes!
When you focus on just the curly quote:
You’ll see it uses 3 bytes. And our messed up string, theyâ€™re, has three characters where it should just have one. That seems like more than a coincidence, right?
It seems like those three bytes should be read as UTF-8, where they’d represent a curly quote. Instead, each byte is showing up as a different character. So, which encoding would represent
[226, 128, 153] as
â€™? If you look at a few tables of popular encodings, you’ll see it’s Windows-1252.
You can check this in
(We need that last
.encode("UTF-8") to display the string in the console.)
Yep! That’s the problem. But it gets worse.
The data is supposed to be UTF-8, but is being misread as Windows-1252. But you’ll probably save that data to a database, or a file, as UTF-8. Ruby will helpfully convert it to UTF-8 for you, so you’ll end up with:
Your string has been badly-encoded twice. Those broken characters now look like they’re supposed to be there. And if you didn’t know how it happened, it’d be almost impossible to untangle it.
How do you get things back to normal? Let’s think about the problem backwards:
You have a UTF-8 string, (theyâ€™re)
converted from a Windows-1252 string, (theyâ€™re)
whose bytes should have been read as UTF-8 (they’re)
To fix it, you just have to follow those backwards steps. Use
encode to convert the UTF-8 string back into a Windows-1252 string. Then, use
force_encoding to force that mis-encoded Windows-1252 string to be read as UTF-8:
Unfortunately, you probably found this problem because a bunch of files or database records had badly encoded data in it. And not every file or record is necessarily badly encoded – you might have a mix of good and bad data. Especially if that data came from the people visiting your site.
If that’s the case, you can’t blindly run that code on every string:
If you run it on good data, you’ll just turn it into bad data. So what can you do?
You can use a heuristic: only change strings that have one of the bad characters in them, like
â. This works well if a character like
â won’t ever appear in a valid string.
The last time I fixed this kind of bug, though, I wanted to play it safe. I used another useful tool to help: my eyes.
Whenever I found a badly encoded string, I printed it out, along with its replacement:
That way, I could spot-check the small number of strings that changed, and make sure they didn’t break any further.
Like I said last week, keeping different interpretations of the same data straight in your head is hard! But if you’re confused, exploring in an
irb console will help. So try it out! Open one up, and see if you can go back and forth between
Practicing complicated ideas like these is the fastest way to feel confident when you need them. And in the free sample chapter of Practicing Rails, you’ll learn the best techniques and processes to do just that.
Permalink - Posted on 2015-09-16 06:59
You only really think about a string’s encoding when it breaks. When you check your exception tracker and see
staring you in the face. Or maybe “they’re” starts showing up as “theyâ€™re”.
So, when you have a bad encoding, how do you figure out what broke? And how can you fix it?
If you can imagine what encoding does to a string, these bugs are easier to fix.
You can think of a string as an array of bytes, or small numbers:
In this encoding,
!, and so on.
It gets trickier when you use characters that are less common in English:
Now it’s harder to tell which number represents which character. Instead of one byte,
ṏ is represented by the group of bytes
[225, 185, 143]. But there’s still a relationship between bytes and characters. And a string’s encoding defines that relationship.
Take a look at what a single set of bytes looks like when you try different encodings:
The bytes didn’t change. But that doesn’t look right at all. Changing the encoding changed how the string printed, without changing the bytes.
And not all strings can be represented in all encodings:
Most encodings are small, and can’t handle every possible character. You’ll see that error when a character in one encoding doesn’t exist in another, or when Ruby can’t figure out how to translate a character between two encodings.
You can work around this error if you pass extra options into
undef options replace characters that can’t be translated with a different character. By default, that replacement character is
?. (When you convert to Unicode, it’s �).
Unfortunately, when you replace characters with
encode, you might lose information. You have no idea which bytes were replaced by
?. But if you need your data to be in that new encoding, losing data can be better than things being broken.
So far, you’ve seen three key string methods to help you understand encodings:
encode, which translates a string to another encoding (converting characters to their equivalent in the new encoding)
bytes, which will show you the bytes that make up a string
force_encoding, which will show you what those bytes would look like interpreted by a different encoding
The major difference between
force_encoding is that
encode might change
You can fix most encoding issues with three steps:
This sounds easy. But just because a string says it’s some encoding, doesn’t mean it actually is:
That’s not right – if it was really UTF-8, it wouldn’t have that weird backslashed number in it. So how do you figure out the right encoding for your string?
A lot of older software will stick to a single default encoding, so you can research where the input came from. Did someone paste it in from Word? It could be Windows-1252. Did it come from a file or did you pull it from an older website? It might be ISO-8859-1.
I’ve also found it helpful to search for encoding tables, like the ones on those linked Wikipedia pages. On those tables, you can look up the characters referenced by the unknown numbers, and see if they make sense in context.
In this example, the Windows-1252 chart shows that the byte
99 represents the “™” character. Byte
99 doesn’t exist under ISO-8859-1. If ™ makes sense here, you could assume the input was in Windows-1252 and move on. Otherwise, you could keep researching until you found a character that seems more reasonable.
This one’s easy. Unless you have a really good reason, you want your strings to be UTF-8 encoded.
There’s one other common encoding you might use in Ruby: ASCII-8BIT. In ASCII-8BIT, every character is represented by a single byte. That is,
str.chars.length == str.bytes.length. So, if you want a lot of control over the specific bytes in your string, ASCII-8BIT might be a good option.
You can do this with the
encode method. In this example, our string was in the Windows-1252 encoding, and we want it to become UTF-8. Pretty straightforward:
Much better. (Even though the order of the encodings in that call always seemed backwards to me).
It can be brain-bending to imagine different interpretations of the same array of bytes. Especially when one of those interpretations is broken. But there’s a great way to become a lot more comfortable with encodings: Play with them.
irb console, and mess around with
force_encoding. Watch how
encode changes the bytes making up the string. Build intuition about what different encodings look like. When you’ve grown more comfortable with encodings and use these steps, you’ll fix in minutes what would have taken you hours before.
Finally, if you want to learn how to make a habit out of learning these kinds of things by doing, grab the free sample chapter of my book. Breaking things in the console is a really fun way to study ideas like this.
Permalink - Posted on 2015-09-08 07:23
When you run into a strange, seemingly unsolvable bug, improving your logging can be the best step you can take. Great logging is the easiest way to detect and fix entire classes of bugs. When you log enough information, you can see how your data changes during a request. You can track the calls you make to other services, and investigate the response. In fact, when debuggers failed, logging helped me fix the toughest bug I’ve ever run into.
But log too much, and your log files will quickly turn into a jumble of unreadable, unhelpful messages. How can you slice just the information you care about out of that pile of data? Can you print messages in a way that’s easy to filter later?
Rails includes TaggedLogging, which can help you quickly categorize related log messages. When you tag a logger, you’ll get a marker at the beginning of your message. So instead of:
You could tag the Rails logger:
And you’d see something like this:
Now, log messages that care about different things can look different.
As you log more often, and log more complicated things, you’ll naturally notice areas where those tags will make your messages clearer. But there are a few places I’ve found tagged logging particularly helpful. I’ll usually tag those right away.
You can log requests you make to other APIs:
That way, you can easily see how and when your app is talking to that API.
Background jobs also work well with tagged logging:
Now, any job that extends LoggedJob will have all of its log messages tagged with the class name of the job.
And if you have a logged-in user, you could tag messages with their user ID:
Finally, if you add a line to your
development.rb), you can have Rails automatically tag your messages:
log_tags lists the tags you want to appear at the beginning of every Rails log entry. Each symbol refers to a method on ActionDispatch::Request, so
You can also pass a Proc that takes a
But I don’t see that very often.
These default tags are nice:
uuid can tie together all the log entries that happen in one request, and if you’re keeping sessions on the server, the session ID is also helpful. With those tags, and enough messages, you can trace some really complicated paths through your app. And usually, that’s what it takes to figure out how a nasty bug happened.
How much do you use the Rails logger in your apps? Have you tried tagged logging? If you haven’t, try finding a place for it. Tagging actions taken by your users is a good start. It’ll help you out the next time you have to debug a crazy multi-step bug.
If you want to learn more about logging and other debugging techniques, I’ve dedicated an entire chapter of Practicing Rails to finding and fixing the errors you’ll run into as you create your apps. Grab the first chapter for free here.
Permalink - Posted on 2015-09-01 07:30
This article is also available in Korean, thanks to Soonsang Hong!
Scopes are a great way to grab the right objects out of your database:
You’d use the scope like this:
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:
So why would you use a scope when you could use regular Ruby class methods? Is it worth keeping these totally separate, 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?
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:
Easy enough, right? What about the class method?
It takes a little bit of extra work. Scopes prefer to return scopes, so they’re easy to chain together:
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:
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.
Because scopes express intent, I use them whenever I’m chaining simple, built-in scopes (like
limit) into more complicated scopes. Finding the right bunch of objects is what scopes were designed for.
There are two exceptions:
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!
Permalink - Posted on 2015-07-29 05:52
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.
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.
Permalink - Posted on 2015-07-21 06:58
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.
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.
(You can install it on other systems using the instructions on the site).
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
Then, in Huffduffer, click the “Huffduff it” link in the header, and you’ll run into the last hoop you have to jump through.
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.
So, here’s that process again:
youtube-dl -x <url_to_talk_video>.
~/Dropbox/Public, or somewhere else that’s publicly accessible.
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.
Permalink - Posted on 2015-07-15 07:13
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?
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.
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.
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.
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.
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.
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!
Permalink - Posted on 2015-07-08 03:23
This article is also available in Korean, thanks to Dohyung Ahn!
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.
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?
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.
Permalink - Posted on 2015-06-30 07:39
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.
ActiveRecord enums are pretty easy. You give your model an
List the values that attribute can take:
And now you can deal with strings instead of numbers.
Instead of this:
You’ll see this:
You can change that attribute using either strings or ints:
Or even using a bang method:
You get methods for asking if your attribute has some specific value:
And you can find all objects with the value you’re looking for:
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:
Which makes them easy to put into an HTML form:
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:
Your phones won’t have the right types anymore. You can get around this by telling
enum which number goes with which value:
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!
Permalink - Posted on 2015-06-23 20:17
This article is also available in Korean, thanks to Soonsang Hong!
Rails’ scopes make it easy to find the records you want:
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:
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.
When you use the Rails association methods, like
has_many, your model usually looks like this:
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:
Now, you can preload your new association with
Instead of 6 SQL calls, we only did two.
class_name, you can have multiple associations to the same object. This comes in handy pretty often.)
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:
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:
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.
Permalink - Posted on 2015-06-16 06:19
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?
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.
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).
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!
Permalink - Posted on 2015-06-09 03:56
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?
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?
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:
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.
Permalink - Posted on 2015-06-01 21:01
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?
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:
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
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?
If you used instances, you’d create and configure your API wrapper when you need it:
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.
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:
And you can still ask for instances of these classes if you need more than what the default gives you:
You could build something like that in Ruby, with a
default_api class method:
And the implementation might look something like this:
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.
Permalink - Posted on 2015-05-26 05:02
Have you seen the Rails Competency Chart?
Brook Riggio of CodeFellows put it together to show all of the concepts a modern Rails developer should know. Take a look:
Frightening, isn’t it? It looks like a two-hundred-tentacled monster that’s preparing to attack you.
It’s no wonder learning Rails is intimidating. Some of the branches, like SQL and Deployment, could be entire career paths. You could spend years on Application Architecture and still not feel like an expert.
But it’s accurate. If you show this chart to a professional Rails dev, you’ll probably hear, “Yep, that sounds about right.” If anything, you’ll hear about what it’s missing.
So how can you deal with all this? How do you learn all this stuff without having started 5 years ago?
Yeah, most professional Rails developers know a lot about a lot of those concepts. But you don’t have to know all these things to start building your Rails apps. You don’t need to study deployment until you’re ready to deploy, and you can look up how to group things in SQL the first time you have to do it.
One thing this chart doesn’t illustrate well (even though the blog post talks about it) is how the different areas reinforce each other. For instance, unit tests, integration tests, acceptance tests, and all the rest use similar skills and knowledge. Yes, there are some differences between the different types of tests. But once you start to understand the fundamentals of testing by writing a bunch of unit tests, you’ll pick up the other types much more quickly.
The more you learn, the faster you’ll learn. Functional programming is a lot easier to learn when you know Object-Oriented Programming. Service-Oriented Architectures can “feel” a little like Object-Oriented Programming. Learning CSS selectors will make using jQuery much easier. Many of the principles you learn will translate across different branches.
If you try to pick up every one of these skills at the same time, you won’t take advantage of the extra speed you’ll get as you master them one-by-one. So focus on a few at a time, and learn them well.
Ask yourself this question:
“What do I need to know to make progress on the problem I’m facing?”
Use your answer to narrow in on which competencies to start with. As you pick those up, you can check out the skills right around it, and take advantage of what you just learned to learn similar things faster. For instance, if you’re feeling comfortable with the command line, you could pretty easily branch out into things like package management and permissions.
By building these skills as you need them, you’ll have a little extra kick of motivation. You’ll be spending time on the stuff that matters to you.
For instance, if I was learning multitenancy because I felt like it’s something I should just know, I’d be asleep halfway through the first blog post. If I was learning it because it was the only way I could get my app to work, I’d be glued to every tutorial and reference guide I could find.
It’s crushing to see a few hundred skills, and know you need to learn them all. Especially when those first few competencies take you weeks or months to pick up. You’ll feel like you’ll never become a professional Rails dev.
The chart’s not wrong. As a Rails dev, you’ll eventually know a lot about most of those things. But we didn’t all start there.
So, start somewhere. Prioritize, and move along the path that leads to your app being built. Branch out to fill in the gaps. And recognize that you’ll get faster as time goes on.
And if you want to learn those skills faster, and remember how to use them when it counts, grab this free sample chapter of Practicing Rails. You’ll learn the method I use to learn new Rails ideas quickly and thoroughly, without getting overwhelmed.