Thursday, June 17, 2010

Build your views before working on the controller


For complex forms you save time by building your view before you write tests and code for the action in the controller. For example take the following view code:


- form_for :ad_request, @ad_request, :url => ad_request_feature_path do |f|
= f.error_messages :class => 'error'
.form
#publication.form-item.first
- f.fields_for :car_selections do |cs|
= cs.label :headline, "Headline:"
= cs.text_field :headline


Unless you bleed rails you probably can't guess what the params hash posted to the controller will look like. Fortunately for lazybones like me you don't have to guess. Simply create the view, run up your app in dev mode, and post this form. Of course you get an error, but if you look in your app logs you are rewarded with a real life example of your params hash, like this:
{"ad_request"=>{"car_selections_attributes"=>{"0"=>{"headline" => "Mini for $15,000 Driveaway", "id"=>"1"}}}
Great. Guess what you should do with that nugget? That's right! Use it as the starting point of your controller test:


it "should save headline" do
car_selection = Factory.create(:car_selection, :id => 1)
ad = Factory.create(:ad_request, :ad_type => 'retail', :car_selections => [car_selection])
post :feature, {"ad_request"=>{"car_selections_attributes"=>{"0"=>{"headline" => "Mini for $15,000 Driveaway", "id"=>"1"}}}
ad.car_selections[0].headline.should == "Mini for $65,000 Driveeaway"
end


This is one of those things that is almost too pedestrian to even talk about, but it can save you time and pain in the long run, especially for the occasional nasty forms with deeply nested objects.

Wednesday, May 19, 2010

Simple Tabbed Navigation in Rails


Let's say I have a webapp that can be broken into 3 broad categories of activity: Lies, Damn Lies, and Statistics. My webapp has a tab for each of these categories. When I am on the page that tells Lies I want the Lies tab brought to the foreground. When I am creating a new Damn Lie I want the Damn Lies tab highlighted, etc. This is basic webapp stuff. In the rails universe many gems have been written to simplify this, but unless you have complex requirements I call YAGNI! I worked out a simple solution for this and thought I would share.

Diving right into the code let's look at the markup that creates the tabs. I keep it in the toplevel application layout, so it appears on all pages of the application:

<% yield :selected_navigation %>
<div id="container">
<div id="tabs">
<ul>
<li class="<%= selected_navigation(:lies) %>">
<%= link_to "Lies", lies_path %>
</li>
<li class="<%= selected_navigation(:damn_lies) %>">
<%= link_to "Damn Lies", damn_lies_path %>
</li>
<li class="<%= selected_navigation(:statistics) %>">
<%= link_to "statistics", statistics_path %>
</li>
<li class="logout">
<%= link_to "Logout", "/logout" %>
</li>
</ul>
</div>
</div>

First, notice the yield for :selected_navigation. Views in the application implement :selected_navigation and use it to set a variable that maps a page to a particular tab. Here is a snippet from a page that maps to the :damn_lies top navigation element:

<% content_for :selected_navigation do%>
<% @selected_navigation = :damn_lies %>
<% end %>

The final piece of the puzzle is the selected_navigation helper that is being called for each li in the layout. It compares the current page's navigation mapping @selected_navigation to the desired tab. If it finds a match the "current" class is added to the tab. And that gives the user a visual cue as to which tab we are currently on. Here is the code for the helper:

def selected_navigation(element)
element == @selected_nav_element ? "current" : ""
end

This is a lightweight solution. I like it because it doesn't require you to put anything in the controller, or to have some annoying configuration file that maps pages or controllers to tabs. So how do you usually do this?

Wednesday, April 21, 2010

If it's soap, why do I feel so dirty?


I have an son 19 months old. He wears white converse lo-tops, each one smaller than a computer mouse. My other baby is a rails app I've just started working on. It is 8 days old today! This little rails app has reached an important milestone. It is live! Deployed! It's like a toddler taking its first steps.

Me: "The internet is a big place baby!"
It: "Gaaaaaa!"
Me: "I don't quite understand."
It: "Gaaa Gaaaa Ga!"
Me: "One second. I'll take a look at the logs... Oh Yuck! Your diaper is full of XML!"
It: *crying*


Integration. Growing pains. You've been there. My little baby integrates with Adobe Indesign CS4 server. And boy, what a piece of junk it is. If you look closely at the words "Indesign Server" you can see that "Server" has been stuck on with a wad of chewing gum and a roll of tape. Integration is done through a little soap interface that doesn't really understand soap. The ruby gem savon couldn't get a message through. I nearly lost my cool. Just as I was about to get out my blowtorch and a troop of monkey patches I had a brainwave. The API only specifies one command, "runScript". Why do I need a soap library for an API with just one command? I don't! I simply created a template from the sample soap request supplied by their instructional PDF. Then I threw in a bit of string interpolation and presto! Soap without all the horrible boiling chemicals, lye and fat. (BTW, Sorry for the lousy baby metaphor. But not for the XML thing. I really feel the same about poopy diapers as I doo about XML.)

Tuesday, April 20, 2010

Engine Yard vs Heroku: Getting Started


Today we evaluated Rails cloud hosting offerings from Heroku and Engine Yard. Each company claims you will have your app up and running in minutes. I thought I would take a moment to share our experiences with each vendor.

Here is the Heroku narrative.
Signup was simple. Just confirm your email address and you are in. Free rails hosting without a bunch of BS. And it is a good service. You can't beat Heroku for that. Deployment is simple if you run a vanilla application, but you can run into all sorts of problems if you don't. Heroku applications run in a sandbox where your filesystem is readonly (except tmp). We ran into 2 problems. First, we are using bundler. Normally you gitignore your .bundler directory in your application, but because of the heroku readonly filesystem you have to commit your .bundler directory so when heroku runs bundle install there is a environment.rb file already in place. Another gotcha is that we use sass, which compiles to css. You have to check in the compiled css files for the same reason. There is a gem called hassle (hilarious) that has been created to get around this problem. Finally, we got the app up and running on Heroku. I still give heroku high marks becuase of the free service and the possibility of a simple deployment. My Heroku pro tip: If you plan to go Heroku, deploy the moment you create the skeleton rails application and make deployment a nightly step in your CI server. That way when you introduce some dependency that Heroku hates, you know immediately.

Now for the Engine Yard narriative. Signup is again pretty easy with EY, but you have to have a credit card to do anything because creating an app instance costs 11 cents an hour. Move along freeloaders. No free rides at Engine Yard! Deployment is very customizeable, yet simple. Give them the URL to yout git repo and click "deploy". EY pulls your app and does the rest. While using bundler at Heroku was major ass pain, with EY it is a big benefit becuase you don't have to manually specify the gems on your server. Simply install the bundler gem. Then create a file called deploy/before_migrate.rb in your application. In that file you can call "bundle install", and you are all done! The beauty of EY is that you can use a fancy web interface to do nearly everything, or you can drop down to SSH and hack around at the command line. So though it looks harder because there are more levers and knobs, in the end deployment at Engine Yard is easier than Heroku because the environment is alot like your development environment. There are no magic readonly filesystem or special remote rake tasks. If I want to see what's up with the app I can just tail a log file or run script/console. Overall high marks for EY's customizeability, and ease of deployment. My EY pro tip: go look at "chef" the deployment tool that EY uses on github. If your app has any custom tasks that you need to run before it starts up you can specify them there.

What about cost?
Heroku offers a free service, which is a totally awesome resource for the Rails community. Hats off to Heroku for that. On the downside, with Heroku everything is an add on. 20$ a month to send emails, 100$ a month for SSL, 200$ a month for a dedicated DB. That adds up! EY's cheapest option runs about 70$ a month. A dedicated DB system costs 170$ a month, but there aren't lots of add on hidden costs. The big kicker is that with Heroku you pay lots of money to run a single application. With EY you pay lots of money and get a server which means you can run as many applications on that one server as you like. I think you get more bang per buck with EY.

I know. Blah blah blah, what is the verdict? Well, sorry to dissappoint, but as usual, it depends. If you want it to be free Heroku is the only game in town. If your application is very, very simple or doesn't have any of these constraints, Heroku is probably the way to go. But, if you are willing to pay for it you get more bang for your buck with EY.

Both companies have great offerings. I'd say use both of them. The great thing about being in the cloud is that you are paying on a hourly or per cpu cycle basis. Just turn the server on when you need it. If you aren't using it, you don't pay.

Monday, April 12, 2010

Rails for Fashionistas


Today somebody asked me if I would use Rails without plugins or gem extensions. Can you believe it? I looked her up and down and gave her the triple snap. Then I asked her If I looked like the kind of programmer that would let my apps go prancing around the inter-tubes naked? Like, even on a bad day I'm going to dress up my application in a few sexy little plugins, not to mention some tastefully chosen gems. At this point she asked me for advice on which plugins and gems to use. Here was my advice:

Wanna wear something classic? Will_paginate is like the little black dress of plugins. It looks good year after year. Want something a bit more risky? Haml and Sass are hot right now, but they'll both probably go the way of the swatch watch. What's out of date? restful_authentication is like soooo rails 1.x. Another thing is that the big fashion houses are always worth watching. 37 Signals? they are like Versace, Gucci and Prada all rolled into one. DHH, OMG, you brought sexy back. Thoughtbot? Yea, they're another one you can count on for high-end ready-to-wear accessories. Like, when I think about factory_girl's Factory.stub method I go out and by my infant son a new fur coat.

So, like, you can tell our conversation was going well, but can you believe it? Some neanderthal wearing a pager interrupted us. He started talking about Struts and some kind of config file generator plugin for eclipse he was working on. Before we could stop him he emailed us the url of his CVS repository. Then he got paged and had to leave. We both looked at each other and laughed until we cried. I mean, please! Don't talk to me about your Java frameworks. I don't shop at Wal-Mart and I sure as hell won't use J-terd. Hey Ricky Martin, 1995 called and they want their animated gifs back!

That's right sweetheart, Rails is all about the bling! Sure, sometimes late at night while github is down and the home shopping network is the only thing on TV I find myself thinking about something Zed Shaw said. Then I pour out some liquor for _why the lucky stiff. I hit rock bottom and imitate Marilyn Monroe making drunk kissy faces to JFK. Camellllotttt! Where have you gone!?! But then @wycats tweets about the Rails 3 beta and I'm like, "Screw it! Rubys are a programmer's best friend!"

Monday, April 5, 2010

Google Custom Search: Cool but Crippled

Wouldn't it be cool if you could jump over Google's fence, steal their magic 'web searchy thingy' and use it for your own insane schemes? Turns out you can. Some time ago Google created a little happy place called Google Custom Search (GCS) where anybody can have fun pointing that magic thingy at whatever they want.

Cool! Anything I want! Lets make a search engine for programmers! We'll only index useful sites about programming. Here is the algorithm:
  1. Create a set of keywords that encompass all possible useful programming topics.
  2. Use the keywords on sites like delicious to get a set of useful urls.
  3. Create a GCS with all the urls
Implementation of that algorithm found here.

That is foolproof. NOT! Google limits you to searching only 5000 sites with GCS. Poop! But wait you say, 5000 seems like alot. Let's see: a quick first attempt at the above algorithm gave me 65 keywords. 10 pages of delicious search results for each keyword gave me 16,000-ish urls. Yipe! I tried running some searches with just 2000 urls and it was kind of sucky.

GCS Fail.

What's the workaround? The only thing I can think of is that maybe 5000 urls is enough for a decent search on one specific topic. Instead of creating one general programming search I could just create a million specific ones on demand. That makes a plain old Google searches sound easy by comparison. GCS is a nice idea, but they've crippled it so there is no possible way it can compete with the standard Google search unless you are working against an extremely focused collection of websites.

Wednesday, February 24, 2010

Vim vs. RubyMine

RubyMine (RM) is my favorite Ruby IDE. Vim is my editor of choice. Which one is best? I'm going to try to find out. Here are the features I will be judging on.
  1. Quickly find files
  2. Keep recently used files at my fingertips
  3. Autocomplete long variable and method names
  4. Do common VCS commands like diff and revert
  5. Supply a tree view of the project directories
  6. Jump to method definitions
  7. Text search
  8. Run Tests
  9. Debug
  10. Performance
  11. Cost
  12. Learning Curve
On its own Vim can't do many of these things, but thanks to some powerful plugins this will be interesting. You can find my entire .vim directory and my .vimrc on github

Things to note
  • I'm using the rails codebase to illustrate my examples.
  • I'm omitting installation discussion and ask you to refer to github if you need details on how things are configured.
  • My plugins have keymappings that are setup to be reminiscent of RM/IntelliJ
  • vividchalk is simply the best color scheme with desert256 a close second
Quickly find files

In vim I use the fuzzyfinder plugin for this. In RM there is "Go To File" (ctrl-shift-n). Both of these pretty much just work, each one has nuances that skew things in their own favor so I'm calling this one a draw. Here is a screenshot of me finding base.rb in active_record with fuzzyfinder.




Keep recently used files at my fingertips


In vim I use the MRU plugin for this. It shows you a list of most recently used files and lets you quickly jump to one. I map this plugin to ctrl-e. RM has the same functionality. Once again a tie.

Autocomplete long variable and method names


In Vim I use Supertab for this and it is an amazing tool that nearly always offers good completions. By contrast RM ctrl-space often times offers no suggestions. Here is an example. Opening up active_record/base.rb to the respond_to? method in each app, when I begin to type DynamicFinderMatch, "Dyn..." and ctrl-space in RubyMine I get no suggestions. With supertab I get 3 suggestions: Dynamic, DynamicFinderMatch and DynamicScopeMatch. Below are some screenshots of Vim and Rubymine tab completion in action. Viva Supertab!





Do common VCS commands like diff and revert

In Vim I use the vcscommand plugin for this. Mostly I do things like diff my working copy against the repository, revert files to pristine condition or look through the VCS logs. vcscommand does all these well, plus it supports more VCS systems including git, hg, and bzr, but Rubymine really shines because of it's excellent visual diff/merge tool. Winner RM. Here is a screenshot of vcscommand showing base.rb's commit history.



Supply a tree view of the project directories

In Vim I use the NERD tree plugin for this. I find nerd tree to be just as good as the project view in RubyMine, though it is more difficult to use because I can't be bothered to remember all the nifty commands and shortcuts for doing things to the filesystem via the NERD tree. Edge RM.



Take me to method definitions

In Vim I use exuberant ctags for this. This is a standard vim feature, not a plugin. Ctags builds an index of your code that vim can use to navigate files. It works ok for standard ruby, but with lots of metaprogramming (rails anyone?) it really sucks. RM command+click offers much better support for this. Caveat, I think rails.vim helps with this and lets you jump to related files (related controllers and views or models and migrations), but for jump to method and variable definitions RM is king.

Text search

You can do inline grepping in vim with grep.vim, but I usually just grep from the command line. Once again this is an area where RubyMine has the edge. RM's collapsable search results that you can click through are powerful.

Run Tests

You can invoke tests from either one (though I don't have it setup in vim because I just use autospec which constantly runs my tests in the background). Still RM has pretty green bars and I'm a sucker for that. Edge RM.

Debugging

Vim has a Ruby Debugger called vim-ruby-debugger. Doing TDD I rarely find myself in need of a debugger so I haven't played with it. From the description and screenshots it looks as good as the RubyMine offering, so I'll give it the benefit of the doubt here and say tie or even who cares.

Performance

RubyMine gobbles up memory. 30 minutes of editing the rails codebase and it is using 703 MB of RAM! Vim is using 11 MB of RAM. RubyMine is slow to startup, and has occasional performance hiccups too. Vim wins.

Cost


RubyMine costs 100$ for a commercial license. Vim is open source. Good Karma. Vim wins.

Learning Curve


Vim requires you to know all sorts of arcane commands and to be really productive you need lots of plugins. So the learning curve is quite steep. RM has a much more intuitive interface and is ready to go out of the box. Edge RM

Conclusion

Ok, RM wins but with an asterisk. RM has the advantage of being completely focused on Ruby, HTML and JavaScript. It does one thing and does it well. Vim on the other hand will happily highlight and edit nearly every programming language or filetype known to man (or machine). 20 years down the road when Rails is a dinosaur, the new COBOL, and you have moved on to working in language X, your RubyMine skills will be irrelevant while the Vim you picked up might still be serving you well... But yea, most people will probably be slightly more productive in RubyMine. So what do you do? I don't know, so I say just learn them both and use them both.