<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><description>This is the company weblog of thoughtbot, a web development business based in Boston, MA.</description><title>GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS</title><generator>Tumblr (3.0; @thoughtbot-giantrobots)</generator><link>http://robots.thoughtbot.com/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/GiantRobotsSmashingIntoOtherGiantRobots" /><feedburner:info uri="giantrobotssmashingintoothergiantrobots" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://tumblr.superfeedr.com/" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><item><title>How grep got its name</title><description>&lt;p&gt;thoughtbot is pairing up with &lt;a href="http://www.codeulatescreencasts.com/"&gt;Ben Orenstein&lt;/a&gt; to present &lt;a href="https://training.thoughtbot.com/courses/14-vim-for-rubyists/registrations/new"&gt;a Vim course&lt;/a&gt;, this time at &lt;a href="http://workbarboston.com/"&gt;WorkBar&lt;/a&gt;. As part of this collaboration &lt;strong&gt;WorkBar is offering $50 off your first month’s membership&lt;/strong&gt; if you &lt;a href="https://training.thoughtbot.com/courses/14-vim-for-rubyists/registrations/new"&gt;register for the Vim course&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One thing you will discover at this course is the history of the command `grep’. This all starts back with `ed’, the original unix editor. ed was a command-line editor that worked identically to the colon-commands in vi and vim—in fact, you can press &lt;code&gt;Q&lt;/code&gt; to get into ed mode (then type &lt;code&gt;vi&lt;/code&gt; to get back into vim). From the ed editor you can issue common line-oriented commands like s, d, y, and so on:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
:%s/rdoc/docr/g
:/include/d
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src="http://cache.deadspin.com/images/2006/05/mr.Ed.jpg" alt="Mr. Ed"/&gt;&lt;/p&gt;
&lt;p&gt;If you’re following along at home you may wonder “how can I see the contents of this file?” Well if you just want to see every line you can use &lt;code&gt;%p&lt;/code&gt; (&lt;code&gt;%&lt;/code&gt; is “the whole file”, and &lt;code&gt;p&lt;/code&gt; is “print to screen”), though it’s more likely that you want to see a small series of lines. &lt;code&gt;10,20p&lt;/code&gt; will show you lines 10 through 20, but maybe it makes more sense to see all lines matching a regular expression.&lt;/p&gt;

&lt;p style="clear:both"&gt;From ed, to see all lines matching “include”, use &lt;code&gt;g/include/p&lt;/code&gt;. To see all lines matching “docr” use &lt;code&gt;g/docr/p&lt;/code&gt;. In general, to see &lt;strong&gt;all lines matching the regular expression “re”&lt;/strong&gt;, use &lt;code&gt;g/re/p&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;… And that’s how grep got its name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://training.thoughtbot.com/courses/14-vim-for-rubyists/registrations/new"&gt;Sign up &lt;strong&gt;now&lt;/strong&gt;&lt;/a&gt; for the Vim course at WorkBar with Ben Orenstein on September 1st from 5PM to 9PM.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/8jiR1tkrURc/871533965</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/871533965</guid><pubDate>Wed, 28 Jul 2010 13:58:00 -0400</pubDate><category>vim</category><category>editor</category><category>course</category><category>training</category><category>developer</category><category>workbar</category><feedburner:origLink>http://robots.thoughtbot.com/post/871533965</feedburner:origLink></item><item><title>Rock 'Em Sock 'Em Robots</title><description>&lt;p&gt;&lt;a href="http://nodeknockout.com/"&gt;Node.js Knockout&lt;/a&gt; is a programming competition, similar to the &lt;a href="http://blog.railsrumble.com"&gt;Rails Rumble&lt;/a&gt;, focused on the increasingly popular &lt;a href="http://nodejs.org"&gt;node.js&lt;/a&gt;. As a company and individuals we’ve been participating in and &lt;a href="http://robots.thoughtbot.com/post/159807934/lets-get-ready-to-rumble"&gt;sponsoring&lt;/a&gt; the Rumble from the beginning. And we’re happy to announce we’re also sponsoring and participating in the Knockout.&lt;/p&gt;

&lt;p&gt;Introducing below, from Lenexa, KS, the not-made-for-actual-boxing, image-not-representative-of-actual-prize, zero-time champion of the world:&lt;/p&gt;

&lt;div style="margin: 16px 0; text-align: center; overflow: hidden;"&gt;
  &lt;img src="http://ui.thoughtbot.com/assets/node-knockout.png" style="float: left;"/&gt;
&lt;/div&gt;

&lt;p&gt;Let us know what you plan on building in the comments. See you in the ring.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/SaId7rGv7tI/816267526</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/816267526</guid><pubDate>Mon, 26 Jul 2010 15:30:00 -0400</pubDate><feedburner:origLink>http://robots.thoughtbot.com/post/816267526</feedburner:origLink></item><item><title>Flutie</title><description>&lt;h2&gt;Background&lt;/h2&gt;

&lt;p&gt;When we start on new client projects or internal apps, we don’t always start the HTML/CSS buildout the same way.  Sometimes a client has sketches; sometimes wireframes; sometimes they have a brand/identity in place already - there’s a big variety in what materials they come to us with.  Likewise, when we start our design process, we don’t always use the same exact things we did the last time.  Part of this is a result of wanting to constantly experiment and make each time better than the last by learning - and part of it is just the unique style of each designer and their thought process.&lt;/p&gt;

&lt;p&gt;Regardless of how we got there though, one major pain point was always in the first few days of HTML/CSS building.  Would we use a css “framework”?  Which one?  Should we put a “reset” in place but no framework?  Should we start with literally nothing and let the site dictate as we go?  Should we start with specific CSS rules and stay narrow, or start with very general CSS rules and assume we’ll have re-use down the road?&lt;/p&gt;

&lt;p&gt;Depending on the team we had working on an application, the answers to these questions were always different.&lt;/p&gt;

&lt;center&gt;
&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/q3ykWbu2Gl0&amp;hl=en_US&amp;fs=1"&gt;
&lt;param name="allowFullScreen" value="true"&gt;
&lt;param name="allowscriptaccess" value="always"&gt;
&lt;embed src="http://www.youtube.com/v/q3ykWbu2Gl0&amp;hl=en_US&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/center&gt;

&lt;h2&gt;Goals&lt;/h2&gt;

&lt;p&gt;We decided that we &lt;strong&gt;did not want to build a new CSS framework&lt;/strong&gt;, but that regardless of any particular approach, we wanted to have these things on each project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A consistent set of CSS styles that every project could start with&lt;/li&gt;
&lt;li&gt;A consistent internal mindset about “start general; then get specific”&lt;/li&gt;
&lt;li&gt;The ability for &lt;em&gt;developers&lt;/em&gt; to create “normal html” and not get burned by some weird CSS float rule to get unexpected results before putting something in front of a client.&lt;/li&gt;
&lt;li&gt;The ability to show designers and developers (and maybe clients) a “style guide” type of page which would show how elements would be displayed unless they were overridden.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One thing maybe worth noting is that we put the entire HTML/CSS skillset into the “designer” bucket at thoughtbot.  We don’t have a “front end developer” position to do HTML/CSS/JS exclusively.  We attempt to hire developers with experience and comfort working with front end technologies, but we primarily consider it a design responsibility to get HTML and CSS work done correctly.  Even with our growing design team, design time is usually at a premium and we want to grease the wheels as much as possible to maximize efficiency.&lt;/p&gt;

&lt;h2&gt;Features&lt;/h2&gt;

&lt;p&gt;To that end, we created &lt;a href="http://rubygems.org/gems/flutie"&gt;flutie&lt;/a&gt;.  Flutie is a Rails 3 Engine, distributed as a gem.  Note that this is &lt;em&gt;NOT&lt;/em&gt; a css framework or grid system.  It is very opinionated about what basic type size, form styles, list/table style and so on should be — but it is very unopinionated about how you go about creating an overall site layout, how you make grids, how you position things, etc.  There are dozens of other tools for those purposes.  This is really a “how can I start with something that doesn’t look awful” tool.  We want to ensure that when a developer with no specific CSS or design knowledge creates some HTML in an application, they produce something that we’re not embarrassed about.&lt;/p&gt;

&lt;p&gt;Flutie provides…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A collection of stylesheets which we believe are a reasonable starting point for general layout and relative size.&lt;/li&gt;
&lt;li&gt;Pretty basic form styles, and styles for the rails flash.&lt;/li&gt;
&lt;li&gt;A page at the /styleguides URL in development mode to view this default state - or to view all the styles within the application layout.  We render within your own layout first, and you can click “default layout” to see flutie by itself.&lt;/li&gt;
&lt;li&gt;The ability for plugins and the main application to insert partials into the styleguide, to view sample styling.&lt;/li&gt;
&lt;li&gt;CSS which is generally simple to override.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also discovered a rails feature that we decided to take advantage of.  You can “register” symbols which point to arrays and will be expanded when using stylesheet_link_tag.  For example, this will expand to include the 7 stylesheets in flutie alongside the “admin” stylesheet, and cache them all together.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;%= stylesheet_link_tag :flutie, ‘admin’, :cache =&gt; true %&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Install&lt;/h2&gt;

&lt;p&gt;To get flutie in place in a rails3 app, just add it to your Gemfile…&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem 'flutie',           '1.0.3'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For rails 2.x apps, you can pull from the rails2 git branch…&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;script/plugin install git://github.com/thoughtbot/flutie.git -r rails2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once installed, you should run a setup rake task&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rake flutie:install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…which will copy some stylesheets into the public directory of the application.&lt;/p&gt;

&lt;p&gt;After that, put the :flutie symbol somewhere in your stylesheet_link_tag or equivalent area.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;%= stylesheet_link_tag :flutie, 'screen', :cache =&gt; true %&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After that, start your server, browse to /styleguides, and check it out.&lt;/p&gt;

&lt;h2&gt;What does this look like?&lt;/h2&gt;

&lt;p&gt;Click through for full screenshot…&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ui.thoughtbot.com/assets/flutie-default.png"&gt;&lt;img class="sink" src="http://ui.thoughtbot.com/assets/flutie-thumb.png" alt=""/&gt;&lt;/a&gt;&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/y9xnMuFZRZ4/762048192</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/762048192</guid><pubDate>Mon, 26 Jul 2010 10:15:00 -0400</pubDate><feedburner:origLink>http://robots.thoughtbot.com/post/762048192</feedburner:origLink></item><item><title>What To Do When You Don't Know What To Do</title><description>&lt;p&gt;Sometimes, test driven development is really annoying, and the abundance of untested applications out there suggests that I am not the first person to have had this thought.&lt;/p&gt;



