<?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:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><description>This is the company blog of thoughtbot, a web design and development agency based in Boston, MA.</description><title>giant robots smashing into other giant robots</title><generator>Tumblr (3.0; @thoughtbot)</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>Your next great teammate</title><description>&lt;p&gt;Every company we speak with could use a great web designer or developer on their team. We think we know where to find such mysterious figures.&lt;/p&gt;
&lt;h2&gt;What does a great teammate look like?&lt;/h2&gt;

&lt;p&gt;Imagine a programmer next to you, noise-canceling headphones on, punishing his keyboard with forceful blows, punctuating each change by slamming the heels of his hands against his desk. While tests run, jolly meme photos float into Campfire.&lt;/p&gt;
&lt;p&gt;Imagine this person writing test-first code that is pushed to production each day. Imagine them refactoring ruthlessly and making other team members stronger through feature branch code reviews.&lt;/p&gt;
&lt;p&gt;37signals doesn’t have to imagine. &lt;a href="http://twitter.com/qrush"&gt;Nick Quaranto&lt;/a&gt; now works with them.&lt;/p&gt;
&lt;p&gt;Nick was an apprentice at thoughtbot. We cannot claim responsibility for his motivation, problem solving abilities, or other Nick-isms, but his time with us was not an aberration.&lt;/p&gt;
&lt;h2&gt;There are plenty of great designers and developers worldwide&lt;/h2&gt;

&lt;p&gt;75% of the new team members we hired last year started as apprentices.&lt;/p&gt;
&lt;p&gt;Last year, we met Prem Sichanugrist, a lifelong Thailand resident. You’ll find him currently ranked &lt;a href="http://contributors.rubyonrails.org/contributors/prem-sichanugrist/commits"&gt;#32 for most commits to Rails&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Galen Frechette creates useful and beautiful stuff like &lt;a href="http://design.thoughtbot.com"&gt;this&lt;/a&gt;. &lt;a href="https://twitter.com/#!/alex_godin"&gt;Alex Godin&lt;/a&gt; was in Techstars New York before he could legally buy a pack of smokes. Gabe Berke-Williams is becoming a prolific (and often funny) &lt;a href="https://github.com/gabebw"&gt;open source contributor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All are former thoughtbot apprentices.&lt;/p&gt;
&lt;h2&gt;Running an apprenticeship program isn’t easy&lt;/h2&gt;

&lt;p&gt;We’ve now run an internal apprentice program for about two years. We’ve also run design and development workshops for years.&lt;/p&gt;
&lt;p&gt;Like many things, these are easy to start but difficult to regularly do well. Apprentices will temporarily slow their mentors down. Questions will arise.&lt;/p&gt;
&lt;p&gt;How much time should be spent pairing? Attending workshops? Reading the Pickaxe or watching Peepcodes? Reading incoming code reviews from a variety of projects?&lt;/p&gt;
&lt;p&gt;We’re getting good at many of these subtle details. As a fairly efficient design-and-code consultancy, we’re the right team to try to push the limits.&lt;/p&gt;
&lt;h2&gt;apprentice.io&lt;/h2&gt;

&lt;p&gt;We’re now opening up our apprenticeship program externally for any company that would like to sponsor apprentices. We’re calling this new program &lt;a href="http://apprentice.io"&gt;apprentice.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you sign up on the website as an employer you get immediate access to the bios of all of the current apprentices and the others from all over the world that we already have scheduled for this year.&lt;/p&gt;
&lt;p&gt;As an employer, you contact and interact with the apprentices directly. Over time we’ll grow the apprentice.io platform to provide mentor-to-employer updates on the progress of apprentices, and more.&lt;/p&gt;
&lt;p&gt;For little more than you may already pay job boards and a lot less than you might pay recruiters, this money now goes to train people.&lt;/p&gt;
&lt;p&gt;We think that’s a powerful idea: what if instead of recruiting, you educate?&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.apprentice.io/employers/new"&gt;Sign up as an employer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you’re a designer or developer interested in apprenticing, please &lt;a href="https://www.apprentice.io/pages/apply"&gt;apply&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you just want to talk about this, please email me at &lt;a href="mailto:apply@apprentice.io"&gt;apply@apprentice.io&lt;/a&gt; or call me at (877) 976-2687 x113.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/p-0gc2eNfPs/17272077669</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/17272077669</guid><pubDate>Wed, 08 Feb 2012 13:47:00 -0500</pubDate><category>apprentice.io</category><category>apprenticeship</category><category>hiring</category><category>designers</category><category>developers</category><feedburner:origLink>http://robots.thoughtbot.com/post/17272077669</feedburner:origLink></item><item><title>Airbrake acquired by Exceptional</title><description>&lt;p&gt;Late last year, Airbrake was acquired by the team at Exceptional, inc. We’re extremely excited about this move and we’d like to explain why.&lt;/p&gt;

&lt;h3&gt;A brief history&lt;/h3&gt;

&lt;p&gt;We created Hoptoad in the fall of 2007 and launched it publicly in spring of 2008. We had been tracking our errors previously with an email notifier that flooded our inboxes with repeat errors, many generated by search engines requesting weird URLs.&lt;/p&gt;

&lt;p&gt;In 2011, we renamed the product Airbrake.&lt;/p&gt;

&lt;p&gt;Over the years, Airbrake handled billions of error reports for thousands of web applications from all over the world. We kept the product focused on grouping similar errors, notifying developers once per error, and displaying the backtrace and session information to help debug the issue.&lt;/p&gt;

&lt;h3&gt;A serious commitment&lt;/h3&gt;

&lt;p&gt;As the number of customers and errors increased, we spent a lot of time addressing scaling issues. There were times we’d have 150,000 requests per minute, or requests with 500MB of session data.&lt;/p&gt;

&lt;p&gt;Running Airbrake was like being under a constant DoS attack.&lt;/p&gt;

&lt;p&gt;So, we spent very little time working toward our vision of a product that integrated more completely with developer tools.&lt;/p&gt;

&lt;p&gt;Last year, we were approached by the Exceptional team and their Chief Strategic Officer, Jonathan Siegel (who has created or invested in &lt;a href="http://rightsignature.com"&gt;RightSignature&lt;/a&gt;, &lt;a href="http://www.rightscale.com/"&gt;RightScale&lt;/a&gt;, &lt;a href="http://intercom.io"&gt;Intercom&lt;/a&gt;, and &lt;a href="http://iron.io"&gt;Iron.io&lt;/a&gt;). Exceptional had a team ready to work toward the same vision we had for Airbrake.&lt;/p&gt;

&lt;h3&gt;The future&lt;/h3&gt;

&lt;p&gt;After getting to know the Exceptional team, we felt their serious financial and team commitment had the best chance to turn our shared vision into reality. We agreed to sell Airbrake to Exceptional.&lt;/p&gt;

&lt;p&gt;The new team has been handling all support issues and feature work for several months now. We’re very pleased with their work so far.&lt;/p&gt;

&lt;p&gt;We continue to provide web design and development consulting and are developing &lt;a href="http://apptrajectory.com"&gt;Trajectory&lt;/a&gt;, &lt;a href="http://copycopter.com"&gt;Copycopter&lt;/a&gt;, and &lt;a href="http://apprentice.io"&gt;apprentice.io&lt;/a&gt; to help solve problems for web design and development teams.&lt;/p&gt;

&lt;h3&gt;Thank you&lt;/h3&gt;

&lt;p&gt;If you’ve been an Airbrake customer, thank you! It’s been a great experience for us and you continue to be in good hands with the new team.&lt;/p&gt;

&lt;p&gt;Read more about the acquisition at &lt;a href="http://techcrunch.com/2012/02/07/exceptional-acquires-error-tracking-application-airbrake/"&gt;TechCrunch&lt;/a&gt; and the past, present, and future of Airbrake at the &lt;a href="http://blog.airbrake.io/airbrake-news/how-exceptional-and-airbrake-first-met/"&gt;Airbrake blog&lt;/a&gt;.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/WA-qgiQbXYA/17212734809</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/17212734809</guid><pubDate>Tue, 07 Feb 2012 17:45:00 -0500</pubDate><category>airbrake</category><category>hoptoad</category><category>error tracking</category><category>exception tracking</category><feedburner:origLink>http://robots.thoughtbot.com/post/17212734809</feedburner:origLink></item><item><title>Design 101: Stop Yelling</title><description>&lt;p&gt;How do you make yourself heard in a loud room? BY YELLING! And when it comes to design, that’s often the approach used for drawing attention to elements. &lt;strong&gt;LOUDER! BIGGER! FASTER!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But there’s a better way.&lt;/p&gt;

&lt;p&gt;Imagine yourself in that loud room again. Now imagine that instead of yelling to get above the noise, you could just turn down everyone else. Instead of shouting at the person you’re talking to and ending up with a strained voice, you’ll be able to have a nice, thoughtful conversation with them.&lt;/p&gt;

&lt;p&gt;While it’s hard to turn down the volume of a room, it’s easy to quiet the background noise in your design and let the important parts speak clearly. Let’s take a closer look at this idea.&lt;/p&gt;

&lt;p&gt;Below is an example of a composition where everything is shouting at you. The big red headline at the top is trying to assert itself, but so is everything else, which means, in the end, nothing stands out.&lt;/p&gt;

&lt;a href="https://workshops.thoughtbot.com/sections/34-design-for-developers"&gt;&lt;img src="http://ui.thoughtbot.com/assets/blog/emphasis/one.png" style="border: 1px solid #ddd; margin: 24px 0;"/&gt;&lt;/a&gt;

&lt;p&gt;So let’s turn down the volume. You have to decide what you’re trying to communicate and how to say it in a clear and concise way. This will drive your design decisions. In the example below, we’ve established a clear hierarchy between each bit of text. The headline still dominates, but we’ve toned down the other text so that your eye moves comfortably and naturally from headline, to subhead, to body text.&lt;/p&gt;

&lt;a href="https://workshops.thoughtbot.com/sections/34-design-for-developers"&gt;&lt;img src="http://ui.thoughtbot.com/assets/blog/emphasis/two.png" style="border: 1px solid #ddd; margin: 24px 0;"/&gt;&lt;/a&gt;

&lt;p&gt;Let’s try another iteration that makes more dramatic use of white space. I tell students in my workshop that white space is the secret ingredient in design. Effective use of white space can transform a mundane design into something that feels elegant and timeless.&lt;/p&gt;

&lt;a href="https://workshops.thoughtbot.com/sections/34-design-for-developers"&gt;&lt;img src="http://ui.thoughtbot.com/assets/blog/emphasis/three.png" style="border: 1px solid #ddd; margin: 24px 0;"/&gt;&lt;/a&gt;

&lt;p&gt;In this example, I’ve made the headline and subhead the same size as the body copy. I’m relying on white space to create the hierarchy, isolating the elements within the composition so they can establish their presence without competing with surrounding elements. Think of that loud room again. Not only have we quieted the voices in the room, we’ve moved everyone to their own corner so they can talk without distraction.&lt;/p&gt;

&lt;p&gt;When thinking about how to create emphasis, don’t be so quick to turn up the volume. Think about how to use hierarchy and white space to communicate your message without shouting it at your audience. You’ll create something more elegant and respectful that still accomplishes your communication goal.&lt;/p&gt;

&lt;p&gt;I’ll be teaching more visual design principles and strategy in my workshop, &lt;a href="https://workshops.thoughtbot.com/sections/34-design-for-developers"&gt;Design for Developers&lt;/a&gt;, which is running Feb 27–28 in our Boston office.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/ZxIlUyhSm9k/17163570631</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/17163570631</guid><pubDate>Mon, 06 Feb 2012 14:31:00 -0500</pubDate><category>design</category><category>typography</category><category>design for developers</category><feedburner:origLink>http://robots.thoughtbot.com/post/17163570631</feedburner:origLink></item><item><title>This week in open source</title><description>&lt;h2&gt;bourbon&lt;/h2&gt;

&lt;p&gt;As a programmer I love the change that made it into version 1.3.6 (&lt;a href="http://github.com/thoughtbot/bourbon/commit/10f978df88195c0f61fd49a6b4895c2b515b0710" title="Version bump to 1.3.6"&gt;10f978d&lt;/a&gt;) of &lt;a href="https://github.com/thoughtbot/bourbon"&gt;bourbon&lt;/a&gt;: Phil LaPier (&lt;a href="http://github.com/plapier"&gt;plapier&lt;/a&gt;) added to work done by Frank (&lt;a href="https://github.com/frankzilla"&gt;frankzilla&lt;/a&gt;) to add a monospaced font family, &lt;code&gt;$monospace&lt;/code&gt;—with support for Bitstream Vera Sans Mono, my favorite monospace typeface (&lt;a href="http://github.com/thoughtbot/bourbon/commit/3467fe3adb025786e4028d6be6572c365a65e83c" title="Added Consolas to the monospaced font-family"&gt;3467fe3&lt;/a&gt; and &lt;a href="https://github.com/thoughtbot/bourbon/commit/c86e568733bbb056f751489c8e0ccf18b4906b56" title="Add monospaced font-family"&gt;c86e5687&lt;/a&gt;). Nice.&lt;/p&gt;

&lt;h2&gt;paperclip&lt;/h2&gt;

&lt;p&gt;Friday saw a new release of &lt;a href="https://github.com/thoughtbot/paperclip"&gt;paperclip&lt;/a&gt; (&lt;a href="http://github.com/thoughtbot/paperclip/commit/1cb40e352eaa0f42560021c32705933f4d4eb46a" title="Bump to version 2.5.2"&gt;1cb40e3&lt;/a&gt;), &lt;a href="http://robots.thoughtbot.com/post/16351438761/every-two-weeks"&gt;in accordance with the prophecy&lt;/a&gt;. It contains Windows support, a bug fix, and two new features.&lt;/p&gt;

&lt;p&gt;Prem Sichanugrist (&lt;a href="http://github.com/sikachu"&gt;sikachu&lt;/a&gt;) has been working on handling characters that are not URL-safe; to this end he added a &lt;code&gt;:restricted_characters&lt;/code&gt; option to &lt;code&gt;has_attached_file&lt;/code&gt;, with a default value of &lt;code&gt;&amp;$+,\/:;=?@&lt;&gt;\[\]\{\}\|\\\^~%# &lt;/code&gt;, which specifies characters to replace with an underscore, &lt;code&gt;_&lt;/code&gt; (&lt;a href="http://github.com/thoughtbot/paperclip/commit/83535184b0a40bb6b73987e210472f5457d15d79" title="Add `:restricted_characters` default options

Introducing `:restricted_characters` in Paperclip::Attachment.default_options  so people can override their blacklist characters by override that setting."&gt;8353518&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/604304e3e824cddc37f183aafd848c0f7548542b" title="Replacing all special characters to underscore

Fixes #703"&gt;604304e&lt;/a&gt;). Benjamin Hüttinger (&lt;a href="https://github.com/maxigs"&gt;maxigs&lt;/a&gt;) added the ability to pass a block, evaluated at runtime, for &lt;code&gt;:fog_host&lt;/code&gt;, &lt;code&gt;:bucket_name&lt;/code&gt;, and &lt;code&gt;:fog_credential&lt;/code&gt; options (&lt;a href="https://github.com/thoughtbot/paperclip/commit/e049ec5337e9aa0ae904bf64d3ab38793d30f8cd" title="allow proc for fog_directory so its possible to call model methods to set the directory"&gt;e049ec5&lt;/a&gt;, &lt;a href="https://github.com/thoughtbot/paperclip/commit/2b562a9be16d2398fec7f3d80685b8c8a199e655" title="allow proc for fog_host"&gt;2b562a9&lt;/a&gt;, &lt;a href="https://github.com/thoughtbot/paperclip/commit/87426153fead3f6555f33bccf41a623d330da9bc" title="allow proc for fog_credentials"&gt;8742615&lt;/a&gt;, and &lt;a href="https://github.com/thoughtbot/paperclip/commit/1c88a72519ddd4566a628457489c6e4e5872ea06" title="changed is_a?(Proc) to responds_to?(:call) for better flexibility"&gt;1c88a72&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The gem itself had problems installing on Windows because a bundled test made sure that filenames with question marks were handled fine; turns out this simply breaks on Windows. Even though no actual programmers use Windows, we removed the offending file (&lt;a href="http://github.com/thoughtbot/paperclip/commit/ed5cd9f192953278a27efa82976c21d78cea9e8f" title="Remove the questionmark filename test for real file"&gt;ed5cd9f&lt;/a&gt;). Jon Yurek (&lt;a href="http://github.com/jyurek"&gt;jyurek&lt;/a&gt;) fixed a long-standing bug where the RSpec matchers (&lt;code&gt;validate_attachment_content_type&lt;/code&gt;, &lt;code&gt;validate_attachment_presence&lt;/code&gt;, and &lt;code&gt;validate_attachment_size&lt;/code&gt;) didn’t handle the &lt;code&gt;:if&lt;/code&gt; argument they were supposed to handle (&lt;a href="http://github.com/thoughtbot/paperclip/commit/5d4ba628dedc90cb035c874f0479985b7dc767a1" title="Validation matchers respect conditionals on the validations"&gt;5d4ba62&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;capybara-webkit&lt;/h2&gt;

