posts by date

04/2008
Testing block helpers with Rspec

One of the many great things about Rspec is that it allows you to test helper methods. Helpers can be complex at times. And when it matters, they definitely need some testing love.

An example of a typical helper may be something like:

def h1(text)
  "<h1 class='heading'>#{text}</h1>"
end

Then you can do <%=h1 'Text Here' -%> in your views. That’s trivial to test, so I won’t go into that. The tricky tests (I think) deal with block helpers. Block helpers are extremely useful and can improve the readability of what’s going on in your view(s). Probably the most useful case is when you have <% if current_user.admin? %> scattered all over the place. Wouldn’t it be better (and DRYer) to wrap that “admin condition” up in one place?

def content_for_admin(&block)
  yield if current_user.admin?
end

Pretty simple. But, how would you test that? Initially, I had somewhat of a hard time writing tests to see if the block was actually yielded or not. Here’s what I do now, but I’m open to (and seeking more) alternatives. Using the content_for_admin helper as the guinea pig:

describe ApplicationHelper do
  attr_accessor :_erbout
  fixtures :users

  before(:each) do
    self._erbout = ''
    @block = "This is the block content"
    @current_user = users(:admin)
  end

  # current_user.admin? # => true
  it "should yield block for an admin" do
    should_receive(:current_user).and_return(@current_user)
    @current_user.should_receive(:admin?).and_return(true)

    html = content_for_admin do
      self._erbout << "<div>#{@block}</div>"
    end
    html.should have_tag('div', @block)
  end

  # current_user.admin? # => false
  it "should not yield block for a non-admin" do
    should_receive(:current_user).and_return(@current_user)
    @current_user.should_receive(:admin?).and_return(false)

    html = content_for_admin do
      self._erbout << "<div>#{@block}</div>"
    end
    html.should_not have_tag('div', @block)
  end
end

Another, similar, approach is to use eval_erb, which let’s you actually write out the ERB as a string (or heredoc) and evaluate the output. I think that’s a little messy, but then again, I’ve never actually tried it.

But other than that, this is the only way I know to test the yielded output of a block helper with Rspec. Do you know of a better way? Or at least, a different way?

Navigation Helper on GitHub

For those who are interested, I’ve moved my navigation helper Rails plugin over to GitHub.

http://github.com/rpheath/navigation_helper/tree/master

You can follow the changes there if you’d like. To install (from your project root):

git clone git://github.com/rpheath/navigation_helper.git vendor/plugins/navigation_helper

I doubt I’ll be pushing changes to the subversion repo anymore, so use the above method if you want the latest and greatest.

Flickr Developer Site

Flickr launched a developer site recently (code.flickr). Dev sites intrigue me, especially those belonging to well-known companies. And for some reason, statements like this always seem to draw me in:

In the last week we deployed new code to Flickr 50 times, including 546 changes by 16 people. We issued over 2,000 new API keys, and third party developers made an average of 704 API calls per second, across 109 public API methods. We added 1 new API method, and updated 7 others. There are approximately 10,000 lines of open source code in our public subversion repository.

Sheesh, 704 API calls per second!? To interface with an API requires a slight bit of knowledge (and actual skill to do properly); I mean, it’s not something cousin Elroy could just “throw together” real quick. So to think there are that many people making that many requests per second is kind of crazy.

You can find running totals for those types of stats at the bottom of the main code.flickr page. Pretty cool.

Git and GitHub: Wow.

I’m just getting my feet wet with Git, but it’s starting to amaze me more and more. At first, I thought, “Yeah, Git sounds pretty cool, but I can’t see learning a new VCS. I know SVN and it’s fine.” Wrong. Wrong. Wrong. Learn it and LOVE it.

Git is Distributed

Git is a distributed VCS as opposed to a centralized one. And what exactly does that mean? It means it’s faster, safer, and far better for collaboration.