&lt;p&gt;The thing is, there are limitations to test driven development.  The workflow of test development essentially goes like this:&lt;/p&gt;



&lt;ol&gt;
&lt;li&gt;Create a user story that encapsulates a chunk of functionality of the application&lt;/li&gt;&#xD;
&lt;li&gt;Write tests for this story (which should fail before you have implemented anything)&lt;/li&gt;&#xD;
&lt;li&gt;Write the code to make the tests pass&lt;/li&gt;&#xD;
&lt;/ol&gt;
&lt;p&gt;What is missing from this flow, however, is a period of time to consider the overall design of the code in the application.  If you’re not careful, your program can end up like an old school map of Africa - the small details are right, but the overall structure is off.&lt;/p&gt;



&lt;div style="text-align: center;"&gt;&lt;img src="http://ui.thoughtbot.com/assets/africa_2.jpg"/&gt;&lt;/div&gt;

&lt;p&gt;Test Driven Development rests on the assumption that you basically know the optimal way to make your tests pass in advance.  If you’ve written several similar apps, you probably do know how to fill in your tests.  However, if you’re new to programming, or if you’re creating a unique program, you may not.&lt;/p&gt;



&lt;p&gt;Recently, my coworker Jason and I encountered this problem when working on the open source app GNITE. GNITE requires an internal large tree structure that can support up to 5 million nodes.  Neither of us had worked with trees that large before, and we didn’t know what the stumbling blocks were going to be.  So, we decided to spike it out.&lt;/p&gt;



&lt;p&gt;A spike is a quickly written, untested piece of code that’s intended to be thrown away.  You intentionally abandon your best practices in the interest of quickly learning about good ways to design your app.  Once you’ve gained everything you can from it, however, you scrap it and don’t build anything else off it.&lt;/p&gt;



&lt;p&gt;In our case, we started out fooling about with jsTree, to display the tree, and the ruby gem ancestry, to organize the tree structure in the database.  (If you want to check it out, it’s up on github &lt;a href="http://github.com/GlobalNamesArchitecture/ancestry-jstree/"&gt;here&lt;/a&gt; and you can see it working &lt;a href="http://ancestry-jstree.heroku.com/"&gt;here&lt;/a&gt;.)   As it turned out, ancestry and jsTree worked well together - ancestry stores the entire lineage of each node on the node itself, which made things like asynchronous search work well with jsTree.&lt;/p&gt;



&lt;p&gt;Happy with our initial findings, and looking to push our luck, we extended our program to parse large, compressed tree files.  Once we had the large tree in the database, the display behavior remained satisfactory, but the act of parsing a tree took a long time - too long to be a regular occurrence on the website.  Initially, we had considered making parsing trees a regular part of the work flow, but the 5 to 10 minute load times suggested that we would need to look into some sort of caching (or, possibly, a different way of storing nodes on the back end with a quicker insertion.)&lt;/p&gt;



&lt;p&gt;In the end, we decided caching uncompressed trees in the database could be a potential solution, given the amount of space we had.  In our case, the most straightforward approach for displaying trees worked out well, but not for saving and loading trees.&lt;/p&gt;



&lt;p&gt;Now that we have a loose idea of the structure we’re going to pursue, we can keep it in mind when we’re writing our code.  And, we have some really relevant example code to work off, which will (hopefully) make the “getting the tests to pass” step in TDD quite a bit easier.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/sDk_19dRpzU/850129015</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/850129015</guid><pubDate>Fri, 23 Jul 2010 12:39:48 -0400</pubDate><feedburner:origLink>http://robots.thoughtbot.com/post/850129015</feedburner:origLink></item><item><title>Missed connections: I saw you testing my website</title><description>&lt;div style="text-align: center;"&gt;&lt;img src="http://media.tumblr.com/tumblr_l5wz5vA2qI1qa5kd1.jpg"/&gt;&lt;/div&gt;

&lt;p&gt;Usability testing is like flossing: everyone knows it’s important, but they don’t do it nearly as much as they should. Because let’s face it, making sites is a lot more exciting than testing them. Well, this past week we ran our first round of in-house usability tests and wanted to share how we did it, what we learned, and what we need to improve.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.slideshare.net/glusman/lean-usability"&gt;This presentation&lt;/a&gt; by Meetup on Lean Usability was a big help in putting together our initial plans. It does a good job of laying out the pros and cons of several approaches and points out what you should focus on at the beginning, before you have any experience to guide you. Read it.&lt;/p&gt;

&lt;h2&gt;How we did it&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We chose to test an important form that we were in process of redesigning for a client. With differing opinions about the approach to certain aspects of the redesign, it was a prime candidate for usability testing.&lt;/li&gt;

&lt;li&gt;We decided to use &lt;a href="http://silverbackapp.com/"&gt;Silverback&lt;/a&gt; to capture the test sessions. We liked it because of the ability to record audio and video of both the user and the screen, giving us an objective record of what happened during the session that could be reviewed later.&lt;/li&gt;

&lt;li&gt;We placed an ad in the “volunteers” section on craigslist. The message gave a quick summary of what we needed the volunteers to do, who we were, and directed them to a &lt;a href="http://wufoo.com/"&gt;Wufoo&lt;/a&gt; form where they provided us with their information. We offered $30 for about 30 minutes of their time and ended up having almost 70 responses in less than 24 hours.&lt;/li&gt;

&lt;li&gt;We decided to schedule 5 sessions, one right after the other, during one afternoon. We picked 5 people whose schedules worked with ours and emailed them to let them know we had scheduled a session for them. We also emailed everyone we didn’t select, thanking them for contacting us.&lt;/li&gt; 

&lt;li&gt;Before the sessions, we wrote up scenarios that would be given to the user. We decided on three tasks, each more complex than the last, that would focus on a key point of the clients’ form we were redesigning. We also prepared a release form that let testers know that we’d be recording audio and video of their session, that this would be viewed by thoughtbot and our client, but would not be used for any other purpose.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What we learned&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;We sent a confirmation message the morning of the testing to all the testers, and ended up having 4 out of 5 show up.&lt;/li&gt; 

&lt;li&gt;The scenarios/instructions are important. Our first tester was completely stumped by the first scenario, and we realized that we had not been as clear as we could have been. We quickly modified the instructions before the next session.&lt;/li&gt;

&lt;li&gt;Silverback has drawbacks. Each of our sessions was between 22 - 30 minutes and takes up more than a GB of hard drive space. Additionally, exporting video of the sessions takes a long time. On a MacBook with an dual core processor and 2 GB of RAM, it takes 2 to 3 hours. (It still takes over an hour on a maxed-out MacBook Pro.)&lt;/li&gt;

&lt;li&gt;It takes time. Recruiting testers, writing scenarios, running sessions, exporting video, sending the results — all of these things take time. Make a realistic estimate of how much time you’ll actually be investing in doing usability testing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What to improve&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The users we recruited for this round of testing didn’t need to have any special qualifications. As we do more testing, we’ll likely encounter a situation where we’ll need users with specific knowledge related to the site they’ll be testing. (Running usability tests on &lt;a href="http://hoptoadapp.com"&gt;Hoptoad&lt;/a&gt; would present this problem.) It’s unclear if craigslist will work in these situations.&lt;/li&gt;

&lt;li&gt;While it’s impossible to completely remove any confusion that the instructions may introduce, we’ll need to do a better job of writing scenarios that are clear.&lt;/li&gt;
&lt;/ul&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/Z7iar6edeF4/841047539</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/841047539</guid><pubDate>Wed, 21 Jul 2010 11:35:00 -0400</pubDate><category>design</category><category>usability testing</category><feedburner:origLink>http://robots.thoughtbot.com/post/841047539</feedburner:origLink></item><item><title>How To: Take Notes Like a Champ</title><description>&lt;h2&gt;Information Overload&lt;/h2&gt;

&lt;p&gt;One of our newest projects here at thoughtbot is a taxonomic naming app called GNITE which we’re building for the &lt;a href="http://www.mbl.edu/"&gt;Marine Biological Lab&lt;/a&gt;. As designer on this project my first challenge was to get a basic understanding of the subject matter and the goals of the project, but I found the information to be complicated especially for someone new to taxonomy. We had the pleasure of visiting the Marine Biology Lab in Woods Hole, MA on Cape Cod recently and in the meetings I dusted off an old note taking trick I frequently used in college but with new tools — an iPad and &lt;a href="http://itunes.apple.com/us/app/adobe-ideas-1-0-for-ipad/id364617858?mt=8"&gt;Adobe Ideas&lt;/a&gt; app.&lt;/p&gt;

&lt;h2&gt;Taking notes vs. absorbing information&lt;/h2&gt;
&lt;p&gt;Design is often about reducing complex systems to their simplest form. Our meetings at the Marine Biology Lab could have produced pages and pages of comprehensive notes but my goal was to organically absorb as much information as possible without the distracting task of transcribing information. Using Adobe Ideas, &lt;a href="http://robots.thoughtbot.com/post/749800833/ipad-sketching-app-review"&gt;an iPad and a stylus&lt;/a&gt;, I took visual notes, writing down key pieces of information, embellishing them, and organizing them visually. The embellishment is the key part - it leaves your ears open to what’s being discussed. When looking back at my notes I can clearly remember who was talking, what the sentiment was, and other subtle things that could be forgotten during normal note taking. The visual nature of the notes jogs my memory in a way pure text or handwriting doesn’t. The outcome is an &lt;strong&gt;understanding of a simplified gestalt&lt;/strong&gt; which isn’t burdened by details.&lt;/p&gt;

&lt;p&gt;Click each image to view it larger:&lt;/p&gt;

&lt;a href="http://ui.thoughtbot.com/assets/note_taking/gnite-notes-1.jpg"&gt;&lt;img style="border: 1px solid #d8d8d8;" src="http://ui.thoughtbot.com/assets/note_taking/gnite-notes-1-668.jpg" alt="notes"/&gt;&lt;/a&gt;
&lt;br/&gt;&lt;p&gt;Adobe Ideas allows &lt;abbr title="Fractal-like. You can zoom way in and way out."&gt;fractalesque&lt;/abbr&gt; zooming. You are able to use vast scale differences to communicate importance as well as benefit from a very flexible canvas, so you almost never run out of space taking notes.&lt;/p&gt;

