giant robots smashing into other giant robots

Written by thoughtbot

gabebw

Nesting content_tag in Rails 3

Nesting content_tag in Rails 3 is counter-intuitive. This looks like it will work:


content_tag(:ul) do
  collection.map do |item|
    content_tag(:li, item.title)
  end
end

But it doesn’t. You get an empty list: <ul></ul>. What’s the deal? To fix it, use the concat method:


content_tag(:ul) do
  collection.map do |item|
    concat(content_tag(:li, item.title))
  end
end

dancroak

irb & script/console tips

Let’s get interactive. You can learn a lot about your application from irb & by extension, script/console.

Wirble: colors

Color matters. You’re picky about your text editor syntax highlighting and maybe you use the excellent redgreen gem for colors in your test backtraces. Gotta have it in irb, too.

First, install Wirble:

sudo gem install wirble

Then, in your ~/.irbrc:

require 'rubygems'
require 'wirble'
Wirble.init
Wirble.colorize

Wirble: history

Wirble has an added bonus: history.

irb(main):001:0> history = "History?"
=> "History?"
irb(main):002:0> exit

Without Wirble, if you drop back into irb, you can’t arrow up to your previous commands. With Wirble, you can.

Wirble: auto-completion

As if that’s not enough, Wirble gives you auto-completion, too. In irb:

>> un_momento = "Spanish for like, 'hold the phone!'"
=> "Spanish for like, 'hold the phone!'"

Type, “un”, then tab:

>> un
un_momento   undef        unless       untaint      untrace_var  until

Local methods

Stick this in your ~/.irbrc:

# Easily print methods local to an object's class
class Object
  def local_methods
    (methods - Object.instance_methods).sort
  end
end

Use the #local_methods method like this:

>> class BasketballPlayer
>>   attr_accessor :name
>> 
?>   def champion?
>>     name == "Kevin Garnett"
>>   end
>> end
=> nil
>> kevin_garnett = BasketballPlayer.new
=> #<BasketballPlayer:0x11988f8>
>> kevin_garnett.name = "Kevin Garnett"
=> "Kevin Garnett"
>> kevin_garnett.champion?
=> true
>> kevin_garnett.local_methods
=> ["champion?", "name", "name="]

Aliases

Don’t forget you can alias in irb. The only one I have is:

alias q exit

It makes irb feel more Vim-ish.

Create test fixtures for a third party service

Your app uses the Flickr API. You want your test suite to use legitimate data but not hit the service.

Given the actual call to the service is:

FlickrClient.search("Bruce Springsteen")

Run the query in script/console and convert the data into yaml:

yaml = FlickrClient.search("Bruce Springsteen").to_yaml

Then use your old Ruby friend, File.open with the write option (“w”) to dump it to a file:

File.open("test/fixtures/flickr/springsteen.yml", "w") { |file| file << yaml }

Add this to your test_helper.rb:

def load_yaml_fixture(path)
  absolute_path = File.join(RAILS_ROOT, "test", "fixtures", path)
  YAML::load_file absolute_path
end

Voila, when you need to mock out calls to the third party service, you can now use this in your test code:

load_yaml_fixture("springsteen.yml")

This pattern is repeatable for any third party service. Just replace the actual call with whatever you’re working on, and name the fixture something intention-revealing.

Print SQL to standard out

Oftentimes script/console is used for debugging, and what better way to do that than to get the SQL generated by each method call. Stick this in your ~/.irbrc:
# Log to STDOUT if in Rails
 if ENV.include?('RAILS_ENV') && !Object.const_defined?('RAILS_DEFAULT_LOGGER')
   require 'logger'
   RAILS_DEFAULT_LOGGER = Logger.new(STDOUT)
 end

This gets you:

>> videos = Video.limited(3)
  Video Load (0.4ms)   SELECT * FROM `videos` LIMIT 3