It’s faster because all changes are committed locally, then pushed to the server at once. So there’s no need to have access to a SVN server at all times. You can imagine the performance gains you get from this. And subconsciously, having those somewhat expensive operations become nearly instantaneous makes you think/work a different way. A better way.

It’s safer because for each user who works with the code, there are multiple versions of the repository (each user essentially has his/her own copy (or branch) of the code). With a centralized VCS (i.e. Subversion), if the server hosting the single repository were to die, you had better hope there’s a backup somewhere. Otherwise, all is lost.

For a lot of (maybe most?) people using Git, collaboration is where its distributed nature shines. You can commit to your hearts content without disturbing anyone else. There aren’t any permissions issues because it’s all local to your machine. You can fork any project, change it however you see fit, then others can pull from your forked repo and merge with their own. And then that person can modify your already modified code, improve it, then tell their friends and they can fork the doubly modified repo, and, well, you see how this “network effect” can make projects blossom. This is entirely different from requiring commit rights to the one-and-only, centralized, repository. It’s a hard model to grasp at first, but it’s incredibly cool once you do.

Branching and Merging

Aside from being distributed, another thing that attracts me to Git is how branches work. Git encourages you to work from a branch, which is great because in concept a branch is ideal for experimenting with a feature. They remove the worry of “screwing up” existing code. And in Git, each “checkout” is actually a branch of the main repo, anyway. So naturally, merging branches works much better than that of many other systems. I think the creator of Git himself said he merges (on a 22,000 file project—the Linux Kernel) on average 4.5 times per day. That’s a lot.

Another cool thing, if you’ve branched (or forked) a repo that you don’t own, you can tell the owner about it (send a pull request) and he/she can merge it with the master branch if it’s worthy. And even if it’s not worthy, someone else might have the same need as you, and fork your forked repo instead of the master.

Learn it. Love it.

At first, I thought having to explicitly add files to the “staging area” was tedious and annoying. Now I think it’s brilliant. It provides more control. I add the files content of my choosing to the index for the next commit, so the commit messages are always meaningful, and it doesn’t hold back my work flow at all. Which brings me to another wonderful thing about Git: it tracks content not files. With Subversion, you know those .svn folders littered all throughout every folder in your entire project? Git just has one .git folder in the project root. And better yet, you remember having to tell Subversion you were deleting/moving each and every file (svn mv and svn rm)? No more. Git doesn’t care what you do. It’s smart enough to figure it out when the time comes.

Not sold yet? A great article called, The Thing About Git shows some advanced usage of Git, and in particular, the infamous Tangled Working Copy Problem that every developer using source control has dealt with. Go read it if you haven’t already.

So, I agree with everyone else who already realizes Git is awesome, because, well, Git is awesome.

GitHub

And then there’s GitHub, a place to host your Git repositories. It was built by the guys at err free, so you know it’s slick. GitHub really wraps a nice interface around the inherent benefits of Git itself. It’s said to be a “social network for programmers”.

They just launched publicly the other day. (I got in early as one of the beta users) With the launch, they’ve released two new features: commit comments and the network graph visualizer. Both incredibly useful and impressive, as expected.

The commit comments are similar to those of the Django Book. But since we’re dealing with commits, the comments can be per line of source code or per commit. Very cool.

And the network graph visualizer is cool because it exposes how Git actually works. If you read the post about the network visualizer, you’ll get to a part that says “think of this as a to-do list,” which at first, I didn’t get. Now I do. As I said earlier, with Git, you can fork a repository and make your own changes separate of the master branch. That’s just awesome in itself, and what’s even cooler is you can choose to pull changes from a forked repo back into yours. What the network graph does is show you what things others have been up to in relation to your code. But it only shows code that you have not yet pulled into your repo. Once (if) you do, it goes away, hence the comparison to a to-do list. And try clicking a user to the left, they become the root and the graph changes. Nice.

Conclusion

Overall I’ve got a long way to go with Git, but it’s exciting to keep learning it. Even as a beginner, I’m finding that I’m able to do more with Git than if I were using a centralized VCS.