&lt;a href="http://ui.thoughtbot.com/assets/note_taking/gnite-notes-2.jpg"&gt;&lt;img style="border: 1px solid #d8d8d8;" src="http://ui.thoughtbot.com/assets/note_taking/gnite-notes-2-668.jpg" alt="notes"/&gt;&lt;/a&gt;
&lt;br/&gt;&lt;p&gt;&lt;a href="http://ui.thoughtbot.com/assets/note_taking/fungi.jpg"&gt;Check out that mushroom!&lt;/a&gt; Someone said “fungi” so I drew a mushroom. As my theory goes, I absorbed whatever was said after that (it was an anecdotal tale of conflicting fungi names, I believe).&lt;/p&gt;
&lt;a href="http://ui.thoughtbot.com/assets/note_taking/gnite-notes-3.jpg"&gt;&lt;img style="border: 1px solid #d8d8d8;" src="http://ui.thoughtbot.com/assets/note_taking/gnite-notes-3-668.jpg" alt="notes"/&gt;&lt;/a&gt;

&lt;h2&gt;But won’t you miss important details?&lt;/h2&gt;
&lt;p&gt;The drawback to taking notes like this is that many details will never get written down. If those details are critical bring a voice recorder. In my case there were two developers in the meetings as well, so I was confident our team-like approach would yield all necessary information (and it did).&lt;/p&gt;

&lt;h2&gt;Life after NDA’s&lt;/h2&gt;
&lt;p&gt;One of the most exciting aspects to this project is it’s open source which opens the possibility to documenting the building process in ways we usually can’t with most client work. This is the first in what I hope will be a series of posts documenting the design process all the way through to the final product.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/ATShmoyKsvc/836560565</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/836560565</guid><pubDate>Tue, 20 Jul 2010 10:37:00 -0400</pubDate><category>design</category><category>process</category><feedburner:origLink>http://robots.thoughtbot.com/post/836560565</feedburner:origLink></item><item><title>CAPE CODE</title><description>&lt;p&gt;Still without plans for August?  Did you know that August is our nation’s warmest and most-traveled month?  Looking for a nice trip?  Well…have I got a deal for you!&lt;/p&gt;

&lt;p&gt;Come relax on the sandy shores of Massachusetts’ own wicked beautiful Cape Cod at our &lt;a href="http://robots.thoughtbot.com/post/595813245/join-us-for-3-days-on-cape-cod"&gt;previously announced&lt;/a&gt; event: &lt;a href="http://capeco.de/"&gt;CAPE CODE&lt;/a&gt;!  Join thoughtbot’s team of designers and developers and stiff management types while we bask in the glorious New England sun.  It’s the most relaxed you can be and learn about web programming at the same time.&lt;/p&gt;

&lt;p&gt;&lt;img class="sink" src="http://media.tumblr.com/tumblr_l5m2bwaN0z1qz4sb2.jpg" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Hey, maybe you can dig up some clams while you’re there.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/kQg9nO_xM88/816027877</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/816027877</guid><pubDate>Thu, 15 Jul 2010 14:19:00 -0400</pubDate><feedburner:origLink>http://robots.thoughtbot.com/post/816027877</feedburner:origLink></item><item><title>Logos Suck When Branding Yourself</title><description>&lt;p&gt;I’ve recently begun a redesign of my portfolio and my biggest blocker is never knowing what to do for a logo or header. Then, last night, it hit me. You don’t need to create anything. Crazy, right? Maybe not for some of you, but for a designer like me, that’s  unheard of.&lt;/p&gt;

&lt;img src="http://ui.thoughtbot.com/assets/fred-yates.jpg" alt="fred yates" style="margin: 0 10px 0 0;float: left;"/&gt;&lt;h2&gt;So how do people recognize me?&lt;/h2&gt;
&lt;p&gt;The answer to this struck me while messing around on twitter, &lt;a href="http://twitter.com/fredyatesiv"&gt;my face is my brand&lt;/a&gt;. I recognize people by their twitter avatar. When someone changes their avatar, I have no idea who is tweeting at me. This is incredibly strong branding and most people don’t even realize it. Now just imagine if every place you were, virtually and physically, always had your brand. If you haven’t figured it out yet, you can make this happen. Make your face your brand and you will reinforce whatever you stand for, everywhere you go. More than just your face being your brand, make one particular photo your brand, everywhere. I can’t count the number of times I’ve seen the same people on different sites and recognized them only because they used the same photo. It’s much weaker, and almost pointless, if you change your photo from place to place.&lt;/p&gt;

&lt;p&gt;Dan Benjamin wrote a great post on his blog, &lt;a href="http://hivelogic.com/articles/why-your-avatar-matters"&gt;Hivelogic&lt;/a&gt;, about the significance of your avatar, and how never changing it is the only way to go. Smart guy over there!&lt;/p&gt;

&lt;h2&gt;Trash that old logo&lt;/h2&gt;
&lt;p&gt;
Some people want to use just their name or some forgettable mark. I was a disciple of this belief for the majority of my design career; I used a fedora and my name set in Museo. That’s idiotic. I don’t wear a fedora, and my name is unmemorable. If I’m banking on an employer remembering me they aren’t going to think of the guy that had a fedora as his logo. They’re going to remember my attitude, the interaction between us, and most importantly my face. When they’re thinking of my face, I need it to be easily findable. I want it on the top of my résumé, &lt;a href="http://fyates.com"&gt;website&lt;/a&gt;, and even my business cards!
&lt;/p&gt;

&lt;h2&gt;Think about these cases&lt;/h2&gt;
&lt;p&gt;I bet you will recognize a few photos and their subject by a simple description, without even showing you the photo.&lt;/p&gt;
&lt;ul style="list-style-position: outside;"&gt;
&lt;li&gt; Everyone knows the creator of Myspace, and that photo he never changed. Imagine if Tom changed his photo every week like most of the power social network users do. Tom would be nobody, unrecognizable, and forgotten forever. Now, even though Myspace is a joke, people from our generation will remember Tom and his face for a long time. In my opinion he is still more recognizable than Mark Zuckerberg.&lt;/li&gt;
&lt;li&gt; Remember that blonde bombshell from the 1950s in &lt;a href="http://www.imdb.com/title/tt0048605/"&gt;The Seven Year Itch&lt;/a&gt;? Standing above the subway vent, holding her white dress down, as the gust from below blew her dress every which way. Everyone knows that powerful picture of Marilyn Monroe and while she never intended for it to be her brand, it is definitely something she is remembered by.&lt;/li&gt;
&lt;li&gt; How about Steve Jobs? He knows this secret. You’ll always see him in his black turtleneck and thin framed glasses. He actually recreates his single brand image every time he goes out in public. This is the perfect case of branding yourself. It may get boring, but it’s instantly recognizable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Actually doing it&lt;/h2&gt;
&lt;p&gt;Like anything else in life, if you’re going to do this, don’t half ass it. Don’t find some weak camera phone picture of you somewhere. Pay, barter, or do whatever you need to get a good photographer to produce at least one good picture of you. thoughtbot hired &lt;a href="http://fromme-toyou.tumblr.com"&gt;Jamie Beck&lt;/a&gt;, a great photographer we know from New York City. She did an all star job and now we all have super photos to brand ourselves with. You should do the same, and see how much more people begin remembering and recognizing you.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/4oyddK0cuEo/804193327</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/804193327</guid><pubDate>Wed, 14 Jul 2010 11:00:56 -0400</pubDate><category>design</category><feedburner:origLink>http://robots.thoughtbot.com/post/804193327</feedburner:origLink></item><item><title>Suspenders now with RSpec, jQuery, and more</title><description>&lt;p&gt;Suspenders is a Rails project template used as a base app for all of our client work. It has gone through a few changes that better reflect our development stack and also allow us to test changes to suspenders itself.&lt;/p&gt;

&lt;h3&gt;RSpec&lt;/h3&gt;

&lt;p&gt;As &lt;a href="http://robots.thoughtbot.com/post/701863189/shoulda-rails3-and-beyond"&gt;you may know&lt;/a&gt;, we are spec’ing our apps with RSpec along with shoulda matchers now. This along with cucumber for integration tests is the testing stack that we’ve been using for a while. RSpec replaces Test::Unit in suspenders.&lt;/p&gt;

&lt;h3&gt;jQuery&lt;/h3&gt;

&lt;p&gt;For our front-end behavior we’re using jQuery. The ecosystem around jQuery Core, jQuery UI, and the slew of third-party plugins help bring life to our applications. Using jQuery also gives us an easy transition for mobile web app development with tools like &lt;a href="http://jqtouch.com/"&gt;jQTouch&lt;/a&gt;. jQuery replaces prototype/scriptaculous in suspenders.&lt;/p&gt;

&lt;h3&gt;Dependencies&lt;/h3&gt;

&lt;p&gt;Our projects depend on a number of gems. Some have native extensions and therefore cannot be vendored in the project - I’m talking about our friends nokogiri and RedCloth. In the past we would check if the gems where installed, and installed them if they weren’t. Now that &lt;a href="http://rubygems.org/gems/suspenders"&gt;suspenders-gem&lt;/a&gt; is the preferred way of installing and using suspenders, we have added these as rubygem dependencies on &lt;a href="http://github.com/thoughtbot/suspenders-gem/commit/f7655644330a7363bec04e0718f303d936ffcbb1"&gt;our gemspec&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Testing suspenders&lt;/h3&gt;

&lt;p&gt;The &lt;a href="http://robots.thoughtbot.com/post/607129437/suspenders-as-a-gem"&gt;creation of suspenders-gem&lt;/a&gt; affords us the opportunity to write integration tests for suspenders. In the past, testing updates to suspenders was a manual process because of the nature of the template. But from now on we can write &lt;a href="http://github.com/thoughtbot/suspenders-gem/blob/master/features/rake_clean.feature"&gt;cucumber scenarios&lt;/a&gt; that verify that the suspenders project starts in a clean state.&lt;/p&gt;

