I spent a long week grappling with text encoding. Please enjoy the fruit of my labors:
A programmer walks into a coffee shop.Programmer: “Do you serve cortados here?”Barista: “No—wrong café. You want the Latin one.”
— Michael Hoffman (@Hoffm) March 22, 2013
Git bisect is like CPR or a fire extinguisher: You shouldn’t need it very often, but when you, it might just save a life.
In case you are not familiar with its splendor, git bisect is a tool for pinpointing the commit that caused a change. Usually, the change you’re interested in is the introduction of a bug. Bisect is handy when, for instance, you discover a regression and you don’t know what caused it or exactly how long it’s been around. Bisect isolates the offending commit with logarithmic efficiency. It accomplishes this by performing a binary search of the commits on your branch, dividing and conquering until only one commit remains.
The basic version of the process is simple. You provide git with a good commit (one you know is after the change) and a bad commit (one you know is before the change). Git then asks you a series of yes-or-no questions of the form: How about this other commit here—is it good? Approximately log-base-2 of the number of questions in your good-bad interval later, you have your culprit.
Here are the commands for navigating through this process:
1 2 3 4 5 6 7 8 9 | |
At this point, Git will proceed to checkout commits for you. Your job is to give the thumbs up or thumbs down, Roman-emperor style.
1 2 3 4 | |
At each step you’ll need to do whatever it is you need to do to check which side of the change the commit is on.
If you’re working on a Rails app, this might involve running rake db:migrate and bundle install, and then checking whether a particular test passes or a particular behavior of your application is present.
When git zeroes in on its target, it will spit out a message telling you what it found, e.g.
1 2 3 4 5 6 | |
At this point, you’ll probably want to get out of bisect mode and back onto your working branch. To do this, run
1
| |
That’s all you really need to know to start using git bisect.
In researching this post, though, I came across some additional commands that are worth learning.
First, if during the bisect process, git lands you on a particularly awkward commit—e.g. one for which the needed environment is hard to replicate from your present position—you can run git bisect skip and git will offer you a different commit to test.
Second—and way cooler—you can automate your yes/no decisions by feeding a custom script to git bisect run.
Git will run the script at every decision point, and will take an exit code of 0 to mean good, and anything else (except 125) to mean bad (details here).
Test frameworks like RSpec exit with 0 only when all tests pass (or none are run), so if you’re trying to identify the commit that caused a test failure, this is your tool.
Checking out the last branch you were on is as simple as git checkout -.
1 2 3 4 5 6 | |
Boom!
I recently submitted my first (tiny!) patch to an open source project. It’s something I’d wanted to do for a long time, but couldn’t figure out how to initiate. Here are some things that surprised me about the process.
This, as I understand it, is the lifecycle of a garden-variety open source contribution:
Perhaps the most difficult part of the whole open source contribution process—and, for me, certainly the longest phase—is identifying a patch that you want to write. If you ask smart, experienced folks how to get started, they’ll often tell you to look at the open source projects that you use the most and to find something to contribute there. I think there’s a lot of value in this advice (and, ultimately, I acted on it), but there s quite a gulf between knowing a piece of software well and finding something you want to change about it, and that others want you to change.
Moreover, the projects you use the most are likely to be high-profile software that a lot of other people use a lot, and that means the barriers to contribution may be relatively high. Ultimately, my way in was finding a bug in Rails, which, after all, is the piece of open source software I use more than any other. The only reason I ended up contributing when I did was dumb luck (or at least the law of large numbers): I found a bug.
Even after you figure out what problem you want to solve, writing the code to solve that problem is still only a small fraction of the work that lies ahead. The process is probably a little different with features, but in the case of a bug fix, there’s loads to do before you even report the bug. You need to make sure that the bug is reproducible on the current master branch of the application. Then you need to determine exactly in which contexts the bug occurs, and to check whether the issue is caused by some problem with—or a corner case intimately related to—the configuration of a particular application that makes use of the open source project.
Much of the rest of the work, as the list above illustrates, is about communication. Basically, it’s an exercise in technical writing and in empathy for your readers: What will the owners of the project want to know about the change I propose? What will future developers need to know about the change I made?
The importance of communication is, of course, not limited to open source projects. It’s a commonplace (but for good reason) that precise, empathic writing is a among the developer’s most essential skills. This is never more true than in the context of an open source project with a large number of contributors. Yes, you will need to actually fix your bug (or build your feature), but chances are, by the time you submit your proposal, you’ll have done enough investigating and writing that you’ll already have a good idea how to do it. Examples used in writing turn into test assertions, which in turn guide production code. Actually writing the code can feel like an afterthought, especially in the case of a small bug fix like the one I submitted.
In addition to preparatory investigation, communication, and writing the patch, the final piece of the puzzle is getting your code where it needs to be so that others can review it: source control. I was surprised to find that, for me, source control was one of the most daunting aspects of the whole process.
I’m quite comfortable using git, but I’d never issued a pull request from a forked repo before, so I had some things to learn. I followed the Rails contributions instructions closely in submitting my original request, and everything went fine. (Steve Klabnik has a good project-agnostic guide here.) However, when I had to iterate on my work, I was less careful and I ran into trouble. Somewhere in the process of pulling in changes that others had made in the interim, resolving conflicts, rebasing and pushing to my feature brach, I ended up garbling my original pull request. I panicked a bit as I imagined the reactions of all of the Rails core members whom I’d just spammed. I closed the sullied request and opened a fresh one.
In retrospect, and as a kind soul pointed out to me, I could simply have fixed the existing request.
But the point is that source control on a large open source project is a high stakes game (or feels that way at any rate), and if this is your first rodeo, you should learn from my mistake and be methodical.
If things go awry, there’s always git push -f.
The good news is that, having done this once, I’ll have an easier time with my next patch. I imagine that the workflow is pretty similar across most projects, so hopefully I won’t find myself up git’s creek again any time soon.
There were lots of reasons I wanted to contribute to open source: to give something back to people from whose work I’ve benefitted greatly, for the pure challenge of it, and, frankly, to build my resume. What I did not anticipate was that getting a patch accepted makes you feel like a million bucks. The Rails community was super supportive of me the entire way, overseeing my fix when they could have written their own patch with less effort. I truly felt that I was being accepted into a community.
The thought of having even the tiniest effect on a ubiquitous piece of software is thrilling. Your code will run on so many servers, your name emblazoned on so many replications of the changelog. This thrill may be a narcissistic one, but I feel it’s alright to revel in it. What’s wrong with feeling satisfied that you’ve applied your skills to improve a product that hundreds (or thousands, or millions) of people use to build cool stuff?
Contributing to open source is a great high; I can’t wait to get my next fix.
There are many approaches to responding to failed requests in Rails. Here I offer the way I currently favor setting things up. I’m hoping that this might start a conversation about best practices; I’m sure I could do better!
The default way Rails handles requests to which your application does not have a contentful response is to serve up static HTML documents stored in the public directory.
In particular, 500 (server error) and 404 (not found) responses result in the application’s rendering 500.html and 404.html, respectively.
This default approach is solid—it can be relied upon to display the correct pages in the correct conditions— but it does not allow customization of those pages. These error pages can’t execute ruby code, and so they can’t use your layouts, can’t interact with your data, and can’t vary based on conditions such as the time, the user, or the nature of the request. Such customizations can imporve user experience and reduce bounce rates when things go wrong.
For these reasons, it’s tempting to rescue all kinds of exceptions and render full-blown erb templates in response to them. I think this strategy is reasonable in the case of 404 errors, and here’s how I do it:
app/controllers/application_controller.rb1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
You can define four_oh_four_path and the corresponding action and template however you’d like.
A similar but lighter-weight approach would be to render a template in your app/view/shared/ directory instead of redirecting to an action.
In any case, we wrap this rescue block in the consider_all_requests_local condition, because we’d still like to get an informative stack trace in development mode.
It’s tempting to treat 500s analogously, but I think that would be a mistake. If your application is returning a 500 response, chances are something has gone wrong, and the behavior it’s exhibiting is not what you expected. Given this, who’s to say whether or not your fancy custom 500 page will load? What if the bug is in the very code that catches and responds to errors?
For these reasons, it is much safer to take the default approach to 500 errors. Don’t like your static 500 page? My suggestion is: make sure that people rarely get to see it.
To get some inspiration for such pages, you could the /500 path your favorite websites.
Here
are
some
examples.
And
here is the page
I recently made for Food52.
(Thanks to
Ryan
for finding the image and helping make the page responsive!)
How do you quickly check what path a certain route helper maps to?
One method I use a lot is to grep rake routes.
So, let’s say I’m looking for a route that has to do with comment approval.
In that case, I might run rake routes | grep approve.
And there’s my answer:
1
| |
There’s one problem with this, though: It’s slooooow.
It’s slow because running rake routes loads up your whole Rails environment.
If your workflow is anything like mine, though, chances are you’ve already have your environement loaded in another tab: the one where you have a Rails console running.
So in cases where you have some idea what the name of the route is, testing it out in the console can save you time.
And, luckily, it couldn’t be simpler.
In the Rails console, the variable app holds a session object on which you can call path and url helpers as instance methods.
So away we go:
1 2 3 4 | |
That’s all there is to it.
(See this post for my way of generating custom slugs like the one in that user path.)
(Searching around a bit, I think I originally got this tip from this wonderful post. Read it to learn about other useful things you can accomplish with app.)
There are some nice gems out there to help you create and manage human-readable slugs in Rails. However, our requirements at Food52 were simple enough—and different enough from the standard case—that I thought I’d have a go at building a slugging system from scratch.
As an example of the desired behavior, given that we want to use the attribute name to generate slugs for users, and given that my user id is 784 and my name is “Michael Hoffman”, the slug for my user page should be:
"784-michael-hoffman"
(We leave the id in because we like it there!
It makes debugging easier and it allows us to use Active Record find to look up objects from params.)
Furthermore, we want our slugs to adapt gracefully to changing circumstances. So, if my name changes, the slug should do…something smart.
Getting a little more abstract, our requirements are as follows:
[:id]-[parameterized-string].That’s the problem. In this post, I explain my solution. Even if your custom slug needs are slightly different, I hope the general strategy might be useful.
Before we begin, we need some background on how Rails handles slugs by default.
Active Record has an instance method #to_param, which Action Pack uses to create URLs.
By default, #to_param returns the id of the object, converted to a string.
(See the source,
here
.)
Thus, the default path to my user page (given standard resourceful routing) would be "/users/784".
However, it is possible to customize slugs by overriding this method on a model-by-model basis.
So, the naive way to get the result we want would be to add a method like this one to the User model:
app/model/user.rb1 2 3 4 5 6 7 8 9 | |
This approach meets the first four requirements, but there are two problems with it. First, we’re going to have to repeat this method (modulo the string to be parameterized) in all the models for which we want human-readable slugs.
Second, it fails to meet the fifth requirement.
Specifically, as users’ names change, we will end up with many different addresses that point to the same content.
For instance, if I change my name to, say, “Michael Danger Hoffman”, then Action-Pack-generated links to my profile will use 784-michael-danger-hoffman, but anyone who’d previously copied the link, or bookmarked it, will be able to reach the same page by visiting the old slug.
Not only is that confusing to humans, it’s also confusing to search bots.
Confusing search bots makes them sad!
Let’s build on the naive solution to create a slugging system that can be applied succinctly across many models. (We’ll deal with the duplicate content problem in a another pass.)
Given a model, there are only two things we need to know about it with regard to slugging:
Ideally, we want a system that would allow us to opt models in to custom sluging, and simultaneously to specify how to calculate the strings those models should use to create slugs.
We can do this by adding a class method to ActiveRecord::Base that redefines #to_param.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
We’re going to want to make ::custom_slugs_with available in all models, so let’s require this file in an initializer:
1
| |
Requiring this file will execute the include call, including ActiveRecordExtensions in ActiveRecord::Base (andmaking the module’s methods available to Active Record’s descendants).
The ::custom_slugs_with method takes as an argument the name of an instance method that specifies the string to be used in the slug.
So, for instance, adding this line to the User model:
1 2 3 4 5 | |
will serve the same purpose as the to_param method in our original, naive solution.
When we want to retrieve the object from its slug, as will often be the case in controller actions, we can use a simple Active Record find. E.g.
app/controllers/users_controller.rb1 2 3 4 5 6 7 8 9 | |
Find is smart enough to parse strings like these and extract the correct id.
Lastly, if we wanted to use an explicit method to generate the string (instead of relying on the attribute, name), we could define that method in the User model and pass its symbolized name into the ::custom_slugs_with.
We still have a lingering problem.
The attributes from which these custom slugs are generated might change.
Moreover, we might be installing this system in an application that already has a different slugging system.
Both of these eventualities will lead us into to the uncomfortable situation I mentioned above: having multiple URLs that refer to the same content.
To get around this problem, let’s treat the record’s current slug—the one we get when we call #to_param on it—as canonical.
Then, when we get a request for an out-of-date or incorrect slug, we can redirect the canonical one.
We’ll do this in basically the same way in every controller, so let’s add our new code to the application controller. The first method checks if the slug is canonical. The second redirects to the canonical slug, as retrieved by Action Pack.
app/controllers/application_controller.rb1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
Now we can call these methods from controller actions that we want to redirect non-canonical slugs:
app/controllers/users_controller.rb1 2 3 4 5 6 7 8 9 10 | |
This gets the job done.
Requests for "/users/784-something-totally-weird" will redirect to "/users/784-Michael-Hoffman" as desired.
Changing my name will change the target of this redirection.
I must admit, though, that I find this solution less than ideal. It requires repeating the redirect-if-bad-slug code in many actions. However, I have not yet found a better approach. If you have one, I’d love to hear it!
Lots of folks were interested in getting git autocomplete going in bash, so I thought I’d offer another useful git/bash tip. This one was suggested by Stephan in the comments of that earlier post.
If you’re using git properly and collaborating on a project, chances are you find yourself changing branches often. This can be quite disorienting. You deploy from the master branch, then get back to that bug fix you were about to work except for—whoops!—now you commited that fix to master and have to back away slowly. Confusions like this one can easily be avoided by putting you branch name front-and-center: at the end of your bash prompt. Here’s how.
Get the git-promt.sh script here.
Put it somewhere like ~/.git-prompt.sh.
If you want to be all CLI about it, you could just run:
1
| |
Now modify your your bash profile (it’s at ~/.bash-profile, in case you’re new to this stuff).
Before the part of the file that declares what your prompt will look like (PS1=[...]), load in the script you just downloaded, like so:
1 2 | |
Now add \$(__git_ps1) to your prompt declaration.
You can put it wherever you like, but I think it’s best suited for the very end, right before the final dollar sign (\$)
If you want to get all fancy, you can make it a pretty color.
My declaration looks like this:
1
| |
(See here for color definitions.)
This declaration results in a prompt looks like this when I’m in the directory ~/src/food52 and on the branch develop:
That’s it. Never git lost again!
I’ve been working on a Rails app that contains lots of mailers with hard-coded recipients. For instance, here’s a mailer that we use to notify folks when someone asks an urgent question on our hotline:
hotline_mailer.rb1 2 3 4 5 6 7 8 9 10 11 12 13 | |
The email address “urgent@mywebapp.com” generates emails to many people. We handle membership in Google apps.
Left to its own devices, this mailer will trigger an email to that list of people every time you hit the controller action that calls for it to be delivered.
That’s bad news if you’re just testing out the action in your development environment. You have a group of people who are getting annoying emails for no reason, and you may not even be getting the emails yourself!
We might consider using a constant in place of the email address, and initializing this constant differently in different environments. However, this approach has two shortcomings:
Luckily, ActionMailer makes a better solution possible. Here’s what you need to do:
lib/development_mail_interceptor.rb1 2 3 4 5 6 7 | |
1 2 | |
1
| |
Lastly, you want to git ignore config/initializers/personal_email.rb, and tell your collaborators to create their own local version of the file.
(You want to git ignore it so that it can be customized per dev box.)
What does this all do?
When you call #deliver on an message, if the environment is development, the to option on the mailer is overridden with your personal address.
(In this example, it’s “personal@mywebapp.com”).
That’s it!
We set up the default in the interceptor in case one of our collaborators doesn’t get the message about creating personal_email.rb.
In that case, that person’s dev mailer emails will be sent to the default you set in the interceptor class.
(In this example it’s “default@mywebapp.com”)
When I first struck upon this solution, I was worried that the interceptor would prevent me from seeing who would actually receive a given email if the code were running in production.
I needn’t have worried.
The interceptor only affects the behavior of the #deliver method; the message object remains intact.
So, if you call
HotlineMailer.notify_urgent_question(question)
you’ll find that object returned has the attribute <To: urgent@mywebapp.com>.
That’s the address this email would go to if the interceptor did not interfere.
However, if you call
HotlineMailer.notify_urgent_question(question).deliver,
the object returned has the attribute <To: personal@mywebapp.com> and sends the email to that address.
I think this is an effective solution, but it could be better. Forcing developers to manually create files in order to properly use your repo is not ideal. If you have an idea to improve this system, I’d love to hear about it in the comments.
While working on a longer (forthcoming) post, I wrote a little benchmarking utility that I want to share. Here it is:
tiny_timer.rb1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
As you can see, this method runs a specified number of trials of a block of code and returns the average time in seconds it took to execute the block. Usage examples:
1 2 3 4 5 6 | |
You can invoke a rake task from another rake task. Here’s how:
examples.rake1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Now when you execute rake examples:outer_task, you will execute the inner task in whatever context you placed it.
Using this contruction allows you to break down unweildy tasks into smaller ones, which perhaps you’ll want to reuse in different contexts elsewhere.
Here’s a toy examples that actually works:
toys.rake1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Running this in the shell, we get:
1 2 3 4 5 6 7 | |
And yes, I know you’re thinking it now: rake tasks can call themselves quite happily.
You can also invoke rake tasks from within ActiveRecord migrations. This can come in handy when you want to initialize a bunch of data immeidately after altering the database schema.
In bash in Mac OS X, you can use [TAB] to autocomplete file paths. Wouldn’t if be nice if you could do the same with git commands and branch names?
You can. Here’s how.
First get the git-completion.bash script (view it here) and put it in your home directory:
1
| |
Next, add the following lines to your .bash_profile.
This tells bash to execute the git autocomplete script if it exists.
1 2 3 | |
Now open a new shell, cd into a git repo, and start typing a git command.
You should find that [TAB] now autocompletes git commands and git branch names.
For example, if you type git then add a space and hit [TAB], you’ll get a readout like this, which lists all available git commands:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
Now to learn what some of these more exotic git commands do! What’s your favorite git command?
(I learned this way of installing git-completion.bash here.)
Pop quiz, hotshot: What does the following Ruby expression return?
1
| |
It turns out I’m not much of a hotshot, because this how I reasoned through this question while at work today:
Array#map evaluates the block for each member of the array and returns a new array of the returned values, in order.n == 1 or n == 3, the block evaluates to 2*n.n == 2 we hit the next keyword and nothing gets evaluated.[2,6].Reinforcing this line of reasoning, a very similar expression,
1
| |
gives the analog of this result:
it prints “2” and then “6” and then return.
The iteration that hits next just gets skipped.
Analogously, the version with map should return [2,6]
Wrong!
In fact, the answer to the quiz is…
1
| |
The error in the reasoning above is contained in premise (3).
It turns out that when next is evaluated, it returns nil.
Similarly,
1
| |
returns the same array, [2, nil, 6], because ... if false returns nil no matter what (syntactically valid) expression ... is.
So, if you’re using map, and you want to skip some elements, you can’t just use next or if.
You also need to deal with the nils when you’re done, like this:
1
| |
Alternatively—although it’s probably more expensive—you could select the elements you want before proceeding with the operations you want to perform on them:
1
| |
Let me know in the comments if you can think of a generalizable implementation that’s more elegant than either of these. In the meantime, may you never make the same mistake I made!
Ever tried to get a sense of an ActiveRecord object by squinting though output like this?
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Yuck.
Luckily, there’s a super simple way to get some nicer formatting.
The Kernel module has a private instance method #y which will print out an active record object (or anything else) as YAML.
Check it out:
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 30 31 32 33 34 35 | |
Notice that, in addition to producing more legible formatting, #y does not truncate values, so we get to see the whole description of the recipe.
Another great use case for this method is visualizing nested hashes and arrays.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Nice, huh?
One caveat:
Apparently this method relies on the Syck YAML parser.
For this reason, it won’t immediately work out of the box with Ruby 1.9.3, which uses the Psych parser by default.
If you’re using 1.9.3 and you want to play around with Kernel#y, run YAML::ENGINE.yamler = 'syck' to change parsers.
And a question: I’d like to know how to get #y to print out ActiveRecord attributes in the same order as they are normally displayed.
(By the way, I highly recommend trying out the recipe mentioned above.)
Learning to code is hard.
I’m not talking about the sense in which we’re all still learning. I mean when you first start out, the first few months. During this period, every tiny bit of progress you make comes at the expense of an excruciating, time-consuming trial.
Personally, I had the great fortune of being around patient, empathic experts who helped me through the worst of it. (Thanks Jon, Jackie, Lauren, et al!) But not everyone is so lucky, and sooner or later a new programmer is bound to encounter RTFM and its new-fangled cousins, GIYF and LMGTFY.
Ever ask an elementary question about coding or about getting your development environment set up, and encounter one of the following responses?
Whether or not they say it explicitly, the authors of these responses are expressing the RTFM sentiment. And RTFM is bullshit.
I’m not the first person to say this, of course. But as a programmer who is still very much in touch with what it’s like to know nothing, I hope I am in a position fortify the empathy of my more seasoned colleagues.
No one feels Meno’s Paradox as viscerally as the Googling noob.
And how will you inquire into a thing when you are wholly ignorant of what it is? Even if you happen to bump right into it, how will you know it is the thing you didn’t know?
Answering technical questions via internet searches is a skill that takes practice to hone and which requires background knowledge. Teaching yourself to code on the internet is a boostrapping process: The more you learn, the better you get at learning it, and before you’ve learned very much, learning is really hard.
If you get stuck and you seek help on the internet, you need to know at least the following in order to have any hope of success:
People who ask stupid technical questions might be stupid people. Or, more likely, they might just be missing one or more of the pieces of knowledge they need to ask a smart quetsion and understand the answer. It’s not their fault they don’t know these things. They are beginners. Learning to figure stuff our using documentation and Google is a skill they’re developing along with all the others.
So, if someone asks a stupid question, consider taking the time answer it, fully and cheerfully. Or don’t answer at all. Just remember: RTFM is some lazy, rude bullshit.
(NB: I learned much of what I discuss here from this post.)
What does a brand new, never-before-mentioned variable evaluate to in Ruby?
Perhaps it seems that the correct answer is: it depends what kind of variable.
Undefined instance variables, for example, evaluate to nil, whereas undefined local variables can’t be evaluated at all.
A little experimentation in irb seems to confirm this hypothesis.
Uninitialize local variables raise a NameError:
1 2 3 4 | |
whereas instance variables evaluate to nil:
1 2 3 4 | |
(Global variables behave the same way in this respect as instance varables.)
So, again, it seems as if the correct answer to our question is, “It depends.” But that’s wrong. In fact, the question has a single, simple correct answer: All types of uninitialized variables evaluate to nil.
Here’s proof:
1 2 3 4 | |
The initialization of local_var is never evaluated, because the condition false is, of course, not met.
Yet, it seems that the mere fact that the parser has parsed local_var suffices to avoid the NameError when evaluating the variable.
Why?
The answer is that the NameError was merely an error of ambiguity:
In our first example, the parser could not decide whether local_var was a local variable, or the name of a method—shorthand for self.local_var.
The error message we got didn’t do a great job of explaining this, but it did hint at it with the phrase “variable or method”.
Once the parser has encountered local_var in an unambiguously variable-like context—namely, local_var = "something or other"— it has no problem evaluating the name as the name of a variable.
And, as I’ve claimed, all uninitialized variable evaluate to nil.
So, what appeared to be a difference between local varables and other types of variables is actually just a coincidence of Ruby syntax. Ruby gives us the flexibility to leave the receiver to which we pass a method implicit: if we don’t explicitly identify a reciever, the message is passed to the current object. However, this flexibilty comes at the price of ambiguity; absent additional context, methods invoked on implcitly defined receivers look to the world (and, more importantly, the parser!) just like local variables.
They’re real!
In Ruby, an array can contain itself:
1 2 3 4 5 6 | |
So you want to mess around with a helper method in the console? It’s super simple, as I just learned here from kch. Basically, Rails gets a bit yo dawg and provides a helper for your helpers—called “helper”.
Here’s an example. Suppose you have a helper module like the following:
cars_helper.rb1 2 3 4 5 6 7 8 9 | |
Fire up a Rails console, and to create the helper-helper, all you have to do in include the module:
1 2 3 4 5 | |
I hope this has been helpful. (Sorry, can’t help myself.)
Ok, I’m done.
In my post about the kata gem, I promised to share something I learned from the calculator kata. Here goes.
The calculator kata asks you to construct a Calculator class the instances of which are initialized with comma-delimited strings of integers.
Next you are asked, one by one, to create a series of instance methods—#sum, #prod, #div, #diff—for the class that perform arithmetic operations on the stored integers.
Starting with #sum only, I wrote the class, obviously enough, like this:
1 2 3 4 5 6 7 8 9 10 11 | |
After adding in another instance method, it made sense to move to conversion from string to array into the initialization method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
I went on to add analogous subtraction and division methods, and then I started to get an itch: Could I avoid writing “inject” four times? More importantly, could I find a way that to write this class that reflected the underlying similarity in function shared by these four methods?
On a kata-fuelled lark, I decided to write the code I wished would work, even though I had no reason to think it would. I passed the arithmetic operation symbols into the methods as arguments, and then into the inject blocks:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
To my surprise this actually does work!!
My initial reaction was: Go Ruby! And then: Thank you, kata.
But, finally, in the spirit of the aphorism that “magic is code you don’t understand yet,” I thought: How do these & blocks work, anyway?
More on that in a later post.
A code kata is a small programming challenge on which a developer can practice her craft. Kata have solutions in the sense that they set our requirements that a program can meet or fail to meet. However, it is the process of thinking through the kata—and perhaps implementing it multiple times in different ways—that is intended to provoke learning.
Of course, you can’t learn anything form a kata unless you do the kata. Enter the kata gem by Wes Bailey.
I learned about the gem from a lightning talk Bailey delivered at the inaugural Steel City Ruby Conference in Pittsburgh. (Incidentally, SCRC was my first programming conference, and it was fantastic. My experience there inspired this blog.)
The kata gem reduces the friction between you and actually sitting down to do kata. It accomplishes this by presenting the kata requirements in bite-sized pieces on the command line. The process of working through a kata via the gem resembles the work flow of test-driven development. (To be clear, working with the gem in no way precludes actual TDD.) This is no accident; Bailey’s DSL for authoring kata is modeled after the Rspec testing framework.
Here are the first two steps of the calculator kata, which asks the coder to create a Calculator class, instances of which are initialized with strings of numbers:
Create a calculator that is initialized with a string expression
- detail: The expression is of the form digits separated by commas: "1,2"
- detail: The expression is accessed by a method named expr
- detail: The expression can be reset for evaluation at any time without re-initializing
- example: Calculator.new "1,2"
Add Method
Create an add method that sums the string expression
- detail: The method will return the sum of the digits
- detail: The expression can contain 0, 1 or 2 numbers
- detail: Then empty string will return 0
- example: "" computes to 0
- example: "1" computes to 1
- example: "1,2" computes to 3
…and so on. Yes, things start off simply, but simple problems allow for focus on technique and experimentation. In my next post, I’ll relate something I learned by experimenting with the calculator kata.
I used to be a philosopher. Now I'm a programmer. To my delight, I'm learning new skills and ideas more rapidly now than when I was pursuing a PhD. I love working in a team and solving hard problems. I am fascinated by Internet startups, and I seize every opportunity to learn how different parts of my company work.
I'm a Rails developer working on making Food52.com even more awesome.
I worked on a small Rails development team building tools that help people make decisions based on the facts. My primary focus was the design and implementation of onText, a suite of automatic text generation features (http://webkite.com/ontext/). onText accurately synthesizes large amounts of ever-changing data and is responsive in real time to preferences expressed by the user. This text demonstrably improves user engagement and makes a great variety of relevant content available to search engines.
I worked in a small team to develop strategies for sourcing, organizing and maintaining large amounts of data about products, services, ideas and people for Pikimal.com. I built spreadsheet applications to automate recurring tasks. At the conclusion of the internship I was given the opportunity to transition to the development team and implement these applications in the codebase.
I prepared lectures and led recitations for courses in logic and ethics.