&lt;p&gt;A new release of &lt;a href="https://github.com/thoughtbot/capybara-webkit"&gt;capybara-webkit&lt;/a&gt; is in the works, and this is what you’ll see in it: Matthew Mongeau (&lt;a href="http://github.com/halogenandtoast"&gt;halogenandtoast&lt;/a&gt;) added the ability to trigger &lt;code&gt;mousedown&lt;/code&gt; and &lt;code&gt;mouseup&lt;/code&gt; events (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/51c4dfe1414a9b1620dfb61db456646f51a782dd" title="Simulate browsers events more closely"&gt;51c4dfe&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/16c16372c86896b060cfa5c1741d95b0653cc3a4" title="Trigger mousedown and mouseup events"&gt;16c1637&lt;/a&gt;) while Joe Ferris (&lt;a href="http://github.com/jferris"&gt;jferris&lt;/a&gt;) has commands block until the page finishes loading (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/18607d0966580000bb04822809c225930ad556d5" title="Try to detect when a command starts a page load and wait for it to finish"&gt;18607d0&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;clearance&lt;/h2&gt;

&lt;p&gt;Oh sweet, a new version of &lt;a href="https://github.com/thoughtbot/clearance"&gt;clearance&lt;/a&gt; is out (&lt;a href="http://github.com/thoughtbot/clearance/commit/6c0c070b711f1bd2f08bdb496af4bd491d41f5c7" title="Bump to 0.15.0."&gt;6c0c070&lt;/a&gt;)! In it you’ll find support for Rails 3.2 from Gabe Berke-Williams (&lt;a href="http://github.com/gabebw"&gt;gabebw&lt;/a&gt;), mostly in following deprecation warnings (&lt;a href="http://github.com/thoughtbot/clearance/commit/6e57d10db5f1a91c5f199d2d1eec8b141077cb71" title="Remove InstanceMethods module. It's deprecated in 3.2 and unnecessary in all versions."&gt;6e57d10&lt;/a&gt;). Some prodding from Matthew Daubert (&lt;a href="https://github.com/MDaubs"&gt;MDaubs&lt;/a&gt;) prompted us to upgrade cucumber-rails to 1.1.1 (&lt;a href="https://github.com/thoughtbot/clearance/commit/691e867632d2c4f27a162dbf52ce14b215676e92" title="`When` is deprecated in step definitions, changed to `step`."&gt;691e867&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/clearance/commit/91f4675dde40c0735fb52601ab7ae89b4a28f3f1" title="Upgrade cucumber-rails, which requires use of the #steps method."&gt;91f4675&lt;/a&gt;). Dan Hodge (&lt;a href="https://github.com/danhodge"&gt;danhodge&lt;/a&gt;) dropped a totally awesome change on us, abstracting out the &lt;code&gt;User&lt;/code&gt; class into &lt;code&gt;Clearance.configuration.user_model&lt;/code&gt;, which can be changed at runtime (&lt;a href="https://github.com/thoughtbot/clearance/commit/085a9b61dcf97ac8715edc0c16dc2705478832e0" title="Find user via the configured user model class"&gt;085a9b6&lt;/a&gt;, &lt;a href="https://github.com/thoughtbot/clearance/commit/a582eec8d9a791051d9f16c5ef82ec539445af0c" title="Defer user_model load so it can be a constant"&gt;a582eec&lt;/a&gt;, and &lt;a href="https://github.com/thoughtbot/clearance/commit/fc6af70702b51fe0285f00c6efcaa228fcfc0e9d" title="Optional config param 'user_model_name' added"&gt;fc6af70&lt;/a&gt;). Dude, that’s awesome.&lt;/p&gt;


&lt;h2&gt;fake_braintree&lt;/h2&gt;

&lt;p&gt;Holy cow it’s version 0.2.0 of &lt;a href="https://github.com/thoughtbot/fake_braintree"&gt;fake_braintree&lt;/a&gt; (&lt;a href="http://github.com/thoughtbot/fake_braintree/commit/0be2aea4fc9ee7a2ec1eaa00263fa8767c435249" title="Prepare for 0.2.0 release."&gt;0be2aea&lt;/a&gt;). In this Gabe Berke-Williams (&lt;a href="http://github.com/gabebw"&gt;gabebw&lt;/a&gt;) gave us the ability to specify a constant amount for a transaction (&lt;a href="http://github.com/thoughtbot/fake_braintree/commit/783719c655935eca6f4904f3ac498ed9f0ad98b1" title="Set amount when generating a transaction."&gt;783719c&lt;/a&gt;), and mimics the behavior around customers with failing credit cards (&lt;a href="http://github.com/thoughtbot/fake_braintree/commit/a2ceb5805bbb8f87133f0d3475713cd133d54f86" title="Don't allow customers to be updated with failing credit cards."&gt;a2ceb58&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;factory_girl&lt;/h2&gt;

&lt;p&gt;No big news in &lt;a href="https://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt; this week. Carlos Antonio da Silva (&lt;a href="http://github.com/carlosantoniodasilva"&gt;carlosantoniodasilva&lt;/a&gt;) updated the docs to mention that &lt;code&gt;.stub&lt;/code&gt; is now &lt;code&gt;.build_stubbed&lt;/code&gt; (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/08018f62a673d734b5cdd41deffa73f49f156f41" title='Change getting started doc to remove old "FactoryGirl.stub" method'&gt;08018f6&lt;/a&gt;). Michael Klishin (&lt;a href="http://github.com/michaelklishin"&gt;michaelklishin&lt;/a&gt;) fixed the build on Travis CI for Rails 3.2 by updating rubygems first (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/850116da11077c56cacb065924eaa655a517c09c" title="Update rubygems on travis-ci.org before running dependency installation

REE will fail to install Rails 3.2 gems w/o rubygems update."&gt;850116d&lt;/a&gt;). Joshua Clayton (&lt;a href="http://github.com/joshuaclayton"&gt;joshuaclayton&lt;/a&gt;) found a spec that was not appropriately named, and fixed it (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/0d67a4235884c22b251ef9d0a3cf24484a573f4d" title="Ensure spec actually ends in _spec"&gt;0d67a42&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;kumade&lt;/h2&gt;

&lt;p&gt;While &lt;a href="https://github.com/thoughtbot/kumade"&gt;kumade&lt;/a&gt; did not see a deploy this week, it did see some feature improvements, some of which come with an API change.&lt;/p&gt;

&lt;p&gt;The hook for running code just before deployment was originally &lt;code&gt;run_predeploy_task&lt;/code&gt; but is now &lt;code&gt;run_pre_deploy_task&lt;/code&gt; (&lt;a href="http://github.com/thoughtbot/kumade/commit/764aebebee26b2dfe9f12f3ceacf6a339cde2aee" title="Renamed run_predeploy_task method."&gt;764aebe&lt;/a&gt;). Chad Boyd (&lt;a href="http://github.com/hoverlover"&gt;hoverlover&lt;/a&gt;) made this change so he could introduce the &lt;code&gt;run_post_deploy_task&lt;/code&gt;, which is further exposed as &lt;code&gt;kumade:post_deploy&lt;/code&gt; to Rake (&lt;a href="http://github.com/thoughtbot/kumade/commit/da74087db9a8adc69bd6c923da3700ddace3f1e7" title="Renamed run_postdeploy_task method."&gt;da74087&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/kumade/commit/f68a487b4f01156bb2614c72b07dba8dce2b4569" title="Copy/paste error."&gt;f68a487&lt;/a&gt;, and &lt;a href="http://github.com/thoughtbot/kumade/commit/967901842e22bbf94804b4ce8d00b6c74620bf24" title="Run kumade:post_deploy if deployment succeeds."&gt;9679018&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Kumade now works with more stuff: Jammit 0.6.5 (&lt;a href="http://github.com/thoughtbot/kumade/commit/ec633102f999d05e4e2e4832540025d9c7430e8a" title="Fixes public root bug with Jammit 0.6.5

The way Jammit defines the public root was changed in
https://github.com/documentcloud/jammit/commit/b6ff4f0d63ddf615874dc9ad023924e94a8e2da1"&gt;ec63310&lt;/a&gt;) thanks to Vesa Vänskä (&lt;a href="http://github.com/vesan"&gt;vesan&lt;/a&gt;), and Ruby 1.9.3 (&lt;a href="http://github.com/thoughtbot/kumade/commit/8e73b90bc4eacc578927be6cf3d71875eb379800" title="Test against 1.9.3 on Travis."&gt;8e73b90&lt;/a&gt;) thanks to Gabe Berke-Williams (&lt;a href="http://github.com/gabebw"&gt;gabebw&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Gabe also fiddled with some source code (&lt;a href="http://github.com/thoughtbot/kumade/commit/7e0e11e31cc7a8559f0a9651198730635fd6e5bc" title="Better wording."&gt;7e0e11e&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/kumade/commit/bb695b9d06acf3fa7de5fccc842c316deb500fe3" title="Clean up test."&gt;bb695b9&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/kumade/commit/92aa8f4028ee523258897401ffa3725668aef9b4" title="Don't use templates when creating git repos in tests."&gt;92aa8f4&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;copycopter_client&lt;/h2&gt;

&lt;p&gt;A small documentation update occured in &lt;a href="https://github.com/thoughtbot/copycopter_client"&gt;copycopter_client&lt;/a&gt; by Joe Ferris (&lt;a href="http://github.com/jferris"&gt;jferris&lt;/a&gt;), reminding us that you can leave the name of the controller or model off of the translation key &lt;em&gt;only&lt;/em&gt; when using &lt;code&gt;t&lt;/code&gt; from a view (&lt;a href="http://github.com/thoughtbot/copycopter_client/commit/64168975a77d2d6a235e81c3ae00d6b25a31cfde" title="Note on preceding dots"&gt;6416897&lt;/a&gt;).&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/LxuqjnOGMkc/16991547467</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16991547467</guid><pubDate>Fri, 03 Feb 2012 16:41:00 -0500</pubDate><category>open source</category><category>bourbon</category><category>paperclip</category><category>capybara-webkit</category><category>clearance</category><category>factory_girl</category><category>kumade</category><category>copycopter</category><feedburner:origLink>http://robots.thoughtbot.com/post/16991547467</feedburner:origLink></item><item><title>Decoupling Data from Presentation</title><description>&lt;p&gt;I’m really happy to see a resurgence in an understanding that writing
integration tests that use classes and DOM structure to perform assertions
within these tests is typically a bad idea. The DOM structure constantly
changes but the data displayed (the stuff we want to assert is present on a
page) typically doesn’t.&lt;/p&gt;

&lt;p&gt;Why write tests against some markup that a designer may change, sometimes
often if he’s iterating over a design? It’ll end up causing everyone headaches
and frustration.&lt;/p&gt;

&lt;p&gt;How can we mark up our documents without performing assertions against a deep
nesting of classes and elements while ensuring our data is displayed properly?&lt;/p&gt;

&lt;p&gt;Data attributes.&lt;/p&gt;

&lt;p&gt;The browsers I care about support HTML5, so why not start using some of its
capabilities to clean up some integration tests?&lt;/p&gt;

&lt;p&gt;Imagine this scenario:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Scenario: See the site description on the homepage
  When I am on the homepage
  Then I should see the site description
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Simple, straightforward, and each step is a similar level of abstraction.&lt;/p&gt;

&lt;p&gt;Now imagine this markup:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;section class="primary-content"&gt;
  &lt;header&gt;
    &lt;h1&gt;Welcome to the site!&lt;/h1&gt;
    &lt;h2&gt;Insert a witty tagline here&lt;/h2&gt;
  &lt;/header&gt;
  &lt;p class="description"&gt;This product will make your life 100 times
  better.&lt;/p&gt;
&lt;/section&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I could write a step like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Then "I should see the site description" do
  page.should have_selector("section.primary-content p.description",
                            text: "This product will make your life 100 times better.")
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This step is asserting that there’s a section element with a class of
primary-content who has a child paragraph tag with a class of description that
contains the correct text.  Classes change. Structure changes. This is begging
to be rewritten.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;section data-role="primary-content"&gt;
  &lt;header&gt;
    &lt;h1&gt;Welcome to the site!&lt;/h1&gt;
    &lt;h2&gt;Insert a witty tagline here&lt;/h2&gt;
  &lt;/header&gt;
  &lt;p data-role="description"&gt;This product will make your life 100 times better.&lt;/p&gt;
&lt;/section&gt;

Then "I should see the site description" do
  page.should have_selector("[data-role='primary-content'] [data-role='description']",
                            text: "This product will make your life 100 times better.")
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, the step is asserting that there’s an element with a role of description
within an element with a role of primary-content that contains the correct
text.&lt;/p&gt;

&lt;p&gt;XHTML introduced a role attribute, but it’s not present currently in HTML5.
Luckily, data attributes are even more flexible and we can use any conventions
we like. &lt;code&gt;data-role&lt;/code&gt; and &lt;code&gt;data-state&lt;/code&gt; are two of my favorites.&lt;/p&gt;

&lt;p&gt;Interested in how to write awesome Cucumber steps? Head to my &lt;a href="https://workshops.thoughtbot.com/sections/38-intro-to-test-driven-rails"&gt;Intro to
Test-Driven Rails
workshop&lt;/a&gt;
on March 26th and March 27th where we’ll cover this and other awesome topics
on writing great tests!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/otw4vEN-fV0/16927767228</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16927767228</guid><pubDate>Thu, 02 Feb 2012 14:10:00 -0500</pubDate><category>cucumber</category><category>presentational classes</category><category>rails</category><category>testing</category><feedburner:origLink>http://robots.thoughtbot.com/post/16927767228</feedburner:origLink></item><item><title>This week in open source</title><description>&lt;h2&gt;bourbon&lt;/h2&gt;

&lt;p&gt;Over the past week &lt;a href="https://github.com/thoughtbot/bourbon"&gt;bourbon&lt;/a&gt; went up to version 1.3.5. A whole bunch of sweet new features are in it now:&lt;/p&gt;

&lt;p&gt;Frank (&lt;a href="http://github.com/frankzilla"&gt;frankzilla&lt;/a&gt;) added a &lt;code&gt;modular-scale&lt;/code&gt; mixin, of which the &lt;code&gt;golden-ratio&lt;/code&gt; mixin is but one implementation (&lt;a href="http://github.com/thoughtbot/bourbon/commit/126a83bf0b32a219be7ab7b92753868db2d3e98d" title="Fixed modular scale file name. Replaced _ with -"&gt;126a83b&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/bourbon/commit/96659a2f75f6ec8d1f0b1617c32794be1e42c74a" title="Merge remote branch 'frankzilla/modular-scale-mixin'"&gt;96659a2&lt;/a&gt;). He also added a parameterized fallback color to &lt;code&gt;linear-gradient&lt;/code&gt; (&lt;a href="http://github.com/thoughtbot/bourbon/commit/60e2c635c54e59d9d55e54c9414f4437a33779fc" title="Added argument to change linear-gradient fallback colour"&gt;60e2c63&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Phil LaPier (&lt;a href="http://github.com/plapier"&gt;plapier&lt;/a&gt;) worked with Gabe Berke-Williams (&lt;a href="http://github.com/gabebw"&gt;gabebw&lt;/a&gt;) on a &lt;code&gt;bourbon&lt;/code&gt; command-line too for working with Sass outside of a Rails app, such as Jekyll, WordPress, or even a static site (&lt;a href="http://github.com/thoughtbot/bourbon/commit/ad1499b30c8bf01b78f037ec09bf20c49a225152" title="Change bourbon generate to bourbon install"&gt;ad1499b&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/bourbon/commit/b55a763d0fc82cf06476ea9e5c4ef02eafb474db" title="Verion bump and readme update"&gt;b55a763&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/bourbon/commit/0ebf9060da97259c38d1ffd876c3e5fc7d1e44d4" title="Generate the proper lib files to make bourbon watch work"&gt;0ebf906&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/bourbon/commit/c2077d845db486b576b63c164e3cb67829ccd591" title="Actually add the generator. gitignore is weird."&gt;c2077d8&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/bourbon/commit/13e70d3282193090865802aedb7f6c18c0b653a2" title="Better scenario names."&gt;13e70d3&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/bourbon/commit/2fc2c900c4f66ed2de8dbd003cd2e27ad954fa74" title="Update README."&gt;2fc2c90&lt;/a&gt;, and &lt;a href="http://github.com/thoughtbot/bourbon/commit/bf34e70a257151a0eacba23af0460986229abb69" title="Users can update their existing bourbon installation."&gt;bf34e70&lt;/a&gt;). You can run &lt;code&gt;bourbon install&lt;/code&gt; to install it and &lt;code&gt;bourbon update&lt;/code&gt; to update an existing installation.&lt;/p&gt;

&lt;h2&gt;capybara-webkit&lt;/h2&gt;

&lt;p&gt;A careful sleuth has updated the documentation for &lt;a href="https://github.com/thoughtbot/capybara-webkit"&gt;capybara-webkit&lt;/a&gt; this week. Marc Schwieterman (&lt;a href="http://github.com/marcisme"&gt;marcisme&lt;/a&gt;) discovered that a fully passing test suite depends on ImageMagick, and documented as much in the contributions guide (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/df392683957e32f5d9257e2c4a5312a06830dd36" title='add imagemagick dependency to contributing guide

Several tests in driver_rendering_spec.rb require the identify command
that is part of Imagemagick. Without it they fail with output similar to
the following.

     MiniMagick::Error:
       Command ("identify -ping
/var/folders/y3/vfvjgwm91f1fmt2syh21czx40000gn/T/mini_magick20120115-49056-pwh5nl-0.png")
failed: {:output=&gt;"sh: identify: command not found\n",
:status_code=&gt;127}'&gt;df39268&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;factory_girl&lt;/h2&gt;

&lt;p&gt;Version 2.5.0 of &lt;a href="https://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt; is out, and there’s a badass new feature in it. But first:&lt;/p&gt;

&lt;p&gt;Joshua Clayton (&lt;a href="http://github.com/joshuaclayton"&gt;joshuaclayton&lt;/a&gt;) fixed a bug where the &lt;code&gt;:parent&lt;/code&gt;’s factory wasn’t being passed along (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/4aecfff1262b6a6bb642b040d87c7f06450f74fe" title="Honor :parent on factory over block nesting.

Closes #280"&gt;4aecfff&lt;/a&gt;). Carlos Antonio da Silva (&lt;a href="http://github.com/carlosantoniodasilva"&gt;carlosantoniodasilva&lt;/a&gt;) fixed the URLs in the readme to point to correct locations (&lt;a href="http://github.com/thoughtbot/factory_girl_rails/commit/aa74edd7cadbb173428fde05bda40b3d7615a9c6" title="Merge pull request #48 from carlosantoniodasilva/patch-1

Update github url in generator template to use https"&gt;aa74edd&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/factory_girl_rails/commit/42f5a10554b1e7ff2ca9b83268f84b12b5ed7f9a" title="Update github url in generator template to use https"&gt;42f5a10&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Oh, and you may remember from last week that Josh deprecated the &lt;code&gt;attributes_for&lt;/code&gt; method admist much controversy. Well, he undid that (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/2d6adfd009f51fa8ed6c57434dca93e8ff5b05ff" title='Revert "Deprecate attributes_for and build_stubbed"

This reverts commit a883315bc4775f5b9996a378d6c4ebe0ebf44a5e.'&gt;2d6adfd&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Josh then implemented a feature that Joe Ferris (&lt;a href="http://github.com/jferris"&gt;jferris&lt;/a&gt;), FactoryGirl’s originator, has wanted for years: you can specify how FactoryGirl should construct the class (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/578036480fd98332259fb42ce11ad4933a0c0f2b" title='Implement initialize_with to allow overriding object instantiation

Factory Girl now allows factories to override object instantiation. This
means factories can use factory methods (e.g. methods other than new) as
well as pass arguments explicitly.

    factory :user do
      ignore do
        things { ["thing 1", "thing 2"] }
      end

      initialize_with { User.construct_with_things(things) }
    end

    factory :report_generator do
      ignore do
        name { "Generic Report" }
        data { {:foo =&gt; "bar", :baz =&gt; "buzz"} }
      end

      initialize_with { ReportGenerator.new(name, data) }
    end

Whitespace

Code recommendations'&gt;5780364&lt;/a&gt;). Joe excitedly documented this (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/ea89aad60a5f5a6131d8177c153719d96bafd766" title="Update README with more to_initialize info"&gt;ea89aad&lt;/a&gt;). This means that FactoryGirl can be used for non-ActiveRecord classes, including immutable classes.&lt;/p&gt;


&lt;h2&gt;paperclip&lt;/h2&gt;

&lt;p&gt;In accordance to &lt;a href="http://robots.thoughtbot.com/post/16351438761/every-two-weeks"&gt;our new gem schedule&lt;/a&gt;, &lt;a href="https://github.com/thoughtbot/paperclip"&gt;paperclip&lt;/a&gt; hit 2.5.1 this week. Mike Burns (&lt;a href="http://github.com/mike-burns"&gt;mike-burns&lt;/a&gt;) cut the release, adding a &lt;a href="https://github.com/thoughtbot/paperclip/blob/b7f9b6f8d305ffba50ad54b9bb588238bac6b8c5/ChangeLog"&gt;ChangeLog&lt;/a&gt; and updating the &lt;a href="https://github.com/thoughtbot/paperclip/blob/b7f9b6f8d305ffba50ad54b9bb588238bac6b8c5/NEWS"&gt;NEWS&lt;/a&gt; file (&lt;a href="http://github.com/thoughtbot/paperclip/commit/b7f9b6f8d305ffba50ad54b9bb588238bac6b8c5" title="The Gemfile.lock was updated, too."&gt;b7f9b6f&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/ec4793ef661901735e17b8f2fababc39b21c25e5" title="Bump to 2.5.1"&gt;ec4793e&lt;/a&gt;). In short: Fog storage is passed the content type, S3 can be encrypted, and ActiveRecord is optional.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/6z-QPUbg-Ac/16588935587</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16588935587</guid><pubDate>Fri, 27 Jan 2012 14:18:34 -0500</pubDate><category>open source</category><category>this week in open source</category><category>bourbon</category><category>capybara-webkit</category><category>factory_girl</category><category>paperclip</category><feedburner:origLink>http://robots.thoughtbot.com/post/16588935587</feedburner:origLink></item><item><title>Designer Tools</title><description>&lt;p&gt;In addition to the &lt;a href="https://github.com/thoughtbot/laptop"&gt;basic development environment&lt;/a&gt; everyone at thoughtbot works with, there are a number of other apps most of the designers here use to keep our work flows efficient and our skills top notch. When I came to thoughtbot as an apprentice a little over three months ago, I was exposed to a variety of new apps that greatly improved my work-flow, so I thought I would share with you some of the apps I open up every morning and a bit on how I use them.&lt;/p&gt;

&lt;h2&gt;The basics&lt;/h2&gt;
&lt;p&gt;These apps are not necessarily design-specific apps but they are so essential in our day to day work-flows that I couldn’t leave them out.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;
  &lt;a href="http://propaneapp.com/"&gt;&lt;strong&gt;Propane:&lt;/strong&gt;&lt;/a&gt; Chat client for 37Signals’ Campfire. This is an indispensable communication tool.
  &lt;/li&gt;
  &lt;li&gt;
  &lt;a href="http://growl.info/"&gt;&lt;strong&gt;Growl:&lt;/strong&gt;&lt;/a&gt; Notifications for anything and everything. Used primarily for Campfire notifications.
  &lt;/li&gt;
  &lt;li&gt;
  &lt;a href="http://www.iterm2.com/"&gt;&lt;strong&gt;iTerm:&lt;/strong&gt;&lt;/a&gt; Terminal emulation for OSX. Mostly beneficial for it’s ability to open multiple windows in tabs.
  &lt;/li&gt;
  &lt;li&gt;
  &lt;a href="http://code.google.com/p/macvim/"&gt;&lt;strong&gt;MacVim:&lt;/strong&gt;&lt;/a&gt; Text editing. If you’re not already using Vim, take the time to start learning. It will greatly speed up your development time and if you’re working with developers who use Vim it will make pairing easier.
  &lt;/li&gt;
  &lt;li&gt;
  &lt;a href="http://mizage.com/#macdivvy"&gt;&lt;strong&gt;Divvy:&lt;/strong&gt;&lt;/a&gt; Helps you keep your screens and windows spaced, aligned and organized efficiently without clicking and dragging all day.
  &lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;
  &lt;a href="http://www.adobe.com/products/creativesuite.html?promoid=ITXQM"&gt;Adobe&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;If you work on the web I am sure you are already familiar with the typical Adobe software that web designers use, so Im not going to get into the details of our Adobe setups here. Most of us prefer to do hand sketches/whiteboarding and move into wire framing with HTML and CSS as soon as possible any way. Static mock-ups tend to have a host of draw backs when working in an agile development process. That said, photoshop, illustrator and &lt;a href="http://robots.thoughtbot.com/post/3564422865/dear-photoshop-user-meet-fireworks"&gt;fireworks&lt;/a&gt; are still our workhorses when it comes to specific graphic design needs.&lt;/p&gt;

&lt;h2&gt;
  &lt;a href="http://skitch.com/"&gt;Skitch&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A handy screen capturing tool that allows you to very easily draw and add notes on top of your screen shots, without having to open up photoshop or some other image editing tool.&lt;/p&gt;

&lt;h2&gt;
  &lt;a href="http://getcloudapp.com/"&gt;Cloud App&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Collaboration and iteration are key ingredients in doing great work and I have found this app to be an effective way of sharing screen shots with team members, clients and other designers so I can get that valuable feedback on the development of my work. When you take screen shot Cloud app automatically uploads your image to web servers and in a drop-down from the Cloud app icon in the OSX menu bar, provides you with a sharable link to that image.&lt;/p&gt;

&lt;h2&gt;
  &lt;a href="http://notational.net/"&gt;Notational Velocity&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Good for general note taking and the keeping of VIM and Git cheat-sheets. Especially if you are new to VIM or Git keeping track of commands and remembering how to get certain things done right can be quite challenging, so we all suggest building up robust cheat-sheets with this little app.&lt;/p&gt;


&lt;h2&gt;
  &lt;a href="http://www.bohemiancoding.com/fontcase"&gt;FontCase&lt;/a&gt;
  or
  &lt;a href="http://www.fontexplorerx.com/"&gt;FontExplorer X&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Great typography is a fundamental element of great design. Managing your fonts effectively will help you find that perfect type-face faster and reduce the time it takes to get started with a solid visual design direction. Taking the time to organise your typefaces in a way that is meaningful to you can also be a good way of curating your collection and more intimately familiarizing your self with the fonts in it.&lt;/p&gt;

&lt;h2&gt;
  &lt;a href="http://www.realmacsoftware.com/littlesnapper/"&gt;Little Snapper&lt;/a&gt;
  or
  &lt;a href="https://gimmebar.com/"&gt;Gimme Bar&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Both are awesome tools for building a personally curated library of design inspiration. Saving images and examples of the things that inspire you is a great way to refine and hone your own personal style and also a great way to help kick off the visual direction for a new project. If you are not using tools like these already, start. It will be hugely beneficial to the quality of work you do.&lt;/p&gt;

&lt;h2&gt;
  &lt;a href="http://giantcomet.com/hues"&gt;Hues&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A great little app for grabbing colors from anywhere on your screen. It provides rgb, hsl, and hex values for any color you select which makes pulling color pallets from photos and images you have stashed in your Gimme Bar or Little Snapper quite nice.&lt;/p&gt;

&lt;h2&gt;
  &lt;a href="http://thoughtbot.com/bourbon/"&gt;Bourbon&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Bourbon is not an app, it’s a library of SASS mixins and functions that greatly speed up front-end development time. It is just as awesome for new comers to .css/.scss as it is for the most seasoned pros. It’s also one of the main reasons the sketch-to-html&amp;css-wire frames process has proven to be so effective and efficient for us.  &lt;a href="http://robots.thoughtbot.com/post/7846399901/introducing-bourbon-sass-mixins"&gt;We have extensively written about bourbon before.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So that’s it for a light-weight overview of the apps I find my self opening on a daily basis. Hopefully I have introduced you to some new and useful tools. I’d also love to hear about some of the tools your using, so feel free to add your comments below!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/tRWTD9rJElo/16521833695</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16521833695</guid><pubDate>Thu, 26 Jan 2012 09:58:00 -0500</pubDate><category>Design</category><category>Designer</category><category>Web tools</category><category>Bourbon</category><category>Design apps</category><feedburner:origLink>http://robots.thoughtbot.com/post/16521833695</feedburner:origLink></item><item><title>A users guide to the Trajectory redesign</title><description>&lt;p&gt;We released a redesign to the &lt;a href="http://apptrajectory.com"&gt;Trajectory&lt;/a&gt; UI today. I want to explain the thinking that went into the redesign, what the benefits to users are, and what’s in store for Trajectory as we move forward.&lt;/p&gt;

&lt;p style="margin-bottom: 0"&gt;&lt;img src="http://ui.thoughtbot.com/assets/blog/trajectory-redesign/main.png" style="margin-bottom: 0;"/&gt;&lt;/p&gt;
&lt;p style="font-size: 12px; color: #666;"&gt;View of the main stories index.&lt;/p&gt;

&lt;p&gt;First, let’s do a quick history lesson. A year and a half ago, we decided to build Trajectory to scratch our own itch. We wanted a lightweight agile project management tool that had a strong focus on discussions, both for the stories being worked on, as well as for longer term planning. The original design for the Trajectory UI emerged out of an iterative process, and evolved as we learned more about the product over the course of its development.&lt;/p&gt;

&lt;p&gt;This redesign was a chance to take stock of what’ve we learned through that process, and lay the groundwork for the future. The most obvious change is the lighter color scheme. We’d heard continual feedback that people found it difficult to quickly scan through stories because of the dark color scheme. The new UI fixes this problem and provides a more pleasant experience for extended, daily use.&lt;/p&gt;

&lt;p&gt;Next, we designed the UI to respond better to differing screen sizes. If you have a large monitor, the site will expand to use the space available to it. Shrink your window down, and the site remains just as usable. There’s more work to be done, but the long term goal is to serve a single web-based interface to all devices, whether it’s a 27” display or your mobile device.&lt;/p&gt;

&lt;p&gt;There are a number of other UI improvements. We’ve improved the searching and filtering of stories. (Pro tip: hit the f key to enter search mode.)&lt;/p&gt;

&lt;p style="margin-bottom: 0;"&gt;&lt;img src="http://ui.thoughtbot.com/assets/blog/trajectory-redesign/search.png" style="margin-bottom: 0;"/&gt;&lt;/p&gt;
&lt;p style="font-size: 12px; color: #666;"&gt;The new search interface.&lt;/p&gt;

&lt;p&gt;It’s now easier to estimate and re-estimate stories. 

&lt;/p&gt;&lt;p style="margin-bottom: 0;"&gt;&lt;img src="http://ui.thoughtbot.com/assets/blog/trajectory-redesign/estimation.png" style="margin-bottom: 0;"/&gt;&lt;/p&gt;
&lt;p style="font-size: 12px; color: #666;"&gt;The new story estimation UI.&lt;/p&gt;

&lt;p&gt;You can also quickly see the progress on stories created from &lt;a href="http://robots.thoughtbot.com/post/13915680987/heres-an-idea"&gt;an Idea&lt;/a&gt;.&lt;/p&gt;

&lt;p style="margin-bottom: 0"&gt;&lt;img src="http://ui.thoughtbot.com/assets/blog/trajectory-redesign/ideas-progress.png" style="margin-bottom: 0;"/&gt;&lt;/p&gt;
&lt;p style="font-size: 12px; color: #666;"&gt;Progress of stories attached to an idea.&lt;/p&gt;

&lt;p&gt;We also performed a heavy refactoring/rewriting of the front-end markup and style. We were able to eliminate and simplify substantial portions of the front-end code, which should hopefully translate to snappier performance within the browser.&lt;/p&gt;

&lt;p&gt;Trajectory is going to be a very important part of what thoughtbot does in 2012. If you haven’t done so yet, &lt;a href="http://apptrajectory.com"&gt;sign up for a free trial&lt;/a&gt; and see what we’re so excited about.&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/NG5p4vNB-4w/16482074033</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16482074033</guid><pubDate>Wed, 25 Jan 2012 16:49:00 -0500</pubDate><category>trajectory</category><feedburner:origLink>http://robots.thoughtbot.com/post/16482074033</feedburner:origLink></item><item><title>Inject that Rails Configuration Dependency!</title><description>&lt;p&gt;Setting up configuration settings in a Rails app has been fairly
straightforward for a while now:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# config/environments/development.rb
Doit::Application.configure do
  config.default_creator = "Person 1"
end

# config/environments/test.rb
Doit::Application.configure do
  config.default_creator = "Test Person"
end

# config/environments/production.rb
Doit::Application.configure do
  config.default_creator = "John Doe"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To access this setting, call &lt;code&gt;Doit::Application.config.default_creator&lt;/code&gt; within
your app. Pretty straightforward, right?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class TodoItem &lt; ActiveRecord::Base
  before_create :assign_default_creator, unless: :creator?

  private

  def assign_default_creator
    self.creator = Doit::Application.config.default_creator
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s imagine you have a todo item and you want to test that the value gets
assigned if no creator is provided.&lt;/p&gt;

&lt;p&gt;Imagine how you’d test this.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe TodoItem do
  it "assigns the default creator when no creator is assigned" do
    Doit::Application.config.stub(:default_creator).and_return("default creator from config")
    subject.save
    subject.creator.should == "default creator from config"
  end

  it "does not assign the default creator if it has been set" do
    Doit::Application.config.stub(:default_creator).and_return("default creator from config")
    subject.creator = "Jane Doe"
    subject.save
    subject.creator.should == "Jane Doe"
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There’s a few things that are gross. First, we’re referencing
&lt;code&gt;Doit::Application&lt;/code&gt; in the model spec. Second, we’re stubbing in both
examples. The latter is a low-hanging fruit so it can be extracted.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe TodoItem do
  it "assigns the default creator when no creator is assigned" do
    config_default_creator_returns("default creator from config")
    subject.save
    subject.creator.should == "default creator from config"
  end

  it "does not assign the default creator if it has been set" do
    config_default_creator_returns("default creator from config")
    subject.creator = "Jane Doe"
    subject.save
    subject.creator.should == "Jane Doe"
  end

  def config_default_creator_returns(value)
    Doit::Application.config.stub(:default_creator).and_return(value)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, interacting with &lt;code&gt;Doit::Application&lt;/code&gt; is confined to one method. Some
people may stub the application in an RSpec &lt;code&gt;before&lt;/code&gt; block, but I don’t like
doing that because one of the specs cares about the stubbed value. I want that
stub right in the example so it’s obvious that the stub and assertion are
close (in number of lines).&lt;/p&gt;

&lt;p&gt;Even though &lt;code&gt;Doit::Application&lt;/code&gt; is confined to one call in the spec, I really
don’t like that the spec cares about its &lt;code&gt;config&lt;/code&gt; at all. What I’d love to do
is assign a custom configuration on my &lt;code&gt;TodoItem&lt;/code&gt; in my test intsead of caring
about &lt;code&gt;Doit::Application&lt;/code&gt; and having to stub on &lt;code&gt;config&lt;/code&gt;. I can do this with
dependency injection.&lt;/p&gt;

&lt;p&gt;Right now, &lt;code&gt;TodoItem&lt;/code&gt; has a dependency on &lt;code&gt;Doit::Application.config&lt;/code&gt;.
Dependency injection would mean &lt;code&gt;TodoItem&lt;/code&gt; gets a &lt;code&gt;class_attribute :config&lt;/code&gt; that
defaults to &lt;code&gt;Doit::Application.config&lt;/code&gt; but can be overridden (say, in our
tests).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe TodoItem do
  it "assigns the default creator when no creator is assigned" do
    subject.config = stub("config", default_creator: "default creator from config")
    subject.save
    subject.creator.should == "default creator from config"
  end

  it "does not assign the default creator if it has been set" do
    subject.config = stub("config", default_creator: "default creator from config")
    subject.creator = "Jane Doe"
    subject.save
    subject.creator.should == "Jane Doe"
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With the class attribute, I’m able to override config on the instance and
replace it with a stub that has a &lt;code&gt;default_creator&lt;/code&gt; method, which I’ve
assigned to the string I expect. I was able to remove my reference of
&lt;code&gt;Doit::Application&lt;/code&gt; from the spec. Perfect!&lt;/p&gt;

&lt;p&gt;Here’s the model code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class TodoItem &lt; ActiveRecord::Base
  class_attribute :config
  self.config = Doit::Application.config

  before_create :assign_default_creator, unless: :creator?

  private

  def assign_default_creator
    self.creator = config.default_creator
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The callback &lt;code&gt;assign_default_creator&lt;/code&gt; now doesn’t care about
&lt;code&gt;Doit::Application.config&lt;/code&gt;, only that &lt;code&gt;config&lt;/code&gt; has a &lt;code&gt;default_creator&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;This post actually stemmed from my interaction with a developer in &lt;a href="https://github.com/thoughtbot/factory_girl/issues/269"&gt;Factory
Girl GitHub Issues&lt;/a&gt; who
asked a pretty interesting question about reloading classes in Factory Girl
after removing the constant and loading the Ruby file again (it seemed like a
code smell and not an issue with Factory Girl).&lt;/p&gt;

&lt;p&gt;At the end of the thread, I suggested he attend my &lt;a href="https://workshops.thoughtbot.com/sections/27-test-driven-rails"&gt;Test-Driven Rails
workshop&lt;/a&gt;
next week, January 30th and 31st, because I’ll be talking about RSpec and
dependency injection (among other things like Cucumber, how, when, and what to
test in a Rails app). It’s perfect for Rails developers who are interested in
writing more cleaner, more stable applications.&lt;/p&gt;

&lt;p&gt;See you there!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/0ykpinsD4z4/16466303962</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16466303962</guid><pubDate>Wed, 25 Jan 2012 13:33:00 -0500</pubDate><category>rails</category><category>rspec</category><category>factory girl</category><category>test-driven rails</category><category>testing</category><category>dependency injection</category><feedburner:origLink>http://robots.thoughtbot.com/post/16466303962</feedburner:origLink></item><item><title>Apprentice.io Three Week Retrospective</title><description>&lt;p&gt;Over the past three weeks I’ve begun my apprenticeship at thoughtbot. The apprenticeship lasts until the end of March.  I’m joined by designers Paul Webb and Edwin Morris, and fellow coder apprentice Alex Patriquin. Each of us is assigned to a mentor, who makes sure we absorb as much as possible of the thoughtbot way of doing things and achieve our specific goals. For me, the apprenticeship is a couple of things: it’s a chance to work in coder nirvana (TDD, heavy refactoring, bookshelf full of great literature, 5-minute meetings, pair programming, investment days, open source - the works), and it’s a chance to vastly increase my Rails skills in a bootcamp-style training environment.&lt;/p&gt;



&lt;p&gt;My head is swimming with new knowledge. I entered this state the first day, and I’ve been there constantly for the past three weeks. Each evening I ride the T home with my poor neurons about to burst with new activity. At night while I sleep my brain indexes all this new knowledge, and the next day I dive in again. If you’ve ever read Ender’s Game, it’s sort of like Battle School for Geeks.&lt;/p&gt;



&lt;p&gt;Let’s get specific. This list is long because I’ve been truly busy. In the past three weeks I have:&lt;/p&gt;



&lt;ul&gt;&lt;li&gt;Mercilessly refactored my code two, three, even four times after writing it. The standards for code quality here are very, very high.&lt;/li&gt;&#xD;
&lt;li&gt;Learned to use Github pull requests for code review.&lt;/li&gt;&#xD;
&lt;li&gt;Responded to around 150 code review comments, most of which made me stop and rethink coding habits I’ve held unconsciously for years. My style is improving fast.&lt;/li&gt;&#xD;
&lt;li&gt;Participated daily in a morning company-wide standup that actually takes less than five minutes, and a team standup that takes another five. That’s only ten minutes of meetings per day!&lt;/li&gt;&#xD;
&lt;li&gt;Switched to using higher-level cucumber tests involving steps like “When I sign up as a new user” as opposed to “When I click the link marked ‘foo’”.&lt;/li&gt;&#xD;
&lt;li&gt;Achieved and maintained 100% perfect TDD discipline - not writing a single line of feature code until a failing test is present.&lt;/li&gt;&#xD;
&lt;li&gt;Completely switched text editors, from Textmate to Vim.&lt;/li&gt;&#xD;
&lt;li&gt;Became &lt;em&gt;faster&lt;/em&gt; in vim than I ever was in Textmate.&lt;/li&gt;&#xD;
&lt;li&gt;Written custom functions for vim.&lt;/li&gt;&#xD;
&lt;li&gt;Learned other new tools including &lt;a href="http://mxcl.github.com/homebrew/" title="Homebrew"&gt;Homebrew&lt;/a&gt;, &lt;a href="http://betterthangrep.com/" title="ack"&gt;ack&lt;/a&gt;, &lt;a href="http://ctags.sourceforge.net/" title="ctags"&gt;ctags&lt;/a&gt;, &lt;a href="http://newrelic.com/" title="New Relic"&gt;New Relic&lt;/a&gt;, &lt;a href="http://www.kissmetrics.com/" title="KISSmetrics"&gt;KISSmetrics&lt;/a&gt;, and &lt;a href="https://github.com/thoughtbot/kumade" title="kumade"&gt;kumade&lt;/a&gt;.&lt;/li&gt;&#xD;
&lt;li&gt;Forked &lt;a href="http://github.com/thoughtbot/dotfiles"&gt;thoughtbot’s dotfiles repo&lt;/a&gt; and started customizing it as my personal dev environment. The dotfiles repo contains bashrc, vimrc, git-config, alises, etc - I can now install it to any computer I use to instantly have my customized dev environment in place.&lt;/li&gt;&#xD;
&lt;li&gt;Watched an app’s user base jump from 100 to 10,000 in a matter of minutes as an article hit TechCrunch.&lt;/li&gt;&#xD;
&lt;li&gt;Gotten a crash-course in startup funding from the other coding apprentice, Alex Patriquin, who boasts, quite accurately, of knowing everybody.&lt;/li&gt;&#xD;
&lt;li&gt;Participated in discussions about new features in rails.&lt;/li&gt;&#xD;
&lt;li&gt;Made my &lt;a href="https://github.com/thoughtbot/paperclip/compare/201f02e324...65e0338f3ed07ddf95958ce71265a0ba76e9c1c6"&gt;very first contribution&lt;/a&gt; to an open source repo.&lt;/li&gt;&#xD;
&lt;li&gt;Been approved to give my first professional presentation - a lightning talk at at Boston.rb meeting.&lt;/li&gt;&#xD;
&lt;li&gt;Consumed 3,000 cups of green tea and a foie gras taco.&lt;/li&gt;&#xD;
&lt;/ul&gt;&lt;p&gt;Did I mention I’ve been busy? That’s just the first three weeks - and I’ve got ten weeks left. I feel excited, involved, and challenged in a completely invigorating way. The team here is universally smart and helpful, and while I’m here I simply can’t help but get better by osmosis at what I do. This is the most fun I’ve had in an office in a long time.&lt;/p&gt;



&lt;p&gt;For more information about this program, and to sign up to sponsor a pool of apprentices, visit &lt;a href="https://www.apprentice.io/"&gt;apprentice.io&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;More later on,&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/AWftg2bZQmc/16382750772</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16382750772</guid><pubDate>Mon, 23 Jan 2012 20:59:53 -0500</pubDate><category>apprentice</category><category>tdd</category><category>vim</category><category>new relic</category><category>kissmetrics</category><category>dotfiles</category><category>startup funding</category><category>techcrunch</category><category>green tea</category><feedburner:origLink>http://robots.thoughtbot.com/post/16382750772</feedburner:origLink></item><item><title>Every Two Weeks</title><description>&lt;p&gt;Our most popular gems—&lt;a href="https://rubygems.org/gems/paperclip"&gt;paperclip&lt;/a&gt;, &lt;a href="http://rubygems.org/gems/capybara-webkit"&gt;capybara-webkit&lt;/a&gt;, &lt;a href="http://rubygems.org/gems/factory_girl"&gt;factory_girl&lt;/a&gt;, and &lt;a href="http://rubygems.org/gems/clearance"&gt;clearance&lt;/a&gt;—will see new releases every two weeks.&lt;/p&gt;

&lt;h2&gt;Trying to be reasonable&lt;/h2&gt;

&lt;p&gt;Release early, release often. In the past we’ve often released new versions of gems in a “when we feel like it” fashion: either we needed the gem to exist for a personal project, or we’re proud of some change we just made, or someone complained to us about an old version. This lead to a problem: when we were just taking pull requests we didn’t think to release a new version.&lt;/p&gt;

&lt;p&gt;By setting up a regular schedule this means that contributions will be more public more quickly. We chose two week cycles as a compromise between releasing very often (every time we take a pull request) and in a wide duration (every three months). Too often and we’d annoy people when they upgrade; too infrequently and the bugs are simply not being fixed for the largest number of people.&lt;/p&gt;

&lt;h2&gt;It’s a process&lt;/h2&gt;

&lt;p&gt;Setting aside time to make a release elevates it from “OK I made these changes gem push woo!” to “I am going to make a proper release”—it reifies the release as a first-class action for us to concentrate on. Changelogs, blog posts, and tweets are side effects of putting the right amount of care into releasing a new version of a gem.&lt;/p&gt;

&lt;h2&gt;When‽&lt;/h2&gt;

&lt;p&gt;Factory Girl (factory_girl and &lt;a href="http://rubygems.org/gems/factory_girl_rails"&gt;factory_girl_rails&lt;/a&gt;) and Paperclip are on a two week release cycle starting January 27th, 2012. Clearance and capybara-webkit are on a two week release cycle starting February 3rd, 2012.&lt;/p&gt;

&lt;p&gt;You can track gem releases using &lt;a href="https://rubygems.org"&gt;the RubyGems Web site&lt;/a&gt; and your favorite feed reader. It’s like this:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Sign up for RubyGems, or sign in if you already have an account.&lt;/li&gt;
  &lt;li&gt;Navigate to the page for the gem you care about.&lt;/li&gt;
  &lt;li&gt;Click “Subscribe”.&lt;/li&gt;
  &lt;li&gt;Click the “Dashboard” link at the top of the Web page.&lt;/li&gt;
  &lt;li&gt;There’s a sweet orange RSS icon in the middle of that page. Subscribe to that link!&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;img src="http://meatexplosion.com/awesome/pre-time-travel.jpg" alt="This blog post would make no sense in The Land Before Time"/&gt;&lt;/p&gt;

&lt;h2&gt;When you say “every two weeks”…&lt;/h2&gt;

&lt;p&gt;Sometimes it doesn’t make sense to cut a release only every two weeks. Important security fixes or bugs that block everyone from using the gem are examples where getting something out as soon as possible is the only way to do it. On the other hand, sometimes there simply haven’t been any changes.&lt;/p&gt;

&lt;p&gt;If we release a new version of a gem on the 26th and the 27th is when a scheduled release is to happen, it’s likely that we’ll skip the schedule. In general we’ll continue the “do I feel like making a release?” thought process, but every two weeks and with a bias towards a positive answer.&lt;/p&gt;

&lt;h2&gt;Or whenever&lt;/h2&gt;

&lt;p&gt;The bi-weekly cycle is new and, like everything else in software and life, worth reconsidering at all times. Please let us know if it’s too often, too seldom, just right, or completely useless to you!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/p3fgHv3XEAY/16351438761</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16351438761</guid><pubDate>Mon, 23 Jan 2012 11:00:05 -0500</pubDate><category>open source</category><category>agile</category><category>versioning</category><category>gtd</category><feedburner:origLink>http://robots.thoughtbot.com/post/16351438761</feedburner:origLink></item><item><title>Factory Girl 2.5 Gets Custom Constructors</title><description>&lt;p&gt;Today marks a big day in the life of Factory Girl; you can now override the
constructor for factories! This is great news for people who’ve been upset
that they can’t use Factory Girl with objects who have constructors with
required arguments, as Factory Girl would previously just call &lt;code&gt;new&lt;/code&gt; without
passing any arguments.&lt;/p&gt;

&lt;p&gt;Here’s the syntax:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# app/models/report_generator.rb
class ReportGenerator
  def initialize(name, data)
    @name = name
    @data = data
  end

  # ...
end

# spec/factories.rb
FactoryGirl.define do
  factory :report_generator do
    ignore do
      name "Generic Report"
      data { {:foo =&gt; "bar", :baz =&gt; "buzz"} }
    end

    initialize_with { ReportGenerator.new(name, data) }
  end

  # ...
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that I wrapped the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; attributes in an ignore block.
Factory Girl doesn’t differentiate between attributes passed in the custom
constructor and normal attributes to assign, so moving them to the ignore
block ensures that I don’t instantiate the report generator and then attempt
to assign &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;Grab a copy of &lt;a href="http://rubygems.org/gems/factory_girl/versions/2.5.0"&gt;2.5.0&lt;/a&gt;
and start using Factory Girl with your other objects today!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/8sBWsPsK0Bo/16196616388</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16196616388</guid><pubDate>Fri, 20 Jan 2012 19:30:00 -0500</pubDate><category>factory girl</category><category>rails</category><feedburner:origLink>http://robots.thoughtbot.com/post/16196616388</feedburner:origLink></item><item><title>This week in open source</title><description>&lt;h2&gt;shoulda-context&lt;/h2&gt;

&lt;p&gt;Hey! &lt;a href="https://github.com/thoughtbot/shoulda-context"&gt;shoulda-context&lt;/a&gt; has a maintainer! His name is Travis Jeffery (&lt;a href="http://github.com/travisjeffery"&gt;travisjeffery&lt;/a&gt;) and he’s got commit rights and everything! Thank you, Travis.&lt;/p&gt;

&lt;p&gt;Yeah!&lt;/p&gt;

&lt;h2&gt;cocaine&lt;/h2&gt;

&lt;p&gt;One feature was added to &lt;a href="https://github.com/thoughtbot/cocaine"&gt;cocaine&lt;/a&gt; over the past week: Daniel Mircea (&lt;a href="http://github.com/viseztrance"&gt;viseztrance&lt;/a&gt;) made it such that you can now pass blank argument values (&lt;a href="http://github.com/thoughtbot/cocaine/commit/a2d01c4532290b7267c1d99bfdd7165413d2dbf3" title="Quote blank command line values."&gt;a2d01c4&lt;/a&gt;). For example, this now works:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
command_line = Cocaine::CommandLine.new(
  "curl",
  "-X POST -d :data :url",
  :data =&gt; "",           # Hey note this!
  :url =&gt; "http://localhost:9000",
  :swallow_stderr =&gt; false)

puts command_line.command
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;…which will produce:&lt;/p&gt;

&lt;pre&gt;curl -X POST -d '' 'http://localhost:9000'&lt;/pre&gt;

&lt;h2&gt;paperclip&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/thoughtbot/paperclip"&gt;paperclip&lt;/a&gt; project saw a few neat commits this week. Jeremy McNevin (&lt;a href="http://github.com/jmcnevin"&gt;jmcnevin&lt;/a&gt;) and ralph (&lt;a href="http://github.com/ralph"&gt;ralph&lt;/a&gt;) pass the file type to Fog now, always (&lt;a href="http://github.com/thoughtbot/paperclip/commit/839b98c612d5bebdfb369a58b130f13e38915c3a" title="Provide content type of file to fog."&gt;839b98c&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/201f02e324a5577b888d7b3ee8c8fbacff9966ae" title="save content type of the file with fog storage engine"&gt;201f02e&lt;/a&gt;). Luke Griffiths (&lt;a href="http://github.com/Sporky023"&gt;Sporky023&lt;/a&gt;), one of our new &lt;a href="http://apprentice.io/"&gt;apprentices&lt;/a&gt;, got his first open source contribution in: you can pass an &lt;code&gt;:s3_encrypted&lt;/code&gt; option for controlling which encryption type S3 should use (&lt;a href="http://github.com/thoughtbot/paperclip/commit/65e0338f3ed07ddf95958ce71265a0ba76e9c1c6" title="s3_encryption =&gt; true is now s3_server_side_encryption =&gt; :aes256"&gt;65e0338&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/af6d343e25c81ceb4bc460916a5ef8628114dab5" title="Can encrypt files on s3 with :s3_encrypted =&gt; true option"&gt;af6d343&lt;/a&gt;). And Jon Yurek (&lt;a href="http://github.com/jyurek"&gt;jyurek&lt;/a&gt;) fixed mixing Paperclip with non-ActiveRecord codebases (&lt;a href="http://github.com/thoughtbot/paperclip/commit/bc6ed16bc8abe3c983dca54556a662ddae8ac252" title="Hide ActiveRecord-specific stuff in the Railtie"&gt;bc6ed16&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;factory_girl&lt;/h2&gt;

&lt;p&gt;The fixture replacement gem, &lt;a href="https://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt;, is now at version 2.4.2 (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/845578c0f2ef17927362593c0d71accecfcf1c7c" title="Bump to 2.4.2"&gt;845578c&lt;/a&gt;). It includes bug fixes, a deprecation, and more Rails support. All commits were by Joshua Clayton (&lt;a href="http://github.com/joshuaclayton"&gt;joshuaclayton&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;There was &lt;a href="https://github.com/thoughtbot/factory_girl/issues/268"&gt;an issue where using an inline trait would cause it not to be reset&lt;/a&gt; (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/70a80fde5845749ae8404bd70b81c5d6183f68fd" title="Reset evaluator class when cloning a FactoryGirl::Factory

Applying traits inline modifies the evaluator class, so it needs to be
reset when cloning in order to ensure that the attributes are correct.

Closes #268"&gt;70a80fd&lt;/a&gt;), and &lt;a href="https://github.com/thoughtbot/factory_girl/issues/242"&gt;an issue with the precedence of inline traits&lt;/a&gt; (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/065c6c17895e13e6a4ba5debfd8d4d1ed500cd74" title="Fix issues with inline traits not taking precedence

Closes #242"&gt;065c6c1&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Josh also deprecated the &lt;code&gt;attributes_for&lt;/code&gt; class method, which once upon a time produced all the attributes that a factory would set (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/a883315bc4775f5b9996a378d6c4ebe0ebf44a5e" title="Deprecate attributes_for and build_stubbed"&gt;a883315&lt;/a&gt;). He provided no reliable workaround.&lt;/p&gt;

&lt;p&gt;Today, &lt;a href="http://weblog.rubyonrails.org/2012/1/20/rails-3-2-0-faster-dev-mode-routing-explain-queries-tagged-logger-store"&gt;Rails 3.2&lt;/a&gt; was released, so we made sure to test against that—and it works! (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/5555f14db7261e47e407de1cee9ad9ebdade5e46" title="Update appraisal to test against Rails 3.2"&gt;5555f14&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;capybara-webkit&lt;/h2&gt;

&lt;p&gt;A new release for &lt;a href="https://github.com/thoughtbot/capybara-webkit"&gt;capybara-webkit&lt;/a&gt;, yeay! Joe Ferris (&lt;a href="http://github.com/jferris"&gt;jferris&lt;/a&gt;) cut the release (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/59ba8611ba6388cf5262eb31ec06cea34fa66698" title="Bump to 0.8.0; add json as a dependency"&gt;59ba861&lt;/a&gt;), first removing a long-standing debugging print statement (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/0bac05ebc4a5c916a9189b37e6d72cf4045ecaac" title="Remove debugging statement"&gt;0bac05e&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Sweet features, bro: Yuri Gadow (&lt;a href="http://github.com/ylg"&gt;ylg&lt;/a&gt;) added support for the fancy text inputs in HTML5 like email, number, search, and so on (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/7e5e99b01fa81110c49597ad5880a46f96584894" title="Trigger text input events with HTML5 text-like fields: email, number, search, tel, text, and url."&gt;7e5e99b&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;John Barker (&lt;a href="http://github.com/excepttheweasel"&gt;excepttheweasel&lt;/a&gt;) updated the README to point out that capybara-webkit does not, in fact, listen on port 8200 (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/228562173698f78ab28696cc9078c7c317eb08fa" title="Capybara webkit doesn't listen on 8200"&gt;2285621&lt;/a&gt;).&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/rQwl6ebeTcA/16188170538</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/16188170538</guid><pubDate>Fri, 20 Jan 2012 16:50:21 -0500</pubDate><category>open source</category><category>this week in open source</category><category>shoulda-context</category><category>cocaine</category><category>paperclip</category><category>factory_girl</category><category>capybara-webkit</category><feedburner:origLink>http://robots.thoughtbot.com/post/16188170538</feedburner:origLink></item><item><title>This week in open source</title><description>&lt;h2&gt;Deprecations&lt;/h2&gt;

&lt;p&gt;We have officially stopped maintaining the following open source products: &lt;a href="https://github.com/thoughtbot/limerick_rake"&gt;limerick_rake&lt;/a&gt;, &lt;a href="https://github.com/thoughtbot/trout"&gt;trout&lt;/a&gt;, &lt;a href="https://github.com/thoughtbot/shoulda-context"&gt;shoulda-context&lt;/a&gt;, and &lt;a href="https://github.com/thoughtbot/jester"&gt;jester&lt;/a&gt;. Do you want to take over any of them? &lt;a href="mailto:support@thoughtbot.com"&gt;Let us know&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;kumade&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/thoughtbot/kumade"&gt;kumade&lt;/a&gt; Heroku deployer now has a rake task hook for running code before the deployment (&lt;a href="http://github.com/thoughtbot/kumade/commit/8bd28248dbff28d83be596d42000e1500f2e52f5" title="Add kumade:pre_deploy rake hook"&gt;8bd2824&lt;/a&gt;). This was done by Joshua Clayton (&lt;a href="http://github.com/joshuaclayton"&gt;joshuaclayton&lt;/a&gt;) in the new version: 0.8.2 (&lt;a href="http://github.com/thoughtbot/kumade/commit/52a93485b91c75879e31f7a94c808a125e1ab9b7" title="Bump to 0.8.2"&gt;52a9348&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;paul_revere&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/thoughtbot/paul_revere"&gt;paul_revere&lt;/a&gt; notification gem has this sweet button to hide a notification. Ben Orenstein (&lt;a href="http://github.com/"&gt;r00k&lt;/a&gt;) changed the duration of this hiding from one day to one year (&lt;a href="http://github.com/thoughtbot/paul_revere/commit/5a773d4028d1c33eb316c2b7d34180b88c2d5cd4" title="Change cookie expiration to 1 year (instead of 1 day)."&gt;5a773d4&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;bourbon&lt;/h2&gt;

&lt;p&gt;Phil LaPier (&lt;a href="http://github.com/plapier"&gt;plapier&lt;/a&gt;) has released version 1.3.1 of &lt;a href="https://github.com/thoughtbot/bourbon"&gt;bourbon&lt;/a&gt;, the much-loved collection of sass mixins (&lt;a href="http://github.com/thoughtbot/bourbon/commit/e90113c959e2b45250b82b1b0294d26ccb7844d7" title="version bump to 1.3.1"&gt;e90113c&lt;/a&gt;). In this version we have a new syntax for animation shorthands, which means the old shorthands are deprecated (&lt;a href="http://github.com/thoughtbot/bourbon/commit/e6dcbf576f5962c71b6914933da75ee362ce4d56" title="Add support for the deprecated animation-basic mixin"&gt;e6dcbf5&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/bourbon/commit/a6d3a32324b73d6ad379742db035b45b1033dd81" title="Removed deprecated animation-shorthand mixin."&gt;a6d3a32&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/bourbon/commit/89cc34063b7d712f44240c864aa30285eee180bf" title="Merge branch 'animation-shorthand'"&gt;89cc340&lt;/a&gt;). Get it while it’s hot!&lt;/p&gt;

&lt;h2&gt;pacecar&lt;/h2&gt;

&lt;p&gt;We have a gem that generates scopes for ActiveRecord objects, named &lt;a href="https://github.com/thoughtbot/pacecar"&gt;pacecar&lt;/a&gt;, which you would love if you also love methods that magically appear. Matt Jankowski (&lt;a href="http://github.com/mjankowski"&gt;mjankowski&lt;/a&gt;) released version 1.5.3 (&lt;a href="http://github.com/thoughtbot/pacecar/commit/06b5e8ee4276ee37e61d339b611a8753d01fa886" title="bump version"&gt;06b5e8e&lt;/a&gt;) with support for Rails 3.1.3 and 3.0.11 (&lt;a href="http://github.com/thoughtbot/pacecar/commit/dcc30d494b14bc083b9f86b521fd8a80d44de711" title="bump to rails 3.1.3 and 3.0.11"&gt;dcc30d4&lt;/a&gt;) and which treats decimals as numeric column types, giving you all the methods that you need for those, too (&lt;a href="http://github.com/thoughtbot/pacecar/commit/ff7bc67fe62b567c7207be5dae66f6d9a914bfa1" title="include decimal in numeric column types"&gt;ff7bc67&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;paperclip&lt;/h2&gt;

&lt;p&gt;The oft-used &lt;a href="https://github.com/thoughtbot/paperclip"&gt;paperclip&lt;/a&gt; file uploader gem hit version 2.5.0 (&lt;a href="http://github.com/thoughtbot/paperclip/commit/071c93871465db9daad1718945b9ef1b4bf6291d" title="Bump to 2.5.0"&gt;071c938&lt;/a&gt;) with a &lt;a href="https://github.com/thoughtbot/paperclip/blob/071c93871465db9daad1718945b9ef1b4bf6291d/NEWS"&gt;NEWS&lt;/a&gt; file describing the changes, written by Mike Burns (&lt;a href="http://github.com/mike-burns"&gt;mike-burns&lt;/a&gt;). That’s me. I like writing about changes.&lt;/p&gt;

&lt;p&gt;Jim Ryan (&lt;a href="http://github.com/jimryan"&gt;jimryan&lt;/a&gt;) changed paperclip to process any &lt;code&gt;:original&lt;/code&gt; style before all others, which can be useful in case order matters (&lt;a href="http://github.com/thoughtbot/paperclip/commit/f56e8635a613e8f3abb4c18ea5f0f0aea3c079d6" title="Moved conditional from #post_process_styles to #process_style? method"&gt;f56e863&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/d3db7a1ce8f956fb677cc85b25e560bb2148436c" title="Process :original style before all other styles"&gt;d3db7a1&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Nathan Hyde gave us a performance gain by only generating the file’s fingerprint if it can be persisted (&lt;a href="http://github.com/thoughtbot/paperclip/commit/9fb92553685ddbd4317e0423ddb9216deeeb1118" title="Don't assign :fingerprint if the value can't be stored (both before and after save).
#fingerprint now consistently returns nil before and after saving an attachment if the value can't be written to the db."&gt;9fb9255&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/4e076813a48cd1466fe0159ab411c11f5620bd4c" title="Don't calculate fingerprint when fingerprint can not be stored."&gt;4e07681&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Alexander Greim (&lt;a href="http://github.com/iltempo"&gt;iltempo&lt;/a&gt;) landed a feature on us: S3 headers can be set at runtime by passing a block as the value of the headers instead of a static hash (&lt;a href="http://github.com/thoughtbot/paperclip/commit/a83de65ca790f311a7ed70638f497ae258f36952" title="added documentation for s3 headers as proc"&gt;a83de65&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/7a8d1e639c4ec04736557e129dc46ebd66dbbdfc" title="S3 headers can be set as a proc now"&gt;7a8d1e6&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Steve Madsen (&lt;a href="http://github.com/sjmadsen"&gt;sjmadsen&lt;/a&gt;) found an edge case where if you set an attachment, save it, set a new atachment, save it, then refresh the missing styles using the rake task, it will crash. And he fixed it (&lt;a href="http://github.com/thoughtbot/paperclip/commit/dc53432b3166a1cc711a526e1057931881babf7d" title="Don't crash when a new attachment is added.

If a model has an existing attachment and styles, and later a new attachment is added (not just new styles), "rake paperclip:refresh:missing_styles" would crash with "TypeError: can't convert nil into Array"."&gt;dc53432&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;And Jon Yurek (&lt;a href="http://github.com/jyurek"&gt;jyurek&lt;/a&gt;) finally fixed &lt;code&gt;Paperclip::Attachment&lt;/code&gt; such that it no longer overrides the Ruby &lt;code&gt;hash&lt;/code&gt; method with an unrelated one (&lt;a href="http://github.com/thoughtbot/paperclip/commit/3fd4c96b28962a95447472eb4046d9f47560c4f8" title="Fix the collision with Object#hash.

Closes #678. Closes #450."&gt;3fd4c96&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;factory_girl&lt;/h2&gt;

&lt;p&gt;As usual, &lt;a href="https://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt; got way more commits than I want to read over in one sitting. For example: Simone Carletti (&lt;a href="http://github.com/weppos"&gt;weppos&lt;/a&gt;) added a ruby version dependency to the Gemspec (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/e6e4d8bacb812002aaef47355cec7473d5b75142" title="Add `required_ruby_version` to the Gemspec.

See http://docs.rubygems.org/read/chapter/20#required_ruby_version

Some features, such as commit 4b6ada72cfe551becf13e9e707d1591833379075, requires Ruby &gt;= 1.8.7.
Also, there's no trace of Ruby 1.8.6 support in the .travis.yml file."&gt;e6e4d8b&lt;/a&gt;). He also fixed the link to our blog (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/11a79a0a40ae791fe4e2d6a558b9657c0b0695b2" title="Update Giant Robots blog URL"&gt;11a79a0&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/factory_girl/commit/30e13dd4ba57e48897ba0b9d19068a6e02939be8" title="http =&gt; https"&gt;30e13dd&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Things like that.&lt;/p&gt;

&lt;p&gt;So on the feature front, Evan Larkin (&lt;a href="http://github.com/elarkin"&gt;elarkin&lt;/a&gt;) made it such that factories still work if you define a class that overrides the &lt;code&gt;to_s&lt;/code&gt; class method (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/8b3ee85f81f346902fe7a508824c27e83758f3f3" title="Supplying a Class to a factory that overrides to_s no longer results in getting the wrong Class constructed"&gt;8b3ee85&lt;/a&gt;). Dmytrii Nagirniak (&lt;a href="http://github.com/dnagir"&gt;dnagir&lt;/a&gt;) added support for neo4j (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/5246fdad261146bb8fa613ce021c12867be58968" title="added spec to support ORMs with 'simple columns' (Neo4j)"&gt;5246fda&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/factory_girl/commit/591ec7afde160ab95c514eeca659af4f20208dc4" title="Be more agnostic to ORMs when using columns. This will allow using FG with neo4j still preserving semantics for other ORMs."&gt;591ec7a&lt;/a&gt;). Joshua Clayton (&lt;a href="http://github.com/joshuaclayton"&gt;joshuaclayton&lt;/a&gt;) made it such that you can call methods that are on the object from within a factory definition (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/d918c1ddae0c2e0d181768934a82917303d10ca6" title="Allow methods to be called from the instance in factory girl attributes

This fixes a regression introduced with the introduction of the
anonymous class.

Closes #264"&gt;d918c1d&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;More wishy-washily, Josh made a bunch of refactorings, the most important of which &lt;a href="http://robots.thoughtbot.com/post/15781666382/factory-girl-2-4-goes-meta"&gt;speeds up the whole product&lt;/a&gt; (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/f2e41389ea3f8fd455d7a14a0241c6a1ce8d801a" title="Factory evaluators use inheritance"&gt;f2e4138&lt;/a&gt;). You can read the rest of the refactorings as code with good commit messages: &lt;a href="http://github.com/thoughtbot/factory_girl/commit/2e2d4903e28f2b00dc5919701e87eeaede84cdac" title="Travis runs the 3.2 Gemfile"&gt;2e2d490&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/factory_girl/commit/40242e903ba311cb7480c305bd5fabf25d4c06de" title="Don't require AS's basic object"&gt;40242e9&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/factory_girl/commit/32ff41ffbe4cf57eb09b008a63e13ccdd7c754bf" title="Test against ActiveRecord 3.2.0.rc2 and fix bad test"&gt;32ff41f&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/factory_girl/commit/ac1df1da3b16367732c54d01b01cd11a1359092c" title="Don't compile unless necessary"&gt;ac1df1d&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/factory_girl/commit/a022dda8f81daf2dc1a32117879002980fa18503" title="Revert "Don't cache build class"

This reverts commit 845a76a59522b116065203e167be66ae771fb73a."&gt;a022dda&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/factory_girl/commit/1c7eab13d635806040bcd65cb626552cc54871f7" title="Add NullObject"&gt;1c7eab1&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/factory_girl/commit/d9e03723459f091c8756cf88469ba6ff5398b5a9" title="Mimic BasicObject without using BasicObject"&gt;d9e0372&lt;/a&gt;, and &lt;a href="http://github.com/thoughtbot/factory_girl/commit/b734b589f83c4d52278f9db206dfc22ddbbff3ec" title="Update travis.yml to run against latest versions of Ruby instead of specifying patchlevel"&gt;b734b58&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The README was improved with the status of all the dependent gems (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/768dfaa730de490b0d057bed3d4769a239891210" title="Add dependency status to README"&gt;768dfaa&lt;/a&gt;), by Steve Richert (&lt;a href="http://github.com/laserlemon"&gt;laserlemon&lt;/a&gt;). Daniel Schierbeck (&lt;a href="http://github.com/dasch"&gt;dasch&lt;/a&gt;) fixed the formatting of sample code (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/1e828893f12f79f9f2b2a67245416c4bcad80f4b" title="Make the examples use Ruby syntax highlighting on GitHub."&gt;1e82889&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In the end, Josh released version 2.4.0 (&lt;a href="http://github.com/thoughtbot/factory_girl/commit/69957ea356b08d02bf1dd47f1fe7954428b6c96e" title="Bump version to 2.4.0"&gt;69957ea&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;capybara-webkit&lt;/h2&gt;

&lt;p&gt;Matthew Mongeau (&lt;a href="http://github.com/halogenandtoast"&gt;halogenandtoast&lt;/a&gt;) had fun taking in pull requests on &lt;a href="https://github.com/thoughtbot/capybara-webkit"&gt;capybara-webkit&lt;/a&gt;. Joe Fiorini (&lt;a href="http://github.com/joefiorini"&gt;joefiorini&lt;/a&gt;) added the &lt;code&gt;requested_url&lt;/code&gt; method that produces the URL after a &lt;code&gt;pushState&lt;/code&gt; (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/7f907a00990b62f89f784341f3b7194596c1bfc1" title="Add command to retrieve URL modified by Javascript

If I use pushState to change the URL Browser#current_url still returns
the URL as it was after the original request. This commit adds a command
for RequestedUrl, which is the QtWebkit method for retrieving a URL
modified by Javascript or a redirect."&gt;7f907a0&lt;/a&gt;). Niklas Baumstark (&lt;a href="http://github.com/niklasb"&gt;niklasb&lt;/a&gt;) added &lt;code&gt;submit&lt;/code&gt; and &lt;code&gt;path&lt;/code&gt; methods (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/352823dc06f815d042806c3bf61f38e6fd71029b" title="added specs for Node#path and adapted Javascript code to pass"&gt;352823d&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/d07cf3db4d73470da881fde9e80b16395f297570" title="added specs for Node#submit and fixed parameter problem"&gt;d07cf3d&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/21f4b84691d00019e158c5256dda69f4b89ff338" title="added specs for Node#path and adapted Javascript code to pass"&gt;21f4b84&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/83905bb48cbb376fceb07c1ae1f60f15a5b35ffb" title='add "submit" method to Node that allows to submit a form node without clicking a button'&gt;83905bb&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/4ceb8740faa453740a958d5c38ac56361b55bb5b" title='implement "path" method for Node'&gt;4ceb874&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;John Hume (&lt;a href="http://github.com/duelinmarkers"&gt;duelinmarkers&lt;/a&gt;) added support for JRuby (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/0979db4675a50f0ca7ee232916a4afde49be02e4" title="Choose platform more reliably. (Works with Jruby.)"&gt;0979db4&lt;/a&gt;). Pete Gieser (&lt;a href="http://github.com/pgieser"&gt;pgieser&lt;/a&gt;) fixed a double-escaping bug in URLs (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/fccb444816269b477d7529a94f79d9e1bcad1fac" title="visit no longer tries to fix invalid URLs"&gt;fccb444&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Matthew Mongeau (&lt;a href="http://github.com/halogenandtoast"&gt;halogenandtoast&lt;/a&gt;) fixed the link to the Capybara README (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/e2c103cda663a734c9a36a6100de0d5ebfd21558" title="Update documentation to point to actual capybara readme."&gt;e2c103c&lt;/a&gt;) and linked to the mailing list (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/d8c640d18674840827e22fce114a1a3bf053c452" title="Added note about mailing list for compilation errors."&gt;d8c640d&lt;/a&gt;), and Jo Liss (&lt;a href="http://github.com/joliss"&gt;joliss&lt;/a&gt;) recommended &lt;code&gt;bundle exec&lt;/code&gt; in more places (&lt;a href="http://github.com/thoughtbot/capybara-webkit/commit/7fe06e966dfa8d9d17cae03d2c4c1639a7c3c469" title='Recommend using "bundle exec" just in case

This avoids issues like this one: https://github.com/jnicklas/capybara/issues/585'&gt;7fe06e9&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;clearance&lt;/h2&gt;

&lt;p&gt;Our authentication system aptly named &lt;a href="https://github.com/thoughtbot/clearance"&gt;clearance&lt;/a&gt; got some love from Chad Pytel (&lt;a href="http://github.com/cpytel"&gt;cpytel&lt;/a&gt;) and Joe Ferris (&lt;a href="http://github.com/jferris"&gt;jferris&lt;/a&gt;), resulting in the release of clearance 0.14.0 (&lt;a href="http://github.com/thoughtbot/clearance/commit/547115969e18e2f3240c2def91d598da957eb3fa" title="bump to 0.13.1"&gt;5471159&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/clearance/commit/214d1ddb6d806c47102117dcaee07b1f61a0ece7" title="Bump to 0.14.0"&gt;214d1dd&lt;/a&gt;, and &lt;a href="http://github.com/thoughtbot/clearance/commit/0dc43a6e2ec923256e8440021d7dbd4d37836942" title="Update the changelog"&gt;0dc43a6&lt;/a&gt;). The big deal is that the &lt;code&gt;deny_access&lt;/code&gt; RSpec match and the flash messages were totally borked. They fixed it (&lt;a href="http://github.com/thoughtbot/clearance/commit/2085f03cf41a242cbbe51ddf0fbeadf32cb6bb86" title="Mutate session when injecting clearance to fix flash messages"&gt;2085f03&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/clearance/commit/23df300891c9012ea94ee68e58d74f3e21d5a2e2" title="Fixed deny_access matcher on Rails 3.1"&gt;23df300&lt;/a&gt;, and &lt;a href="http://github.com/thoughtbot/clearance/commit/160366ea39f60286bf1805d8c759ddedd0aa10cb" title="Updated appraisal gemfiles"&gt;160366e&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;fake_braintree&lt;/h2&gt;

&lt;p&gt;Version 0.1.1 of &lt;a href="https://github.com/thoughtbot/fake_braintree"&gt;fake_braintree&lt;/a&gt; was released, in which Gabe Berke-Williams (&lt;a href="http://github.com/gabebw"&gt;gabebw&lt;/a&gt;) fixed a bug in the failure message for the &lt;code&gt;have_accessor_for&lt;/code&gt; matcher (&lt;a href="http://github.com/thoughtbot/fake_braintree/commit/9d97aa6b77c5f2f1b1f1f8a54613cc25ad52d25d" title="Better failure message."&gt;9d97aa6&lt;/a&gt;) and also refactored everything (&lt;a href="http://github.com/thoughtbot/fake_braintree/commit/0a45900bef61c8981aeafdf6cb08856844caf683" title="Reword spec."&gt;0a45900&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/59a7b600023ee71614d025542922f92247ee11b6" title="Move into a method."&gt;59a7b60&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/3daf2aa2a965501189f2379e2afcbf4c93a085f3" title="Better method names."&gt;3daf2aa&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/0f955c6e79ecb6350220326a5fa389af216cdca0" title="We can just merge the hashes."&gt;0f955c6&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/3e8745f3ac0d5422223c5a7a1b861294d02b6c4d" title="Better variable name."&gt;3e8745f&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/bb1f339fca33d75e7ca54e0721c472e1a74ccd04" title="Let's inline."&gt;bb1f339&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/6d7d90caebbc35da59c6e6362108112d2644213d" title="Well that didn't need to be public either."&gt;6d7d90c&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/ac0d550a04d00279a7ba752d9f255318c4b2ef69" title="Use double quotes."&gt;ac0d550&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/d2f470e82f3499b5260e0e00bed62f763b1773d5" title="Less direct access of ivar."&gt;d2f470e&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/3c66129ba5f0f182fa25b0d2e181ce7b5c36e1ea" title="Some dup'ing was required."&gt;3c66129&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/8cf7d9cf9d635817233644d4dd22643cf210029d" title="Abstract. No need to dup hash."&gt;8cf7d9c&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/157b2a75e200e49f8f636793eab6886637c32a31" title="Make the Subscription class behave like the others."&gt;157b2a7&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/8f2137686fb556875fe5c8e930dcf242a8e5bda8" title="Move some methods around."&gt;8f21376&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/29429ef27f2c05bf3633605f04486638ab462165" title="Better naming."&gt;29429ef&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/e4cef67622f97cb92199ab43a0ce87a845cdc9b3" title="Relying on the ivar being set is just weird."&gt;e4cef67&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/99284367aff80498c19a5bdb06996ebbbf0b4fbf" title="Fix lying method name."&gt;9928436&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/94cca243601badd8846509efe300614727293787" title="Move higher-level method up in the file."&gt;94cca24&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/7bd4e2067f2eb9a0d77cc6971e51544624b1e2cf" title="Move customer CC creation logic into method. Generate CC token in a different way."&gt;7bd4e20&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/2dde9ed72e39cfe6bb31fe40f730b285003642d4" title="Refactor to fewer 'if' statements."&gt;2dde9ed&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/e775167cda8ab3d5e52fa23624ff5c31e2e161e0" title="Higher-level code goes first. Better variable names."&gt;e775167&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/a72e31b131f3bc21d7caf04b739b3a9c167f30b0" title="Push more nil-checks down."&gt;a72e31b&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/57f36231fa5224b0b50ebf32d19b70a9d93a9b9e" title="Big refactor. Push a lot of the nil-checking logic down."&gt;57f3623&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/d58002429762f03287a84036cfa508199ba1fdf5" title="Well that didn't have to be public."&gt;d580024&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/ad82f0e7974598e0ac316d9b7ecab625fe4cf7c2" title="Make the flow clearer."&gt;ad82f0e&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/3385e125e276b07a529b8c1efa66e46cfdf04ece" title="Abstraction"&gt;3385e12&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/cacb537a45ca1003f3b54ab7f0c995c2517911c8" title="Abstract some more."&gt;cacb537&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/ae86ebec055e2d73b56c58ba2b8d77e24b61a74c" title="Make the abstraction clearer."&gt;ae86ebe&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/c6cead670dd72b60e53b7574305dd4140aa2b98a" title="Move logic to a method."&gt;c6cead6&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/a352f33169dfc849b5ca05bf53d5e8f66fd5d97d" title="Cleanup."&gt;a352f33&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/f7a6cf5f940fc667dc4780f12245dde280244b11" title="Bump to v0.1.1"&gt;f7a6cf5&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/9f1fb3bb8c09761d07972e21c5874a4a6ea0a67a" title="About to release 0.1.1"&gt;9f1fb3b&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/124706d75a4c00f8f5ae7d5c863784152b520aef" title="Better variable name. More abstraction."&gt;124706d&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/ef8b13a6708ea930a7f73945b302802da756cfac" title="Fix example description."&gt;ef8b13a&lt;/a&gt;, and &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/b20e3182530157621729d06fe58e83cfe3840df6" title="De-dupe logic."&gt;b20e318&lt;/a&gt;).&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/L4CrgWf8qsc/15797366562</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/15797366562</guid><pubDate>Fri, 13 Jan 2012 18:51:00 -0500</pubDate><category>open source</category><category>kumade</category><category>deprecations</category><category>cries for help</category><category>paul revere</category><category>bourbon</category><category>pacecar</category><category>paperclip</category><category>factory_girl</category><category>capybara-webkit</category><category>clearance</category><category>fake braintree</category><feedburner:origLink>http://robots.thoughtbot.com/post/15797366562</feedburner:origLink></item><item><title>Factory Girl 2.4 Goes Meta</title><description>&lt;p&gt;&lt;a href="https://github.com/thoughtbot/factory_girl"&gt;Factory Girl&lt;/a&gt; has been getting
some hardcore internal refactorings over the past few months.
&lt;a href="http://robots.thoughtbot.com/post/8835133151/never-fear-traits-are-here"&gt;Traits&lt;/a&gt;
are a great example of something that’s started very bare-bones with a few
caveats and been transformed to one of my favorite features of the Factory
Girl syntax. It required a pretty decent chunk of refactoring and there were
bugs for quite a while due to the way attributes in general were handled.&lt;/p&gt;

&lt;h2&gt;The Old Way&lt;/h2&gt;

&lt;p&gt;Internally, Factory Girl has four different types of attributes (Dynamic, Static,
Association, and Sequence); when compiling attributes, we were sorting
attributes by the order attributes were added, moving all static attributes
to the beginning of the list (with a &lt;code&gt;priority&lt;/code&gt; attribute). This worked for
99% of all cases but did have bugs (&lt;a href="https://github.com/thoughtbot/factory_girl/issues/247"&gt;the most recent involved traits and
dynamic attributes&lt;/a&gt;). I
wanted to resolve this once and for all.&lt;/p&gt;

&lt;h2&gt;The New Way&lt;/h2&gt;

&lt;p&gt;Factory Girl now creates a new class per factory (&lt;a href="https://github.com/thoughtbot/factory_girl/commit/f2e41389"&gt;with some awesome usage of
&lt;code&gt;Class.new&lt;/code&gt;&lt;/a&gt;) and
defines methods on that class for each attribute declared in the factory
files. This means Factory Girl doesn’t have to worry about sorting attributes
anymore; every attribute is effectively lazily-evaluated so it’ll return the
correct value every time. Factory Girl also uses inheritance for these
anonymous classes, resulting in a pretty significant speedup of factory
interaction (namely because we were copying all parent attributes and
callbacks to each child to mimic inheritance before).&lt;/p&gt;

&lt;h2&gt;What Does It Mean?&lt;/h2&gt;

&lt;p&gt;Factory Girl is now faster!&lt;/p&gt;

&lt;p&gt;Here’s some benchmarks from Factory Girl 2.3.0:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;                                user     system      total        real
build x10000                4.920000   0.010000   4.930000 (  5.028088)
trait build x10000          6.180000   0.010000   6.190000 (  6.296030)
inline trait build x10000   5.870000   0.010000   5.880000 (  5.989512)
deep build x10000           8.100000   0.020000   8.120000 (  8.285039)
attributes_for x10000       3.200000   0.010000   3.210000 (  3.289043)
create x500                 1.010000   0.320000   1.330000 (  4.186271)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And from Factory Girl 2.4.0:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;                                user     system      total        real
build x10000                3.050000   0.000000   3.050000 (  3.121359)
trait build x10000          3.260000   0.010000   3.270000 (  3.353590)
inline trait build x10000   6.700000   0.040000   6.740000 (  7.037460)
deep build x10000           3.400000   0.010000   3.410000 (  3.503984)
attributes_for x10000       0.820000   0.010000   0.830000 (  0.886641)
create x500                 0.710000   0.310000   1.020000 (  3.980102)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Grab a copy of &lt;a href="http://rubygems.org/gems/factory_girl/versions/2.4.0"&gt;Factory Girl
2.4.0&lt;/a&gt; and speed up your
suite!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/5VutPMq4bA8/15781666382</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/15781666382</guid><pubDate>Fri, 13 Jan 2012 14:40:00 -0500</pubDate><category>factory girl</category><category>rails</category><category>benchmark</category><category>metaprogramming</category><feedburner:origLink>http://robots.thoughtbot.com/post/15781666382</feedburner:origLink></item><item><title>Vim Macros and You</title><description>&lt;p&gt;Ever get the urge to update a ton of files? I know I do. For example, I
recently changed multiple hundred coffeescript files from the syntax of&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;MyGreatClass = Backbone.Model.extend(
  defaults:
    awesome: true
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class @MyGreatClass extends Backbone.Model
  defaults:
    awesome: true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;How long did it take me? A couple of minutes. Here’s how.&lt;/p&gt;

&lt;h2&gt;Ack (or Grep)&lt;/h2&gt;

&lt;p&gt;I like &lt;a href="http://betterthangrep.com/"&gt;ack&lt;/a&gt;. To find all the files I need to
edit, I’d write something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ack '^[^\s].*\=.*\.extend\($' app/assets/javascripts -l
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This finds everything that doesn’t start with a space, has an equals sign, and
has &lt;code&gt;.extend(&lt;/code&gt; at the end of the line.&lt;/p&gt;

&lt;h2&gt;Opening a list of files in vim&lt;/h2&gt;

&lt;p&gt;After looking over the results of ack and ensuring that everything that
matched is what I want to edit, I’ll open those files in vim.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vim $(ack '^[^\s].*\=.*\.extend\($' app/assets/javascripts -l)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Vim Macros&lt;/h2&gt;

&lt;p&gt;If you’ve been using vim and haven’t taken advantage of macros (especially if
you’re editing a lot of files in a similar fashion), you’re missing out. Open
up vim and type &lt;code&gt;:help q&lt;/code&gt; to get the nitty-gritty; I’ll summarize here.&lt;/p&gt;

&lt;p&gt;To start recording a macro, press (in normal mode) q and then a letter or
number. This will record a macro to whatever register you chose (via the
letter or number).&lt;/p&gt;

&lt;p&gt;Once you’re recording a macro, anything you type will be recorded to that
macro so that it can be replayed. What I would type to change these files to
the new format would be:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;qqgg0iclass @&lt;esc&gt;f=cwextends&lt;esc&gt;2f.DGdd:wnq
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Whoa, brain overload. Let’s break it down:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;qq             # records the macro to the q buffer
gg             # first line in file
0              # first character in line
iclass @&lt;esc&gt;  # inserts class @ at the cursor and returns to normal mode
f=             # finds the first equal after the cursor
cwextends&lt;esc&gt; # changes the word (=) and moves to insert mode, adds extends, and returns to normal mode
2f.            # finds the second period after the cursor
D              # deletes the remainder of the line
G              # moves to the end of the file
dd             # deletes the line
:wn            # writes the file and moves to the next file in the list
q              # stops recording
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should be fairly straightforward; the only thing I really want to point
out is the &lt;code&gt;:wn&lt;/code&gt;. The &lt;code&gt;n&lt;/code&gt; in that command moves to the next file in the list
of files you opened with vim. This is one half of what makes editing all these
files really fast.&lt;/p&gt;

&lt;h2&gt;Replaying a Macro&lt;/h2&gt;

&lt;p&gt;Now that you have your macro, it’s time to replay it. To replay a macro, press
(in normal mode) &lt;code&gt;@q&lt;/code&gt; (assuming you stored your macro into the &lt;code&gt;q&lt;/code&gt; register). If
you were to run that macro, it’ll run it against the current file, write the file,
and move to the next. Since vim supports prefixing many commands with a number
(for the number of times to repeat the command), running &lt;code&gt;100@q&lt;/code&gt; will run that
macro on the first one hundred open files that I’ve opened with vim.
Typically, this should be all you need to batch-edit, but if there are more
files, just run that command again (or start with a higher number). If there
are no more files to edit, vim will let you know.&lt;/p&gt;

&lt;p&gt;Ben also mentioned recursive macros (my mind was blown) by adding &lt;code&gt;@q&lt;/code&gt; right
before the last q (which will run the &lt;code&gt;q&lt;/code&gt; macro before stopping recording).
Just make sure your q register is empty! This would allow you to run your macro
once, without specifying the number of times to run it, because vim will run
the macro until it’s out of files. Fancy!&lt;/p&gt;

&lt;h2&gt;Vim for fun and profit&lt;/h2&gt;

&lt;p&gt;Want to kick ass at vim? Pick up a copy of &lt;a href="https://workshops.thoughtbot.com/vim"&gt;Vim for Rails
Developers&lt;/a&gt; and become blazing-fast! If
you want to hang out with fellow vim users to swap awesome tips like this, be
sure to head to the &lt;a href="http://www.meetup.com/The-Boston-Vim-Meetup/"&gt;Boston Vim
Meetup&lt;/a&gt;!&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/AKGCK2fBp2U/15348543318</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/15348543318</guid><pubDate>Fri, 06 Jan 2012 10:47:00 -0500</pubDate><category>vim</category><category>speed</category><category>coffeescript</category><category>macros</category><feedburner:origLink>http://robots.thoughtbot.com/post/15348543318</feedburner:origLink></item><item><title>Use Bundler's binstubs!</title><description>&lt;p&gt;If you’re not using bundler’s binstubs with RVM integration yet, you should give it a try! This means you don’t have to type “bundle exec” ever again.&lt;/p&gt;
&lt;p&gt;Setup:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;One time, run &lt;code&gt;chmod +x $rvm_path/hooks/after_cd_bundler&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Once for each project, run &lt;code&gt;bundle install -—binstubs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;With rvm integration enabled, the “bin” directory is added to your path each time you cd into a project directory with binstubs. That means you can just run “rake”. If you aren’t ignoring the “bin” directory in your project, you should do so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
# .gitignore
bin/
&lt;/code&gt;&lt;/pre&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/aEQkurj90Hg/15346721484</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/15346721484</guid><pubDate>Thu, 05 Jan 2012 10:18:00 -0500</pubDate><category>rvm</category><category>bundler</category><category>binstubs</category><feedburner:origLink>http://robots.thoughtbot.com/post/15346721484</feedburner:origLink></item><item><title>Evaluating alternative Decorator implementations in Ruby</title><description>&lt;p&gt;Recently, decorators have become a big part of my Ruby on Rails life.&lt;/p&gt;

&lt;p&gt;We used them heavily in a recent client project, Harold Giménez wrote &lt;a href="http://robots.thoughtbot.com/post/13641910701/tidy-views-and-beyond-with-decorators"&gt;a great post&lt;/a&gt; about them, Avdi Grimm is writing about them in &lt;a href="http://avdi.org/devblog/2011/11/15/early-access-beta-of-objects-on-rails-now-available-2/"&gt;Objects on Rails&lt;/a&gt;, and Jeff Casimir has &lt;a href="http://jumpstartlab.com/news/archives/2011/12/01/blow-up-your-views/"&gt;a great presentation&lt;/a&gt; about them.&lt;/p&gt;

&lt;p&gt;Until recently, I still had some questions, however, such as:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Should I roll my own decorators?&lt;/li&gt;
&lt;li&gt;If I roll my own, what are the tradeoffs of different implementations?&lt;/li&gt;
&lt;li&gt;Do I care about the “transparent interface” requirements of the Gang of Four’s decorator definition?&lt;/li&gt;
&lt;li&gt;Is it good or bad that the decorated object’s class is the decorator instead of the component?&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I’d like to try to answer those questions here.&lt;/p&gt;

&lt;h2&gt;Intent&lt;/h2&gt;

&lt;p&gt;A decorator is a design pattern. Its intent, as described in &lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612"&gt;Design Patterns&lt;/a&gt; by the Gang of Four is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;Use it instead of inheritance&lt;/h2&gt;

&lt;p&gt;An example I’ve seen a couple of times for decorators is the “coffee with milk and sugar” example. One that I found particularly helpful was &lt;a href="http://lukeredpath.co.uk/blog/decorator-pattern-with-ruby-in-8-lines.html"&gt;Luke Redpath’s article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s a Ruby implementation of that example using class inheritance (subclassing):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class CoffeeWithSugar &lt; Coffee
  def cost
    super + 0.2
  end
end

class CoffeeWithMilkAndSugar &lt; Coffee
  def cost
    super + 0.4 + 0.2
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The problems with inheritance include:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Choices are made statically.&lt;/li&gt;
&lt;li&gt;Clients can’t control how and when to decorate a component.&lt;/li&gt;
&lt;li&gt;Tight coupling.&lt;/li&gt;
&lt;li&gt;Changing the internals of the superclass means all subclasses must change.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;In Ruby, &lt;strong&gt;including a module is also inheritance&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module Milk
  def cost_of_milk
    0.4 if milk?
  end
end

class Coffee
  include Milk
  include Sugar

  def cost
    2 + cost_of_milk + cost_of_sugar
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;How a decorator works&lt;/h2&gt;

&lt;p&gt;Using Gang of Four terms, a &lt;strong&gt;decorator&lt;/strong&gt; is an object that encloses a &lt;strong&gt;component&lt;/strong&gt; object. It also:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;conforms to interface of component so its presence is transparent to clients.&lt;/li&gt;
&lt;li&gt;forwards (delegates) requests to the component.&lt;/li&gt;
&lt;li&gt;performs additional actions before or after forwarding.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This approach is more flexible than inheritance because you can mix and match responsibilities in more combinations and because the transparency lets you nest decorators recursively, it allows for an &lt;strong&gt;unlimited number&lt;/strong&gt; of responsibilities.&lt;/p&gt;

&lt;h2&gt;Alternative implementations in Ruby&lt;/h2&gt;

&lt;p&gt;I’ve researched and found &lt;a href="http://github.com/croaky/decorators"&gt;four common implementations of decorators&lt;/a&gt; in Ruby:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Module + Extend + Super decorator&lt;/li&gt;
&lt;li&gt;Plain Old Ruby Object decorator&lt;/li&gt;
&lt;li&gt;Class + Method Missing decorator&lt;/li&gt;
&lt;li&gt;SimpleDelegator + Super + Getobj decorator&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;There’s probably others but these seem to be the most common.&lt;/p&gt;

&lt;h2&gt;Module + Extend + Super decorator&lt;/h2&gt;

&lt;p&gt;This implementation is described, and I think advocated for, in the &lt;a href="http://www.amazon.com/Design-Patterns-Ruby-Russ-Olsen/dp/0321490452"&gt;Design Patterns in Ruby&lt;/a&gt; book. It consists of:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;module&lt;/li&gt;
&lt;li&gt;super&lt;/li&gt;
&lt;li&gt;extend&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Staying with the “coffee with milk and sugar” example for consistency, it is implemented like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Coffee
  def cost
    2
  end
end

module Milk
  def cost
    super + 0.4
  end
end

module Sugar
  def cost
    super + 0.2
  end
end

coffee = Coffee.new
coffee.extend(Milk)
coffee.extend(Sugar)
coffee.cost   # 2.6
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The benefits of this implementation are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;it delegates through all decorators&lt;/li&gt;
&lt;li&gt;it has all of the original interface because it is the original object&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The drawbacks of this implementation are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;can not use the same decorator more than once on the same object&lt;/li&gt;
&lt;li&gt;difficult to tell which decorator added the functionality&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;The “Plain Old Ruby Object” (PORO) decorator&lt;/h2&gt;

&lt;p&gt;My recommendation is to start with this style of decorator in your Ruby programs, including Rails apps, and then move to something else only when this style fails you.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Coffee
  def cost
    2
  end

  def origin
    "Colombia"
  end
end

class Milk
  def initialize(component)
    @component = component
  end

  def cost
    @component.cost + 0.4
  end
end

coffee = Coffee.new
Sugar.new(Milk.new(coffee)).cost  # 2.6
Sugar.new(Sugar.new(coffee)).cost # 2.4
Sugar.new(Milk.new(coffee)).class # Sugar
Milk.new(coffee).origin           # NoMethodError
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The benefits of this implementation are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;can be wrapped infinitely using Ruby instantiation&lt;/li&gt;
&lt;li&gt;delegates through all decorators&lt;/li&gt;
&lt;li&gt;can use same decorator more than once on component&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The drawbacks of this implementation are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;cannot transparently use component’s original interface&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;This drawback also means that &lt;strong&gt;this decorator isn’t really a decorator under the Gang of Four definition&lt;/strong&gt;. I maintain that we should still call it a decorator, however, because it otherwise looks and acts overwhelmingly like a decorator.&lt;/p&gt;

&lt;p&gt;This is a sticky opinion, however, so let’s consider the “transparent interface” requirement from Gang of Four in more detail.&lt;/p&gt;

&lt;h2&gt;Do we care about the “transparent interface” requirement?&lt;/h2&gt;

&lt;p&gt;Let’s say the interface we care about decorating is &lt;code&gt;cost&lt;/code&gt;. If so, we don’t need to also support &lt;code&gt;origin&lt;/code&gt; method. Then, the PORO decorator meets our practical needs.&lt;/p&gt;

&lt;p&gt;By redefining the scope of “interface” to be the subset of the object’s entire interface that we care about, we meet the Gang of Four definition. Is that cheating?&lt;/p&gt;

&lt;p&gt;I say no. Consider how many methods are on &lt;code&gt;Object&lt;/code&gt; in Ruby 1.9.3:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&gt; Object.new.methods.size
=&gt; 56
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;An &lt;code&gt;Object&lt;/code&gt; in Rails has more than double the number of methods:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&gt; Object.new.methods.size
=&gt; 118
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;An &lt;code&gt;ActiveRecord&lt;/code&gt; Object has even more:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&gt; User.new.methods.size
=&gt; 366
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We’re not using hundreds of methods on each object, especially in typical use from a Rails view.&lt;/p&gt;

&lt;p&gt;However, if we used the PORO decorator in a Rails app to decorate an &lt;code&gt;ActiveRecord&lt;/code&gt; object, we’re probably reducing the interface by about 300 methods.&lt;/p&gt;

&lt;p&gt;Depending on how we use the object in the app, that may or may not be a problem.&lt;/p&gt;

&lt;p&gt;In practice, when TDD’ing a new feature, I have not found this to be an actual problem. That’s why I say start with this decorator.&lt;/p&gt;

&lt;p&gt;If it’s not a problem, great. Your test suite should tell you. You might decide to add one or two more methods that do very clear delegation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def comments
  @component.comments
end

def any?
  @component.any?
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, you might feel like this is tedious or repetitive. So, let’s say we do care about the “transparent interface” requirement later on.&lt;/p&gt;

&lt;p&gt;That’s usually accomplished with &lt;code&gt;method_missing&lt;/code&gt; or something from Ruby’s &lt;code&gt;delegate&lt;/code&gt; library like &lt;code&gt;Delegator&lt;/code&gt;, &lt;code&gt;SimpleDelegator&lt;/code&gt;, &lt;code&gt;DelegateClass&lt;/code&gt;, or &lt;code&gt;Forwardable&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;“Method Missing” decorator&lt;/h2&gt;

&lt;p&gt;Here’s a &lt;code&gt;method_missing&lt;/code&gt; implementation of a Ruby decorator:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module Decorator
  def initialize(component)
    @component = component
  end

  def method_missing(meth, *args)
    if @component.respond_to?(meth)
      @component.send(meth, *args)
    else
      super
    end
  end

  def respond_to?(meth)
    @component.respond_to?(meth)
  end
end

class Coffee
  def cost
    2
  end

  def origin
    "Colombia"
  end
end

class Milk
  include Decorator

  def cost
    @component.cost + 0.4
  end
end

coffee = Coffee.new
Sugar.new(Milk.new(coffee)).cost   # 2.6
Sugar.new(Sugar.new(coffee)).cost  # 2.4
Sugar.new(Milk.new(coffee)).origin # Colombia
Sugar.new(Milk.new(coffee)).class  # Sugar
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The benefits of this implementation are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;can be wrapped infinitely using Ruby instantiation&lt;/li&gt;
&lt;li&gt;delegates through all decorators&lt;/li&gt;
&lt;li&gt;can use the same decorator more than once on the same component&lt;/li&gt;
&lt;li&gt;transparently uses component’s original interface&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The drawbacks of this implementation are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;uses method_missing&lt;/li&gt;
&lt;li&gt;the class of the decorated object is the decorator&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Do we care that the class is the decorator?&lt;/h2&gt;

&lt;p&gt;We should not. This is Ruby, land of duck typing.&lt;/p&gt;

&lt;p&gt;However, Rails inflects (&lt;code&gt;object.class.name&lt;/code&gt;) for polymorphic relationships, &lt;code&gt;form_for&lt;/code&gt;, and other places. When I tried to convert a few older Rails view helpers to decorators, &lt;strong&gt;this was an actual problem&lt;/strong&gt; in the form of &lt;code&gt;ActiveRecord&lt;/code&gt; errors during test runs.&lt;/p&gt;

&lt;p&gt;In some cases, this revealed a deeper problems. By re-working the model code, I was able to use PORO decorators and the overall codebase was cleaner. Other times, I just thought it was less time-consuming to make the &lt;code&gt;class&lt;/code&gt; appear to be the component’s class and move on.&lt;/p&gt;

&lt;h2&gt;“SimpleDelegator + Super + Getobj” decorator&lt;/h2&gt;

&lt;p&gt;So, a Rails compromise is this decorator implementation. I’m trying to use it only as a last resort.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Coffee
  def cost
    2
  end

  def origin
    "Colombia"
  end
end

require 'delegate'

class Decorator &lt; SimpleDelegator
  def class
    __getobj__.class
  end
end

class Milk &lt; Decorator
  def cost
    super + 0.4
  end
end

coffee = Coffee.new
Sugar.new(Milk.new(coffee)).cost   # 2.6
Sugar.new(Sugar.new(coffee)).cost  # 2.4
Milk.new(coffee).origin            # Colombia
Sugar.new(Milk.new(coffee)).class  # Coffee
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The benefits of this implementation are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;can be wrapped infinitely using Ruby instantiation&lt;/li&gt;
&lt;li&gt;delegates through all decorators&lt;/li&gt;
&lt;li&gt;can use same decorator more than once on component&lt;/li&gt;
&lt;li&gt;transparently uses component’s original interface&lt;/li&gt;
&lt;li&gt;class is the component&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The drawbacks of this implementation are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;it redefines &lt;code&gt;class&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I honestly don’t know exactly what sort of problems can result from using &lt;code&gt;method_missing&lt;/code&gt; or redefining &lt;code&gt;class&lt;/code&gt; but I imagine they’ll be manifested in the form of a time-consuming debugging session.&lt;/p&gt;

&lt;h2&gt;Plan of action&lt;/h2&gt;

&lt;p&gt;I think I now understand the tradeoffs of different Ruby implementations and have a plan for using them:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;PORO to start&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SimpleDelegator&lt;/code&gt; if I need the “transparent interface” requirement or the decorated object’s &lt;code&gt;class&lt;/code&gt; is causing problems for Rails&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I still have other questions like:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;What’s the difference between a decorator and a presenter?&lt;/li&gt;
&lt;li&gt;What’s the difference between a decorator and a strategy? And a composite?&lt;/li&gt;
&lt;li&gt;Should I use a gem like Draper?&lt;/li&gt;
&lt;li&gt;Is there any reason to use classic Rails view helpers anymore?&lt;/li&gt;
&lt;li&gt;Should I be using a different templating system like Mustache?&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I think I have answers to some, but that’s another post…&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/eSjsR9HB9Ac/14825364877</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/14825364877</guid><pubDate>Mon, 26 Dec 2011 16:13:00 -0500</pubDate><category>design patterns</category><category>ruby</category><category>decorators</category><category>method_missing</category><category>inheritance</category><category>delegating</category><feedburner:origLink>http://robots.thoughtbot.com/post/14825364877</feedburner:origLink></item><item><title>A quick screencast that shows how I use CSS snippets to speed up...</title><description>&lt;iframe src="http://player.vimeo.com/video/33041038?title=0&amp;byline=0&amp;portrait=0" width="400" height="249" frameborder="0"&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;span&gt;A quick screencast that shows how I use CSS snippets to speed up my workflow.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Links Mentioned in video:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/zen-coding/downloads/detail?name=TextMate.Zen.CSS.1.3.1.zip&amp;can=2&amp;q="&gt;Textmate Zen CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kuroir/SCSS.tmbundle"&gt;Textmate SCSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tisho/css-snippets-snipmate"&gt;Vim CSS Snippets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/1398610"&gt;My Vim CSS Snippets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/MOeO4NJrq7c/13641180479</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/13641180479</guid><pubDate>Wed, 21 Dec 2011 09:00:00 -0500</pubDate><category>css</category><category>snippets</category><category>vim</category><category>textmate</category><feedburner:origLink>http://robots.thoughtbot.com/post/13641180479</feedburner:origLink></item><item><title>This week in open source</title><description>&lt;h2&gt;paperclip&lt;/h2&gt;

&lt;p&gt;Much of the work over the past week was done in &lt;a href="https://github.com/thoughtbot/paperclip"&gt;paperclip&lt;/a&gt;, so now you can upload files to your Rails apps with more flare and style!&lt;/p&gt;

&lt;p&gt;It now supports an option for keeping old files, so you can pass &lt;code&gt;:keep_old_files&lt;/code&gt; to &lt;code&gt;has_attached_file&lt;/code&gt; and, when you destroy an attachment (&lt;code&gt;@user.avatar.destroy&lt;/code&gt;) it won’t actually delete the underlying files (&lt;a href="http://github.com/thoughtbot/paperclip/commit/345ec743fc512f290e90451a7776d824f7e3b566" title="Add 'keep_old_files' option.


From https://github.com/pcreux/paperclip/commit/52374958ef83f1641cf008aead27c23b25fb842d

Conflicts:

	lib/paperclip/attachment.rb"&gt;345ec74&lt;/a&gt;). Many people find this useful for S3 storage, which hints that there may be a deeper problem elsewhere. This is thanks to Eike Bernhardt (&lt;a href="http://github.com/teefax"&gt;teefax&lt;/a&gt;) but was originally written by Philippe Creux (&lt;a href="https://github.com/pcreux"&gt;pcreux&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Christoph Lupprich (&lt;a href="http://github.com/kitto"&gt;kitto&lt;/a&gt;) saw a quick way to speed up the &lt;code&gt;#public_url&lt;/code&gt; method for Fog storage using AWS as the provider, so he did (&lt;a href="http://github.com/thoughtbot/paperclip/commit/989ec0eeaf5c94285a9ee89264c70af4f1ca17b2" title="Fix Fog's slow `public_url` access"&gt;989ec0e&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I’ve long wanted a migration helper, and Daniel Schierbeck (&lt;a href="http://github.com/dasch"&gt;dasch&lt;/a&gt;) wrote it with some git cleanup from Alexey Mahotkin (&lt;a href="http://github.com/thoughtbot/paperclip/commit/693b5280c0679751ad12d8e862b509750c981e9d" title="Add a test for #drop_attached_file"&gt;693b528&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/b922111b25058b419c98ce53502ee41dbf5a8474" title="Remove an unused require statement"&gt;b922111&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/f82c0d94f1fad37575b33ba67998ea7fa1f1fe41" title="Further refactor the schema implementation"&gt;f82c0d9&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/f3eacd2483ef9fdf2ac3c3a0758370c3ee7bed85" title="Document Paperclip::Schema"&gt;f3eacd2&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/e0a6732409be0031c708579e2710d39c36495065" title="Refactor the implementation of the schema helpers"&gt;e0a6732&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/ffbfc24e42aefc1cfb009697ad1311e00480ee8e" title="Add a proper test suite of the schema helper"&gt;ffbfc24&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/500f1bb11ecd10dd6ac01a0f8a7635ba4245015b" title="Add a helper that creates the Paperclip columns

    This can be used in migrations, i.e.

      create_table :users do |t|
        t.has_attached_file :avatar
      end

(three commits squashed into one by Alexey Mahotkin &lt;squadette@gmail.com&gt;)"&gt;500f1bb&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/b70ffbc9fc34e69a4b7086c1733e6421b6ead9a8" title="Shorten migration roll-back also"&gt;b70ffbc&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/65a6ae8c19e10cd3886a6696e6cf7739fa2bac82" title="Fix the build on 1.9.2: require ./test/helper instead of just test/helper."&gt;65a6ae8&lt;/a&gt;). It looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class AddAvatarColumnsToUser &lt; ActiveRecord::Migration
  def self.up
    change_table :users do |t|
      t.has_attached_file :avatar
    end
  end

  def self.down
    drop_attached_file :users, :avatar
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There were also some important internal changes. For example, Prem Sichanugrist (&lt;a href="http://github.com/sikachu"&gt;sikachu&lt;/a&gt;) replaced the AWS::S3 gem with AWS::SDK (&lt;a href="http://github.com/thoughtbot/paperclip/commit/1df1b030c93ae6b452b0eec51781b8a29a7867e8" title="Make sure that `aws-sdk` is installed by checking for AWS::Core instead"&gt;1df1b03&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/81129ad11c932897c2003144e8a2c76a5c613878" title="Do not calling `AWS.stub!` right away, it's leaking to S3LiveTest"&gt;81129ad&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/88a8af955db647375411173c566a26ececc7118b" title="Change ENV['S3_TEST_BUCKET'] to ENV['S3_BUCKET']"&gt;88a8af9&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/75f413da0f346be3f4b08199c3b7966d2bd5442d" title="Use AWS::SDK instead of AWS::S3

The original commit came from @amazonwebservices and @trevorrowe in #579.
I had to revise the commit and make sure all the test cases are passing.
All credits still goes to those guys, thanks a lot!"&gt;75f413d&lt;/a&gt;, &lt;a href="http://github.com/thoughtbot/paperclip/commit/2cf73787912d4eebfbdb5b9abfb386a80f534ce8" title="Remove duplicate test from the merge"&gt;2cf7378&lt;/a&gt;). He called out AWS (&lt;a href="https://github.com/amazonwebservices"&gt;amazonwebservices&lt;/a&gt;) and Trevor Rowe (&lt;a href="https://github.com/trevorrowe"&gt;trevorrowe&lt;/a&gt;) for helping, and John Joseph Bachir (&lt;a href="http://github.com/jjb"&gt;jjb&lt;/a&gt;) updated the docs appropriately (&lt;a href="http://github.com/thoughtbot/paperclip/commit/308f1a0f0cd6be6b4190db2f2a71018eba13a2c4" title="documentation for including aws-sdk in Gemfile"&gt;308f1a0&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Prem also got Paperclip passing on Rubinius (&lt;a href="http://github.com/thoughtbot/paperclip/commit/001fd99feff71509bd3227ac64ba3ca443dc931d" title="Remove Rubinius cache files for real this time."&gt;001fd99&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In bug fixes, base URLs with a &lt;code&gt;?&lt;/code&gt; but no &lt;code&gt;=&lt;/code&gt; will produce Paperclip URLs using &lt;code&gt;?&lt;/code&gt; (&lt;a href="http://github.com/thoughtbot/paperclip/commit/128d664c1143d119922393fde342431c1523535e" title="URLGenerator should disregard a ? which isn't followed by an =

In some case, we seriously don't want to prepend the timestamp with &amp; if there wasn't a query string there. If the original URL doesn't have any query string, we should add the ?."&gt;128d664&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/bb22be301a783b2e2ab58f7904231ffd8211766c" title="Use Net::HTTP instead of curl

There was some problem with command line parsing with a special character."&gt;bb22be3&lt;/a&gt;). Prem thinks that’s the right behavior now, but it’s tricky to nail down.&lt;/p&gt;

&lt;p&gt;Nick Padgett (&lt;a href="http://github.com/npadgett"&gt;npadgett&lt;/a&gt;) found an edgecase where we were calling &lt;code&gt;strip&lt;/code&gt; on a non-string object, sometimes, and fixed that (&lt;a href="http://github.com/thoughtbot/paperclip/commit/34913f12894b53031456c5cbbcb7117a8d912bbc" title="Standardize strip with resy of application.  Without to_s, causes errors like "undefined method `strip' for image/bmp:MIME::Type"."&gt;34913f1&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Dimitrij Denissenko (&lt;a href="http://github.com/dim"&gt;dim&lt;/a&gt;) handled the case where using the &lt;code&gt;:id_partition&lt;/code&gt; pattern in a URL or path pattern raises a &lt;code&gt;NoMethodError&lt;/code&gt; on an unsaved resource (&lt;a href="http://github.com/thoughtbot/paperclip/commit/ac822448489df3aa97ce896f3023d874ab36f12c" title="Fixed ID partitioning interpolation, when cloning attachments"&gt;ac82244&lt;/a&gt;). He and I are now enemies for life for his use of &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Prem fixed another bug: if you have a path or URL pattern with &lt;code&gt;:class&lt;/code&gt; in it it will show a warning. He removed this warning (&lt;a href="http://github.com/thoughtbot/paperclip/commit/b4ff2c5777df6ac3b0942dc645cfde2d1ace62c8" title="Do not show warning if :class exists in the interpolation URL

This fixes #660"&gt;b4ff2c5&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Prem worked with Steve Richert (&lt;a href="http://github.com/laserlemon"&gt;laserlemon&lt;/a&gt;) to show the Gemnasium results in the README (&lt;a href="http://github.com/thoughtbot/paperclip/commit/3e209072794363df84a17c4ec6133221e8be9f8f" title="Add dependency status to the README via Gemnasium"&gt;3e20907&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/paperclip/commit/777ac90092cc2ad7f71ea4b3633ac0372df22f35" title="Update Cucumber dependency

This is necessary so Gemnesium will be green."&gt;777ac90&lt;/a&gt;), and Prem also updated the README to be more readable (&lt;a href="http://github.com/thoughtbot/paperclip/commit/adcd03c93efc140c44433b3fe4a6d563a251061d" title="First pass on editing the README for more readability."&gt;adcd03c&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;fake_braintree&lt;/h2&gt;

&lt;p&gt;The fake credit card processor, &lt;a href="https://github.com/thoughtbot/fake_braintree"&gt;fake_braintree&lt;/a&gt;, hit 0.0.6 (&lt;a href="http://github.com/thoughtbot/fake_braintree/commit/eed875ecdedef2609a91ae47fe6688eac963f178" title="Bump to 0.0.6"&gt;eed875e&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/0934f1e6a74c058ca277ad271e3861a4ea298965" title="Update the Changelog even more."&gt;0934f1e&lt;/a&gt;) this week as Ben Orenstein (&lt;a href="http://github.com/r00k"&gt;r00k&lt;/a&gt;) added support for discounted subscriptions (&lt;a href="http://github.com/thoughtbot/fake_braintree/commit/757c0aad2998cab4475552410c60b949fc1bcf92" title="Add basic support for adding discounts to subscriptions."&gt;757c0aa&lt;/a&gt;) and Gabe Berke-Williams (&lt;a href="http://github.com/gabebw"&gt;gabebw&lt;/a&gt;) exposed the transactions that have run (&lt;a href="http://github.com/thoughtbot/fake_braintree/commit/8dde09c6a78ec4cab020ae9b095d454d4643d217" title="Ensure that FakeBraintree.transactions is exposed."&gt;8dde09c&lt;/a&gt; and &lt;a href="http://github.com/thoughtbot/fake_braintree/commit/ab93137eb58e736b24cb96c94cec1e44dd084403" title="Use mattr_accessor."&gt;ab93137&lt;/a&gt;).

&lt;/p&gt;&lt;h2&gt;suspenders&lt;/h2&gt;

&lt;p&gt;Taking a stance on whether we play along with the little Open Directory Project game, &lt;a href="https://github.com/thoughtbot/suspenders"&gt;suspenders&lt;/a&gt; now defaults to &lt;code&gt;NOODP&lt;/code&gt; on every page which, as Matt Jankowski (&lt;a href="http://github.com/mjankowski"&gt;mjankowski&lt;/a&gt;) points out, tells Web crawlers to never bother looking for ODP details (&lt;a href="http://github.com/thoughtbot/suspenders/commit/6275d0f280145394e15732694da547adf72b7ca6" title="Google will prefer ODP listings over the site meta description unless this is in place"&gt;6275d0f&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;shoulda-matchers&lt;/h2&gt;

&lt;p&gt;The sweet &lt;a href="https://github.com/thoughtbot/shoulda-matchers"&gt;shoulda-matchers&lt;/a&gt; collection of RSpec matchers now has more accurate error messages for the &lt;code&gt;allow_value&lt;/code&gt; matcher (&lt;a href="http://github.com/thoughtbot/shoulda-matchers/commit/25c2623bb9d96cf6a446ecc141fdfefe5c4860fa" title="Merge branch 'master' of https://github.com/clemenshelm/shoulda-matchers"&gt;25c2623&lt;/a&gt;), thanks to Clemens Helm (&lt;a href="https://github.com/clemenshelm"&gt;clemenshelm&lt;/a&gt;). It uses the underlying internationalization information to generate this.&lt;/p&gt;

&lt;h2&gt;bourbon&lt;/h2&gt;

&lt;p&gt;Another documentation update on &lt;a href="https://github.com/thoughtbot/bourbon"&gt;bourbon&lt;/a&gt; as Phil LaPier (&lt;a href="http://github.com/plapier"&gt;plapier&lt;/a&gt;) explained that multiple background images with shorthand notation are unsupported (&lt;a href="http://github.com/thoughtbot/bourbon/commit/798aa1ce860e7f2c2741c4ac2bf0b402ac226ff1" title="Added unsupported background-image mixin to docs"&gt;798aa1c&lt;/a&gt;), after clarifying that multiple background images themselves have fancy comma-separated syntax (&lt;a href="http://github.com/thoughtbot/bourbon/commit/aa6683149d6538d883dd0b16fc02794300572917" title="Added a note about shorthand notation for background-image"&gt;aa66831&lt;/a&gt;).&lt;/p&gt;</description><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/cBfhx33Dsv8/14323715264</link><guid isPermaLink="false">http://robots.thoughtbot.com/post/14323715264</guid><pubDate>Fri, 16 Dec 2011 17:03:24 -0500</pubDate><category>this week in open source</category><category>paperclip</category><category>shoulda</category><category>braintree</category><category>suspenders</category><category>rspec</category><category>bourbon</category><feedburner:origLink>http://robots.thoughtbot.com/post/14323715264</feedburner:origLink></item></channel></rss>