&lt;h3&gt;Take her for a ride!&lt;/h3&gt;

&lt;img src="http://www.blogcdn.com/www.autoblog.com/media/2008/08/misuse-of-hydraulics.jpg" alt="Suspenders ride"/&gt;&lt;p&gt;Along with these major changes, versions of all other dependencies were bumped to the latest stable versions. Take suspenders for a ride and let us know what you think:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem install suspenders
suspenders create billion_dollar_idea
&lt;/code&gt;&lt;/pre&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/HORGcx5_uv0/806379268</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/806379268</guid><pubDate>Tue, 13 Jul 2010 08:55:00 -0400</pubDate><feedburner:origLink>http://robots.thoughtbot.com/post/806379268</feedburner:origLink></item><item><title>Capturing Errors on a Global Scale</title><description>&lt;p&gt;Has your database gone down recently?  What about timeouts from third-party services?  Exceptions can be raised anywhere in your app, and Hoptoad’s here to track them for you.  Problem is, these exceptions can manifest themselves in your controllers or models, and that’s not helpful when you have to sort through all of them because of Hoptoad’s grouping logic.&lt;/p&gt;

&lt;p&gt;To help, we’ve introduced global error classes for all paid accounts.  Per project, you can list exception classes that you’d like to be grouped together in Hoptoad.  We handle the nitty-gritty so your life is easier when you’re trying to resolve these issues that come up.  Since we’re not ones to leave you high and dry, we’ve started everyone off with a list of common global exceptions from Rails projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mysql::Error&lt;/li&gt;
&lt;li&gt;MemCache::MemCacheError&lt;/li&gt;
&lt;li&gt;Mongrel::TimeoutError&lt;/li&gt;
&lt;li&gt;ThinkingSphinx::ConnectionError&lt;/li&gt;
&lt;li&gt;Net::HTTPFatalError&lt;/li&gt;
&lt;li&gt;OpenURI::HTTPError&lt;/li&gt;
&lt;li&gt;ActiveResource::ResourceNotFound&lt;/li&gt;
&lt;li&gt;ActiveResource::TimeoutError&lt;/li&gt;
&lt;li&gt;ActiveResource::ServerError&lt;/li&gt;
&lt;li&gt;Net::SMTPServerBusy&lt;/li&gt;
&lt;li&gt;Net::SMTPFatalError&lt;/li&gt;
&lt;li&gt;Net::SMTPSyntaxError&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To change the list of global errors, go edit a project.&lt;/p&gt;

&lt;p&gt;&lt;img style="float: none" src="http://ui.thoughtbot.com/assets/hoptoad-global-errors-edit-project.jpg" alt="Edit a project"/&gt;&lt;/p&gt;

&lt;p&gt;Under the name of the project, you’ll see a list of Global Error Classes (again, prepopulated with a handful of common errors).  We separated by new lines, but spaces or commas will work as well.&lt;/p&gt;

&lt;p&gt;&lt;img style="float: none" src="http://ui.thoughtbot.com/assets/hoptoad-global-errors-error-class-list.jpg" alt="List of global error classes"/&gt;&lt;/p&gt;

&lt;p&gt;Once those are set up, you’re ready to roll!  Here’s a snapshot of how a global error shows up after adding &lt;code&gt;RuntimeError&lt;/code&gt; to the list.&lt;/p&gt;

&lt;p&gt;&lt;img style="float: none" src="http://ui.thoughtbot.com/assets/hoptoad-global-errors-global-error.jpg" alt="RuntimeError as a global error"/&gt;&lt;/p&gt;

&lt;p&gt;That’s about all there is to it!  Note that this isn’t retroactive, so your old errors will still be in the same groups as they were before.  Another reminder: if you’re on our Egg plan, be sure to upgrade; your first month is free!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/aJBAs49XY2Q/785376264</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/785376264</guid><pubDate>Thu, 08 Jul 2010 10:33:00 -0400</pubDate><category>development</category><category>hoptoad</category><feedburner:origLink>http://robots.thoughtbot.com/post/785376264</feedburner:origLink></item><item><title>Quit your job and come work for thoughtbot</title><description>&lt;p&gt;Things are humming along and we’re ready to add another designer to the team.&lt;/p&gt;



&lt;p&gt;We’re looking for someone who can produce great designs, really cares about the quality of their HTML and CSS code, and wants to be a part of a kick ass team that builds great stuff.&lt;/p&gt;



&lt;p&gt;If this is you, and you’re either in Boston or willing to relocate, &lt;a title="thoughtbot jobs page" href="http://thoughtbot.com/jobs"&gt;get in touch&lt;/a&gt;, because we want to talk to you.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ui.thoughtbot.com/assets/designer_work.jpg" alt="designer work" title="Work our design team has produced."/&gt;&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/rKI4iKn3MJs/785283576</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/785283576</guid><pubDate>Thu, 08 Jul 2010 09:59:00 -0400</pubDate><category>design</category><category>business</category><feedburner:origLink>http://robots.thoughtbot.com/post/785283576</feedburner:origLink></item><item><title>Test Time Bombs</title><description>&lt;p&gt;Testing with times and dates have come a long way, now that &lt;a href="http://github.com/jtrupiano/timecop"&gt;Timecop&lt;/a&gt; is around. Prior to Timecop, we would use a stubbing library like &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; to stub out just what we needed, but why do that when Van Damme could beat the right values out of &lt;code&gt;Time&lt;/code&gt;?&lt;/p&gt;

&lt;center&gt;&lt;img src="http://img.skitch.com/20100702-meh4iid8ngyat91anq4arty732.jpg"/&gt;&lt;/center&gt;

&lt;h3&gt;The Bomb&lt;/h3&gt;

&lt;p&gt;I wrote this Cucumber feature, models have been changed to protect the innocent.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  Scenario: List latest posts under a tag
    Given the following posts exist:
      | Post   | Tag list | Created on   | Expires on   |
      | post1  | yankees  | May 1, 2010  | July 1, 2010 |
      | post2  | yankees  | June 1, 2010 | July 1, 2010 |
      | post3  | yankees  | May 5, 2010  | July 1, 2010 |
      | post4  | yankees  | May 30, 2010 | July 1, 2010 |
      | post5  | yankees  | May 29, 2010 | July 1, 2010 |
    When I visit the tags page
    And I follow "yankees"
    Then I should see the following posts in order:
      | title  |
      | post2  |
      | post4  |
      | post5  |
      | post3  |
      | post1  |
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Most of these steps are from &lt;a href="http://github.com/thoughtbot/factory_girl/blob/master/lib/factory_girl/step_definitions.rb"&gt;factory_girl&lt;/a&gt; and &lt;a href="http://github.com/brynary/webrat"&gt;webrat&lt;/a&gt;, except for the last one, which parses the page using Nokogiri and looks for the titles in the order listed. This feature passed when I wrote it (June 30th). Of course, on July 1st, I ran the test again, and &lt;code&gt;FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF&lt;/code&gt;. 

&lt;/p&gt;
&lt;p&gt;Timecop wasn’t too helpful here, because the code actually used MySQL’s &lt;code&gt;NOW()&lt;/code&gt; function instead of accepting a date parameter for today. So that’s one thing I could have fixed instead, but I didn’t want to touch any other code in the app.&lt;/p&gt;

&lt;p&gt;Another obvious solution: bump up the expired date by a year, forget about it until next year. If you’re thinking of this solution, try imagining this guy kicking you in the face:&lt;/p&gt;

&lt;center&gt;&lt;img src="http://img.skitch.com/20100702-kqjgk5twksyniinhui5c8ick8e.jpg"/&gt;&lt;/center&gt;

&lt;h3&gt;Future-proofing&lt;/h3&gt;

&lt;p&gt;Van Damme’s given us another chance. Let’s refactor this feature.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   Scenario: List latest posts under a tag
    Given the following posts with tags exist:
      | title  | tag list | created              |
      | post1  | yankees  | 2.months.ago         |
      | post2  | yankees  | 1.month.ago + 4.days |
      | post3  | yankees  | 1.month.ago          |
      | post4  | yankees  | 1.month.ago + 2.days |
      | post5  | yankees  | 1.month.ago + 1.day  |
    When I visit the tags page
    And I follow "yankees"
    Then I should see the following posts in order:
      | title  |
      | post2  |
      | post4  |
      | post5  |
      | post3  |
      | post1  |&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using a bit of ActiveSupport’s time helpers, we can future proof this step by always moving forward instead of locking to a specific date. The step definition then uses &lt;code&gt;eval&lt;/code&gt; to get the real dates back:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Given /^the following posts with tags exist:$/ do |table|
  table.hashes.each do |row|
    created_on = eval(row['created'])
    Factory(:post, :title      =&gt; row['title'],
                   :tag_list   =&gt; row['tag list'],
                   :created_on =&gt; created_on,
                   :expires_on =&gt; created_on + 1.year)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;KABOOM&lt;/h3&gt;