Flickr Video

Several months ago I posted about Flickr Video. For the most part, I was in favor of neglecting it. My position hasn’t changed, really, but I feel compelled to give kudos on their implementation.

I’m relatively satisfied about the way Yahoo has introduced this (inevitable) feature. I personally like how they’re intertwined with the photos. I didn’t really expect that. One might not even know video is supported by Flickr until it’s time to upload. Even the URL for a video is of the form ”/photos/[user]/[id]”.

I think limiting the length of a video to a max of 90 seconds was a good move, too. I know that won’t last, but the initial 90 second limit may weed out those who were wanting to use Flickr as a YouTube clone.

Considering the impossible reality that Flickr would remain 100% based on photos, overall, I think video couldn’t have been introduced any better. That’s not to say I’ll ever upload a video, but it is what it is. And considering the millions and millions of Flickr users, all with different concerns about video, I think they’ve met both sides of the argument on common ground.

Is Time Machine worth it?

I bought the iMac in December of 2007. I couldn’t believe how fast and responsive everything was. Especially compared to my old PC. But things aren’t quite as ripe as they once were.

One of the many cool things about the Mac (er, Leopard) is Time Machine. I have a 500GB external drive (primarily for photos) that I partitioned. I’m now using 300GB for Time Machine and 200GB for photos. It’s pretty cool to know that everything is backed up automatically, all the time.

But here’s the kicker, I can’t remember ever needing a backup. Of anything. And the truth is, I’m starting to notice a slight lag in load times and such, and it’s always when I hear the external drive boot up to process the automatic back ups. It seems like, as the back ups increase, the load times get slower. I’m starting to wonder if it’s worth it. I can’t believe how spoiled I am, because if you’d use it for a day and I pointed out the times when I think it’s “lagging”, you’d probably think I was crazy. But in this day and age, every (milli)second counts.

What would you do? The right answer is probably to keep the backups. But I’m on the edge, here. If I notice any more decline in performance, Time Machine is history (pardon the pun).

Afraid of Ruby 1.9

Ignore this post. I bit on an April fools joke that I read on April 6th. Way to pay attention. Anyway, the only valid point here is related to send, but that’s hardly a big deal.

I’ve come to absolutely love Ruby. I just love the syntax. But lately I’ve been reading a bit about Ruby 1.9, and it makes me a little worried about Ruby’s (and Rails’) future.

Here are a few of the methods being removed in Ruby 1.9:

  • method_missing—Yep, that’s right. No more method_missing. This is disastrous for Rails, as well as a good chunk of meta-programming practices. The argument is the same as it always is, too much abuse. But the dynamism of things like method_missing is what makes Ruby so exciting (and challenging), IMHO.
  • const_missing—Maybe not quite as important, but const_missing is getting removed for the same reason: too much abuse. I’ll admit, I’ve not used this one too much, but I’ve read about a few clever ways people are using it (unicode-based character escapes, for example).
  • send—And finally, send will no longer be available in Ruby 1.9. While there are more important things to worry about (see both bullets above), this is still something to deal with. I’m using send all over the place in all of my projects. The AR::Base.send(:include, RPH::Module) pattern is a commonality that can be found in most plugins. I believe there’s a drop-in replacement for send (I can’t remember what it is), so a quick fix would be to create an alias method (send) for the newly named version.

They say it takes 10 years or so to learn a programming language. Applying that logic to Ruby, I’m only 20% of the way there. So maybe these changes won’t hurt Ruby. Maybe they’ll be better for the language. I don’t really know. I’m a far cry from a language designer. But man, I’m having a rough time finding the positive with getting rid of method_missing and const_missing. Only time will tell, I suppose.

Maybe it’s time to see what advances PHP has made? Just kidding. Ruby had me at “Hello World”.

2008 by Ryan Heath | Get In Touch

flickr

DesolateInfinityLooking upDazedBlurred