=> [#<Video id: 1, ...>]

Without the ~/.irbrc love, you’d be missing:

Video Load (0.4ms)   SELECT * FROM `videos` LIMIT 3

pp

After you’ve required rubygems for Wirble, require pretty print, too:

require 'pp'

This is just a nice way to have better formatting at your fingertips. It’s especially helpful when dealing with an Array of ActiveRecord objects:

>> pp videos
[#<Video id: 1, youtube_id: "TcMklv40YMY", name: "Merb, Rubinius and the Engine Yard Stack", upload_time: nil, view_count: 6171, description: "Google Tech Talks\nOctober 20, 2008\n\nABSTRACT\n\nIn th...", created_at: "2008-12-21 00:32:33", updated_at: "2008-12-21 00:32:33">,
 #<Video id: 2, youtube_id: "JySmT-dGOj0", name: "MERB SPORTS Team-Vorstellung 2008", upload_time: nil, view_count: 495, description: "MERB SPORTS stellt sich für die VDRM-Saison 2008 v...", created_at: "2008-12-21 00:32:33", updated_at: "2008-12-21 00:32:33">,
 #<Video id: 3, youtube_id: "6bc-FNNWIsM", name: "Merb && Moi", upload_time: nil, view_count: 58, description: "Amusing yes?", created_at: "2008-12-21 00:32:33", updated_at: "2008-12-21 00:32:33">]

lolconomy

thoughtbot is filled with vim and vigor

Slowly over the past year thoughtbot has turned from an all-TextMate (and one Emacs) group into a mostly-vim group. Here are some tips, tricks, and scripts we’ve mastered along the way:

From Mike Burns

I’ve been a vim user for six years, and brought the vim fever to thoughtbot. I tend to rely more on the built-in commands than on scripts and plugins. My favorite commands start with f and t (think first and ‘till - see :help f or :help t):

Finding characters with f and t rocks. For example, if you’re at the beginning of:

{:foo => 1, :bar => 3, :baz => 8, :barney => -1}

And you want to put a newline after the comma, you can do:

f,a<ENTER>

To jump to the next comma and repeat the prior action you can do:

;.

This is because ; repeats the prior f or t, and . repeats the prior modification.

If you have to do this a lot in a row, you could make a macro from it:

qa0f,a<ENTER><ESC>q

This sets the macro named ‘a’ as: go to the beginning of the line, find the first comma, and append a newline after it. You can then repeat this macro with @a and repeat that macro (the one you just did) with @@.

You can also use t and f as a motion for, say, c and d. Like if you’re at the beginning of:

<img src="/images/michaelphelpssupersaiyan.gif" />

And you need to change the image source to “/images/giant_french_spider.jpg”. It goes like this:

2f/ ct"giant_french_spider.jpg<ESC>

The 2 in front of f finds the second /; the space immediately after moves to the next character (could also use l (lowercase L) instead). Then change the text up to (but not including) the doublequote with ct"; type the text and hit escape to get back to command mode.

From Jason Morrison

Three of my favorite things in Vim are the rails.vim plugin, the ack.vim plugin, and visual block mode.

The rails.vim plugin does an excellent job of syntax highlighting, navigating from one file to another (type :help :RT for a description of how to quickly jump between e.g. models and tests or a controller action and its view), and a slew of other things.

The Ack plugin for Vim nicely integrates Ack search results into a new buffer.

Finally, visual block mode, a killer feature available in several editors, comes in handy when changing swaths of similar code. Let’s say you start with this:

{
  :first_name    => (primary_contact && primary_contact.first_name),
  :last_name     => (primary_contact && primary_contact.last_name),
  :organization  => (primary_contact && primary_contact.company)
}

and then you:

  1. Place the cursor after the first “primary_contact”
  2. Type control-v to enter visual block mode
  3. Type f. to move onto the first period
  4. Type jj to move down twice
  5. Type c to change the highlighted text
  6. Type an underscore, and hit escape to apply the change to all selected lines.

then you end up with:

{
  :first_name    => (primary_contact_first_name),
  :last_name     => (primary_contact_last_name),
  :organization  => (primary_contact_company)
}

Often this can be done with a search/replace, but this is the technique I usually favor due to its brevity.

From Chad Pytel

vim was my first programming text editor, and its been fun to come back to it after all this time. It fits like an old glove.

I haven’t gotten used to visual editing mode yet, so I tend to use line numbers to quickly do things. for example, to move lines 40 through 50 to line 30, you can do:

40,50m30

Many of the commands you’d use with visual mode, work with line numbers too, for example:

35,70=
14,16y
16,20d

From Jon Yurek

Getting around in vim is way quicker than just holding down the arrow keys. If you’re checking a bit of code and moving between it and somewhere else, you should set a mark. m<letter> sets a mark, which you can jump to with '<letter>. Likewise, jumping to a specific line is as simple as :<line-number>. Got a failing test on line 146? :146 and you’re there. So you can set a mark for the line you’re on with ma, jump to line 20 with :20, fix your typo, then jump back with 'a, and you don’t have to remember exactly what line you’re on.

Thing is, when you do that, you may find your cursor is at the bottom of the screen, making further code hard to read. Fix that with z., which will zip the line the cursor is on to the middle of the window. You can also snap it to the top (z<ENTER>) or bottom (z-) just as easily.

When you cut a line with d (or yank it with y), the text you paste goes into a register. You can control the register it goes into by hitting "<letter> first. For example, "gyy will copy the current line into the g buffer. You can paste this text back by specifying the register before your p command: "gp.

From Dan Croak

I’m a casual vim user, mostly when pairing with Joe. My favorite commands are basic, but nice:

:AV

Say I’m in app/models/user.rb. This opens the Alternate file (unit test) in a Vertical window split next to the model.

gf

From Tim Pope’s rails.vim:. When I put my cursor over a piece of text and type gf in a Rails app, I go to the file I’d expect. It works for partials, requires, and more.

My configuration comes directly from Joe’s dotfiles.