&lt;p&gt;So this is a simple way of avoiding time bombs in your tests. There’s no real way to prevent them always, you just need to consider how you’re dealing with time based code. If you’ve left time bombs in your test suites, feel free to own up and share your story too. Before Van Damme gets you.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/XVKQVIFUcFo/762390522</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/762390522</guid><pubDate>Fri, 02 Jul 2010 14:29:00 -0400</pubDate><feedburner:origLink>http://robots.thoughtbot.com/post/762390522</feedburner:origLink></item><item><title>iPad sketching app review</title><description>&lt;p&gt;
                              &lt;img style="margin: 0;" src="http://ui.thoughtbot.com/assets/ipadsketching/ipadsketchingphoto.jpg" alt="Sketching on an iPad"/&gt;&lt;span style="display: block; font-size: 9px; color: #999; text-align: right;"&gt;Photo by &lt;a style="color: #999; font-weight: normal;" href="http://fromme-toyou.tumblr.com"&gt;Jamie Beck&lt;/a&gt;&lt;/span&gt;
                            &lt;/p&gt;
                            
                            
                            &lt;h3&gt;Sketching on an iPad&lt;/h3&gt;
                            &lt;p&gt;When I first held an iPad I knew it would have significance to a web designer as a sketching tool. It’s portable, connected, and friendly, and with the apps that have emerged since launch we now have many options to choose from based on what needs and wants we might have. I’m reviewing three apps: Adobe Ideas, Draft, and Sketchbook Pro from the perspective of a web designer, focusing on tasks such as layout sketching. I aim to help you decide which tool or tools is best suited for you and your working environment.&lt;/p&gt;
                            
                            &lt;h3&gt;Tools of the trade&lt;/h3&gt;
                            &lt;p&gt;Before discussing the apps I should point out I do all sketching on the iPad using a stylus, specifically the &lt;a href="http://tenonedesign.com/sketch.php"&gt;Pogo Sketch&lt;/a&gt;, so unless you find your index finger particularly capable, I suggest purchasing a stylus.&lt;/p&gt;
                            
                            &lt;div class="clearfix" style="background: transparent url(http://ui.thoughtbot.com/assets/ipadsketching/dots.png) top left repeat-x; padding: 35px 0 15px 0;"&gt;
                              &lt;div style="float: left; width: 320px;" class="clearfix"&gt;
                                &lt;a href="http://itunes.apple.com/us/app/adobe-ideas-1-0-for-ipad/id364617858?mt=8"&gt;
                                  &lt;img style="float: left; display: block;" src="http://ui.thoughtbot.com/assets/ipadsketching/icon-adobe.png" alt="icon"/&gt;&lt;/a&gt;  
                                &lt;div style="width: 200px; margin-left: 85px;"&gt;
                                  &lt;h3&gt;Adobe Ideas&lt;/h3&gt;
                                  &lt;span&gt;Free (&lt;a href="http://itunes.apple.com/us/app/adobe-ideas-1-0-for-ipad/id364617858?mt=8"&gt;app store link&lt;/a&gt;)&lt;/span&gt;
                                &lt;/div&gt;
                                &lt;p style="clear: left;"&gt;Adobe Ideas is a basic sketching app that is geared towards clean results and simple, quick usage. You have one marker tool at your disposal which can be adjusted with radius, color and opacity controls via a vertical slider. When sketching, the UI is limited to a slim control bar on the left which can be hidden, but it’s unobtrusive enough that it doesn’t distract.&lt;/p&gt;
                                  
                                  &lt;p&gt;Adobe Ideas’ files are vector based which comes with two fantastic upsides: you’re able to zoom in and out easily and to extraordinary levels, and the exported file is a lightweight .PDF which can be manipulated or printed easily. The resolution independence means you can magnify to add small, sophisticated details, and pan around the canvas in case your drawing ends up bigger than you intended. Sketches are auto-saved so you don’t have to worry about losing work or saving files. I use Adobe Ideas on a daily basis and since it’s free I highly recommend giving it a try.&lt;/p&gt;
                                 &lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Free, simple but powerful toolset, lightweight vector export &lt;/p&gt;
                                 &lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; none&lt;/p&gt;
                              &lt;/div&gt;
                              &lt;div style="float: right; width: 334px;"&gt;
                                &lt;a href="http://ui.thoughtbot.com/assets/ipadsketching/ss-adobe-768.jpg"&gt;&lt;img src="http://ui.thoughtbot.com/assets/ipadsketching/ss-adobe-334.jpg" alt="icon"/&gt;&lt;/a&gt;
                              &lt;/div&gt;
                              &lt;br style="clear: both;"/&gt;
&lt;/div&gt;
                            
                            
                            &lt;div class="clearfix" style="background: transparent url(http://ui.thoughtbot.com/assets/ipadsketching/dots.png) top left repeat-x; padding: 35px 0 15px 0;"&gt;
                              &lt;div style="float: left; width: 320px;" class="clearfix"&gt;
                                &lt;a href="http://http://itunes.apple.com/us/app/draft/id375570329?mt=8"&gt;
                                  &lt;img style="float: left; display: block;" src="http://ui.thoughtbot.com/assets/ipadsketching/icon-37s.png" alt="icon"/&gt;&lt;/a&gt;  
                                &lt;div style="width: 200px; margin-left: 85px;"&gt;
                                  &lt;h3&gt;Draft&lt;/h3&gt;
                                  &lt;span&gt;$9.99 (&lt;a href="http://http://itunes.apple.com/us/app/draft/id375570329?mt=8"&gt;app store link&lt;/a&gt;)&lt;/span&gt;
                                &lt;/div&gt;
                                &lt;p style="clear: left;"&gt;When &lt;a href="http://37signals.com/"&gt;37 Signals&lt;/a&gt; released Draft I was curious how their pragmatic approach would translate in to an app, particularly one in a realm I am highly interested in. Draft is task oriented: the tools are extremely limited (one brush radius, and only white and red) and one eraser. The advantages to this approach are a consistent output, and with no options to monkey with you are kept from getting lost worrying about style. This is, in essence, a grand equalizer - someone with artistic abilities and someone without will produce very similar sketches using Draft. Draft has a static canvas which can become a problem if you run out of space, but I quickly got used to the limitation. At the time of this writing, Draft only has one level of undo which can be frustrating given the longstanding prevalence of multiple undos in most creative apps.&lt;/p&gt;
                                
                                &lt;p&gt;Draft’s killer feature, however, is integration with 37 Signals’ own chat app, &lt;a href="http://campfirenow.com/"&gt;Campfire&lt;/a&gt;. Through a sharing button you’re two taps away from posting the image instantly in a Campfire chat room — and if you use Campfire as extensively as we do at thoughtbot, this feature will blow your mind. Draft is all about communicating ideas quickly, and if you think of it as a portable, miniature dry erase board you will be satisfied.&lt;/p&gt;
                                    &lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Task oriented approach, excellent &lt;a href="http://campfirenow.com/"&gt;Campfire&lt;/a&gt; integration, consistent output&lt;/p&gt;
                                    &lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; $9.99 is potentially prohibitive to some users given limited features, only one level of undo&lt;/p&gt;
                              &lt;/div&gt;
                              &lt;div style="float: right; width: 334px;"&gt;
                                &lt;a href="http://ui.thoughtbot.com/assets/ipadsketching/ss-37s-768.jpg"&gt;&lt;img src="http://ui.thoughtbot.com/assets/ipadsketching/ss-37s-334.jpg" alt="icon"/&gt;&lt;/a&gt;
                              &lt;/div&gt;
                              &lt;br style="clear: both;"/&gt;
&lt;/div&gt;                     
                            

                            &lt;div class="clearfix" style="background: transparent url(http://ui.thoughtbot.com/assets/ipadsketching/dots.png) top left repeat-x; padding: 35px 0 15px 0;"&gt;
                              &lt;div style="float: left; width: 320px;" class="clearfix"&gt;
                                &lt;a href="http://itunes.apple.com/us/app/sketchbook-pro/id364253478?mt=8"&gt;
                                  &lt;img style="float: left; display: block;" src="http://ui.thoughtbot.com/assets/ipadsketching/icon-sketchbook.png" alt="icon"/&gt;&lt;/a&gt;  
                                &lt;div style="width: 200px; margin-left: 85px;"&gt;
                                  &lt;h3&gt;Sketchbook Pro&lt;/h3&gt;
                                  &lt;span&gt;$9.99 ($3.99 until July 4th) (&lt;a href="http://itunes.apple.com/us/app/sketchbook-pro/id364253478?mt=8"&gt;app store link&lt;/a&gt;)&lt;/span&gt;
                                &lt;/div&gt;
                                &lt;p style="clear: left;"&gt;Autodesk’s Sketchbook Pro is a different breed of sketching app from the previous two. It’s a derivative of a desktop version, and it inherits many of the features and capabilities. And when I say “capabilities” I mean a shocking feature set that is almost hard to believe it’s available on an iPad - such as layers, natural brushes, .PSD export, and a professional color picker. When you’re sketching on Sketchbook Pro it feels very close to sketching on paper with traditional media. Despite the iPad’s lack of pressure sensitivity, brush strokes can taper off at the end giving a very natural and satisfying experience. There is also the ability to magnify the document, but since it’s a bitmap image zooming exposes pixelization. &lt;/p&gt;
                                &lt;p&gt; For replicating natural media there is no comparison - Sketchbook Pro is incredible, but for web design and communication purposes the wide variety of features and brushes can often leave you tweaking and stylizing, instead of focusing on the task. It has a deep UI that requires a learning curve but mastery can open some exciting possibilities and ease of use. For those experienced in traditional media and who may feel stifled by Adobe Ideas’ uniform tools, Sketchbook Pro will go a long way towards satisfying your delicate artistic sensibilities.&lt;/p&gt;
                                &lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Amazing natural media capabilities, professional toolset, .PSD export&lt;/p&gt;
                                &lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; UI takes getting used to, numerous features can distract from task oriented sketching&lt;/p&gt;  
                              &lt;/div&gt;
                              &lt;div style="float: right; width: 334px;"&gt;
                                &lt;a href="http://ui.thoughtbot.com/assets/ipadsketching/ss-autodesk-768.jpg"&gt;&lt;img src="http://ui.thoughtbot.com/assets/ipadsketching/ss-autodesk-334.jpg" alt="icon"/&gt;&lt;/a&gt;
                              &lt;/div&gt;
                              &lt;br style="clear: both;"/&gt;
&lt;/div&gt;                   
                            
                       
                            
                            
                            &lt;div class="clearfix" style="background: transparent url(http://ui.thoughtbot.com/assets/ipadsketching/dots.png) top left repeat-x; padding: 35px 0 15px 0;"&gt;              &lt;h3&gt;What else?&lt;/h3&gt;
                              &lt;p&gt;While using these apps I’ve experimented and looked for useful ways to shoehorn them into my work routine. Both Adobe Ideas and Sketchbook Pro allow for importing of images which you can draw on top of - as an example I’ve drawn on a browser window and utilized a grid system:&lt;/p&gt;
                              &lt;img src="http://ui.thoughtbot.com/assets/ipadsketching/uses.jpg" alt="very useful"/&gt;
&lt;/div&gt;         
                            
                            
                           &lt;div class="clearfix" style="background: transparent url(http://ui.thoughtbot.com/assets/ipadsketching/dots.png) top left repeat-x; padding: 35px 0 15px 0;"&gt;              &lt;h3&gt;Conclusion&lt;/h3&gt;
                              &lt;p&gt;All three of these apps are well designed and well executed, so choosing one (or a tag team of two) depends on which best fits in to your workflow. If flat, smooth sketches and vector-flexibility is key to you, Adobe Ideas is a fantastic solution. If you’re an avid Campfire user or value a focused approach, Draft is a great choice. If you’re a suppressed artist living in a designer’s body, Sketchbook Pro will let you embellish sketches with an imbued sense of creativity. &lt;/p&gt;
                            &lt;/div&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/zGKagXDlvck/749800833</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/749800833</guid><pubDate>Tue, 29 Jun 2010 10:34:00 -0400</pubDate><category>design</category><category>ipad</category><feedburner:origLink>http://robots.thoughtbot.com/post/749800833</feedburner:origLink></item><item><title>This should_change your mind</title><description>&lt;p&gt;There’s been a bunch of hullabaloo about our recent deprecation of the Shoulda macros &lt;code&gt;should_change&lt;/code&gt; and &lt;code&gt;should_not_change&lt;/code&gt;.  A lot of people have asked, “why remove it?”  Short answer: we don’t use it anymore.  Long answer: &lt;strong&gt;it’s confusing and may encourage bad programming practices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Consider this example of &lt;code&gt;should_change&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;context "updating a post" do
  setup do
    @post = Post.create(:title =&gt; "old")
    put :update, :post =&gt; {:title =&gt; "new"}, :id =&gt; @post.to_param
  end

  should_change("the post title", :from =&gt; "old", :to =&gt; "new") { @post.title }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This reads well and seems to be fairly straightforward.  Sadly, &lt;strong&gt;this doesn’t work&lt;/strong&gt; because of how &lt;code&gt;should_change&lt;/code&gt; works internally (hence the confusing part).  It would actually need to be written like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;context "given a post" do
  setup do
    @post = Post.create(:title =&gt; "old")
  end

  context "updating" do
    setup do
      put :update, :post =&gt; {:title =&gt; "new"}, :id =&gt; @post.to_param
    end

    should_change("the post title", :from =&gt; "old", :to =&gt; "new") { @post.title }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;@post&lt;/code&gt; instance variable needs to be assigned a context above the context containing &lt;code&gt;should_change&lt;/code&gt;.  I &lt;em&gt;told&lt;/em&gt; you it was confusing.&lt;/p&gt;

&lt;p&gt;Now, onto the bad practice aspect.  This tests that the post was saved!  Come on, we don’t want to do that here.  That’s why we write Cucumber scenarios!  We’re testing &lt;em&gt;the controller&lt;/em&gt;, right?  If that’s the case, then we shouldn’t care whatsoever if &lt;code&gt;update_attributes&lt;/code&gt; worked with specific data passed to it, just that it was called and that we handle the result accordingly.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;context "updating a post" do
  setup do
    @post = Factory :post
    Post.stubs(:find =&gt; @post)
  end

  context "when the update is successful" do
    setup do
      @post.stubs(:update_attributes =&gt; true)
      put :update, :post =&gt; {:title =&gt; "new"}, :id =&gt; @post.to_param
    end

    should set_the_flash.to(/updated/)
    should redirect_to(posts_path)
  end

  context "when the update is unsuccessful" do
    setup do
      @post.stubs(:update_attributes =&gt; false)
      put :update, :post =&gt; {:title =&gt; "new"}, :id =&gt; @post.to_param
    end

    should render_template(:edit)
    should assign_to(:post).with(@post)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is more inline with what we &lt;em&gt;really&lt;/em&gt; want to test; that the controller handled &lt;code&gt;update_attributes&lt;/code&gt; correctly when the update worked and when it didn’t.  Leave the model logic and whether it should save or not in the model (and its tests), and test the controller to ensure it handles whether the model was updated.&lt;/p&gt;

&lt;p&gt;I mentioned before that Cucumber scenarios should cover overall integration.  Something like these would work:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Scenario: Update a post successfully
  Given I am signed in
  And I authored a post titled "Great Scott"
  When I go to edit the "Great Scott" post
  And I fill in "Title" with "Willard Scott"
  And I press "Update"
  Then I should see the flash message "Your post was updated successfully"
  And I should have authored "Willard Scott"

Scenario Example: Update a post unsuccessfully
  Given I am signed in
  And I authored a post titled "Great Scott"
  When I go to edit the "Great Scott" post
  And I fill in "&lt;required field&gt;" with ""
  And I press "Update"
  Then I should see error messages
  When I fill in "&lt;required field&gt;" with "&lt;valid value&gt;"
  And I press "Update"
  Then I should see "Your post was updated successfully"
  Examples:
    | required field | valid value       |
    | Title          | Awesome Post Name |
    | Body           | Awesome story     |
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m sure this isn’t the only way people were using &lt;code&gt;should_change&lt;/code&gt;, but hopefully this clarifies how deprecating the methods will encourage better tests.&lt;/p&gt;

&lt;p&gt;Do you use &lt;code&gt;should_change&lt;/code&gt; and think it’s by far the best way to test certain pieces of code?  I’d like to see some people who’ll sorely miss it post some real code (&lt;a href="http://pastebin.com/"&gt;Pastebin&lt;/a&gt; or &lt;a href="http://gist.github.com/"&gt;Gist&lt;/a&gt;).&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/Qi7OWFnUJFk/731871832</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/731871832</guid><pubDate>Thu, 24 Jun 2010 13:38:00 -0400</pubDate><category>Development</category><feedburner:origLink>http://robots.thoughtbot.com/post/731871832</feedburner:origLink></item><item><title>Ben Orenstein is a Ruby buddy of ours in Boston who is teaching...</title><description>&lt;object width="400" height="254"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ke7SfUFvvxo&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/ke7SfUFvvxo&amp;rel=0&amp;egm=0&amp;showinfo=0&amp;fs=1" type="application/x-shockwave-flash" width="400" height="254" allowFullScreen="true" wmode="transparent"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a href="http://codeulatescreencasts.com"&gt;Ben Orenstein&lt;/a&gt; is a Ruby buddy of ours in Boston who is teaching our &lt;a href="https://training.thoughtbot.com/courses/12-vim-for-rubyists/registrations/new"&gt;vim training&lt;/a&gt; on Friday afternoon/early evening.&lt;/p&gt;

&lt;p&gt;Check out this video he made giving a few suggestions for reaching vim mastery. I think you’ll find Ben is a good teacher who thinks deeply about how people learn.&lt;/p&gt;

&lt;p&gt;It’s not too late to &lt;a href="https://training.thoughtbot.com/courses/12-vim-for-rubyists/registrations/new"&gt;register&lt;/a&gt;, and you have ample time to &lt;a href="https://training.thoughtbot.com/courses/14-vim-for-rubyists/registrations/new"&gt;register for the next session in September&lt;/a&gt;. Hope to see you there!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/swLvvUPAoVI/729462910</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/729462910</guid><pubDate>Wed, 23 Jun 2010 15:43:00 -0400</pubDate><feedburner:origLink>http://robots.thoughtbot.com/post/729462910</feedburner:origLink></item><item><title>Giant Robots Redesign Wallpapers</title><description>&lt;p&gt;To celebrate the &lt;a href="http://robots.thoughtbot.com/post/726335248/giant-robots-gets-an-overhaul"&gt;redesign of this very blog&lt;/a&gt; we’re sharing some GIANT ROBOTS themed desktop wallpaper. They’re available in a few common screen sizes for your convenience.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://ui.thoughtbot.com/assets/wallpaper/GR-668.jpg" alt="thoughtbot wallpaper giant robots"/&gt;&lt;/p&gt;
&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-1440x900.jpg"&gt;1440x900&lt;/a&gt;&lt;br/&gt;&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-1920x1200.jpg"&gt;1920x1200&lt;/a&gt;&lt;br/&gt;&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-2560x1600.jpg"&gt;2560x1600&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;img src="http://ui.thoughtbot.com/assets/wallpaper/GR-Backlit-668.jpg" alt="thoughtbot wallpaper giant robots"/&gt;&lt;/p&gt;
&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Backlit-1440x900.jpg"&gt;1440x900&lt;/a&gt; &lt;br/&gt;&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Backlit-1920x1200.jpg"&gt;1920x1200&lt;/a&gt; &lt;br/&gt;&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Backlit-2560x1600.jpg"&gt;2560x1600&lt;/a&gt; &lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;img src="http://ui.thoughtbot.com/assets/wallpaper/GR-Zoom-668.jpg" alt="thoughtbot wallpaper giant robots"/&gt;&lt;/p&gt;
&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Zoom-1440x900.jpg"&gt;1440x900&lt;/a&gt;&lt;br/&gt;&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Zoom-1920x1200.jpg"&gt;1920x1200&lt;/a&gt;&lt;br/&gt;&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Zoom-2560x1600.jpg"&gt;2560x1600&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;img src="http://ui.thoughtbot.com/assets/wallpaper/GR-Loner-Ralph-668.jpg" alt="thoughtbot wallpaper giant robots"/&gt;&lt;/p&gt;
&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Loner-Ralph-1440x900.jpg"&gt;1440x900&lt;/a&gt;&lt;br/&gt;&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Loner-Ralph-1920x1200.jpg"&gt;1920x1200&lt;/a&gt;&lt;br/&gt;&lt;a href="http://ui.thoughtbot.com/assets/wallpaper/GR-Loner-Ralph-2560x1600.jpg"&gt;2560x1600&lt;/a&gt;&lt;br/&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/zShSkML0kyA/729237454</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/729237454</guid><pubDate>Wed, 23 Jun 2010 12:08:00 -0400</pubDate><category>design</category><feedburner:origLink>http://robots.thoughtbot.com/post/729237454</feedburner:origLink></item><item><title>Giant Robots Gets An Overhaul </title><description>&lt;p&gt;Last week we started on a blog redesign, it’s live now in case you hadn’t noticed (get in here RSS subscribers!). It was the last of our products that needed an overhaul to get up to date with some of our current styles. First we did the &lt;a href="http://hoptoadapp.com"&gt;Hoptoad&lt;/a&gt; and Widgetfinger (RIP) skins, then we did &lt;a href="http://thoughtbot.com"&gt;thoughtbot.com&lt;/a&gt; and finally our &lt;a href="http://training.thoughtbot.com"&gt;training app&lt;/a&gt;. Giant Robots was the last on our list and I finally had a little downtime to work on it.&lt;/p&gt;

&lt;p&gt;We approached it similar to the thoughtbot.com redesign with two designers having a go, and taking the best of both ideas for a final version. Kyle and I both took a few stabs at the design. He was tasked with taking a more minimal approach because I knew I’d be trying an over the top, elaborate design. Our only goal was to match the brand/feel of thoughtbot.com so it wasn’t such a harsh transition when you came to the blog. Other goals included making the content area a little wider, getting rid of a lot of extraneous stuff, and to update the look and feel to a more modern styled blog.&lt;/p&gt;

&lt;h2&gt;Review and Compare&lt;/h2&gt;
&lt;img src="http://ui.thoughtbot.com/assets/fred-kyle-blog-design.png" alt="Blog Redesign"/&gt;&lt;p&gt;When we compared two of our multiple versions, there were things from both that helped contribute to the final design. When I looked at them I definitely knew I liked Kyle’s approach more, sticking with the bare minimums and keeping it as clean as possible. The main things that persisted from my design were the colors and the body styles. From Kyle’s came the minimal approach. His simplicity and elegant typography really struck me.&lt;/p&gt;

&lt;p&gt;Amidst the design process Kevin said something that stuck with me and became a goal of mine when putting the final design together. We had been looking at a blog post on &lt;a href="http://blog.twitter.com"&gt;twitter’s blog&lt;/a&gt; and Kevin mentioned that the content was his only focus. It’s what he initially was drawn to, and what he stayed focused on. I wanted this to happen with the new Giant Robots. This became my first goal, to have the content be the primary focus, and nothing else. I know this should always be the case, but sometimes we veer off the content is king path a little to make things look snazzy, I know at least I do. The main method of achieving this was to strip everything else from around the site. Every time I thought I had finished stripping things away, I realized we could take more. There’s even been things removed since the design was pushed live less than 24 hours ago. We think the new design is a success, let us know how you feel.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/-LQpqwDKJAY/726335248</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/726335248</guid><pubDate>Tue, 22 Jun 2010 15:46:00 -0400</pubDate><category>design</category><feedburner:origLink>http://robots.thoughtbot.com/post/726335248</feedburner:origLink></item><item><title>factory_girl 1.3: integrating effectively with Rails 3</title><description>&lt;p&gt;&lt;img height="359" width="300" src="http://ui.thoughtbot.com/assets/factory_girl_bw.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;factory_girl has always had little Rails-specific code. It only depends on Ruby, and in order to use it in your application, it asks three things of your models:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They can be instantiated without parameters&lt;/li&gt;
&lt;li&gt;All properties have writer methods&lt;/li&gt;
&lt;li&gt;They respond to &lt;code&gt;#save!&lt;/code&gt; (this is only necessary for the “create” strategy)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, despite this simple API, there’s one feature in factory_girl that has traditionally caused some issues with Rails: automatic factory definition loading.&lt;/p&gt;
&lt;p&gt;The definition loader has simple rules: if it finds any of &lt;code&gt;test/factories.rb&lt;/code&gt;, &lt;code&gt;spec/factories.rb&lt;/code&gt;, &lt;code&gt;test/factories/**/*.rb&lt;/code&gt;, or &lt;code&gt;spec/factories/**/*.rb&lt;/code&gt;, it will load those files in no particular order. For most applications, this just makes things a little nicer.&lt;/p&gt;
&lt;h2&gt;Hacking around Rails dependency management&lt;/h2&gt;
&lt;p&gt;In early versions of factory_girl, it looked for definitions as soon as you loaded &lt;code&gt;factory_girl.rb&lt;/code&gt;. Unfortunately, this broke down when Rails 2.1 introduced gem dependency management. Loading factory_girl during the application initialization phase meant that the factory definitions might reference your models before all the gems and plugins they depended on were fully loaded. Contributer technicalpickles &lt;a href="http://github.com/thoughtbot/factory_girl/commit/153ecd0"&gt;fixed that&lt;/a&gt; by detecting Rails and deferring definition loading until Rails was initialized. This solution worked effectively for the entire Rails 2.x series of releases.&lt;/p&gt;
&lt;h2&gt;Bundler: effective but strict dependency management&lt;/h2&gt;
&lt;p&gt;The upcoming Rails 3 release uses a new library for managing application dependencies: &lt;a href="http://gembundler.com/"&gt;bundler&lt;/a&gt;. Bundler’s behavior is more predictable and understandable than Rails 2’s dependency manager ever was. However, with the introduction of Bundler, two important changes were introduced that impacted many libraries that integrate silently with each other:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rails is no longer initialized by the time your gem is loaded&lt;/li&gt;
&lt;li&gt;Load order is no longer configurable, so you can’t depend on another gem’s constants being defined when you integrate with it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yehuda Katz, the author of Bundler, discussed this topic in depth &lt;a href="http://yehudakatz.com/require-order/"&gt;on his blog&lt;/a&gt;. In his discussion, he suggests a solution that could be added to Rubygems:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s.integrates_with "rails", "~&gt; 3.0.0.beta2", "haml/rails" 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, this functionality doesn’t exist yet, so we’ve decided to create a separate factory_girl_rails gem. This way, we can declare an explicit dependency on Rails, including the version, and automatic definition loading still takes place for Rails apps without any additional application code.&lt;/p&gt;
&lt;h2&gt;What this means for you&lt;/h2&gt;
&lt;p&gt;This doesn’t change much for an application that uses factory_girl. It boils down to this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you’re using Rails 2, just depend on the factory_girl gem, and Rails 2 will pick up the existing &lt;code&gt;rails/init.rb&lt;/code&gt; and load your definitions.&lt;/li&gt;
&lt;li&gt;If you’re using Rails 3, just add factory_girl_rails to your Gemfile. This gem depends on factory_girl and will set up definition loading for you.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A lesson on “easy to add” features&lt;/h2&gt;
&lt;p&gt;I originally added this feature to factory_girl because it was convenient, and seemed easy to add. However, this trivial feature has turned out to be the most difficult to maintain part of factory_girl, and is the single feature that is most likely to outright break an application. I plan on maintaining this feature because we’re used to having it and we’ve worked out most of the kinks at this point, but next time you consider adding an “easy” feature to your own library, also consider whether or not it’s essential to your library’s core mission.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/pJxTllU8RYY/722112946</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/722112946</guid><pubDate>Mon, 21 Jun 2010 11:18:00 -0400</pubDate><category>factory_girl</category><category>rails3</category><category>development</category><feedburner:origLink>http://robots.thoughtbot.com/post/722112946</feedburner:origLink></item><item><title>Sailing down the Hudson with RVM</title><description>&lt;p&gt;We recently decided our CI server needed an overhaul. I really enjoyed &lt;a href="http://integrityapp.com"&gt;Integrity&lt;/a&gt; as a build server, but after trying out &lt;a href="http://hudson-ci.org"&gt;Hudson&lt;/a&gt; it’s hard to say I want to go back. Hudson has several huge advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Totally self contained. Integrity was a constant mashup. I don’t want to maintain the codebase for my CI server anymore.&lt;/li&gt;
&lt;li&gt;Live console output. When your builds take 20-30 minutes, this is really nice.&lt;/li&gt;
&lt;li&gt;Metrics/graphing built in! None so far on the other side of homegrown Ruby CI servers.&lt;/li&gt;
&lt;li&gt;Kickass plugin installing, don’t need to hack a Gemfile or fix bad code (so far).&lt;/li&gt;
&lt;li&gt;Building multiple branches in the same project is no longer a hassle.&lt;/li&gt;
&lt;li&gt;Jobs won’t stomp over each other, and I don’t need separate configuration/database for them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s the details of what I went through to get our new CI server up and running. Be warned, these are probably specific to our projects and needs, but the general process can definitely help anyone who’s looking to get started.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://img.skitch.com/20100618-njew6cxqpshc4574i392ppu68c.jpg"/&gt;&lt;/p&gt;
&lt;h2&gt;Basic Loadout&lt;/h2&gt;
&lt;p&gt;We started with a fresh Ubuntu 9.04 LTS install. First up was a basic iptables setup, all the commands you need are on &lt;a href="http://articles.slicehost.com/2008/4/25/ubuntu-hardy-setup-page-1"&gt;this SliceHost article.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next up we needed to install Hudson. Follow the instructions here: &lt;a href="http://hudson-ci.org/debian/"&gt;http://hudson-ci.org/debian/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The nice part about this install (instead of custom compiling it) is that it comes with an init script that is really handy to stop/start the server. &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Installing+Hudson+on+Ubuntu"&gt;There’s more tips on installing here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If apt-get starts whining, just run &lt;code&gt;sudo apt-get install -f&lt;/code&gt;. The hudson package should install the Java dependencies you’ll need for now.&lt;/p&gt;
&lt;p&gt;Let’s also install some other basics we’ll need eventually. You may disagree with my choices here, but too bad, I’m the one maintaining CI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install zsh vim git-core build-essential postfix ack-grep
curl
chsh /usr/bin/zsh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The postfix install will prompt you for your server’s host name, we’ll want it eventually for emails. If you’re confused, &lt;a href="http://articles.slicehost.com/2008/7/29/postfix-installation"&gt;check this article out.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By now you should be able to visit http://YOUR_SERVER_IP:8080 and Hudson should be alive and kicking.&lt;/p&gt;
&lt;h2&gt;Apache Setup&lt;/h2&gt;
&lt;p&gt;That’s annoying though, we want to serve requests on port 80. Supposedly doing this with Hudson itself is a bad idea, since it would need to run as root. Apache does a better job, and &lt;a href="http://www.zzorn.net/2009/11/setting-up-hudson-on-port-80-on-debian.html"&gt;this tutorial goes over the reasons why&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here’s what I had to do to get this working:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install apache2 libapache2-mod-proxy-html
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2dissite 000-default
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That will install apache2, get the proxy mod enabled to forward requests along to hudson from the root domain, and disable the default site. Next step is editing &lt;code&gt;/etc/apache2/apache2.conf&lt;/code&gt; and adding the following directive to the bottom:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# where your server lives!
ServerName ci.thoughtbot.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next up we’ll need to actually make a virtual host for apache to serve (thanks to &lt;a href="http://serverfault.com/questions/140125/port-to-subdomain"&gt;this StackOverflow question&lt;/a&gt; for the right incantations). Create &lt;code&gt;/etc/apache2/sites-available/hudson&lt;/code&gt; with the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;VirtualHost *:80&gt;
  ProxyPass         /  http://localhost:8080/
  ProxyPassReverse  /  http://localhost:8080/
  ProxyRequests     Off

  # Local reverse proxy authorization override
  # Most unix distribution deny proxy by default 
  # (ie /etc/apache2/mods-enabled/proxy.conf in Ubuntu)
  &lt;Proxy http://localhost:8080/*&gt;
    Order deny,allow
    Allow from all
  &lt;/Proxy&gt;
&lt;/VirtualHost&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the final touch to enable hudson and fire up apache:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo a2ensite hudson
sudo /etc/init.d/apache2 restart&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Hudson Configuration&lt;/h2&gt;
&lt;p&gt;Port 80 is much better. Now to continue with the configuration! We’re just using a &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Standard+Security+Setup"&gt;standard security setup&lt;/a&gt; with one user. The process is a bit confusing, you have to enable authorization, then go out and sign up to set the password. After that, make sure you set the anonymous user permissions so they can see jobs on the home page.&lt;/p&gt;
&lt;p&gt;If you’re an idiot like me and locked yourself out while doing this, &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Disable+security"&gt;disabling security&lt;/a&gt; is pretty simple.&lt;/p&gt;
&lt;p&gt;As for plugins, we chose so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Git SCM (allows us to check out from git)&lt;/li&gt;
&lt;li&gt;GitHub (links files in builds on github)&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://github.com/jgp/hudson_campfire_plugin"&gt;Campfire&lt;/a&gt; (You’ll need Maven locally to build this, the default one &lt;strong&gt;does not work&lt;/strong&gt;.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After installing the plugins and restarting, I disabled a bunch we didn’t need too, like Maven, CVS, etc. I would also check the “Prevent CSRF” button, that’s just a ridiculous option not to have on.&lt;/p&gt;
&lt;h2&gt;Databases&lt;/h2&gt;
&lt;p&gt;Let’s get mysql and postgres installed first.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install mysql-server mysql-client libmysqlclient15-dev
sudo apt-get install postgresql postgresql-client postgresql-contrib&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Redis is up next. We’re running the release candidate of 2.0, which is a bit of a pain to set up so far since &lt;code&gt;make install&lt;/code&gt; was removed. I came up with an &lt;a href="http://gist.github.com/444033"&gt;upstart script&lt;/a&gt;to run it instead.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo adduser redis
sudo su - redis
curl -O &lt;a href="http://redis.googlecode.com/files/redis-2.0.0-rc1.tar.gz"&gt;http://redis.googlecode.com/files/redis-2.0.0-rc1.tar.gz&lt;/a&gt;
tar zxvf redis-2.0.0-rc1.tar.gz
cd redis-2.0.0-rc1.tar.gz
make
logout
sudo bash -c "curl &lt;a href="http://gist.github.com/raw/444033/9784f426402d5bece09894fcc6f98a33db5f5d15/redis.upstart"&gt;http://gist.github.com/raw/444033/9784f426402d5bece09894fcc6f98a33db5f5d15/redis.upstart&lt;/a&gt; &gt; /etc/event.d/redis"
sudo start redis&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Finally, Ruby!&lt;/h2&gt;
&lt;p&gt;Now that &lt;a href="http://rvm.beginrescueend.com/"&gt;RVM&lt;/a&gt; exists, we can completely isolate projects from each other using &lt;a href="http://rvm.beginrescueend.com/gemsets/"&gt;gemsets&lt;/a&gt;. First we’re going to need even more system packages to deal with ruby and the other gems we’ll be installing eventually (nokogiri, paperclip, etc):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install bison openssl libreadline5 libreadline-dev zlib1g zlib1g-dev libssl-dev                                                                                                            libsqlite3-0 libsqlite3-dev sqlite3 libreadline5-dev libreadline6-dev                                                                                                              libxml2-dev subversion autoconf libxslt-dev imagemagick&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jump in as the hudson user now and set up RVM:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo su - hudson
bash &lt; &lt;( curl &lt;a href="http://rvm.beginrescueend.com/releases/rvm-install-head"&gt;http://rvm.beginrescueend.com/releases/rvm-install-head&lt;/a&gt; )
echo "[[ -s $HOME/.rvm/scripts/rvm ]] &amp;&amp; source $HOME/.rvm/scripts/rvm" &gt; .profile
echo "---\ngem: --no-ri --no-rdoc" &gt; .gemrc&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Install the rubies you need now. Our starting lineup:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rvm install 1.8.6
rvm install 1.8.7
rvm install ree
rvm install jruby&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Maybe not finally.&lt;/h2&gt;
&lt;p&gt;We’ll need to get the hudson user set up with git and github too. Make sure to upload your public key &lt;code&gt;~/.ssh/id_rsa.pub&lt;/code&gt; to github so you can start cloning repos.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-keygen -t rsa
git config --global user.email "hudson@thoughtbot.com"
git config --global user.name "hudson"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For each app, create the gemset, databases, and get the gems you need. &lt;a href="http://gembundler.com"&gt;Bundler&lt;/a&gt; would make this easier, but we’re not on it for all projects yet.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo su - hudson
rvm gemset create hoptoad
rvm gemset use hoptoad
mysql -u root
&gt; create database hoptoad_development;
&gt; create database hoptoad_test;
gem install mysql nokogiri json&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make a new Hudson job, check from SCM periodically, enable the post build notifications you want. Here’s the build script we’re using for hoptoad so far:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bash -l -c "rvm use 1.8.6-p287 &amp;&amp; rvm gemset use hoptoad &amp;&amp; rake db:migrate db:test:prepare default"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Debug, rinse, and repeat until it’s green.&lt;/p&gt;
&lt;h2&gt;Made it!&lt;/h2&gt;
&lt;p&gt;RVM made this process a lot easier, I used to have to compile multiple versions of Ruby on my own and it was just a pain to manage. Gemsets are a killer feature too, and it’s easy to move them around to another Ruby version with the copy command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rvm gemset copy 1.8.6@factory_girl 1.8.7@factory_girl&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Overall the process was pretty smooth, and like any CI solution this took a while to set up and has its share of annoyances:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Campfire plugin was obnoxious to figure out. Not sure why they ship a broken one, but the custom one from GitHub works great.&lt;/li&gt;
&lt;li&gt;Unfortunately, I couldn’t figure out how to make GitHub’s post-receive URLs trigger a build. It worked with a GET request, but POST requests seem to need some special authentication. Hudson has a cron-job style SCM polling, so that works instead.&lt;/li&gt;
&lt;li&gt;Lots of clicking around to configure everything, my vim-senses are tingling for a command line interface.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope these guidelines help those new to continuous integration with Hudson or otherwise. Of course, there’s &lt;a href="http://github.com/blog/471-continuous-integration-spring-cleaning"&gt;plenty of other options&lt;/a&gt; in the Ruby-verse, but hopefully you won’t pass up what Hudson has to offer.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://30.media.tumblr.com/tumblr_l4476sXhS61qz4sngo1_500.jpg"/&gt;&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/xKRYA3dxHsA/712609699</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/712609699</guid><pubDate>Fri, 18 Jun 2010 16:59:00 -0400</pubDate><category>development</category><feedburner:origLink>http://robots.thoughtbot.com/post/712609699</feedburner:origLink></item><item><title>Redesigning the toad</title><description>&lt;p&gt;Over the last few weeks, we released several redesigned pages for Hoptoad. With the launch of its new Bossfrog plan, we redesigned the homepage and plans and pricing page. Yesterday, we released the redesign of the sign up form. The biggest goal for the redesign was to convert more of Hoptoad’s visitors to users.  We also wanted to keep the process from the homepage to signing up to be a cohesive experience.&lt;/p&gt;
&lt;p&gt;The idea for the Hoptoad  homepage was to give a new coat of paint based on some of the feedback and metrics that have been collected, not do a total redesign. We added more entry points into the plans and pricing page, added clearer messaging about what Hoptoad is, and highlighted that it’s not just a Rails service.&lt;/p&gt;
&lt;p&gt;&lt;a href="#ht_home_old" class="zoom"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_home_old_thum.jpg"/&gt;&lt;/a&gt;&lt;a href="#ht_home_new" class="zoom"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_home_new_thum.jpg"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The plans and pricing page and sign up page have adapted the style of the homepage. The plans have been grouped vertically so that they are easily comparable. The backgrounds fade out from largest to smallest to help convey the difference in size.&lt;/p&gt;
&lt;p&gt;&lt;a href="#ht_plans_old" class="zoom"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_plans_old_thum.jpg"/&gt;&lt;/a&gt;&lt;a href="#ht_plans_new" class="zoom"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_plans_new_thum.jpg"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On the sign up page the plan information has been moved to the side so that it won’t get in the way of users filling out the form. Inputs have been made bigger, given more space and more emphasis. The form has been broken down into only two sections instead of three, making it seem like less to fill out. Lastly, the create account button has been made bigger and more inviting.&lt;/p&gt;
&lt;p&gt;&lt;a href="#ht_signup_old" class="zoom"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_signup_old_thum.jpg"/&gt;&lt;/a&gt;&lt;a href="#ht_signup_new" class="zoom"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_signup_new_thum.jpg"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Check out the revamped design at &lt;a href="http://hoptoadapp.com"&gt;hoptoadapp.com&lt;/a&gt; and let us know what you think.&lt;/p&gt;
&lt;p id="ht_signup_old"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_signup_old.jpg"/&gt;&lt;/p&gt;
&lt;p id="ht_signup_new"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_signup_new.jpg"/&gt;&lt;/p&gt;
&lt;p id="ht_home_new"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_home_new.jpg"/&gt;&lt;/p&gt;
&lt;p id="ht_home_old"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_home_old.jpg"/&gt;&lt;/p&gt;
&lt;p id="ht_plans_new"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_plans_new.jpg"/&gt;&lt;/p&gt;
&lt;p id="ht_plans_old"&gt;&lt;img src="http://ui.thoughtbot.com/assets/hoptoad-redesign/ht_plans_old.jpg"/&gt;&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/A74pbx_n8As/704639714</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/704639714</guid><pubDate>Wed, 16 Jun 2010 10:49:00 -0400</pubDate><category>design</category><feedburner:origLink>http://robots.thoughtbot.com/post/704639714</feedburner:origLink></item></channel></rss>
