<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Luigi Montanez</title>
 <link href="http://luigimontanez.com/atom.xml" rel="self"/>
 <link href="http://luigimontanez.com/"/>
 <updated>2013-05-31T08:16:46-04:00</updated>
 <id>http://luigimontanez.com/</id>
 <author>
   <name>Luigi Montanez</name>
   <email>luigi.montanez@gmail.com</email>
 </author>

 
 
 <entry>
   <title>QR Codes In China And The Troubling State of Tech Reporting</title>
   <link href="http://luigimontanez.com/2013/qr-codes-china-troubling-state-tech-reporting/"/>
   <updated>2013-05-31T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2013/qr-codes-china-troubling-state-tech-reporting/qr-codes-china-troubling-state-tech-reporting</id>
   <content type="html">&lt;p&gt;A slide deck by Mary Meeker, partner at Kleiner Perkins, has been making the rounds:&lt;/p&gt;

&lt;iframe src=&quot;http://www.slideshare.net/slideshow/embed_code/22135327?rel=0&quot; width=&quot;600&quot; height=&quot;500&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px&quot; allowfullscreen=&quot;&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot;&gt; &lt;/iframe&gt;
&lt;div style=&quot;margin-bottom:5px&quot;&gt; &lt;strong&gt; &lt;a href=&quot;http://www.slideshare.net/kleinerperkins/kpcb-internet-trends-2013&quot; title=&quot;KPCB Internet Trends 2013&quot; target=&quot;_blank&quot;&gt;KPCB Internet Trends 2013&lt;/a&gt; &lt;/strong&gt; from &lt;strong&gt;&lt;a href=&quot;http://www.slideshare.net/kleinerperkins&quot; target=&quot;_blank&quot;&gt;Kleiner Perkins Caufield &amp;amp; Byers&lt;/a&gt;&lt;/strong&gt; &lt;/div&gt;

&lt;p&gt;One graph in particular caught my eye: Slide 64 reports a 4X year-over-year increase in QR code usage in China. There were around 2 million scans in March 2012, and 9 million scans in March 2013.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/slide-64.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That certainly looks impressive! The audience is left to conclude that QR code adoption in China is turning out to be quite different from what it’s been like in the U.S.&lt;/p&gt;

&lt;p&gt;But something about this smelled fishy to me. China is a country of 1.3 billion people, so 9 million of anything isn’t that big. If those 9 million scans were performed by 9 million different people – a presumption that’s highly optimistic – that would mean just 0.7% of the population scanned a QR code. &lt;/p&gt;

&lt;p&gt;But surely, the 4X year-over-year growth is something notable, right? Not when you consider that QR code usage will go up as more people use smartphones. A mere three slides later in the deck, we see how much iOS + Android usage has grown in China:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/slide-67.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In February 2012, China’s active base looks to be around 70 million, which grew to nearly 250 million in February 2013. So year-over-year growth in nearly the same time window is about 3.5X, which almost fully accounts for the 4X growth in QR code scanning.&lt;/p&gt;

&lt;p&gt;Based on this quick analysis, QR codes look to be as much a dud in China as they have been here in America. Certainly not as impressive as the slide makes it out to be.&lt;/p&gt;

&lt;p&gt;I searched &lt;a href=&quot;https://www.google.com/search?q=china+qr+codes&quot;&gt;Google&lt;/a&gt; to find corroborating data, and instead saw that the tech press has been breathlessly reporting on that same slide I had noticed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://techcrunch.com/2013/05/29/people-actually-use-qr-codes-in-china/&quot;&gt;TechCrunch&lt;/a&gt; claims that “people actually use” QR codes in China, repeating key points from the slide deck, and concluding with a personal anecdote about a recent trip to Beijing. &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.bizreport.com/2013/05/qr-code-scanning-takes-off-in-china.html&quot;&gt;BizReport&lt;/a&gt; says that QR code scanning is “taking off” in China, then repeats the key points from the slide deck, and at least does some additional research to dig up links on QR codes in cemeteries and watermelons.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.technologyreview.com/view/515506/internets-annual-report-card-shows-chinas-rise/&quot;&gt;MIT Technology Review&lt;/a&gt; wrote an article on the broader points about China that Meeker made, but also uncritically repeats what was stated in the deck.&lt;/li&gt;
  &lt;li&gt;And &lt;a href=&quot;http://vr-zone.com/articles/qr-codes-are-getting-popular-in-china/32549.html&quot;&gt;VR-ZONE&lt;/a&gt; lazily rewrites the TechCrunch article.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these articles simply repeat something that was stated, in some cases verbatim, without even a hint of any critical thought going into the production of content.&lt;/p&gt;

&lt;p&gt;So who’s at fault here? On the individual level, Meeker should have done a little more digging into why QR code usage has risen, especially considering that the answer was right there three slides later. Each of the articles linked to above were written by tech reporters, and they bear the brunt of responsibility for not doing any due diligence for their readers.&lt;/p&gt;

&lt;p&gt;But the real fault lies in the broken institution of journalism itself. The tech industry, particularly around consumer Internet and mobile, is severely underserved by its reporters. The quality of journalism is consistently bad – lacking depth, insight, and expertise. Original, long-form reporting is rare. Pundits with opinions have disproportionate mindshare, particularly those who write about Apple and Google. They certainly drive pageviews. But punditry alone isn’t good enough.&lt;/p&gt;

&lt;p&gt;The Wall Street Journal is the &lt;a href=&quot;http://en.wikipedia.org/wiki/List_of_newspapers_in_the_United_States_by_circulation&quot;&gt;most widely circulated newspaper&lt;/a&gt; in America. Imagine if it only consisted of its right-wing editorial section. Sure, those pundits might be able to attract some readers, but not nearly enough to be sustainable. The reason the Wall Street Journal is so successful is because it produces extremely high-quality journalism around business and finance. It serves its industry very well.&lt;/p&gt;

&lt;p&gt;So what the tech industry needs is an equivalent of what the Wall Street Journal is to those in the finance industry. Or maybe – and excuse while I hold my nose – what POLITICO is to Washington, D.C. and political junkies. &lt;/p&gt;

&lt;p&gt;The current outlets just don’t cut it. The newspapers in Silicon Valley don’t have much reach. On the Web, Ars Technica and The Register produce quality material, but not enough. The hugely popular gadget blogs are more about consumerism as entertainment instead of the technology that’s really at the heart of the industry: software.&lt;/p&gt;

&lt;p&gt;Imagine a news organization that had the technical expertise and industry connections to really dive into the Heroku/RapGenius kerfuffle, or the Adria Richards incident, or why exactly Ruby on Rails had so many critical security patches a few months ago. This industry is so important, and it deserves better journalism.&lt;/p&gt;

&lt;p&gt;It’s time to do something about that.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>What I'll Miss Most About Google Reader: Speed and Magic</title>
   <link href="http://luigimontanez.com/2013/what-ill-miss-most-about-google-reader-speed-magic/"/>
   <updated>2013-03-17T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2013/what-ill-miss-most-about-google-reader-speed-magic/what-ill-miss-most-about-google-reader-speed-magic</id>
   <content type="html">&lt;p&gt;Last week, Google announced that it &lt;a href=&quot;http://googlereader.blogspot.com/2013/03/powering-down-google-reader.html&quot;&gt;plans to shut down Google Reader&lt;/a&gt; later this year. I’m a passionate fan of Google Reader – using it several times a week – and I was very disappointed to read about the decision.&lt;/p&gt;

&lt;p&gt;I’ve been heartened to see the flurry of activity around building a replacement, culminating with the announcement that &lt;a href=&quot;http://www.digg.com/reader&quot;&gt;Digg is planning their own Reader&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the midst of the hand-wringing and &lt;a href=&quot;http://www.change.org/petitions/google-keep-google-reader-running&quot;&gt;petition-signing&lt;/a&gt; on Twitter, I saw an astute observation:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p&gt;Lots of boo hoo about Google Reader. Not much mention of any specific feature that dies with it.&lt;/p&gt;&amp;mdash; Sam Schenkman-Moore (@samsm) &lt;a href=&quot;https://twitter.com/samsm/status/312188661158535168&quot;&gt;March 14, 2013&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p&gt;Must be frustrating. Google Reader competitors reading this whining get no insight into what to create to replace it.&lt;/p&gt;&amp;mdash; Sam Schenkman-Moore (@samsm) &lt;a href=&quot;https://twitter.com/samsm/status/312188872484347906&quot;&gt;March 14, 2013&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;So as a sort of PSA to whomever builds the next feed reader I wind up using, here’s what I think makes Google Reader so special: speed and magic. &lt;/p&gt;

&lt;h2 id=&quot;speed&quot;&gt;Speed&lt;/h2&gt;

&lt;p&gt;For an app that displays lots of content from many different sources, Google Reader is consistently fast. It’s snappy. I click – and boom! – I see what I wanted to see. The load times are nearly imperceptible. Sadly, the alternatives I tried this week were decidedly un-snappy.&lt;/p&gt;

&lt;p&gt;But more important for me – as a practitioner of a &lt;a href=&quot;http://luigimontanez.com/2010/mouseless-monday-1-vimium-google-chrome/&quot;&gt;mouseless lifestyle&lt;/a&gt; – is Google Reader’s extensive support for Vim-like keyboard shortcuts.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/google-reader-shortcuts.png&quot; width=&quot;600px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Those jumping shortcuts (g then _) are game-changing. So, so good. The movement key choices are actually a bit quirky. I find myself hitting the ‘N’ and ‘P’ keys more than the home keys like ‘J’ and ‘K’. But over the years I’ve developed muscle memory, and I go into a zen-like state when processing my feeds.&lt;/p&gt;

&lt;p&gt;The next feed reader I use needs to work as fast as I can think. It needs to load content quickly, and it needs to have Vim-like keyboard shortcuts baked in.&lt;/p&gt;

&lt;h2 id=&quot;magic&quot;&gt;Magic&lt;/h2&gt;

&lt;p&gt;To subscribe to a blog through its feed, one must find the RSS (or Atom) link somewhere on that blog. This takes some technical savvy. There’s a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag that makes it browser-discoverable. If the blog doesn’t have that, it may have an RSS link or that orange icon somewhere in the header, sidebar, or footer.&lt;/p&gt;

&lt;p&gt;In recent years, I’ve noticed that some blogs just don’t provide any sort of link to a feed. No &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag that gets detected by a browser. No RSS icon. And that’s where Google Reader’s magic comes in.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/google-reader-subscribe.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Because in that “Subscribe” box, I can pop in the URL of the blog I want to subscribe to, and Google Reader just knows the feed for it. It’s never failed me. It. Just. Works.&lt;/p&gt;

&lt;p&gt;The next feed reader I use needs to be a little magical when it comes to feed detection, because I don’t have the patience to hunt down feed URLs. Taking it a step further, I’d like a browser extension that automatically adds the blog I’m viewing directly to my feed reader and doesn’t interrupt my flow. It should Just Work.&lt;/p&gt;

&lt;h2 id=&quot;two-virtues-of-great-web-apps&quot;&gt;Two Virtues of Great Web Apps&lt;/h2&gt;

&lt;p&gt;There’s a larger point here: Speed and magic are the two most important virtues of great web apps. Be as fast (or faster) than the user can think. Don’t make the user wait. And delight the user by providing magically pleasant experiences.&lt;/p&gt;

&lt;p&gt;Google understands this; those virtues are what make the best Google products so great. I consider Google Reader to be one of the best web apps ever made. Here’s hoping that the creators of the next great feed reader keep speed and magic on the front burner.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>The Rise of the Activist Engineer</title>
   <link href="http://luigimontanez.com/2013/rise-activist-engineer/"/>
   <updated>2013-01-08T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2013/rise-activist-engineer/rise-activist-engineer</id>
   <content type="html">&lt;p&gt;I’ve had a unique career for a software developer. An idealistic Howard Dean supporter during college, I went to work for his PAC &lt;a href=&quot;http://www.democracyforamerica.com&quot;&gt;Democracy for America&lt;/a&gt; immediately after graduation. One brutally cold Vermont winter is one too many, so I then spent a few years building websites as a consultant for political campaigns, advocacy organizations, and labor unions. I proceeded to work at the &lt;a href=&quot;http://sunlightfoundation.com&quot;&gt;Sunlight Foundation&lt;/a&gt; for a few years before settling into my current role at &lt;a href=&quot;http://www.upworthy.com/engineers&quot;&gt;Upworthy&lt;/a&gt;. I’ve always been employed to build web apps, but I’ve done it exclusively for organizations that aligned with my particular worldview.&lt;/p&gt;

&lt;h3 id=&quot;obama-2012&quot;&gt;Obama 2012&lt;/h3&gt;

&lt;p&gt;This mission-driven approach to a career is commonplace for those of us inside the Beltway, but until recently wasn’t very common for those who work in the larger tech industry. That appears to be changing. A tipping point seems to have been reached with the staffers of the Obama 2012 re-election campaign. The campaign’s Tech Team has been the subject of &lt;a href=&quot;http://www.quora.com/obamatech&quot;&gt;glowing press profiles&lt;/a&gt; in the aftermath of their victory. &lt;/p&gt;

&lt;p&gt;Previous presidential elections, particularly on the Democratic side, have spawned tech companies. Consultancies like &lt;a href=&quot;http://www.bluestatedigital.com/&quot;&gt;Blue State Digital&lt;/a&gt; and &lt;a href=&quot;http://www.echoditto.com/&quot;&gt;EchoDitto&lt;/a&gt; formed in the wake Howard Dean’s 2004 primary campaign, and Barack Obama’s victorious 2008 effort yielded startups like &lt;a href=&quot;https://www.optimizely.com/&quot;&gt;Optimizely&lt;/a&gt; and &lt;a href=&quot;https://www.nationalfield.com&quot;&gt;NationalField&lt;/a&gt;. While many of the Obama 2012 tech staffers came from outside the political sphere, it stands to reason that quite a few will continue to be involved in politics and advocacy.&lt;/p&gt;

&lt;p&gt;Beyond the several dozen engineers employed directly by the Obama campaign, the fawning press coverage about them will surely inspire many others around the country, and maybe around the world, to focus their talents towards politics and advocacy.&lt;/p&gt;

&lt;p&gt;From a software developer’s perspective, what the Obama Tech Team did wasn’t technically groundbreaking. Instead, it’s clear that the team was thoroughly competent, given the time and resources needed to succeed. That sort of work environment is highly appealing. The Obama Tech Team’s lasting contribution will be the example they set for the future.&lt;/p&gt;

&lt;h3 id=&quot;changing-the-world&quot;&gt;Changing the World&lt;/h3&gt;

&lt;p&gt;The prospects for more activist engineers are bolstered by a failed promise of Silicon Valley. A long-time refrain has been that VC-backed Silicon Valley startups can indeed change the world. But the current crop of consumer web and mobile startups don’t live up to that ideal. SnapChat and Facebook Poke aren’t changing the world, they’re enabling people to be even more self-centered and insular. Airbnb and Uber, two terrific services that are profoundly disrupting their markets, don’t make that dent in the universe Steve Jobs once spoke of.&lt;/p&gt;

&lt;p&gt;The change the world lottery is even harder to win than the startup lottery. Facebook, Twitter, Apple, Google. And winning the change the world lottery is fleeting. The average engineer who spends a year working for Google or Facebook will do more good for the world by donating her considerable year-end bonus to various charities. If you want to change the world, apply your talents to actually changing the world. &lt;/p&gt;

&lt;p&gt;As &lt;a href=&quot;http://cbracy.tumblr.com/post/39314979304/silicon-valleys-problem&quot;&gt;noted by Catherine Bracy&lt;/a&gt;, Silicon Valley has culturally created such an enormous bubble around itself that it’s blind to issues experienced by the rest of the world. Yes, SOPA and PIPA were bad, but our current prison system is horrific.&lt;/p&gt;

&lt;p&gt;The situation isn’t completely dire, of course. Bright spots are emerging. It’s important to identify and organize those engineers who want to contribute their talents directly, and that’s &lt;a href=&quot;http://cbracy.tumblr.com/post/36921516103/my-experience-leading-the-obama-campaigns-tech-field&quot;&gt;what Catherine Bracy did&lt;/a&gt; as she led the Obama campaign’s San Francisco Tech Field Office.&lt;/p&gt;

&lt;h3 id=&quot;civic-hacking&quot;&gt;Civic Hacking&lt;/h3&gt;

&lt;p&gt;The movement that best organizes software developers towards change is the one centered around open government and open data. Civic hackers directly apply their skills to make government work better and be more accountable. The organization that best harnesses developer energy is Code for America, focused on &lt;a href=&quot;http://codeforamerica.org/projects/&quot;&gt;improving city governments&lt;/a&gt; and now working towards a &lt;a href=&quot;http://codeforamerica.org/2012/11/07/citizenship-beyond-the-election/&quot;&gt;fascinatingly anarchist definition of citizenship&lt;/a&gt;. Anarchist is a scary word, and I don’t mean that Code for America promotes disorder or nihilism. But they are building tools that begin to obviate the need for government, replacing it with civic action. To me that’s a profoundly disruptive version of civic hacking.&lt;/p&gt;

&lt;p&gt;Literally hundreds of web and mobile apps have been built out of this movement, and it’s still in its early stages. As uber civic hacker &lt;a href=&quot;http://civic.io/2012/12/31/the-year-that-civic-hacking-changed-everything/&quot;&gt;Mark Headd recently wrote&lt;/a&gt;, the barrier to even more activity isn’t a lack of energy, it’s a lack of raw government data to work with. Governments need more convincing, which will require more activism.&lt;/p&gt;

&lt;p&gt;Civic hacking is a sort of gateway drug for activist engineers. The concepts behind open government like transparency, engagement, and accountability cut across partisan lines. It broadly appeals to many people, particularly when contrasted with putting your life on hold to work for a presidential campaign for 16 months. The organizations that lead the movement are all prolific at &lt;a href=&quot;https://github.com/sunlightlabs&quot;&gt;publishing&lt;/a&gt; &lt;a href=&quot;https://github.com/mysociety&quot;&gt;their&lt;/a&gt; &lt;a href=&quot;https://github.com/codeforamerica&quot;&gt;work&lt;/a&gt; on GitHub, setting examples for all to see.&lt;/p&gt;

&lt;h3 id=&quot;open-source-and-free-software&quot;&gt;Open Source and Free Software&lt;/h3&gt;

&lt;p&gt;Speaking of GitHub, it’s worth considering the open source and free software movements. Does Richard Stallman fall under the banner of activist engineer? Linus Torvalds? The Ubuntu and Apache teams? Have they not changed the world?&lt;/p&gt;

&lt;p&gt;I’d argue that most open source software is about craft rather than seeking societal change. Rails and Django are terrific at improving the lives of the developers who work with them every day. But they’re ultimately tools used to build things, not outcomes in and of themselves.&lt;/p&gt;

&lt;p&gt;By contrast, Richard Stallman, the fierce advocate of free software, is literally on a mission to change the world. He’s an activist engineer, but his activism narrowly focuses on free software. While he did build the original GNU tools and Emacs, these days Richard Stallman is more like a community organizer, spreading the gospel of free software around the world.&lt;/p&gt;

&lt;h3 id=&quot;building-a-sustained-community&quot;&gt;Building a Sustained Community&lt;/h3&gt;

&lt;p&gt;Community will be key for determining whether the rise of activist engineers can be sustained for the long run. Lots of pathways have been cleared. It’s now up to the activist engineers out there to build on top of the foundations that have been laid.&lt;/p&gt;

&lt;p&gt;Progressive technologists &lt;a href=&quot;http://www.huffingtonpost.com/jim-pugh/obama-for-america-data_b_2325478.html&quot;&gt;Jim Pugh and Nathan Woodhull recently pleaded&lt;/a&gt; for someone, anyone, to keep the technology created for Obama 2012 maintained and ready for the next election. But I don’t think it’ll be so bad if the code is abandoned. What would be disastrous for the Democratic side is if the community of activist engineers built up to support it collapses.&lt;/p&gt;

&lt;p&gt;Technologies change. An app built in 2012 shouldn’t necessarily be used in 2016. But people matter, and we don’t go out of date nearly as fast as Rails code.&lt;/p&gt;

&lt;p&gt;Activist engineers have arrived. We’re here. Now will we recognize our collective power, grow our ranks, and shape the future?&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>A Reminder: The Web Exists</title>
   <link href="http://luigimontanez.com/2012/reminder-web-exists/"/>
   <updated>2012-09-26T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2012/reminder-web-exists/reminder-web-exists</id>
   <content type="html">&lt;p&gt;Lost in the last week’s reporting around the new Apple Maps app in iOS 6 has been one salient fact: Google Maps continues to be available to all iOS users at &lt;a href=&quot;http://maps.google.com&quot;&gt;maps.google.com&lt;/a&gt;. It’s the same Google Maps that iOS users have grown to know and love, with the exception of Street View. And it even prompts for “installation” to the home screen, so access is quick and easy:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://asset3.cbsistatic.com/cnwk.1d/i/tim/2012/09/20/Photo_Sep_20%2C_1_30_04_PM_270x405.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Image by &lt;a href=&quot;http://howto.cnet.com/8301-11310_39-57517187-285/how-to-bring-back-google-maps-in-ios-6/&quot;&gt;CNET&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The tech press, which presumably exists to serve its audience, has largely ignored the existence of &lt;a href=&quot;http://maps.google.com&quot;&gt;maps.google.com&lt;/a&gt;, instead opting to focus on the corporate drama behind Apple’s decision to dump Google’s maps and roll their own solution. Take this piece from the &lt;a href=&quot;http://bits.blogs.nytimes.com/2012/09/25/google-working-on-maps-for-iphone-ipad/&quot;&gt;NY Times&lt;/a&gt;, which reports that a Google-made Maps app is still months away from completion. A reader of the story would be left dejected: Google Maps is months away, and still has to be approved by Apple for inclusion in the App Store.&lt;/p&gt;

&lt;p&gt;But that’s simply not the case – Google Maps is available to all iOS users right now at &lt;a href=&quot;http://maps.google.com&quot;&gt;maps.google.com&lt;/a&gt;. And because it’s just a web site, it’s available to any device that has a web browser. In this way the tech press is similar to the political press, valuing conflict and process over long-standing realities. The end result is sadly the same: the public loses out.&lt;/p&gt;

&lt;p&gt;John Gruber, the Rush Limbaugh of Apple punditry, similarly neglects to mention the alternative of &lt;a href=&quot;http://maps.google.com&quot;&gt;maps.google.com&lt;/a&gt; on &lt;a href=&quot;http://daringfireball.net/&quot;&gt;Daring Fireball&lt;/a&gt;. He mentions the Maps issue in four separate posts:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A link to an article on how iOS 6 Maps is a huge improvement in China.&lt;/li&gt;
  &lt;li&gt;A link to an article on Counternotions that rebuts the criticisms.&lt;/li&gt;
  &lt;li&gt;A link to the &lt;a href=&quot;http://theamazingios6maps.tumblr.com/&quot;&gt;Amazing iOS 6 Maps&lt;/a&gt; Tumblr.&lt;/li&gt;
  &lt;li&gt;A link to a process article on the prospects for a Google Maps app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While Gruber’s audience is the devoted Apple faithful, the lack of a mention of &lt;a href=&quot;http://maps.google.com&quot;&gt;maps.google.com&lt;/a&gt; is a clear disservice to his readership.&lt;/p&gt;

&lt;p&gt;The larger problem here is a general lack of respect for Web-based solutions. Apple’s push for native apps on iOS has severely hurt the Web. Users become paralyzed, thinking that if there’s no solution available on the App Store, it must not exist. Startups like &lt;a href=&quot;http://lift.do&quot;&gt;Lift&lt;/a&gt; and &lt;a href=&quot;http://simple.com&quot;&gt;Simple&lt;/a&gt; require a native iOS app to use their Web-based services. That’s a trend that needs to be reversed.&lt;/p&gt;

&lt;p&gt;We can’t let ourselves forget about the Web.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>On Starting a Startup</title>
   <link href="http://luigimontanez.com/2012/on-starting-a-startup/"/>
   <updated>2012-07-03T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2012/on-starting-a-startup/on-starting-a-startup</id>
   <content type="html">&lt;p&gt;We launched &lt;a href=&quot;http://www.upworthy.com&quot;&gt;Upworthy&lt;/a&gt; 99 days ago on March 26. We started as a company two months earlier on January 30. There were various news stories &lt;a href=&quot;http://allthingsd.com/20111214/facebook-moveon-vets-working-on-mystery-media-start-up-for-lefties/&quot;&gt;written&lt;/a&gt; about us as the &lt;a href=&quot;http://www.guardian.co.uk/media/2011/dec/15/facebook-the-onion-moveon-start-up-media&quot;&gt;team was being built&lt;/a&gt;, as &lt;a href=&quot;http://mediadecoder.blogs.nytimes.com/2012/03/26/new-site-wants-to-make-the-serious-as-viral-as-the-shallow/&quot;&gt;we&lt;/a&gt; &lt;a href=&quot;http://allthingsd.com/20120326/viral-with-a-purpose-upworthy-finds-serious-web-content-worth-sharing/&quot;&gt;launched&lt;/a&gt;, and a &lt;a href=&quot;http://www.thedailybeast.com/articles/2012/04/29/with-upworthy-internet-heavies-push-social-media-with-significance.html&quot;&gt;month after we launched&lt;/a&gt;. Read those if you’re not familiar with our story. What follows are some of my thoughts and reflections on the experience of starting a startup.&lt;/p&gt;

&lt;h2 id=&quot;choosing-a-technology&quot;&gt;Choosing a Technology&lt;/h2&gt;

&lt;p&gt;The engineering team started out as a team of two: the &lt;a href=&quot;https://twitter.com/#!/tones/&quot;&gt;CTO&lt;/a&gt; and me. I was anointed Founding Engineer. My background is in Ruby on Rails, but in recent years I’ve soured on it a bit. Eric, a &lt;a href=&quot;http://konklone.com/&quot;&gt;colleague of mine&lt;/a&gt; when I was at the Sunlight Foundation started using Sinatra for all his projects, and he seemed quite happy. So after some evaluating and thinking, Tim and I settled on &lt;a href=&quot;http://www.padrinorb.com/&quot;&gt;Padrino&lt;/a&gt;, a framework built on top of Sinatra that incorporates most of the best parts of Rails.&lt;/p&gt;

&lt;p&gt;At the end of our first day as a company, I made sure to create a paid private account on GitHub, generate a skeleton Padrino app, and push the initial commit.&lt;/p&gt;

&lt;p&gt;I’ve been very happy with our decision to build on top of Padrino. The built-in admin interface was a huge time saver when building towards the minimum viable product, and nearly every major Ruby library out there is compatible with Padrino and Sinatra. Some of the technologies we use are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://mongoid.org/en/mongoid/index.html&quot;&gt;Mongoid&lt;/a&gt; and &lt;a href=&quot;http://www.mongodb.org/&quot;&gt;MongoDB&lt;/a&gt; for our main data store.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://redis.io/&quot;&gt;Redis&lt;/a&gt; for caching and &lt;a href=&quot;https://github.com/defunkt/resque/&quot;&gt;Resque&lt;/a&gt; for background processing.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Twitter Bootstrap&lt;/a&gt; and &lt;a href=&quot;http://lesscss.org/&quot;&gt;LESS&lt;/a&gt; for stylesheets.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/railsjedi/jammit-sinatra&quot;&gt;Jammit Sinatra&lt;/a&gt; for asset packaging, though &lt;a href=&quot;http://ricostacruz.com/sinatra-assetpack/&quot;&gt;Sinatra AssetPack&lt;/a&gt; looks appealing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We launched on Heroku, and while I’m not as happy with that decision as Padrino, I’d still recommend Heroku for startups like us. There’s been some widespread downtime in recent weeks, but some of the blame can be shared with AWS. For a startup with limited sys admin resources, Heroku makes much more sense than directly managing AWS services. Yes, we do have to architect our app with Heroku in mind, but it’s not nearly as severe as hosting on Google App Engine. There’s always been a reasonable solution for what we want to do.&lt;/p&gt;

&lt;h2 id=&quot;buying-the-domain&quot;&gt;Buying the Domain&lt;/h2&gt;

&lt;p&gt;Naming our website and acquiring the domain was probably the hardest thing to accomplish. We stumbled on Upworthy very late in the process. It was preceded by weeks of head scratching and hair pulling because the domain name industry is completely broken. It’s been reported that if Obama wins a second term, he’ll try to &lt;a href=&quot;http://www.gq.com/news-politics/blogs/death-race/2012/07/exclusive-in-his-second-term-obama-will-pivot-to-the-drug-war.html&quot;&gt;reform The Drug War&lt;/a&gt;. Well, I hope he also tries to reform the domain name system and disband ICANN. There are too many good domains being squatted on. Offering seemingly large amounts of money to those domain squatters is fruitless. They call themselves “domain investors” and believe that they’re a legitimate market force. But all they’re doing is stifling innovation, enabled by a broken institution in ICANN.&lt;/p&gt;

&lt;p&gt;When we settled on a name (not Upworthy) a few weeks into the project, as the first technical hire, I took on the responsibility of securing the domain for us. It was expiring in the middle of February. After doing &lt;a href=&quot;http://www.quora.com/What-are-the-best-practices-to-buy-a-domain-name-thats-about-to-be-deactivated&quot;&gt;some research&lt;/a&gt;, it was clear that I wouldn’t be able to just register for the domain name manually on the day it became available. So I dutifully registered on the Big 3 backorder services. The domain backorder market is a rigged game, where those companies have deals with registrars that give them the first crack at registering domains the millisecond they expire. And when multiple people register a backorder on the acquiring backorder service, there’s an auction held for a few days and the domain goes to the highest bidder.&lt;/p&gt;

&lt;p&gt;It’s capitalism at its not-so-finest. We braced ourselves for an auction.&lt;/p&gt;

&lt;p&gt;On the expiration date, the moment of truth came (for .com domains it happens at 2pm ET). And it went. None of the backorder services I registered with picked up the domain. Instead the domain name was snatched by a service called &lt;a href=&quot;https://www.backorderzone.com/&quot;&gt;BackorderZone&lt;/a&gt;, which I had never heard of. And we were left out of the auction, because only people who bid on the domain on the winning service before it’s snatched up get to participate. I felt like a complete failure. We tried to negotiate with the ultimate winner of the auction, but it didn’t pan out.&lt;/p&gt;

&lt;p&gt;At that point, we already had a design, a brand, an app, and a logo. But we had no domain name. After some desperate brainstorming sessions, the name Upworthy came to Eli as he was on a run, and we quickly went with it. It was close enough to our initial choice that we were able to launch just two weeks later.&lt;/p&gt;

&lt;p&gt;So what are the lessons here?&lt;/p&gt;

&lt;p&gt;If you’re going to try to negotiate for a domain name or snatch an expiring one, realize that the chances of you obtaining it are actually very small, unless you’re willing to spend six figures. If you try to snatch up an expiring domain, use BackorderZone. The operation is just one guy in Pennsylvania and apparently he knows what he’s doing.&lt;/p&gt;

&lt;p&gt;But I recommend not playing that game at all. Make up a new word like we did. Combine two short words. I think we lucked out by not getting that first domain name, because I think Upworthy more accurately connotes what it is we’re trying to do.&lt;/p&gt;

&lt;h2 id=&quot;facebook-one-fifth-of-the-web&quot;&gt;Facebook: One-Fifth of the Web&lt;/h2&gt;

&lt;p&gt;So what exactly are we trying to do? We want to make stuff that matters as shareable and viral as funny pictures of kittens. And these days, that means optimizing for social networks. Particularly Facebook.&lt;/p&gt;

&lt;p&gt;As a software developer and early adopter, my social network of choice is Twitter. And Upworthy certainly has a &lt;a href=&quot;https://twitter.com/#!/Upworthy&quot;&gt;strong presence on Twitter&lt;/a&gt;: a following of 10,000 built up in the last 100 days. If you do a &lt;a href=&quot;https://twitter.com/#!/Upworthy&quot;&gt;real-time search&lt;/a&gt; for “upworthy”, you’ll find a constant stream of tweets linking to us.&lt;/p&gt;

&lt;p&gt;But Twitter traffic simply doesn’t compare to the traffic we see from Facebook. I could tell you that Facebook is like the Sun, and all the other social media sites (Twitter, Reddit, Pinterest, StumbleUpon) are like the planets. But then you’ll probably picture something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://en.es-static.us/upl/2011/02/solar_system.jpg&quot; width=&quot;550px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That’s actually not to scale. Because in reality, the Sun is unfathomably huge. This more accurately depicts Facebook’s dominance:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://mail.colonial.net/~hkaiter/astronomyimagesC/planets-scale.jpg&quot; width=&quot;550px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One in five web pages loaded is a Facebook page. Until I started at Upworthy, I didn’t appreciate how nearly everyone is on Facebook. Normal people. It’s truly a form of mass media, and the other social networks we frequent like Twitter and Reddit aren’t in the same league. Facebook, whether you like it or not, is the present and future of the Web. If you’re in the business of spreading ideas, knowledge, and information, you’d be sorely mistaken to ignore it.&lt;/p&gt;

&lt;p&gt;You know about the Like button, but here’s a tip: It’s not very effective. Use their (deprecated) &lt;a href=&quot;https://developers.facebook.com/docs/share/&quot;&gt;Share pop up&lt;/a&gt; instead. Shared items make it into friends’ news feeds, not liked items.&lt;/p&gt;

&lt;h2 id=&quot;a-lean-startup&quot;&gt;A Lean Startup&lt;/h2&gt;

&lt;p&gt;I love the taste of the Lean Startup Kool-Aid. I’ve found the books so important that I own both Kindle and paperback versions of them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://theleanstartup.com/book&quot;&gt;The Lean Startup&lt;/a&gt; by Eric Ries&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.runningleanhq.com/&quot;&gt;Running Lean&lt;/a&gt; by Ash Maurya&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.stevenblank.com/startup_index_qty.html&quot;&gt;The Startup Owner’s Manual&lt;/a&gt; by Steve Blank and Bob Dorf&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Lean Startup methodology is a great way to think about building a business. It provides much needed structure in treating a business as an experiment. Make hypotheses. Run tests. Prove hypotheses with data and results.&lt;/p&gt;

&lt;p&gt;As an engineer, I’m not too involved in the day-to-day of running the business. But I’m glad for the knowledge gained from the Lean Startup movement.&lt;/p&gt;

&lt;h2 id=&quot;two-memoirs&quot;&gt;Two Memoirs&lt;/h2&gt;

&lt;p&gt;At the beginning of my time at Upworthy, I relaxed at night by reading &lt;a href=&quot;http://www.amazon.com/iWoz-Computer-Invented-Personal-Co-Founded/dp/0393330435/ref=tmm_pap_title_0&quot;&gt;iWoz&lt;/a&gt;, the autobiography of Apple co-founder Steve Wozniak. Woz was responsible for engineering the Apple I and Apple II. He essentially invented the personal computer as we know it.&lt;/p&gt;

&lt;p&gt;I never quite adored a book until reading iWoz. It’s probably the favorite book of my adult life. Woz is kind, honest, and intelligent, and that all comes through on the page. People like Steve Jobs end up running multi-billion dollar companies, but they can’t do it without people like Woz. He simply wanted to make awesome stuff. There was one passage in the book where Woz talked about his creative process: He’d think and think on a problem for days, and when he came to a solution, he’d implement it quickly in a matter of hours. That’s how I work, and it was re-affirming and inspiring to read that I shared that in common with him.&lt;/p&gt;

&lt;p&gt;I read another book, just in the last week, called &lt;a href=&quot;http://www.amazon.com/Boy-Kings-Journey-Social-Network/dp/1451668252/&quot;&gt;The Boy Kings&lt;/a&gt;. It’s a memoir of Facebook employee number 51, Kate Losse. She started out in customer service and worked her way up the company over the course of several years. It’s an engaging, well-written look inside Facebook as it grew, and it most clearly describes the “brogrammer” culture that pervades tech startups.&lt;/p&gt;

&lt;p&gt;It’s a bit of an anthropological study of the “boys” of Facebook, as Kate refers to them, viewing them and their project with a critical eye. Obviously, Mark Zuckerberg is described in great detail, but I was most fascinated by the descriptions of co-founder Dustin Moskovitz, the world’s youngest self-made billionaire. He’s portrayed in the vein of Woz: genuinely kind, perceptive, and a hell of an engineer. While Mark schemed up plans for world domination, Dustin was busy making sure the site stayed up. The memoir is from the view of just one person, but I can’t help but think about how different Facebook would be if Dustin was the CEO and not Mark. And it led me to think about how different Apple would be if Wozniak led it and not Jobs.&lt;/p&gt;

&lt;p&gt;Those two memoirs drove home two important points for me: First, that I want to be an engineer in the mold of Dustin Moskovitz and Woz. I respect them infinitely more than I respect Zuckerberg or Jobs. And second, technology companies really do have the power to change the world. Apple and Facebook aren’t just companies; they’re institutions. Both books tell the story of how those institutions were built.&lt;/p&gt;

&lt;p&gt;Upworthy is about to complete its first hundred days. I can’t wait to see what the next  hundred days, and then the next thousand days bring for us. I’m thrilled to be at the ground-level, as we build something that’s trying to change the world in our own way.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Actually, Social Media Buttons Work Really Well</title>
   <link href="http://luigimontanez.com/2012/actually-social-media-buttons-work-really-well/"/>
   <updated>2012-05-31T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2012/actually-social-media-buttons-work-really-well/actually-social-media-buttons-work-really-well</id>
   <content type="html">&lt;p&gt;Yesterday, an epic rant against social media buttons titled &lt;a href=&quot;http://informationarchitects.net/blog/sweep-the-sleaze/&quot;&gt;Sweep the Sleaze&lt;/a&gt; made its rounds on the Web. The gist: Don’t bombard your audience with buttons to share stuff on social networks. Instead, make good content that they’ll be compelled to share organically.&lt;/p&gt;

&lt;p&gt;The advice is well-reasoned and generally correct, and was covered by &lt;a href=&quot;http://theoatmeal.com/comics/facebook_likes&quot;&gt;The Oatmeal&lt;/a&gt; a few months back and by &lt;a href=&quot;http://37signals.com/svn/posts/93-its-the-content-not-the-icons&quot;&gt;37signals&lt;/a&gt; a few years back.&lt;/p&gt;

&lt;p&gt;But this part smelled fishy to me:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;But do these buttons work? It’s hard to say.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Some people probably do use those buttons. Maybe even a lot of people. And maybe you do and think I’m dead wrong about this. Maybe I am. And maybe someone needs to do some serious research to know for sure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s quite easy to do a bit of research and find out just how many people use those buttons, particularly the Twitter button thanks to Twitter’s data-generous API. So I sought to answer the question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If a website displays those annoying Twitter buttons, just how many tweets linking to it are made by people using those sleazy-ass buttons?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s a &lt;a href=&quot;https://gist.github.com/2843398&quot;&gt;gist&lt;/a&gt; of the script I used:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2843398.js?file=counter.rb&quot;&gt;&lt;/script&gt;

&lt;p&gt;It scans through the latest 500 or so tweets that link to a particular website, and checks the &lt;code&gt;source&lt;/code&gt; field of each tweet, looking for the clearly marked &lt;code&gt;Tweet Button&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I first ran the analysis on a new website called &lt;a href=&quot;http://politwoops.sunlightfoundation.com&quot;&gt;Politwoops&lt;/a&gt; that was launched yesterday by my former employer, The Sunlight Foundation. The site is a good test subject because it displays the Twitter button prominently in the header, it’s about Twitter, and it went a bit viral yesterday.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Search term: politwoops.sunlightfoundation.com
Total tweets analyzed: 498
Tweets from button: 111 (22.3%)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So here we have a Twitter-savvy audience, and 22% who linked to the site did so using that flippin’ Twitter button on the website.&lt;/p&gt;

&lt;p&gt;How about the 37signals blog, an even savvier audience made up of folks who’ve been on Twitter for half a decade? Surely, none of them will find use for that superfluous tweet button that appears on the bottom of each post:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Search term: 37signals.com/svn
Total tweets: 499
Tweets from button: 70 (14.0%)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Smaller, but still significant.&lt;/p&gt;

&lt;p&gt;Switching audiences, let’s look at viral media website BuzzFeed. They serve content optimized for sharing on social networks, and they prominently display social media buttons on each post.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Search term: buzzfeed.com
Total tweets: 495
Tweets from button: 191 (38.6%)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Huge! BuzzFeed’s audience consists of more normal folks, not the ones who get worked up over a topic like this. The buttons are meant to remove friction, and here we see that they really appear to be doing so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s time for a confession&lt;/strong&gt;: I knew those buttons were effective well before running this analysis, because my startup &lt;a href=&quot;http://www.upworthy.com&quot;&gt;Upworthy&lt;/a&gt; is all about spreading stuff that matters through social media. Here’s the analysis for our website:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Search term: upworthy.com
Total tweets: 499
Tweets from button: 319 (63.9%)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can tell by viewing &lt;a href=&quot;http://www.upworthy.com/who-wants-to-cry-and-have-their-faith-in-humanity-restored&quot;&gt;one of our nuggets&lt;/a&gt; that we really, really optimize for sharing. Yes, we have buttons that are hard to miss. But we’re also very thoughtful about crafting share text that will (a) make you want to use it to share and (b) make others want to click.&lt;/p&gt;

&lt;p&gt;It’s true that a social media strategy simply isn’t about sticking buttons on a website. It requires high quality content, and just as importantly, packaging that content in a shareable way. It’s not sleazy to try to get your audience to share your stuff. &lt;strong&gt;Share buttons are well-placed reminders that sharing is an option.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can look at a page on Upworthy and think, “Boy, that share button stuff is so offputting. People who fall for it must be gullible buffoons!” Or you can look at it and think, “This content is good and important and should be shared. Buttons that make it easier to do so are worth the pixels and bandwidth.” If you’re in the latter camp, I should mention that &lt;a href=&quot;http://www.upworthy.com/jobs&quot;&gt;we’re hiring&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And if you think this piece of content is worth sharing on Twitter, please go ahead and click the button below…&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/share?url=http%3A%2F%2Fluigimontanez.com%2F2012%2Factually-social-media-buttons-work-really-well&amp;amp;text=Actually%2C%20social%20media%20buttons%20work%20really%20well%3A&amp;amp;related=LuigiMontanez&amp;amp;count=none&quot; class=&quot;twitter-share-button&quot; data-lang=&quot;en&quot; data-count=&quot;none&quot;&gt;Tweet&lt;/a&gt;
&lt;script&gt;!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=&quot;//platform.twitter.com/widgets.js&quot;;fjs.parentNode.insertBefore(js,fjs);}}(document,&quot;script&quot;,&quot;twitter-wjs&quot;);&lt;/script&gt;&lt;/p&gt;

</content>
 </entry>
 
 
 
 <entry>
   <title>Developer Happiness and MongoDB</title>
   <link href="http://luigimontanez.com/2012/developer-happiness-mongodb/"/>
   <updated>2012-05-23T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2012/developer-happiness-mongodb/developer-happiness-mongodb</id>
   <content type="html">&lt;p&gt;MongoDB continues to be the &lt;a href=&quot;http://www.google.com/insights/search/#q=mongodb%2Ccouchdb%2Criak%2Credis&amp;amp;date=today%2012-m&amp;amp;cmpt=q&quot;&gt;most popular&lt;/a&gt; of the NoSQL data stores, and it continues to generate &lt;a href=&quot;http://www.quora.com/MongoDB/Which-companies-have-moved-away-from-MongoDB-and-why&quot;&gt;disgruntled blog posts&lt;/a&gt; from former users. I’ve been using MongoDB since the summer of 2009, and my experiences have been consistently positive. In fact, MongoDB is my current default data store when building a new web app, and has been since shortly after I started using it. I understand all the criticisms being levied at Mongo, but they’re not going to change my position.&lt;/p&gt;

&lt;p&gt;Why not? Because using MongoDB makes me happy.&lt;/p&gt;

&lt;h3 id=&quot;matzs-revolution&quot;&gt;Matz’s Revolution&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Ruby is designed to make programmers happy.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yukihiro “Matz” Matsumoto created a programming language optimized for developer happiness. Ruby wasn’t optimized for technical goals like speed or scale (insert Rails-can’t-scale joke here). It was optimized for the happiness of the human beings who would spend all day looking at it.&lt;/p&gt;

&lt;p&gt;DHH, creator of Ruby on Rails, adopted Matz’s philosophy. The rise in popularity of Rails had a lot to do with how good the out-of-the-box experience was. Developer happiness leads to observable benefits in productivity. Here’s an excerpt from the 37signals ebook, &lt;a href=&quot;http://gettingreal.37signals.com/ch10_Optimize_for_Happiness.php&quot;&gt;Getting Real&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Happiness has a cascading effect. Happy programmers do the right thing. They write simple, readable code. They take clean, expressive, readable, elegant approaches. They have fun.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Left out of that quote is that happy programmers are more creative. And happiness and creativity  build off another, creating a virtuous cycle of collaboration. The Django committers were already quite content with their toolset when they borrowed some ideas from the Rails core team, and vice versa. Sinatra’s creator wasn’t happy with some aspects of Rails, so he made his own thing, and shared his happiness with like-minded Ruby developers who realized they felt the same way. The creator of CoffeeScript borrowed aspects of Ruby and Python and drastically improved the experience for those of us who weren’t having much fun writing JavaScript.&lt;/p&gt;

&lt;h3 id=&quot;the-freedom-of-choice&quot;&gt;The Freedom of Choice&lt;/h3&gt;

&lt;p&gt;Programmers tend to be quite passionate about the tools they use: operating systems, text editors, IDEs, languages, frameworks, libraries. And they want to switch when they’ve discovered a better tool for the job. Freedom of choice is incredibly important. But strangely for web developers, the choice for data store was always made for them: an RDBMS.&lt;/p&gt;

&lt;p&gt;The NoSQL movement introduced genuine choice in data stores for the first time in the Web era. The differences between MySQL and Postgres and Oracle started to look small when compared to the new paradigms available. The realization that a relational database isn’t the only way to persist data is an epiphany.&lt;/p&gt;

&lt;p&gt;Decades of RDBMS dominance led to dogma. Incontrovertible truths. Data belongs in the rows and columns of a table. Tables must be normalized. Repeating data is bad. Tables are joined. Transactions are necessary and schemas must be defined, otherwise chaos will ensue. NoSQL freed developers from those chains. And the newly liberated are happy.&lt;/p&gt;

&lt;h3 id=&quot;choice-and-control-in-mongodb&quot;&gt;Choice and Control in MongoDB&lt;/h3&gt;

&lt;p&gt;MongoDB is schemaless, which means the data schema is defined by the application, not the database. Data migrations are run to actually transform data, not merely for a simple change in the database schema. As a result, they’re run far more infrequently, which in turns speeds up the development process. If your application needs a &lt;code&gt;middle_initial&lt;/code&gt; field, you add it to your application. MongoDB doesn’t need to be told about it.&lt;/p&gt;

&lt;p&gt;MongoDB is document-oriented. Data isn’t confined to rows. It instead lives in a richly structured JSON document. Thanks to that, the dogma of normalization can be thrown out the window. A blog post has many comments. Well then, those comments should be stored inside the blog post, not in a separate table. A blog post has many tags. Store those tags inside the blog post and forget about the rule that says you need a join table named &lt;code&gt;blog_posts_tags&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The schemaless, documented-oriented nature of MongoDB translates into a newly found sense of developer control. Your data schema mirrors the actual look of your application. You can glance at a mockup for a new feature, and quickly envision how the data will be persisted.&lt;/p&gt;

&lt;p&gt;For example, a blog post has an author. If the application has user accounts, those authors are persisted in a &lt;code&gt;users&lt;/code&gt; collection. The old dogmatic way of thinking dictates that in order to display that user’s name on a blog post, there must be a foreign key and a join query. But in MongoDB, the developer has control over the way the data is stored. I’d store a reference to the user, but I’d also store the user’s full name right there, inside the blog post. The blog post document is a faithful representation of what makes it to the screen. It’s not bound to the rules and conventions of the data store it’s contained in.&lt;/p&gt;

&lt;p&gt;The tradeoff with such denormalization is that you’ll have to write a little bit of code to update all the blog posts by the author if the name is ever changed. But that’s a trivial bit of housekeeping that quickly becomes second nature. It’s much more natural than adhering to &lt;a href=&quot;http://en.wikipedia.org/wiki/Boyce%E2%80%93Codd_normal_form&quot;&gt;Boyce-Codd Normal Form&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;MongoDB is flexible. It puts the developer in control, instead of dictating how it must be used. A breath of fresh air.&lt;/p&gt;

&lt;h3 id=&quot;json&quot;&gt;JSON&lt;/h3&gt;

&lt;p&gt;JSON is a near-perfect format for persisting data in object-oriented applications. Because it’s literally an object notation, there’s little &lt;a href=&quot;http://en.wikipedia.org/wiki/Object-relational_impedance_mismatch&quot;&gt;impedance mismatch&lt;/a&gt; between the native objects in the programming language and how they’re stored in Mongo. ORMs were created because objects needed mapping to relational tables. That’s no longer the case with MongoDB, though object-document mappers do exist, and provide useful utilities like callbacks and validations.&lt;/p&gt;

&lt;p&gt;JSON is a joy to work with because it eliminates so much friction. Unlike XML, it’s simple, succinct, and quickly scannable. It’s self-documenting. A JSON document represents a fully-formed object, so no parsing is necessary. It’s become the lingua franca for exchanging data on the Web. And it’s universal: every programming language understands it.&lt;/p&gt;

&lt;p&gt;Queries and commands in MongoDB are done via calls to JavaScript functions, which take in a JSON object for the various conditions and options. This results in a magical side effect when interfacing with MongoDB from a driver in another language. Querying in any object-oriented language remains straight-forward and natural because the ideas in JavaScript and JSON are easily translated. A JSON object easily maps to a hash in Ruby, or a dictionary in Python. There’s little mental overhead needed.&lt;/p&gt;

&lt;p&gt;Every developer I know loves JSON. It makes them happy. When using MongoDB, you get to think in JSON all day long.&lt;/p&gt;

&lt;h3 id=&quot;minimum-viable-features&quot;&gt;Minimum Viable Features&lt;/h3&gt;

&lt;p&gt;MongoDB ships with an assortment of useful utilities that make working with it just a little bit nicer. There’s GridFS for file storage. Geospatial indexing to do lat/long calculations. Map/reduce for aggregation. There’s even a way to get full-text search capabilities using an index on an array of strings.&lt;/p&gt;

&lt;p&gt;These aren’t full replacements for more robust solutions. They’re more like minimum viable features. There’s always a networked filesystem or S3 for file storage and PostGIS for serious geospatial work. There’s Hadoop for map/reduce and Elastic Search for full-text search. But the ability to do those things in MongoDB for simple use cases makes the development process a little more pleasant.&lt;/p&gt;

&lt;p&gt;There are also neat little tidbits scattered around. Documents in MongoDB have a unique identifier, automatically indexed, called an &lt;code&gt;ObjectId&lt;/code&gt;. By default it’s generated as a GUID with the timestamp embedded inside. No longer do you have to store a separate &lt;code&gt;created_at&lt;/code&gt; timestamp. Or you can if you want. You have the choice, after all.&lt;/p&gt;

&lt;h3 id=&quot;unintentionally-delivering-happiness&quot;&gt;Unintentionally Delivering Happiness&lt;/h3&gt;

&lt;p&gt;It seems to me that the creators of MongoDB never set out to optimize for happiness. I’d guess that Redis is the one NoSQL data store where the creators actively think about developer happiness.&lt;/p&gt;

&lt;p&gt;Instead, 10gen’s marketing has been focused on scaling. The brand itself, Mongo, came out of the word hu&lt;strong&gt;mongo&lt;/strong&gt;us. And much of the criticism of MongoDB has come from the technology choices made in the name of scaling. But the reality is that scaling any technology is difficult, and there’s no silver bullet.&lt;/p&gt;

&lt;p&gt;The criticism that most strikes fear, uncertainty, and doubt in the hearts of developers is that MongoDB loses data. I’ve never experienced it. Turn on journaling, use a replica set in production, and make solid backups. You’ll be fine.&lt;/p&gt;

&lt;p&gt;I build web software for a living, and I want to choose the tools that will make me happy while doing it. That’s the value most important to me, and I find myself sticking with MongoDB.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>How rel=nofollow Works</title>
   <link href="http://luigimontanez.com/2012/how-rel-nofollow-works/"/>
   <updated>2012-01-12T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2012/how-rel-nofollow-works/how-rel-nofollow-works</id>
   <content type="html">&lt;p&gt;There has been a furious storm around Google’s new &lt;a href=&quot;http://googleblog.blogspot.com/2012/01/search-plus-your-world.html&quot;&gt;Search, Plus Your World&lt;/a&gt; features. The hubbub is centered around a complaint by Twitter that links shared on Twitter are not surfacing in the search results.&lt;/p&gt;

&lt;p&gt;Google responded on &lt;a href=&quot;https://plus.google.com/u/0/116899029375914044550/posts/24uqWqvALud&quot;&gt;Google+&lt;/a&gt; with a terse statement:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We are a bit surprised by Twitter’s comments about Search plus Your World, because they chose not to renew their agreement with us last summer (&lt;a href=&quot;http://goo.gl/chKwi&quot;&gt;http://goo.gl/chKwi&lt;/a&gt;), and since then we have observed their rel=nofollow instructions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before ascribing evil motives to Google, it’s important to understand exactly what &lt;code&gt;rel=nofollow&lt;/code&gt; does, and how Twitter is currently using it. The &lt;code&gt;rel=nofollow&lt;/code&gt; attribute is placed inside the HTML link tag. It’s an anti-spam measure that tells the Googlebot to &lt;strong&gt;not&lt;/strong&gt; follow the link when crawling the Web. So &lt;code&gt;&amp;lt;a href=&quot;http://example.com&quot; rel=&quot;nofollow'&amp;gt;Click here&amp;lt;/a&amp;gt;&lt;/code&gt; will be rendered as a clickable link to the user, but the Googlebot will not follow the link as it is crawls the web page containing that link.&lt;/p&gt;

&lt;p&gt;Twitter.com incorporates &lt;code&gt;rel=nofollow&lt;/code&gt; in all outbound links contained in tweets, most likely in an effort to deter spammers. The HTML for a tweet on Twitter.com looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;tweet&quot;&amp;gt;Check out this link: &amp;lt;a href=&quot;http://t.co/123&quot;
rel=&quot;nofollow&quot;&amp;gt;http://t.co/123&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This means that while the Googlebot will index the text of the tweet, it will not follow any link in that tweet. Thus, Google will never know what a particular tweet links to because Twitter explicitly told it not to follow any links.&lt;/p&gt;

&lt;p&gt;So Google launches Search Plus, and we start to see results that indicate that “John Doe shared this on Some Site”:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/search-plus.png&quot; alt=&quot;search-plus&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/search-plus2.png&quot; alt=&quot;search-plus2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But we’ll never see “Jane Smith shared this on Twitter” because Twitter uses &lt;code&gt;rel=nofollow&lt;/code&gt; on all outbound links in tweets. So even if @JaneSmith shared a relevant link, Twitter explicitly told Google not to index that link. Google will still index the text of the tweet. But without knowing what link the tweet points to, Google has no way inform us that a link was shared on Twitter.&lt;/p&gt;

&lt;p&gt;It’s frustrating to see tech pundits severely misinterpret the facts and come to false conclusions. Here’s &lt;a href=&quot;http://marketingland.com/schmidt-google-not-favored-happy-to-talk-twitter-facebook-integration-3151&quot;&gt;Danny Sullivan&lt;/a&gt;, who’s an expert on this stuff:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;My take is that Google, by mentioning this in its post, is trying to suggest that Twitter is hurting itself by blocking its own pages using nofollow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s clearly not what Google is saying. This has nothing to do with pages on Twitter.com. Twitter is telling Google to not index (outbound) links in tweets, and Google is complying. The consequence is that a link shared on Twitter will never be known to Google, and won’t be displayed.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://parislemon.com/post/15664060982/misdirection-doublespeak-non-answers-and-straight-up&quot;&gt;MG Siegler&lt;/a&gt; perpetuates the misinterpretation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;But even more interesting is what Google said after blaming Twitter for Google screwing them: “since then we have observed their rel=nofollow instructions.” It’s subtle, but it sure sounds like Google is implying that they’re no longer crawling twitter.com — at Twitter’s request — so they don’t have the access needed to include Twitter in Search+. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;But that doesn’t actually mean this at all. Sullivan also points this out in his post and also notes that it sounds like bullshit misdirection. All it means is that in some cases, Google won’t follow links from and to twitter.com. But as Sullivan notes, Google has over &lt;strong&gt;3 billion&lt;/strong&gt; Twitter pages in their index.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once again, this is completely off the mark and insinuates all sorts of bad intention. Google is simply complying with Twitter.com’s directive to not follow outbound links in tweets it crawls, and the consequence is that there will never be “… shared this on Twitter” in the search results.&lt;/p&gt;

&lt;p&gt;The same issue would affect any website that chooses to put &lt;code&gt;rel=nofollow&lt;/code&gt; on all its outbound links. Usually the directive is used in places like the comments section of a blog post (to deter spam), but Twitter has decided to use it for all tweets. There is no great conspiracy against Twitter here. Google is simply following the rules of &lt;code&gt;rel=nofollow&lt;/code&gt;.&lt;/p&gt;

</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>MongoDB 2.0 Should Have Been 1.0</title>
   <link href="http://luigimontanez.com/2011/mongodb-2.0-should-have-been-1.0/"/>
   <updated>2011-11-07T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2011/mongodb-2.0-should-have-been-1.0/mongodb-2.0-should-have-been-1.0</id>
   <content type="html">&lt;p&gt;No open source project has received more criticism in recent years than MongoDB. Most of the flak has revolved around technical implementation decisions made for the project, and perceptions of how the company behind MongoDB, 10gen, has used advantages gained from those design decisions in marketing their product. It seems that more blog posts have been written on why one should &lt;strong&gt;not&lt;/strong&gt; use MongoDB than on why one should use it.&lt;/p&gt;

&lt;p&gt;In a now-404ed July 2010 entry (&lt;a href=&quot;http://redbeard0531.s3.amazonaws.com/mikeals_blog_backup/MongoDB+Performance+&amp;amp;+Durability.html&quot;&gt;mirror&lt;/a&gt;), Mikael Rogers, at the time an employee of the company behind CouchDB, wrote a highly-trafficked critique of MongoDB’s asynchronous writes and lack of single-server durability. Because of the design decisions made regarding persisting to disk, sending a hard kill signal to a standalone MongoDB instance could result in the database becoming corrupted beyond recovery. This was no good, of course. To their credit, engineers at 10gen worked to &lt;a href=&quot;http://www.paperplanes.de/2011/1/10/mongodb_and_data_durability.html&quot;&gt;address the problem&lt;/a&gt; and added in single-server durability in the 1.8 release.&lt;/p&gt;

&lt;p&gt;A few months later, Ethan Gunderson wrote a post titled “&lt;a href=&quot;http://ethangunderson.com/blog/two-reasons-to-not-use-mongodb/&quot;&gt;Two Reasons You Shouldn’t Use MongoDB&lt;/a&gt;”. Copping to an over-the-top title, he described the implications of the design decision to have a global write lock, as well as the lack, at the time, of single-server durability. His message was that developers need to understand MongoDB’s design decisions and the associated tradeoffs.&lt;/p&gt;

&lt;p&gt;Being document-based datastores, Riak and CouchDB are the most direct competitors to MongoDB. The employees of Basho, the company behind Riak, seem to have several bones to pick with both MongoDB and 10gen. At JSConf, Basho employee Sean Cribbs was giving a presentation on Riak. When asked a question comparing Riak to MongoDB, he &lt;a href=&quot;https://twitter.com/#!/sintaxi/status/65550206825005057&quot;&gt;responded&lt;/a&gt;, “Mongo loses data.” &lt;strong&gt;UPDATE&lt;/strong&gt;: Sean has just written a post titled &lt;a href=&quot;http://seancribbs.com/tech/2011/11/07/mongodb-and-riak-in-context-and-an-apology/&quot;&gt;MongoDB and Riak, In Context (and an apology)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A week later, in a &lt;a href=&quot;http://basho.com/blog/technical/2011/05/11/Lies-Damn-Lies-And-NoSQL/&quot;&gt;weird self-congratulatory blog post&lt;/a&gt;, Basho COO Antony Falco laid into the marketing of MongoDB by 10gen. Strangely, he never once named the technology or the company while simultaneously accusing &lt;em&gt;them&lt;/em&gt; of spreading FUD. His message: 10gen is flat out lying in its marketing of MongoDB, and it’s hurting the entire NoSQL community. Light on technical specifics but heavy on philosophical generalities, Falco’s screed seems to function as a rallying cry for his troops at Basho.&lt;/p&gt;

&lt;p&gt;Several days ago, Michael Schurter, an engineer at Urban Airship, detailed his company’s &lt;a href=&quot;http://blog.schmichael.com/2011/11/05/failing-with-mongodb/&quot;&gt;trials and tribulations&lt;/a&gt; with MongoDB. Among them were the global write lock, the daunting complexity associated with running a MongoDB cluster, and the possibility of data loss.&lt;/p&gt;

&lt;p&gt;Most recently, an anonymous ex-user, apparently compelled by social responsibility, left a Pastebin titled “&lt;a href=&quot;http://pastebin.com/FD3xe6Jt&quot;&gt;Don’t use MongoDB&lt;/a&gt;”. Eight reasons are given, all of which rehash points made in the posts above. Most damaging are the accusations that MongoDB randomly loses data. But there’s no hard evidence given. And because of the anonymous nature of a Pastebin posting, the 10gen CTO is left to &lt;a href=&quot;http://news.ycombinator.com/item?id=3202959&quot;&gt;respond point-by-point&lt;/a&gt; on the comment thread in Hacker News with no real dialogue possible.&lt;/p&gt;

&lt;p&gt;And so the critiques range from “understand the design tradeoffs and take appropriate steps” to “you’d be crazy to fall for the marketing hype – never ever use MongoDB”. Evaluating who is most correct is left as an exercise for the reader.&lt;/p&gt;

&lt;p&gt;There is no doubt that MongoDB has benefitted from an aggressive marketing push. There are more &lt;a href=&quot;http://www.10gen.com/events&quot;&gt;MongoDB conferences&lt;/a&gt; held (organized by 10gen) and &lt;a href=&quot;http://www.10gen.com/books&quot;&gt;MongoDB books&lt;/a&gt; written (mainly by 10gen employees) than for the other NoSQL datastores combined. Here’s a chart from Google that compares relative search interest over the last 12 months:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/nosql-nov-2011.png&quot; alt=&quot;NoSQL search terms&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’ll close with a criticism of my own: &lt;a href=&quot;http://blog.mongodb.org/post/10126837729/mongodb-2-0-released&quot;&gt;MongoDB 2.0&lt;/a&gt;, released in September, should have been version 1.0. Looking back, it’s clear that certain features added post-1.0 should have been added before a 1.0 was declared:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Configurable fsync time in &lt;a href=&quot;http://www.mongodb.org/display/DOCS/1.2.x+Release+Notes&quot;&gt;1.2&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Background index creation in &lt;a href=&quot;http://www.mongodb.org/display/DOCS/1.4+Release+Notes&quot;&gt;1.4&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Sharding and replica sets in &lt;a href=&quot;http://www.mongodb.org/display/DOCS/1.6+Release+Notes&quot;&gt;1.6&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Single-server durability as an option in &lt;a href=&quot;http://www.mongodb.org/display/DOCS/1.8+Release+Notes&quot;&gt;1.8&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Single-server durability as the default in &lt;a href=&quot;http://www.mongodb.org/display/DOCS/2.0+Release+Notes&quot;&gt;2.0&lt;/a&gt;, as well as a standalone compact command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The single-server durability issue was a huge one. Declaring a 1.0 version well before the issue was addressed was a major misstep by 10gen. Replica sets were the second attempt at a replication solution, much improved from the previous master/slave setup. However the two replication solutions were drastically different, and the transition should have been happening between 0.X releases, not 1.X releases. In an alternate universe, holding off on the 1.0 release may have tempered some criticism MongoDB has received.&lt;/p&gt;

&lt;p&gt;MongoDB is on its way to becoming the default datastore for web apps. At version 2.0, it is finally a stable product free of unexpected surprises. That is, a proper 1.0 release. With this stability, developers should seriously consider working with it. Its developer experience is unmatched in the world of datastores, though Redis comes in at a close second.&lt;/p&gt;

&lt;p&gt;The focus of my next blog post will be on developer happiness and MongoDB.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I have given presentations at three 10gen-sponsored MongoDB conferences. At the New York City event in May 2010, I ate a 10gen-sponsored turkey sandwich for lunch. At the D.C. event in November 2010, I had pre-conference drinks on the company’s tab and received the O’Reilly MongoDB book as a thank you gift.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Apps for Failed Institutions</title>
   <link href="http://luigimontanez.com/2011/apps-for-failed-institutions/"/>
   <updated>2011-10-04T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2011/apps-for-failed-institutions/apps-for-failed-institutions</id>
   <content type="html">&lt;p&gt;It’s been a rough few years. Our once-great institutions, many built up in the aftermath of World War II, have crumbled. The public has &lt;a href=&quot;http://www.chrishayes.org/articles/twilight-elites/&quot;&gt;lost faith&lt;/a&gt;. Take a look at this recent &lt;a href=&quot;http://www.gallup.com/poll/149216/Americans-Rate-Computer-Industry-Best-Federal-Gov-Worst.aspx&quot;&gt;Gallup poll&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/gallup-poll.gif&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It seems Americans only like two things: technology and food. And they dislike nearly everything else, with Big Oil and the federal government at the bottom of the list. The Gallup poll, covering industry, omits other institutions like higher education, organized religion, and professional sports. But it’s easy to guess how those would fare in a public poll.&lt;/p&gt;

&lt;p&gt;Americans have acted out on these frustrations. Politically, there have been wave elections for three consecutive cycles, in starkly different directions. The Tea Party tapped into the stewing anxieties of middle America. And young protesters are now occupying Wall Street, and will soon occupy city centers across the country, in response to unemployment and unchecked corporate dominance.&lt;/p&gt;

&lt;p&gt;There are two lessons we software developers can take from the poll above. First, we chose the right profession. Not only are we highly employable, but people actually like us for what we do, at least as much as they like Mario Batali and Chipotle. But second, and most importantly, we have an incredible opportunity to remake society’s institutions through the software and services we can create.&lt;/p&gt;

&lt;p&gt;This is a big, ambitious undertaking. The good news is that it’s already happening. Consider banks. Even before the Great Recession, online banks like ING Direct, and online brokerages like E*TRADE democratized personal finance, making it more straightforward. Their presence alone, of course, was not able to stave off financial disaster. They didn’t shake things up enough. Maybe &lt;a href=&quot;https://banksimple.com/&quot;&gt;BankSimple&lt;/a&gt; will help solve the problem, but it’s likely to be only the tip of the iceberg. We need to fundamentally remake the way we save and invest money, and we need more than one software company to do it.&lt;/p&gt;

&lt;p&gt;Healthcare is another failed institution. America spends dramatically more per capita on healthcare than the other Western countries, yet Americans are sicker and die of illness earlier. And despite the rhetoric, the truth is that healthcare will remain a private enterprise no matter what party is in power. It’s time for a drastic rethinking of health insurance, preventive medicine, and personal wellness. And software will have an enormous impact on how we get there. &lt;a href=&quot;http://fitbit.com&quot;&gt;FitBit&lt;/a&gt; and &lt;a href=&quot;http://massivehealth.com/&quot;&gt;MassiveHealth&lt;/a&gt; are a start, but again, there needs to be more.&lt;/p&gt;

&lt;p&gt;The other industries on the bottom of that list need to be rebooted as well. The bust of the housing market led to the Great Recession. How can we lead people to make responsible decisions about where they live and how they get around? Sure, we may like flying on some airlines like Virgin America or Southwest, but air travel still generally stinks. Is the educational system truly preparing students for life in the 21st century? The &lt;a href=&quot;http://www.khanacademy.org/&quot;&gt;Khan Academy&lt;/a&gt; is on to something, but they could probably use some help. If a web app can help us connect to old classmates, another web app can surely help us get rid of our dependence on fossil fuel. It just hasn’t had a Mark Zuckerberg to invent it yet.&lt;/p&gt;

&lt;p&gt;In the past decade, no institution has fallen out of favor more than the federal government:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/gallup-poll-2.gif&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It’s a tragedy of democracy.&lt;/p&gt;

&lt;p&gt;Everyone has formed an opinion on what exactly is wrong with our government. And many people are working earnestly to fix it. But no one will actually succeed. Why? Because no one has had a novel idea about politics and government in decades. The same old coalitions, the same old parties, the same old advocacy groups are fighting against each other using the same old tactics. The political system is prime for something completely new and different. Something that will come in and fundamentally change the game. It won’t look like anything Washington has seen before. And it’ll certainly be built on top of software. Software that any of us could conceive of and create.&lt;/p&gt;

&lt;p&gt;Software developers need to own up to the responsibility of making the world better. No more working on small things. We have a unique skillset that’s perfect for this moment in history. Such endeavors aren’t just the domain of the big thinkers. We don’t need to be invited to TED. All the ideas we need are right in front of us. We live them. We can fire up our favorite text editor, hack away during nights and weekends, and deploy to Heroku for free.&lt;/p&gt;

&lt;p&gt;Ideas are out there. Time to build them. Time to change the world.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>DROID 3 Review</title>
   <link href="http://luigimontanez.com/2011/droid-3-review/"/>
   <updated>2011-07-11T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2011/droid-3-review/droid-3-review</id>
   <content type="html">&lt;p&gt;There are barely any DROID 3 reviews on the Web, so I thought I’d try my hand at gadget blogging. I ordered the DROID 3 from Verizon Wireless on Thursday July 7, the day it was announced, and it was delivered the next day. The DROID 3 is my third DROID. I used the original DROID from the summer of 2010 until a month ago. I’ve used the DROID 2 Global for the past month. And now I’m the owner of a DROID 3.&lt;/p&gt;

&lt;p&gt;Here are my DROID, DROID 2 Global, and DROID 3:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/droids1.jpg&quot; alt=&quot;DROIDs&quot; width=&quot;600px&quot; /&gt;
&lt;img src=&quot;http://luigimontanez.com/images/droids2.jpg&quot; alt=&quot;DROIDs&quot; width=&quot;600px&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-original-droid&quot;&gt;The Original DROID&lt;/h3&gt;

&lt;p&gt;I love the original DROID. Released seven months before the iPhone 4, it sports a high resolution display with nearly invisible pixels. It’s well-built and solid. “It feels like a gun,” remarked a colleague upon holding it. The DROID &lt;a href=&quot;http://www.wired.com/magazine/2011/04/mf_android/all/1&quot;&gt;literally saved Motorola&lt;/a&gt;, and propelled Android OS to the pole position it occupies today in the smartphone market. And it’s the first and only phone on Verizon to run stock Android. I was thrilled to switch to it after two years on AT&amp;amp;T with an iPhone 3G.&lt;/p&gt;

&lt;p&gt;But earlier this year, the DROID started showing its age. The interface ran slow. Very slow. I rooted it, ran a &lt;a href=&quot;http://www.peteralfonso.com/&quot;&gt;custom Gingerbread ROM&lt;/a&gt;, and dabbled with overclocking. But the frustrations continued to mount. Battery life was abysmal. I had planned to wait for the DROID Bionic, but its launch was delayed with no firm date announced.&lt;/p&gt;

&lt;h3 id=&quot;the-droid-2-global&quot;&gt;The DROID 2 Global&lt;/h3&gt;

&lt;p&gt;About a month ago, I bought a used DROID 2 Global on eBay. It has two notable qualities. First, it’s fast. The 1.2 Ghz CPU and dedicated GPU provide a welcome upgrade over the original DROID. Second, the DROID 2 Global’s build quality is atrocious. Unlike the original, it’s not solid. Its back is covered in cheap plastic, and the plastic front bezel is painted as fake chrome. The power button is sticky and soft. In other words, the DROID 2 Global doesn’t feel like a gun. It feels like a cheap plastic toy.&lt;/p&gt;

&lt;p&gt;The MOTOBLUR skin is unwelcome. The typography is sloppy, particularly in the status bar. Overall, the DROID 2 Global’s CPU covers up for a lot of unforced errors on the part of Motorola. I planned to upgrade as soon as a better phone came out.&lt;/p&gt;

&lt;h3 id=&quot;the-droid-3&quot;&gt;The DROID 3&lt;/h3&gt;

&lt;p&gt;Not wanting to wait for the DROID Bionic, or Samsung Galaxy S II, I pulled the trigger and bought an unsubsidized DROID 3 on launch day. Overall, I’ve been happy with my purchase. The build quality is closer to the original DROID. This phone feels solid, and the larger screen size (increased to 4 inches from 3.7 inches) is a plus. The slide-out keyboard feels great, with an additional fifth row dedicated to numbers. Because I incorporate numbers into my passwords (using &lt;a href=&quot;http://luigimontanez.com/2010/password-recipes/&quot;&gt;password recipes&lt;/a&gt;), signing into my various accounts was much more pleasant with the new keyboard. The DROID 3 runs Gingerbread 2.3, a step up from Froyo 2.2 on DROID and DROID 2 Global. And its internals, featuring a dual-core 1 Ghz processor, enable a smooth user experience.&lt;/p&gt;

&lt;p&gt;The most controversial aspect of the DROID 3 (and other Motorola phones of this generation) is it’s qHD (quarter HD at 960x540) display. A high resolution display is usually very welcome, but the &lt;a href=&quot;http://www.droid-life.com/2011/05/26/a-closer-look-at-the-droidx2-and-its-qhd-display-pentile-at-its-finest/&quot;&gt;PenTile screen technology&lt;/a&gt; Motorola incorporates is decidedly unwelcome. It’s significantly poorer than the display shared by the DROID and DROID 2 Global. Pixels on solid colors are visible. Gradients look jagged. Scrolling white text on a black background results in a hideous effect. When playing games like Angry Birds, or scrolling through home screens, there’s a shadowing that occurs with fast moving elements across the screen.&lt;/p&gt;

&lt;p&gt;Motorola seems to have tailored its MOTOBLUR skin with the shortcomings of the screen in mind. The PenTile technology does best when displaying shades of blue, and so MOTOBLUR has ditched Gingerbread’s green and black motif for a blue one. Where Android likes use white text on a black background for Settings, MOTOBLUR has inverted that to hide the problems associated with that color combination. Speaking of colors, greens aren’t at all vibrant, like on the Samsung Nexus S. Instead, bright greens end up looking like pea soup. The pixelation on reds and yellows is especially painful. The home screen interface on MOTOBLUR is silly, so I switched to &lt;a href=&quot;https://market.android.com/details?id=com.gau.go.launcherex&quot;&gt;GO Launcher EX&lt;/a&gt; on the recommendation of &lt;a href=&quot;http://twit.tv/twig102&quot;&gt;Leo Laporte&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But after several days, I think I can live with the inferior qHD screen. The pixelation is only noticeable when looking for it, though I wish it weren’t noticeable at all. It’s disappointing that the original DROID, released in the fall of 2009, looks significantly better than the new DROID 3.&lt;/p&gt;

&lt;p&gt;Battery life is yet to be determined. It was excellent for the first two days, and then rapidly dropped from 100% to 40% in the course of a few hours on the third day, despite not being actively used. I’ve disabled GSM support (the phone is global). That may help things.&lt;/p&gt;

&lt;p&gt;One disappointment that may be a fluke: My DROID 3’s main camera stopped working after the first day. All I get is a black screen in the camera app, even though I do get a working picture when switching to the front-facing camera. I’ll have to ask Verizon for a replacement unit.&lt;/p&gt;

&lt;p&gt;I do plan on keeping that replacement unit for the long term. The DROID 3 is a good phone, despite its screen, and it’s a worthy successor to the original DROID. To read first impressions from other DROID 3 owners, head on over to the &lt;a href=&quot;http://androidforums.com/motorola-droid-3/371621-droid-3-first-impressions.html&quot;&gt;Android Forums&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>When Steve Jobs and Local Government Collide</title>
   <link href="http://luigimontanez.com/2011/steve-jobs-local-government-collide/"/>
   <updated>2011-06-09T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2011/steve-jobs-local-government-collide/steve-jobs-local-government-collide</id>
   <content type="html">&lt;p&gt;Soon after he unveiled iCloud at the WWDC keynote, Steve Jobs went to a Cupertino City Council hearing to present Apple’s plans to build a new campus. The city council recorded the visit, and has made it available on YouTube.&lt;/p&gt;

&lt;object width=&quot;480&quot; height=&quot;390&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/gtuz5OmOh_M?version=3&amp;amp;hl=en_US&amp;amp;rel=0&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;embed src=&quot;http://www.youtube.com/v/gtuz5OmOh_M?version=3&amp;amp;hl=en_US&amp;amp;rel=0&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;480&quot; height=&quot;390&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; /&gt;&lt;/object&gt;

&lt;p&gt;For many reasons, it’s a remarkable thing to watch:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;While not as polished as his keynotes, Jobs still gives a brilliant performance. He forcefully but respectfully conveys his message: Apple wants to stay in Cupertino and build this campus. Let us do that.&lt;/li&gt;
  &lt;li&gt;His slide deck complements the serene images of the new Apple campus. When displaying text, he uses a light beige background instead of the slate grey standard for Apple keynotes (and in Apple Keynote). There’s a California cool to it all.&lt;/li&gt;
  &lt;li&gt;The main building may resemble a spaceship as Jobs mentions, but it’s also very reminiscent of the Pentagon outside Washington, D.C. The Pentagon can hold 26,000 employees. This new Apple Ring will accommodate 13,000. Apple, infamous for its secrecy, wants to build a gorgeous fortress in Cupertino.&lt;/li&gt;
  &lt;li&gt;There’s a remarkable diversity in the audience at the hearing, and within the city council itself. There are few places in America where immigrants speaking in broken English can be elected to office.&lt;/li&gt;
  &lt;li&gt;But the city council members don’t acquit themselves very well, being generally starstruck. The question about free wi-fi comes off as petty. The question about safety standards is superfluous. One councilman gets sentimental. Serious questions could have been asked of Jobs – what will an influx of 12,000 employees do to area traffic? – but they weren’t.&lt;/li&gt;
  &lt;li&gt;The implicit threat Jobs makes during his presentation – that Apple will leave Cupertino if this campus isn’t approved – is made explicit during the question period. That’s when it becomes clear why Jobs is there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steve Jobs has been on medical leave from Apple since the beginning of the year. But he’s still the public face of the company. When Apple needs him, he’s there. And as shown by this city council hearing, he’s &lt;a href=&quot;http://www.macobserver.com/tmo/article/cupertino_on_new_apple_campus_no_chance_were_saying_no/&quot;&gt;damn effective&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Web-Based Slide Decks Done Right</title>
   <link href="http://luigimontanez.com/2011/web-based-slide-decks-done-right/"/>
   <updated>2011-06-07T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2011/web-based-slide-decks-done-right/web-based-slide-decks-done-right</id>
   <content type="html">&lt;p&gt;For software developers, the era of using desktop presentation software like Powerpoint and Keynote will soon be over. Slide decks can now be created using modern HTML5 technologies. Web-based slides make a lot of sense, especially for those comfortable writing code. They’re just web sites, so no special software is needed to view them. They’re built with code: HTML, CSS, and JS. Web-based slide decks can be programmed and interactive. And recently, tools have emerged to help developers build them.&lt;/p&gt;

&lt;h3 id=&quot;desktop-style-web-apps&quot;&gt;Desktop-Style Web Apps&lt;/h3&gt;

&lt;p&gt;Using the Web to put together a slide deck is not a new idea. Back in 2007, Google integrated a presentations app into their larger Google Docs suite of tools. Much like the rest of Google Docs, the presentation app was largely inspired by productivity software offered by Microsoft, but this tool lived on the Web. Unsurprisingly, Microsoft soon followed with a Web version of Powerpoint in their Office Live suite.&lt;/p&gt;

&lt;p&gt;In 2008, the Web framework &lt;a href=&quot;http://cappuccino.org/&quot;&gt;Cappuccino&lt;/a&gt; was born, and with it came &lt;a href=&quot;http://280slides.com/&quot;&gt;280 Slides&lt;/a&gt;, built by former Apple engineers. Cappuccino, and the language it’s built on, &lt;a href=&quot;http://cappuccino.org/learn/tutorials/objective-j-tutorial.php&quot;&gt;Objective-J&lt;/a&gt;, are a complete abstraction on top of the modern Web stack. Try out 280 Slides – it’s impressive technology.&lt;/p&gt;

&lt;p&gt;By early 2009, Web-based slide decks meant relying full-featured in-browser apps that attempted to replicate what was found in desktop clients. A paradigm shift had not yet occurred.&lt;/p&gt;

&lt;h3 id=&quot;slidedown-and-showoff&quot;&gt;Slidedown and ShowOff&lt;/h3&gt;

&lt;p&gt;In the spring of 2009, Pat Nakajima released &lt;a href=&quot;https://github.com/nakajima/slidedown&quot;&gt;Slidedown&lt;/a&gt;, a novel approach to making a slide deck for the Web. The toolchain introduced was familiar for web developers: Create content using Markdown and code. Use the command line to generate the slideshow as a single HTML file. Post it on a web server. Slidedown relies heavily on jQuery for slide transitions and animation.&lt;/p&gt;

&lt;p&gt;GitHub’s &lt;a href=&quot;https://github.com/schacon&quot;&gt;Scott Chacon&lt;/a&gt; made a splash in early 2010 with &lt;a href=&quot;https://github.com/schacon/showoff&quot;&gt;ShowOff&lt;/a&gt;. With a workflow similar to Slidedown, ShowOff generates a presentation as a self-contained Sinatra app. In the era of &lt;a href=&quot;http://heroku.com&quot;&gt;Heroku&lt;/a&gt;, hosting the Sinatra app is trivial. Today, &lt;a href=&quot;http://nosql-railswaycon-2011.heroku.com/&quot;&gt;many&lt;/a&gt; &lt;a href=&quot;http://knowsql.heroku.com/&quot;&gt;presentations&lt;/a&gt; at Ruby conferences use ShowOff.&lt;/p&gt;

&lt;h3 id=&quot;embracing-html5-and-css3&quot;&gt;Embracing HTML5 and CSS3&lt;/h3&gt;

&lt;p&gt;Starting in 2010, HTML5 and CSS3 were clearly becoming the Next Big Thing on the Web. Google’s Chrome team launched &lt;a href=&quot;http://www.html5rocks.com/&quot;&gt;HTML5 Rocks&lt;/a&gt;*, an all-encompassing resource for HTML5 technologies. One of the most eye-catching parts of the site is a &lt;a href=&quot;http://slides.html5rocks.com/&quot;&gt;fully HTML5 slide deck&lt;/a&gt; about (what else?) HTML5. Breaking from the reliance on JavaScript in Slidedown and ShowOff, Google opted to use CSS3 to accomplish effects that were once cumbersome to implement in the browser. Maximizing the potential of modern browsers, this was clearly the way forward.&lt;/p&gt;

&lt;p&gt;In May 2010, Adam Zaptletal released &lt;a href=&quot;https://github.com/adamzap/landslide&quot;&gt;Landslide&lt;/a&gt;, an HTML5 slide deck generator that borrowed heavily from Google’s original HTML5 Rocks presentation. I used it earlier this year for a &lt;a href=&quot;http://luigimontanez.com/html5&quot;&gt;presentation to journalists on HTML5&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But Google wasn’t done. Last month at their annual developer conference, Google I/O, all &lt;a href=&quot;http://io-2011-html5-games-hr.appspot.com/&quot;&gt;presentations&lt;/a&gt; &lt;a href=&quot;http://io2011-zerotohero.appspot.com/&quot;&gt;by&lt;/a&gt; &lt;a href=&quot;http://io-2011-html5-games-hr.appspot.com/&quot;&gt;the&lt;/a&gt; Chrome team used an I/O-themed HTML5 slide deck. While not yet formally announced, Google has actually released the slide template as an open source project, called &lt;a href=&quot;http://code.google.com/p/html5slides/&quot;&gt;htm5slides&lt;/a&gt; on Google Code. Googlers Eric Bidelman and Arne Roomann-Kurrik went a step further for their &lt;a href=&quot;http://www.htmlfivewow.com/&quot;&gt;HTML5 Wow&lt;/a&gt; presentation, and released that code as its own &lt;a href=&quot;http://code.google.com/p/html5wow/&quot;&gt;open source project&lt;/a&gt;. HTML5 Wow features bleeding-edge stuff, like WebGL and the File API.&lt;/p&gt;

&lt;p&gt;Mozilla has been getting in on the fun as well. Technical Evangelist Paul Rouget recently released &lt;a href=&quot;http://paulrouget.com/dzslides/&quot;&gt;DZSlides&lt;/a&gt;, with the accompanying slide show &lt;a href=&quot;http://paulrouget.com/e/html5inthewild/&quot;&gt;HTML5 in the Wild&lt;/a&gt;. DZSlides enforces almost no theming, and importantly, includes support for embedding slide decks. Presenters know that the ability to embed their slide deck through &lt;a href=&quot;http://slideshare.net&quot;&gt;Slideshare&lt;/a&gt; is a major reason to stick with traditional formats like .ppt, .keynote, or .pdf. DZSlides is a pure HTML5 solution that replaces Slideshare’s Flash embed. It should be noted that as of this writing, DZSlides doesn’t render correctly in the latest Webkit-based browsers. The latest Firefox and Aurora builds do support the correct behavior.&lt;/p&gt;

&lt;p&gt;Today, solid options exist for creating slide decks in HTML5. With the current tools, using code to craft a presentation is easy, and frankly, more fun than using Powerpoint or Keynote. And there are no barriers to entry for inventing a custom solution.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;* I wrote an article about &lt;a href=&quot;http://www.html5rocks.com/tutorials/casestudies/sunlight_streamcongress.html&quot;&gt;WebSockets and EventSource&lt;/a&gt; published on HTML5 Rocks.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Leveling Up for JSConf and NodeConf</title>
   <link href="http://luigimontanez.com/2011/leveling-up-jsconf-nodeconf/"/>
   <updated>2011-03-21T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2011/leveling-up-jsconf-nodeconf/leveling-up-jsconf-nodeconf</id>
   <content type="html">&lt;p&gt;Both &lt;a href=&quot;http://2011.jsconf.us/&quot;&gt;JSConf&lt;/a&gt; and &lt;a href=&quot;http://nodeconf.com/&quot;&gt;NodeConf&lt;/a&gt; are taking place in Portland during the first week of May, a mere six weeks away. Having been to both previous JSConf US conferences, I have a good idea of what to expect:  bleeding edge web technology presented by programmer pioneers. I’ve been to an uncountable number of developer conferences in the past four years, and I’ve picked up a lot of good stuff along the way. But JSConf has been the only one that really expanded my horizons.&lt;/p&gt;

&lt;p&gt;Confession: I usually leave JSConf overwhelmed. There’s too much new material for me to absorb effectively. This year, throw NodeConf into the mix, and I fear even more goodness will just go over my head. As a Ruby on Rails developer, I don’t do enough day-to-day JavaScript to call myself an expert. I want to change that between today and May 1.&lt;/p&gt;

&lt;p&gt;I’ll be going on a self-imposed JavaScript training regimen these next six weeks. I’ll mix in some comprehensive exercise, some good nutrition, and hopefully when game day approaches, Coach will tell me I’m ready. Here’s the plan:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Build a useful web app using &lt;a href=&quot;http://brunchwithcoffee.com/&quot;&gt;Brunch&lt;/a&gt; on the frontend and &lt;a href=&quot;http://expressjs.com/&quot;&gt;Express&lt;/a&gt; on the backend. This exposes me to Node, CoffeeScript, and many more important JavaScript libraries.&lt;/li&gt;
  &lt;li&gt;Figure out how to use &lt;a href=&quot;http://socket.io/&quot;&gt;Socket.IO&lt;/a&gt; to keep it real(time).&lt;/li&gt;
  &lt;li&gt;Explore frontend libraries &lt;a href=&quot;http://knockoutjs.com/&quot;&gt;Knockout&lt;/a&gt; and &lt;a href=&quot;http://www.sproutcore.com/&quot;&gt;SproutCore&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Truly understand what Brendan Eich talks about in his &lt;a href=&quot;http://www.aminutewithbrendan.com/&quot;&gt;A Minute with Brendan&lt;/a&gt; podcast.&lt;/li&gt;
  &lt;li&gt;Catch up on other podcasts like &lt;a href=&quot;http://jsconflive.com/&quot;&gt;JSConf Live&lt;/a&gt; and &lt;a href=&quot;http://yayquery.com/&quot;&gt;yayQuery&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Pour myself a glass of wine and watch Paul Irish’s two &lt;a href=&quot;http://paulirish.com/2011/11-more-things-i-learned-from-the-jquery-source/&quot;&gt;videos&lt;/a&gt; on the jQuery source code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What have I missed? How do you plan to level up in preparation for JSConf and NodeConf?&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>This Day in History, as told by Gmail</title>
   <link href="http://luigimontanez.com/2011/day-in-history-told-by-gmail/"/>
   <updated>2011-02-26T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2011/day-in-history-told-by-gmail/day-in-history-told-by-gmail</id>
   <content type="html">&lt;p&gt;My colleague &lt;a href=&quot;http://jamesturk.net/&quot;&gt;James Turk&lt;/a&gt; looked back at his &lt;a href=&quot;http://jamesturk.net/post/3496075956/today-in-history&quot;&gt;recent life as told by Gmail&lt;/a&gt;. I’ve decided to do the same for this day, February 26.&lt;/p&gt;

&lt;h2 id=&quot;section&quot;&gt;2005&lt;/h2&gt;

&lt;p&gt;Doing the advanced search in Gmail, I noticed that when given a date to search on, Gmail will actually return email from that day along with email from the day before and the day after. This is a welcome feature, as I didn’t send or receive any email on this day in 2005. I received a mere seven emails during that three day time window.&lt;/p&gt;

&lt;p&gt;It was my senior year of college at Georgia Tech. I received an email from the Georgia Tech College Democrats president, who became my girlfriend three weeks later (and still is). I registered for Dice.com and CyberCoders, two IT industry job search sites.&lt;/p&gt;

&lt;p&gt;A recruiter from Microsoft scheduled a phone interview with me. Two months later I was invited to Redmond for on-campus interviews with the Office Online operations team. I was twenty-one years old, and Microsoft paid for my first ever rental car (I would not drive another rented car for five years). The Emerald City was sparkling and gorgeous on the April Sunday I arrived and did the tourist thing on Microsoft’s dime.&lt;/p&gt;

&lt;p&gt;The next morning, I got ready in a Redmond hotel room watching the white smoke announcement of Joseph Ratzinger as the new Pope. I completely flubbed the marathon session of interviews. It was during my third interview of the day when I realized I was simply not qualified for the job, having no experience with IIS or .NET. I left Seattle knowing I wouldn’t be offered a job. That summer I took a developer position with &lt;a href=&quot;http://democracyforamerica.com&quot;&gt;Democracy for America&lt;/a&gt;(DFA) in Vermont, for a salary that was probably a third of what I would have earned at Microsoft.&lt;/p&gt;

&lt;h2 id=&quot;section-1&quot;&gt;2006&lt;/h2&gt;

&lt;p&gt;I was now braving a winter in Burlington, Vt., as the lone developer at a small PAC. I was testing out a new contribution system I was building for DFA, a mini-ActBlue, making small donations through the system to the first candidate we’d raise money for, &lt;a href=&quot;http://en.wikipedia.org/wiki/Ciro_Rodriguez&quot;&gt;Ciro Rodriguez&lt;/a&gt;. DFA later scrapped that system and just used ActBlue.&lt;/p&gt;

&lt;p&gt;In my search for a Mac text editor, I purchased &lt;a href=&quot;http://www.beforedawnsolutions.com/applications/skedit&quot;&gt;skEdit&lt;/a&gt;, which was my editor of choice until I purchased TextMate in May. I also signed up for a DreamHost account to host my personal website.&lt;/p&gt;

&lt;p&gt;Nearly a year into our relationship, most of it spent hundreds of miles apart (she was still in Atlanta at Georgia Tech), a good percentage of the 36 email conversations and chat logs were with my girlfriend.&lt;/p&gt;

&lt;h2 id=&quot;section-2&quot;&gt;2007&lt;/h2&gt;

&lt;p&gt;I moved back to Atlanta in early January. I exchanged several emails with Jerome Armstrong concerning a new campaign platform I was to build in Rails. I ended up living in Atlanta for two years, working remotely for Jerome’s consultancy based just outside DC.&lt;/p&gt;

&lt;p&gt;At this time, I was also talking to folks who wanted to draft Al Gore in the presidential race. I had registered ForGore.com and launched an ineffective website a few months later. Email traffic was still reasonable, at 47 conversations for the three day period.&lt;/p&gt;

&lt;h2 id=&quot;section-3&quot;&gt;2008&lt;/h2&gt;

&lt;p&gt;Fully into my consulting gig in an election year, I was inundated with client requests. I was doing Salesforce.com work for the U.S. Senate campaigns of John Kerry and Mark Warner, and building a social network for the SEIU. I was harried and overwhelmed with the workload, and the 117 conversations in this period reflected that. I also bought a first generation iPod Touch for my girlfriend, which was my third anniversary present to her.&lt;/p&gt;

&lt;h2 id=&quot;section-4&quot;&gt;2009&lt;/h2&gt;

&lt;p&gt;My girlfriend graduated from college after the fall semester, and we moved together to Northern Virginia. My remote work for the consulting agency was now on-site work and I was an actual employee. While there were 222 conversations in Gmail for this period, that was a function of automated email. Our team was using Pivotal Tracker and practicing continuous integration, and the system sent out emails after every commit to GitHub with the build results. I named our CI server Phyllis Schafly so that broken test suite notifications came from her.&lt;/p&gt;

&lt;p&gt;I was subscribed to the Sunlight Labs mailing list, which was seeing loads of activity around the first &lt;a href=&quot;http://sunlightlabs.com/contests/appsforamerica/&quot;&gt;Apps for America&lt;/a&gt; contest. My app entry was a precursor to &lt;a href=&quot;http://poligraft.com&quot;&gt;Poligraft&lt;/a&gt;, a tool I would build a year and half later as an employee at Sunlight. Also, I received an Eventbrite notification about the first ever &lt;a href=&quot;http://transparencycamp.org&quot;&gt;TransparencyCamp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GMAT prep books I had checked out of the library were due. I took the GMAT a few weeks later, did horribly average on the math section, and decided I didn’t want to get an MBA after all. I purchased the Beta of The RSpec Book, which wouldn’t be published until December 2010.&lt;/p&gt;

&lt;h2 id=&quot;section-5&quot;&gt;2010&lt;/h2&gt;

&lt;p&gt;Now working for Sunlight, email load was a bit lighter at 138. The Sunlight staff was abuzz with the positive reaction to our first ever production of &lt;a href=&quot;http://sunlightlive.com&quot;&gt;Sunlight Live&lt;/a&gt;. Today in 2011, I’m working on a follow-up project to Sunlight Live: a generalized platform for reporting on real-time events called &lt;a href=&quot;http://github.com/sunlightlabs/datajam&quot;&gt;Datajam&lt;/a&gt;. I was working on the website for &lt;a href=&quot;http://politiwidgets.com&quot;&gt;Politiwidgets&lt;/a&gt;, and bought an ebook from Manning called &lt;a href=&quot;http://www.manning.com/trebitowski/&quot;&gt;iPhone and iPad in Action&lt;/a&gt;. This was a new title for the book. It was first called iPhone in Action, and today it’s called &lt;a href=&quot;http://www.manning.com/jharrington/&quot;&gt;iOS 4 in Action&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 
 
 <entry>
   <title>The Strange Populist Outrage Against Google</title>
   <link href="http://luigimontanez.com/2011/strange-populist-outrage-google/"/>
   <updated>2011-02-02T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2011/strange-populist-outrage-google/strange-populist-outrage-google</id>
   <content type="html">&lt;p&gt;The debate over the great 2011 clickstream controversy has played out in phases that seem hilariously obvious in retrospect. First, &lt;a href=&quot;http://searchengineland.com/google-bing-is-cheating-copying-our-search-results-62914&quot;&gt;outrage combined with confusion&lt;/a&gt; over what exactly happened. Then, a &lt;a href=&quot;http://www.bing.com/community/site_blogs/b/search/archive/2011/02/01/thoughts-on-search-quality.aspx&quot;&gt;rebuttal replete with generalities&lt;/a&gt; that only hints at an explanation. Third, a &lt;a href=&quot;http://googleblog.blogspot.com/2011/02/microsofts-bing-uses-google-search.html&quot;&gt;less outraged rebuttal to that rebuttal&lt;/a&gt;, that strangely waits to the last paragraph to make its point. And now, a &lt;a href=&quot;http://www.puremango.co.uk/2011/02/what-on-earth-are-google-doing/&quot;&gt;populist revolt&lt;/a&gt; against the original Google claim, pointing out &lt;a href=&quot;http://www.roughlydrafted.com/2011/02/01/why-is-google-so-hysterically-hypocritical-about-bing-using-its-public-data/&quot;&gt;perceived hypocrisy in Google’s position&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look back at the facts, ignoring the rhetoric for now:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Google suspected Bing of stealing its search results, and conducted some experiments. In a trial of 100 search terms, they were able to prove that Bing did somehow manage to copy Google results in seven (out of 100) cases.&lt;/li&gt;
  &lt;li&gt;Google posited that clickstream data from IE or Bing Toolbar was causing this to happen. That is, users who opted in to share their data anonymously with Microsoft were sending back data on what they typed, which sites they visited, and what they clicked on. One website is often Google, and so Google results were effectively brought into the Bing search algorithm.&lt;/li&gt;
  &lt;li&gt;Harry Shum of Bing more or less verifies that this is what happened in his blog post and appearance yesterday morning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So Bing is effectively using some Google results in its search engine. It’s not direct copying, but the effect is the same. This is certainly wrong, though it’s not outright “cheating” as was originally posited. Bing is using the fruits of the core offering of its direct competitor to make its own core offering better. Bing should immediately blacklist any clickstream data coming from Google. It’s just that simple.&lt;/p&gt;

&lt;p&gt;But it’s not that simple, because the current populist revolt against Google seems to believe that Google has no right to be upset. The thinking goes: Google uses the the Web’s shared work, so they have no right to cry foul when Bing uses their search results. This is all part of the game!&lt;/p&gt;

&lt;p&gt;That position is even more indefensible than Bing’s. Search engines provide a service to users: their own unique take on what links should be presented to a user based on a search phrase. Providing value on top of existing work is a legitimate way to do business. That’s what Google, and all search engines, do. It is not legitimate, however, to take existing work and simply pass it off as your own. That’s what Bing is doing, even though it was unintentional.&lt;/p&gt;

&lt;p&gt;Journalists translate events into words. If Journalist A takes Journalist B’s reporting on a certain event and passes it off as his own without citation, we’d all agree that would be wrong. Even if Journalist A didn’t know he was copying work, it would still be wrong. And we don’t fault journalists for observing the world as it is and profiting off the reporting of that world.&lt;/p&gt;

&lt;p&gt;Bing is using work done by Google’s core offering for its own core offering. That’s wrong and needs to stop.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Cr-48 Chrome Notebook with Decals</title>
   <link href="http://luigimontanez.com/2011/cr-48-with-decals/"/>
   <updated>2011-01-24T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2011/cr-48-with-decals/cr-48-with-decals</id>
   <content type="html">&lt;p&gt;Today I received a present from Google in the form of the Cr-48 Chrome Notebook. Shipments of the Cr-48 stopped just before Christmas, according to various reports on Twitter and &lt;a href=&quot;http://thechromesource.com/&quot;&gt;The Chrome Source&lt;/a&gt;. It appears they’ve started back up, and now included in the box are a set of decals to decorate the drab black top of the notebook. There’s one large decal meant to cover most of the top cover, and a set of small stickers for a touch of personalization:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/Cr-48-1.jpg&quot; width=&quot;500px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/Cr-48-2.jpg&quot; width=&quot;500px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/Cr-48-3.jpg&quot; width=&quot;500px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/images/Cr-48-4.jpg&quot; width=&quot;500px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The hardware seems the same from previous reports. The touchpad is still a bit flaky, especially when attempting a two-finger scroll. I’m a fan of relying totally on the keyboard anyway, so &lt;a href=&quot;http://luigimontanez.com/2010/mouseless-monday-1-vimium-google-chrome/&quot;&gt;Vimium&lt;/a&gt; becomes even more indispensable.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Protect Yourself with Password Recipes</title>
   <link href="http://luigimontanez.com/2010/password-recipes/"/>
   <updated>2010-12-14T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2010/password-recipes/password-recipes</id>
   <content type="html">&lt;p&gt;Are you now more wary about your passwords after the Gawker incident? Good. The lesson is simple: if you supply a password to a website, expect it to get stolen. Malicious hackers succeed at getting user passwords all the time. And user data breaches are almost never as public as with what happened to Gawker. But if you follow two simple rules, you’ll be able to protect yourself from greater damage when the inevitable FAIL happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule #1&lt;/strong&gt;: Don’t supply a password if you don’t have to. Many sites today offer registration via pre-existing accounts with Facebook, Google, or Twitter. Take advantage of those. &lt;strong&gt;UPDATE&lt;/strong&gt;: In February 2013, Twitter itself was compromised, but the method described below would have protected you against that attack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule #2&lt;/strong&gt;: When you do have to supply a password, you should always create a unique password for every single site. That way, if your password gets stolen from one site (and it will), only your account with that site will be compromised. Furthermore, your unique password should not contain any word in any language. It should be a nonsensical series of letters, numbers, and punctuation. Otherwise, attackers can guess your password through dictionary or brute-force attacks.&lt;/p&gt;

&lt;p&gt;The lazy way to accomplish Rule #2 is through a password manager like &lt;a href=&quot;http://agilewebsolutions.com/onepassword&quot;&gt;1Password&lt;/a&gt; or my personal favorite, &lt;a href=&quot;http://lastpass.com&quot;&gt;LastPass&lt;/a&gt;. I prefer LastPass because it’s a simple browser extension and it’s free, while 1Password is a $40 desktop app. Both will generate unique, one-time passwords for your accounts, and store them securely. Of course, you still need a “master password” for those apps.&lt;/p&gt;

&lt;p&gt;But I prefer managing passwords the old-fashioned way: using my mind. I don’t like completely relying on an app I may not have access to on the various devices I want to use.&lt;/p&gt;

&lt;p&gt;So how do you generate a unique yet memorable password that’s unguessable by man and machine? Come up with your own &lt;strong&gt;password recipe&lt;/strong&gt; for constructing a password based on the website’s domain name. To make this concrete, walk through this example with google.com:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;There are 6 letters in “google” (the secondary-level domain), and 3 letters in “com” (the top-level domain). Multiply 6 by 3 to get 18. &lt;strong&gt;18&lt;/strong&gt; is the first part of the password.&lt;/li&gt;
  &lt;li&gt;Now come up with a phrase you’ll remember, like “All’s well that ends well”. Take the first letter of each word to build the second part of your password, &lt;strong&gt;awtew&lt;/strong&gt;. Note that this step has nothing to do with the website’s domain name, which is completely fine.&lt;/li&gt;
  &lt;li&gt;The next part of the password will be based on the “google” part of the domain name again. This time, we’ll take all the consonants and capitalize them: &lt;strong&gt;GGL&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Last, let’s subtract the 3 letters in “com” from the 6 letters in “google”: &lt;strong&gt;3&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So our password for Google would be &lt;strong&gt;18awtewGGL3&lt;/strong&gt;. Our password for Yahoo.com would be &lt;strong&gt;15awtewYH2&lt;/strong&gt;, while LifeHacker.com would have the password of &lt;strong&gt;30awtewLFHCKR7&lt;/strong&gt;. But of course, come up with your own recipe, don’t use the one above.&lt;/p&gt;

&lt;p&gt;The idea is that you memorize four or five steps to build a unique but reconstructable password. Here are more ideas for individual steps for your password recipe:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Choose different punctuation for different top-level domain names. % for .com, @ for .org, ! for .net, ^ for everything else.&lt;/li&gt;
  &lt;li&gt;Pick out the first or second letter/consonant/vowel from the secondary-level domain name, and capitalize it or repeat it a couple times.&lt;/li&gt;
  &lt;li&gt;Apply math in different ways. Multiply the number of vowels by your lucky number, then add 13. Or use division to come up with a remainder.&lt;/li&gt;
  &lt;li&gt;Come up with a nonsense word to always use, but make sure it’s not in the dictionary or discoverable via Google. This is effectively the same as taking the first letter of each word from a longer phrase.&lt;/li&gt;
  &lt;li&gt;Determine some universal rules that will make guessing your password even less likely. If the letter “a” is to be used, always use a capital “V” instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So that’s all there is to it: Come up with your own recipe for constructing passwords based on the domain name of the site. Make sure it’s repeatable and consistent – your formula should always produce the same password for the same domain.&lt;/p&gt;

&lt;p&gt;I’ve been using this technique since 2005, when Steve Gibson recommended it on episode #5 of &lt;a href=&quot;http://www.grc.com/SecurityNow.htm&quot;&gt;Security Now&lt;/a&gt;. Steve called it the “Personal Password Policy”, but I like the phrase “password recipe” better. Speaking of Steve, watch him &lt;a href=&quot;http://www.youtube.com/watch?v=r9Q_anb7pwg&quot;&gt;review LastPass&lt;/a&gt; earlier this year. I personally use LastPass to remember my passwords, but I don’t let it generate passwords for me – that’s what my password recipe is for.&lt;/p&gt;
</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>Reading Code is Good, Writing Documentation is Better</title>
   <link href="http://luigimontanez.com/2010/reading-code-is-good-writing-documentation-is-better/"/>
   <updated>2010-10-15T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/reading-code-is-good-writing-documentation-is-better/reading-code-is-good-writing-documentation-is-better</id>
   <content type="html">&lt;p&gt;Yesterday, John Nunemaker wrote a widely disseminated blog post on &lt;a href=&quot;http://railstips.org/blog/archives/2010/10/14/stop-googling/&quot;&gt;reading code&lt;/a&gt;. He argues that instead of searching Google or asking a mailing list when trying to figure out how to use a software library, developers should open up its codebase and just start reading. John is 100% right. In fact, I too once opened up the Typhoeus library to figure out which options were available to me. Having a high level of code literacy – when it’s not your code – is essential to our craft.&lt;/p&gt;

&lt;p&gt;But considering that point alone ignores what should be an important social contract when it comes to libraries. Software libraries, whether they be called gems or packages or jars, are a unique kind of software: their users are software developers, not actual end-users.&lt;/p&gt;

&lt;p&gt;And we software developers are busy. We have work to do. We hate wasting time (when we don’t choose to, that is). &lt;strong&gt;If I have to open up your codebase while working with your software library, then something went wrong while using your software library&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As a library author, you should not expect your users to read your code to understand how to use your code. Instead, you should write thorough and clear documentation. A single blog post isn’t enough, and neither is relying on sparsely written inline documentation.&lt;/p&gt;

&lt;p&gt;In this age of GitHub, your library should be fully documented in a README. Tom Preston-Werner advocates for &lt;a href=&quot;http://tom.preston-werner.com/2010/08/23/readme-driven-development.html&quot;&gt;Readme Driven Development&lt;/a&gt;: write your Readme first, before a single line of code. Every object, method, and parameter that is meant to be available to the users of your library needs to be described. Critically, there should be no ambiguity. If you’re writing inline documentation, feel free to repeat most of it in the Readme. If you practice test-driven development, you can usually copy and paste bits of your test cases into your Readme.&lt;/p&gt;

&lt;p&gt;Beyond the Readme, consider setting up a dedicated website. If your library is sufficiently complex, breaking the documentation down into distinct sections and pages may make more sense. Some projects that practice this are &lt;a href=&quot;http://mongoid.org&quot;&gt;Mongoid&lt;/a&gt;, &lt;a href=&quot;http://datamapper.org&quot;&gt;DataMapper&lt;/a&gt;, and of course, &lt;a href=&quot;http://guides.rubyonrails.org&quot;&gt;Rails&lt;/a&gt;. Though they’re technically command-line tools, both &lt;a href=&quot;http://gembundler.com&quot;&gt;Bundler&lt;/a&gt; and &lt;a href=&quot;http://rvm.beginrescueend.com/&quot;&gt;RVM&lt;/a&gt; have terrific documentation too. &lt;a href=&quot;http://yehudakatz.com&quot;&gt;Yehuda Katz&lt;/a&gt; likes to keep a completely separate repository from the codebase for a documentation site.&lt;/p&gt;

&lt;p&gt;Reading code is sometimes necessary. Maybe a bug or error has occurred, and the stack trace tells you it’s happening from inside the library you’re using. There are at least two possible causes here. You may not be using the library correctly, or there may be an actual bug with the library. Good documentation, along with helpful error messages, would help you avoid the first case. The second case–a genuine bug–is actually the more forgivable mistake by the library author. One never intends to introduce bugs, but one does make the decision to not write documentation.&lt;/p&gt;

&lt;p&gt;To be clear: reading code is an important skill to have. Developers should not be afraid to do it. But if I were asked to choose between two programmers, one who writes good documentation but is awful at reading other people’s code, and another who never writes documentation but is great at reading code, I would favor the first programmer. Being able to read code is good, but writing documentation is better.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>A Rubyist's Guide to the Twitter OAuth Dance</title>
   <link href="http://luigimontanez.com/2010/rubyists-guide-twitter-oauth-dance/"/>
   <updated>2010-09-01T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/rubyists-guide-twitter-oauth-dance/rubyists-guide-twitter-oauth-dance</id>
   <content type="html">&lt;p&gt;Twitter’s &lt;a href=&quot;http://dev.twitter.com/pages/basic_auth_shutdown&quot;&gt;switchover to OAuth&lt;/a&gt; is complete, and developers are realizing what a huge pain in the ass it now is to authorize with the Twitter API. No doubt about it: &lt;a href=&quot;http://dev.twitter.com/pages/auth&quot;&gt;OAuth is complicated&lt;/a&gt;. For developers who just want to quickly work with the Twitter API, the OAuth dance is tedious and complicated. Simple HTTP authentication with a username and password has been replaced with four steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Register a Twitter application, which is an OAuth consumer&lt;/li&gt;
  &lt;li&gt;Use the consumer key and secret to generate a request token and secret&lt;/li&gt;
  &lt;li&gt;Use the request token and secret to generate an access token and secret&lt;/li&gt;
  &lt;li&gt;Use the access token and secret to access the API&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The problem with OAuth 1.x (OAuth 2.0 will solve these shortcomings) is that it’s geared towards the use case of external, user-centric applications. For a developer who wants to write a quick script to access the API, or integrate the API into an existing app, OAuth 1.x is overkill. There’s &lt;a href=&quot;http://dev.twitter.com/doc&quot;&gt;documentation from Twitter&lt;/a&gt; on all of this, but when I tried it out for myself the other night, it was an exercise in frustration, and I found myself following documentation from various places to get it working.&lt;/p&gt;

&lt;h3 id=&quot;registering-the-app&quot;&gt;Registering the App&lt;/h3&gt;

&lt;p&gt;First, register an app, called a consumer in OAuth parlance, at &lt;a href=&quot;http://dev.twitter.com/apps&quot;&gt;dev.twitter.com/apps&lt;/a&gt;. I’m using a single “Utwilities” app for all my one-off uses of the API.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Utwilities.png&quot; alt=&quot;Utwilities&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’m not sure if creating one app for multiple uses violates the &lt;a href=&quot;http://dev.twitter.com/pages/api_terms&quot;&gt;API terms of service&lt;/a&gt;, but I don’t want to go through the ceremony of registering a new consumer every time I want to use the Twitter API.&lt;/p&gt;

&lt;h3 id=&quot;skipping-the-dance&quot;&gt;Skipping the Dance&lt;/h3&gt;

&lt;p&gt;Steps 2 to 4 outlined above are commonly referred to as the OAuth dance, where the consumer app generates a one-time request token that’s then used to generate the user-specific access token. The user-specific access token (and secret) is used in largely the same way as the username/password combination of that now bygone era. The great news is that Twitter lets us skip these steps by automatically generating an access token for the same user that registered the app. You can view your access token and secret in the sidebar of the app page:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/AccessToken.png&quot; alt=&quot;Access Token&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Things get really easy once you have the access token, especially with the &lt;a href=&quot;http://twitter.rubyforge.org/&quot;&gt;Ruby Twitter gem&lt;/a&gt;. As documented, you’ll need to instantiate and authorize an OAuth client, then use that to instantiate a Twitter client.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;twitter&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;Twitter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:OAuth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;consumer token&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;consumer secret&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;authorize_from_access&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;access token&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;access secret&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;Twitter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Tweeting with OAuth access!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;joining-the-dance&quot;&gt;Joining the Dance&lt;/h3&gt;

&lt;p&gt;There will be times, however, when you need to authorize access to the consumer app for a Twitter user that isn’t the app owner. In that case, you’ll need to dance, and this is where things get hairy.&lt;/p&gt;

&lt;p&gt;The important thing to know is that there are currently two ways a user can grant OAuth access. The first, and most popular, method is based on webpage redirects. You’ve gone through this process if you’ve ever authorized a third-party app that uses the Twitter API on your behalf. It’s great for end-users, but I won’t be covering that here.&lt;/p&gt;

&lt;p&gt;The second method is better for developers: granting OAuth access when a web redirect isn’t possible or practical. This is necessary when generating a key as a developer – when the code will only be needing one access token and doesn’t need to support Twitter authorization for end-users. Authorization in this manner requires, believe it or not, a PIN number.&lt;/p&gt;

&lt;p&gt;Using your app’s consumer key and secret, instantiate an OAuth client. Then ask for a request token.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;Twitter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:OAuth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;consumer key&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;consumer secret&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_token&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;request_token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Use the &lt;code&gt;request_token&lt;/code&gt; to visit a URL that gives you back a PIN number:&lt;/p&gt;

&lt;pre&gt;
https://twitter.com/oauth/authorize?oauth_token=REQUEST_TOKEN_HERE&amp;amp;oauth_callback=oob
&lt;/pre&gt;

&lt;p&gt;When you open that URL in your browser, substituting the &lt;code&gt;request_token&lt;/code&gt; appropriately, you’ll be asked to authorize and then will be presented with a PIN. You can now ask for an access token:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;authorize_from_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;THE_PIN_HERE&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Save these to your database or keep in a config file&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;access_token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access_token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;access_secret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access_token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Now you can use the client&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;Twitter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;oauth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Tweeting after generating an OAuth PIN!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;oauth-20&quot;&gt;OAuth 2.0&lt;/h3&gt;

&lt;p&gt;OAuth 2.0 promises a much &lt;a href=&quot;http://intridea.com/2010/4/22/oauth2-gem-just-in-time-for-facebook-graph&quot;&gt;easier workflow&lt;/a&gt;, but Twitter doesn’t support it yet. See Michael Bleigh’s slides from RailsConf for details. For now though, we have to dance.&lt;/p&gt;

&lt;div style=&quot;width:425px&quot; id=&quot;__ss_4475471&quot;&gt;&lt;strong style=&quot;display:block;margin:12px 0 4px&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/mbleigh/the-present-future-of-oauth&quot; title=&quot;The Present Future of OAuth&quot;&gt;The Present Future of OAuth&lt;/a&gt;&lt;/strong&gt;&lt;object id=&quot;__sse4475471&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=presentfutureofoauth-100611091233-phpapp01&amp;amp;rel=0&amp;amp;stripped_title=the-present-future-of-oauth&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot; /&gt;&lt;embed name=&quot;__sse4475471&quot; src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=presentfutureofoauth-100611091233-phpapp01&amp;amp;rel=0&amp;amp;stripped_title=the-present-future-of-oauth&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot; /&gt;&lt;/object&gt;&lt;/div&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>The Computer for the Room</title>
   <link href="http://luigimontanez.com/2010/the-computer-for-the-room/"/>
   <updated>2010-08-23T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/the-computer-for-the-room/the-computer-for-the-room</id>
   <content type="html">&lt;p&gt;The computer on your desk. The computer in your hand. And the computer for the room.&lt;/p&gt;

&lt;p&gt;The definition of the personal computer is expanding. Ever since the first PCs appeared on the market in the 1970’s, computers have been things we put on our desks. Even the laptop, renamed the notebook after too many lawsuits, works best on a desk. We interact with these computers with a keyboard and some sort of pointing device – either a mouse or a trackpad.&lt;/p&gt;

&lt;p&gt;Beyond technical and physical considerations, the definition of a personal computer encompasses several important social constructs. Personal computers are general purpose, not single purpose. They run software that can be installed by the user – though the manufacturer will always pre-install some software. Most importantly, there are few barriers to entry to writing software for that computer. Manufacturers of personal computers actively promote the development of new software for their machines. Recently, having a personal computer has meant the ability to connect to the Internet – specifically the Web.&lt;/p&gt;

&lt;p&gt;And until about 2007, that’s what a computer was: the machine on your desk that ran software, most importantly a web browser. Phones, video game consoles, set-top boxes, and graphing calculators were electronic devices, not computers.&lt;/p&gt;

&lt;p&gt;These days, Apple is routinely excoriated for their App Store policies. But they don’t get enough credit for how much they changed the ecosystem of personal computing in 2007 and 2008 with the iPhone. Apple recognized that the Web democratized software development. Anyone who could afford $10 a month for Dreamhost and learn how to develop on the LAMP stack could create software that ran on every personal computer that was connected to the Internet.&lt;/p&gt;

&lt;p&gt;Through Mobile Safari on that first iPhone in 2007, Apple made the full Web (sans Flash) available on a machine that wasn’t a desktop or notebook computer. Anyone who could program a LAMP application could build software for the iPhone. However, it became clear that the Web in 2007 was not quite there yet in terms of standards and browser technology. So native iPhone development was introduced in 2008. Once again, Apple chose a drastically different path than their predecessors – a path in favor of an ecosystem of software development. For $99 a year, anyone could write software for the iPhone.&lt;/p&gt;

&lt;p&gt;When compared to the wide open Web, or the no-approval-needed Android Market, Apple’s App Store is correctly regarded as a walled-garden. But it’s an easy walled-garden to get into – especially when compared to software development for RIM or Microsoft phones, or for video game consoles or set-top boxes.&lt;/p&gt;

&lt;p&gt;Because of Apple’s moves, the mobile phone industry is no longer about phones. It’s about personal computers that can make phone calls and receive text messages, among many other things. Similarly, the television industry will no longer be about TV shows and movies. It will be about personal computers that deliver television content, among many other things.&lt;/p&gt;

&lt;p&gt;Android and iOS, operating systems designed for the computer in your hand, are making their way to the computer for the room. Google has already announced their &lt;a href=&quot;http://google.com/tv&quot;&gt;Google TV&lt;/a&gt; initiative: Android computers running a full version of the Google Chrome web browser. Watch the &lt;a href=&quot;http://www.youtube.com/googledevelopers#p/p/B09682344C2F233B/0/ASZbArr7vdI&quot;&gt;announcement video from Google I/O&lt;/a&gt; for all you need to know about Google TV. Similarly, Apple will likely rebrand their closed AppleTV device as iTV, with full support for iOS and the Web. Kevin Rose recently blogged about &lt;a href=&quot;http://kevinrose.com/blogg/2010/8/21/why-apples-itv-will-change-everything.html&quot;&gt;how disruptive the iTV will be&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;User interface is a point of contrast when considering the three kinds of computers. The computer on your desk uses a keyboard and mouse (or trackpad), something unlikely to change. As a workstation, nothing beats the one-hundred physical buttons on the keyboard. The computer in your hand uses touch, specifically multitouch gestures like pinch and swipe. Touch has been a revelation because it’s a natural interface. We already interact with the world around us through touch, but we need high school classes dedicated to learning how to type on a keyboard.&lt;/p&gt;

&lt;p&gt;Disappointingly, Google seems to think a wireless keyboard with a trackpad is the way to go for Google TV. The rumor mill is predicting that iPhones and iPads will act as a remote control for the iTV. But there are far more appealing alternatives for the computer for the room. The first is voice. Like touch, it’s a natural interface. Recently, Google launched sophisticated &lt;a href=&quot;http://www.google.com/mobile/voice-actions/&quot;&gt;Android voice actions&lt;/a&gt; that work surprisingly well. The problem with voice commands is that no one wants to use them in public. It looks silly. But in the privacy of a room, voice commands make a lot of sense. Hopefully voice is available on the Google TV platform.&lt;/p&gt;

&lt;p&gt;A third natural interface is gesture and facial recognition: talking with our hands and facial expressions. Here, Microsoft has a huge head start with &lt;a href=&quot;http://en.wikipedia.org/wiki/Kinect&quot;&gt;Kinect for XBox&lt;/a&gt;, and we have yet to see if Google and Apple will develop similar technologies. Moving away from the keyboard and mouse combination and towards natural user interfaces will be key for the widespread adoption of computers for the room.&lt;/p&gt;

&lt;p&gt;Interestingly, the iPad already works both as a computer in your hand and a computer for the room, just as long you can touch it:&lt;/p&gt;

&lt;object width=&quot;560&quot; height=&quot;340&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/vTSDPKktbUk?fs=1&amp;amp;hl=en_US&amp;amp;rel=0&amp;amp;hd=1&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;embed src=&quot;http://www.youtube.com/v/vTSDPKktbUk?fs=1&amp;amp;hl=en_US&amp;amp;rel=0&amp;amp;hd=1&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;560&quot; height=&quot;340&quot; /&gt;&lt;/object&gt;

&lt;p&gt;Admittedly, the phrase “computer for the room” is a bit awkward. It doesn’t have the same flow as “mobile computing” or “desktop computing”. So how about “console computing”?&lt;/p&gt;

&lt;p&gt;The term console is already overloaded, but it may be appropriate in this case. Nintendo and Playstation systems are already referred to as consoles. The stereo and climate system in a car is controlled by the center console. While computer programmers and system administrators think of a command-line interface when they hear the word console, most people think of a console as a device that’s not quite a computer. It won’t be much of a stretch for people to realize that yes, that thing sitting under their TV, is in fact a computer. And having the Apple and Google brand on those consoles will help change our mindset.&lt;/p&gt;

&lt;p&gt;Personal computing for this decade will look very different than what we’ve been used to so far: The computer on your desk. The computer in your hand. And the computer for the room. While the first computers for the room will be geared towards home entertainment, they will evolve into shared computers embedded throughout our lives. They will be in our bathrooms and kitchens, in our office conference rooms and doctors’ waiting rooms. In ten years, we’ll wonder how we ever lived without them.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Ten Ruby Conferences (and Three Camps) in Eight Weeks</title>
   <link href="http://luigimontanez.com/2010/ten-ruby-conferences-and-three-camps-in-eight-weeks/"/>
   <updated>2010-07-19T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/ten-ruby-conferences-and-three-camps-in-eight-weeks/ten-ruby-conferences-and-three-camps-in-eight-weeks</id>
   <content type="html">&lt;p&gt;In a fifty-two day stretch, beginning on Thursday, August 19, and ending on Saturday, October 9, the Ruby community will self-organize in a way that no other technical community has ever done. Ten conferences and three camps will take place, mainly in the US.&lt;/p&gt;

&lt;p&gt;Here’s the list:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Aug. 19-21: &lt;a href=&quot;http://capeco.de/&quot;&gt;CapeCo.de&lt;/a&gt; - Brewster, MA&lt;/li&gt;
  &lt;li&gt;Aug. 21: &lt;a href=&quot;http://www.rsrails.com.br/&quot;&gt;RS on Rails&lt;/a&gt; - Porto Alegre, Brazil&lt;/li&gt;
  &lt;li&gt;Aug. 26-28 &lt;a href=&quot;http://www.lonestarrubyconf.com/&quot;&gt;Lone Star Ruby Conference&lt;/a&gt; - Austin, TX&lt;/li&gt;
  &lt;li&gt;Aug. 27-29: &lt;a href=&quot;http://rubykaigi.org/2010/en&quot;&gt;RubyKaigi&lt;/a&gt; - Tsukuba, Japan&lt;/li&gt;
  &lt;li&gt;Sep. 3-4: &lt;a href=&quot;http://rubyhoedown.com/&quot;&gt;RubyHoedown&lt;/a&gt; - Nashville, TN&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Sep. 9-10: [Ruby&lt;/td&gt;
          &lt;td&gt;Web](http://rubywebconf.org/) - Snowbird Resort, UT&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;Sep. 11: &lt;a href=&quot;http://windycityrails.org/&quot;&gt;Windy City Rails&lt;/a&gt; - Chicago, IL&lt;/li&gt;
  &lt;li&gt;Sep. 17-18: &lt;a href=&quot;http://gogaruco.com/&quot;&gt;Golden Gate Ruby Conference&lt;/a&gt; - San Francisco, CA&lt;/li&gt;
  &lt;li&gt;Sep. 17-19: &lt;a href=&quot;http://rubydcamp.org/&quot;&gt;Ruby DCamp&lt;/a&gt; - Northern Virginia&lt;/li&gt;
  &lt;li&gt;Sep. 25: &lt;a href=&quot;http://sunnyconf.com/&quot;&gt;SunnyConf&lt;/a&gt; - Phoenix, AZ&lt;/li&gt;
  &lt;li&gt;September: &lt;a href=&quot;http://bcardarella.com/spost/757623068/rails-camp-new-england-3&quot;&gt;RailsCamp New England&lt;/a&gt; - Vermont (dates and location TBD)&lt;/li&gt;
  &lt;li&gt;Oct. 1-3: &lt;a href=&quot;http://erubycon.com/&quot;&gt;JRubyConf&lt;/a&gt; - Columbus, OH (replaces erubycon this year)&lt;/li&gt;
  &lt;li&gt;Oct. 6-9: &lt;a href=&quot;http://mountainrb.com/&quot;&gt;Mountain.rb&lt;/a&gt; - Boulder, CO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Credit goes to the organizers of this past weekend’s excellent &lt;a href=&quot;http://rubymidwest.com/upcomingconferences.html&quot;&gt;Ruby Midwest&lt;/a&gt; for compiling most of the list above.&lt;/p&gt;

&lt;p&gt;And that’s not all for the year. Later in October, there’s &lt;a href=&quot;http://www.actsasconference.com/&quot;&gt;Acts As Conference&lt;/a&gt; in Orlando, and of course, &lt;a href=&quot;http://rubyconf.org&quot;&gt;RubyConf&lt;/a&gt; in New Orleans in November. Also, there will be a &lt;a href=&quot;http://railscamps.com/#au_per_nov_2010&quot;&gt;RailsCamp Perth&lt;/a&gt; in Australia from November 12-15. Add to that a smattering of &lt;a href=&quot;http://devnation.us/&quot;&gt;DevNation&lt;/a&gt; events across the country geared towards Rubyists and like-minded developers. For nearly everyone in the US, there will be an event within a drivable distance.&lt;/p&gt;

&lt;h3 id=&quot;the-importance-of-meetup&quot;&gt;The Importance of Meetup&lt;/h3&gt;

&lt;p&gt;So what does all this unprecedented activity mean? Yes, this proves that the Ruby community is stronger than ever, and continues to grow. In most major cities, and in many smaller ones, evening &lt;a href=&quot;http://meetup.com/ruby&quot;&gt;Ruby Meetups&lt;/a&gt; are a common occurrence at least once a month. Rubyists meet, watch a couple of presentations, and have dinner or drinks together. In some places, these monthly meetings have been augmented with lunches, hack nights, or other gatherings. There’s nothing particularly unique to Rubyists about any of this. Meetup.com has been used for this purpose for nearly a decade – providing a service that helps witches, knitters, Tea Party activists, social media consultants, web designers, and software developers to self-organize.&lt;/p&gt;

&lt;p&gt;But what’s striking about the list above is that no other technical community today could pull off thirteen organized events in the span of two months. Ruby developers today are a small subset of software developers. There are many, many more programmers who write Java and C# for a living. There are probably more Pythonistas than Rubyists. But there currently isn’t, nor has there been, a culture of self-organized regional conferences and camps for developers in other languages like there is for Ruby.&lt;/p&gt;

&lt;h3 id=&quot;the-big-shows&quot;&gt;The Big Shows&lt;/h3&gt;

&lt;p&gt;Why has this phenomenon happened in the Ruby community, and nowhere else? Developer conferences are not at all unique to Ruby. Apple’s WWDC, Microsoft’s PDC and Tech:Ed, and Sun’s JavaOne (now Oracle’s OpenWorld) are well-established and heavily-attended. But huge international conferences need huge budgets and big name sponsors, which forces them to be more like trade shows than developer events. It should be noted that there’s only one Ruby conference with a “show floor”, and that’s RailsConf.&lt;/p&gt;

&lt;p&gt;Also, Ruby has never had a large corporation to champion it. No Sun, Microsoft, or Apple to bankroll events. So the build it quickly, think small mindset that attracts many to Ruby is carried over to its community’s conferences. To be fair to Java developers, a group of them did create the &lt;a href=&quot;http://www.nofluffjuststuff.com/home/main&quot;&gt;No Fluff, Just Stuff&lt;/a&gt; series of smaller, regional conferences as a direct response to the trade show nature of the big Java shows. But even those events are driven by central planning, not grassroots enthusiasm.&lt;/p&gt;

&lt;h3 id=&quot;how-about-python&quot;&gt;How about Python?&lt;/h3&gt;

&lt;p&gt;Python, like the other languages, does have its big conferences. There’s &lt;a href=&quot;http://www.pycon.org/&quot;&gt;PyCon&lt;/a&gt; and there’s &lt;a href=&quot;http://djangocon.us/&quot;&gt;DjangoCon&lt;/a&gt;. Similarly, the big conferences in the Ruby world are &lt;a href=&quot;http://rubyconf.org&quot;&gt;RubyConf&lt;/a&gt; and &lt;a href=&quot;http://railsconf.com&quot;&gt;RailsConf&lt;/a&gt;. The Python and Ruby communities share many of the same values and attract similar kinds of developers. Many cities have Python meetups. The biggest tech company out there, Google, loves Python. It’s widely used in academia. But there is no regional Python conference ecosystem.&lt;/p&gt;

&lt;p&gt;While the conception and production of regional Ruby events are organic, they are not without some coordination. Some time in 2006, when Ruby was exploding in popularity thanks to Rails, the wise old sages who had been organizing RubyConf since 2002 made a concerted effort to encourage local Meetup leaders to organize their own conferences. A few took the bait, others then sought to emulate them, and every year since more and more regional conferences have sprung up. The RubyConf organizers, a non-profit called &lt;a href=&quot;http://rubycentral.org&quot;&gt;RubyCentral&lt;/a&gt;, even have a &lt;a href=&quot;http://static.rubycentral.org/Reg_conf_grant_2010.pdf&quot;&gt;grant program&lt;/a&gt; and have set up a &lt;a href=&quot;http://groups.google.com/group/regional-rubyconf-organizers&quot;&gt;mailing list&lt;/a&gt; for would-be regional conference organizers.&lt;/p&gt;

&lt;h3 id=&quot;tying-it-together&quot;&gt;Tying it Together&lt;/h3&gt;

&lt;p&gt;Ten conferences and three camps in the span of eight weeks. Credit for that falls on the Ruby community as a whole, and especially to those brave few who’ve decided that organizing a conference was a good way to spend their free time. But credit also goes to Ruby Central for planting the seeds for self-organized regional conferences.&lt;/p&gt;

&lt;p&gt;Other developer communities should be taking notes. There’s no reason in particular, it seems, for this to not be possible with Javascript, Python, Clojure, Scala, or any other “progressive” language. But it hasn’t happened. The thriving open-source platforms like Ubuntu and Android are hampered by having central authorities in Canonical and Google. Maybe the regional conference phenomenon will always be unique to Ruby.&lt;/p&gt;

&lt;p&gt;How the Ruby community got to this moment is utterly fascinating, at least to me. But beyond the reasons above, there must have been other contributing factors. What have I missed?&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Mouseless Monday #3 - Divvy</title>
   <link href="http://luigimontanez.com/2010/mouseless-monday-3-divvy/"/>
   <updated>2010-06-14T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/mouseless-monday-3-divvy/mouseless-monday-3-divvy</id>
   <content type="html">&lt;p&gt;Window resizing is one of the more inefficient actions in modern desktop operating systems. It’s particularly bad on Mac OS X. That little green button at the top left of every window doesn’t really do anything useful, and dragging to resize requires the user to hone in on that little handle at the window’s bottom right corner.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href=&quot;http://mizage.com/divvy&quot;&gt;Divvy&lt;/a&gt; for Mac OS X, the best window resizer ever created. It’s a mouseless dream. Bringing it up is easy with a quick key combination. Once shortcut keys are set up, resizing a window is a simple keypress. It works in concert with the operating system in an elegant way.&lt;/p&gt;

&lt;p&gt;Go to the Divvy site and watch the &lt;a href=&quot;http://mizage.com/divvy&quot;&gt;See Divvy in Action video&lt;/a&gt; right now. It explains everything you need to know.&lt;/p&gt;

&lt;h3 id=&quot;shortcut-heaven&quot;&gt;Shortcut Heaven&lt;/h3&gt;

&lt;p&gt;By default, the user can resize windows by dragging the desired shape on Divvy’s mock up of the desktop. But keyboard shortcuts are Divvy’s real strength, and they’re completely customizable by the user. To bring up Divvy, I’ve set the key combination to be &lt;code&gt;Ctl+Cmd+Space&lt;/code&gt;, a close analog to the &lt;code&gt;Ctl+Space&lt;/code&gt; combo I use for &lt;a href=&quot;http://www.obdev.at/products/launchbar/index.html&quot;&gt;Launchbar&lt;/a&gt;. My shortcuts for window sizes are:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Divvy1.png&quot; alt=&quot;Divvy 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Divvy2.png&quot; alt=&quot;Divvy 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There’s the fullscreen shortcut and then three complementary pairs: left/right, top/bottom, dominant/sidebar. I use the left/right and top/bottom combinations for coding, and the sidebar shortcut works well for chat and Twitter apps.&lt;/p&gt;

&lt;h3 id=&quot;bryan-liles-on-mouselessness&quot;&gt;Bryan Liles on Mouselessness&lt;/h3&gt;

&lt;p&gt;I participated in &lt;a href=&quot;http://igniterailsconf.com&quot;&gt;Ignite RailsConf&lt;/a&gt; last week, and it was a great time. Bryan Liles gave a talk on going mouseless on the Mac. Video hasn’t been posted yet, but his &lt;a href=&quot;http://www.scribd.com/doc/32745064/Bryanl-Ignite-Railsconf&quot;&gt;slides&lt;/a&gt; share some great resources.&lt;/p&gt;

&lt;p&gt;A few months back, Bryan recorded a detailed screencast and wrote a blog post about his &lt;a href=&quot;http://smartic.us/2010/02/04/using-your-mac-without-the-mouse/&quot;&gt;mouseless techniques&lt;/a&gt;:&lt;/p&gt;

&lt;object width=&quot;600&quot; height=&quot;338&quot;&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;movie&quot; value=&quot;http://vimeo.com/moogaloop.swf?clip_id=9196815&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; /&gt;&lt;embed src=&quot;http://vimeo.com/moogaloop.swf?clip_id=9196815&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; allowscriptaccess=&quot;always&quot; width=&quot;600&quot; height=&quot;338&quot; /&gt;&lt;/object&gt;

&lt;p&gt;Bryan’s presentation style is certainly one of a kind. To catch everything, I suggest referring back to his blog post and taking notes on points to explore as you watch the video.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>How We Use MongoDB at Sunlight</title>
   <link href="http://luigimontanez.com/2010/how-we-use-mongodb-at-sunlight/"/>
   <updated>2010-05-28T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/how-we-use-mongodb-at-sunlight/how-we-use-mongodb-at-sunlight</id>
   <content type="html">&lt;p&gt;&lt;em&gt;This post originally appeared on the &lt;a href=&quot;http://sunlightlabs.com/blog/2010/how-we-use-mongodb-sunlight/&quot;&gt;Sunlight Labs blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last week, &lt;a href=&quot;http://sunlightlabs.com/people/david&quot;&gt;David&lt;/a&gt; and I attended &lt;a href=&quot;http://www.10gen.com/event_mongony_10may21&quot;&gt;MongoNYC&lt;/a&gt;, a one-day conference focused on &lt;a href=&quot;http://mongodb.org&quot;&gt;MongoDB&lt;/a&gt;. We like Mongo here at Sunlight. We like it a lot. &lt;/p&gt;

&lt;p&gt;Working with Mongo, it’s become clear that it’s a more natural way to store data. We primarily use Python and Ruby, and because Mongo allows us to think in JSON, everything tends to just click. JSON documents are close enough to objects in Python and Ruby that mapping between application and database becomes almost effortless. Mongo has really shined in two specific use cases: as a datastore for a resource oriented web service, and as a datastore for results from scraping a web site.&lt;/p&gt;

&lt;h3 id=&quot;powering-a-resource-oriented-json-api&quot;&gt;Powering a Resource Oriented JSON API&lt;/h3&gt;

&lt;p&gt;We currently have two APIs powered by Mongo, and we’ve blogged about both recently: the &lt;a href=&quot;http://sunlightlabs.com/blog/2010/national-data-catalog-api/&quot;&gt;National Data Catalog&lt;/a&gt; API and &lt;a href=&quot;http://sunlightlabs.com/blog/2010/drumbone-api/&quot;&gt;Drumbone&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A great thing about Mongo is that it allows you to store data as you’d naturally want work with it, particularly through the use of &lt;a href=&quot;http://www.mongodb.org/display/DOCS/Updating+Data+in+Mongo#UpdatingDatainMongo-EmbeddingDocumentsDirectlyinDocuments&quot;&gt;Embedded Documents&lt;/a&gt;. Looking at an &lt;a href=&quot;http://nationaldatacatalog.com/data/worldwide-m1-earthquakes-past-day&quot;&gt;example entry&lt;/a&gt; on the National Data Catalog, it’s easy to determine the Mongo document schema just by looking at the page design. We have a single document representing the earthquake data source, and it has fields that represent the title, homepage, and documentation URL. Embedded in the document are collections representing the downloads, ratings, and comments made for this entry. There’s no need to think about tables and joins – a catalog entry can be thought of as a JSON document.&lt;/p&gt;

&lt;p&gt;It’s easy to create a resource oriented web service with a framework like Sinatra, but for the National Data Catalog, David wrote a framework called &lt;a href=&quot;http://github.com/djsun/sinatra_resource&quot;&gt;sinatra_resource&lt;/a&gt;, that provides a nice DSL for exposing Mongo documents as resources.&lt;/p&gt;

&lt;p&gt;For the Drumbone API, Eric exposed Mongo’s ability to &lt;a href=&quot;http://www.mongodb.org/display/DOCS/Dot+Notation+(Reaching+into+Objects)&quot;&gt;reach deep into embedded documents&lt;/a&gt; with dot notation through the query string. So, let’s say you want to grab only two of the fields from the earmarks sub-object:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// ?sections=last_name,first_name,state,earmarks&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;legislator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Lee&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CA&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Barbara&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;earmarks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;average_number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;total_amount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;average_amount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;22994535&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;total_number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;last_updated&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2010-03-18&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;fiscal_year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2010&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You would modify the parameter string to use dot notation like so:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// ?sections=last_name,first_name,state,earmarks.total_amount,earmarks.total_number&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;legislator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;last_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Lee&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CA&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Barbara&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;earmarks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;total_amount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;total_number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The ability to ask for partial responses from an API is a huge win when it comes to speed and efficiency, and Mongo makes supporting it dead simple.&lt;/p&gt;

&lt;h3 id=&quot;storing-results-from-parsing-and-scraping&quot;&gt;Storing Results from Parsing and Scraping&lt;/h3&gt;

&lt;p&gt;Not coincidentally, both the National Data Catalog and Drumbone aggregate lots of data from disparate sources. For the National Data Catalog, we scrape other catalogs like &lt;a href=&quot;http://data.gov&quot;&gt;data.gov&lt;/a&gt; and the &lt;a href=&quot;http://data.octo.dc.gov/&quot;&gt;DC Data Catalog&lt;/a&gt; to create our central catalog. Drumbone uses API data from &lt;a href=&quot;http://govtrack.us&quot;&gt;GovTrack&lt;/a&gt;, &lt;a href=&quot;http://transparencydata.com&quot;&gt;TransparencyData&lt;/a&gt;, and &lt;a href=&quot;http://usaspending.gov&quot;&gt;USASpending.gov&lt;/a&gt;, among others.&lt;/p&gt;

&lt;p&gt;Using a relational database to store data from different sources with divergent schemas usually means creating a lot of small, single-purpose tables, or creating one generic key/value table. With Mongo, schema isn’t enforced on the data level, making parsing and scraping much less tedious when it comes to data storage.&lt;/p&gt;

&lt;p&gt;We’re converting the &lt;a href=&quot;http://sunlightlabs.com/blog/2010/fifty-state-project-redux/&quot;&gt;Fifty State Project&lt;/a&gt; to MongoDB. We’re scraping the legislative web sites for all fifty states, and while we have a baseline schema for legislators, bills, and votes, we also want to preserve all valuable but unique data that a given state may provide.&lt;/p&gt;

&lt;h3 id=&quot;lightning-talk&quot;&gt;Lightning Talk&lt;/h3&gt;

&lt;p&gt;Here’s video of a lightning talk I gave at MongoNYC, with the slide deck below it. I go over what we do at Sunlight, and how we use MongoDB in our projects. Please excuse the sound quality, as I was not wearing a microphone and the walls to the room were thin, so at some points you can hear the session next door in the background.&lt;/p&gt;

&lt;embed src=&quot;http://blip.tv/play/AYHh52oC&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;480&quot; height=&quot;350&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; /&gt;
&lt;p&gt;&amp;lt;/embed&amp;gt;&lt;/p&gt;

&lt;div style=&quot;width:425px&quot; id=&quot;__ss_4206620&quot;&gt;&lt;strong style=&quot;display:block;margin:12px 0 4px&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/luigimontanez/civic-hacking-mongonyc&quot; title=&quot;Civic Hacking @ MongoNYC&quot;&gt;Civic Hacking @ MongoNYC&lt;/a&gt;&lt;/strong&gt;&lt;object id=&quot;__sse4206620&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=mongonyc-100521150000-phpapp02&amp;amp;stripped_title=civic-hacking-mongonyc&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot; /&gt;&lt;embed name=&quot;__sse4206620&quot; src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=mongonyc-100521150000-phpapp02&amp;amp;stripped_title=civic-hacking-mongonyc&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot; /&gt;&lt;/object&gt;&lt;/div&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Stop Using the text-indent:-9999px CSS Trick</title>
   <link href="http://luigimontanez.com/2010/stop-using-text-indent-css-trick/"/>
   <updated>2010-05-25T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/stop-using-text-indent-css-trick/stop-using-text-indent-css-trick</id>
   <content type="html">&lt;p&gt;The usage of &lt;code&gt;text-indent:-9999px&lt;/code&gt; to display a site logo or other image while hiding text should be avoided. It’s a technique used by web spammers trying to game search engines like Google, and is considered spammy behavior. Instead, use an &lt;code&gt;&amp;lt;image&amp;gt;&lt;/code&gt; tag and put the text inside its &lt;code&gt;alt&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;At &lt;a href=&quot;http://transparencycamp.org&quot;&gt;TransparencyCamp&lt;/a&gt; two months ago, I attended an excellent session on Searchability by &lt;a href=&quot;http://ninebyblue.com&quot;&gt;Vanessa Fox&lt;/a&gt;. This spurred me to dive deeper into the topic. I concluded that Googleability matters, and it matters a lot. But when you hear the term SEO, your BS detector probably goes off, and justifiably so. It’s unfortunate that the so-called SEO experts, modern day snake oil salesmen, have ruined the field’s reputation. But for web developers, being aware and proactive about searchability is incredibly important. Building sites with searchability and accessibility in mind is just as important as practicing test-driven development and keeping code DRY.&lt;/p&gt;

&lt;p&gt;One thing that stuck out in my mind during Vanessa’s talk was her recommendation to avoid using the &lt;code&gt;text-indent:-9999px&lt;/code&gt; CSS trick when implementing things like logos as a page header. So the HTML is semantic:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;&amp;lt;a href=&quot;/&quot;&amp;gt;My Site Title&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While the CSS pushes the text far off the page and replaces it with a logo:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;h1 a {
  background: url(logo.png) no-repeat left top;
  text-indent: -9999px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is widely considered a &lt;a href=&quot;http://aext.net/2010/02/css-text-indent-style-your-html-form/&quot;&gt;best practice&lt;/a&gt;, because users will see your site logo, while search engines see the text contained in the &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; tags. But the reality is that this technique is also used by spammers to game search engines.&lt;/p&gt;

&lt;p&gt;Bottom line: Don’t try to trick Google. You can’t.&lt;/p&gt;

&lt;p&gt;This particular issue was discussed further on a podcast called &lt;a href=&quot;http://www2.webmasterradio.fm/office-hours/2010/rich-snippets-to-google-search-results/&quot;&gt;Webmaster Radio Office Hours&lt;/a&gt;, with Google Senior Developer Programs Engineer &lt;a href=&quot;http://maileohye.com/&quot;&gt;Maile Ohye&lt;/a&gt;. In the discussion, which starts about 4 minutes into the podcast, Vanessa and Maile discuss Google’s view on the technique. In summary, here’s what Maile said:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When you make things accessible for screen readers and people you also do it for search engines. It’s the fundamental first step in site development.&lt;/li&gt;
  &lt;li&gt;There’s a lot you can do that don’t involve what are traditionally spammy techniques like text-indent:-9999px, which has been used to hide text and links in the past by spammers, because they thought only search engines would read it and users wouldn’t know. So they used that to boost their rankings. So it’s kind of gotten a bad rep from our standpoint, and we see it more as a spam technique than we do an accessibility technique.&lt;/li&gt;
  &lt;li&gt;Instead, use the &lt;code&gt;alt&lt;/code&gt; attribute. Or, put text around the image and have descriptive headings and captions for it.&lt;/li&gt;
  &lt;li&gt;text-indent:-9999px is really a band-aid solution. You kind of cross into a black-hat/spam technique with it.&lt;/li&gt;
  &lt;li&gt;Don’t take the risk, you don’t want to be accidentally classified as spam.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, this is what good markup would look like, without any need for CSS tricks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;&amp;lt;a href=&quot;/&quot;&amp;gt;&amp;lt;img src=&quot;logo.png&quot; alt=&quot;My Site Title&quot; /&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Google understands the &lt;code&gt;alt&lt;/code&gt; attribute, and will not punish you for using it.&lt;/p&gt;

&lt;p&gt;If searchability is something that interests you, subscribe to the &lt;a href=&quot;http://googlewebmastercentral.blogspot.com/&quot;&gt;Google Webmaster Central Blog&lt;/a&gt;, where Maile regularly posts. Vanessa has also penned a new book, &lt;a href=&quot;http://www.amazon.com/Marketing-Age-Google-Strategy-Business/dp/0470537191&quot;&gt;Marketing in the Age of Google&lt;/a&gt;, that contains a great chapter on searchability principles and practices for web developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ADDENDUM&lt;/strong&gt;: Incredibly, Maile has &lt;a href=&quot;http://maileohye.com/html-text-indent-not-messing-up-your-rankings/&quot;&gt;published a blog post&lt;/a&gt; on this exact topic right as I’m set to publish it. So read her take, and become a true believer.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Grassroots Fundraising for Open Source Software</title>
   <link href="http://luigimontanez.com/2010/grassroots-fundraising-open-source-software/"/>
   <updated>2010-05-21T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/grassroots-fundraising-open-source-software/grassroots-fundraising-open-source-software</id>
   <content type="html">&lt;p&gt;&lt;em&gt;This originally appeared on the &lt;a href=&quot;http://sunlightlabs.com/blog/2010/grassroots-fundraising-open-source-software/&quot;&gt;Sunlight Labs&lt;/a&gt; blog.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By now, you’ve heard of &lt;a href=&quot;http://www.joindiaspora.com/&quot;&gt;Diaspora&lt;/a&gt;, the &lt;a href=&quot;http://www.kickstarter.com/projects/196017994/diaspora-the-personally-controlled-do-it-all-distr&quot;&gt;Kickstarter&lt;/a&gt;-funded effort to build an open, privacy-minded alternative to Facebook. In recent weeks, helped by a widely-circulated &lt;a href=&quot;http://www.nytimes.com/2010/05/12/nyregion/12about.html&quot;&gt;New York Times article&lt;/a&gt;, the project has raised $180,000 from 5,500 backers. Considering that the project, while &lt;a href=&quot;http://www.joindiaspora.com/2010/04/30/a-response-to-mr-villa.html&quot;&gt;well-thought out&lt;/a&gt; by four undergrads at NYU, has not produced a single line of code, these figures are surprising to say the least. But hoping for the best, assuming that this project does deliver something tangible and useful at the end of the summer, it would inform a workable funding model for open source software projects.&lt;/p&gt;

&lt;h3 id=&quot;righting-a-wrong&quot;&gt;Righting a Wrong&lt;/h3&gt;

&lt;p&gt;Since 2003, Internet-based grassroots fundraising has had a major effect on presidential campaigns. Think of Howard Dean with his bat, Obama’s record-breaking numbers, and the moneybombs of Ron Paul. Surely, donors to those campaigns knew that their contributions would provide a direct benefit to their preferred candidate. But beyond that, donors felt their money would help the nation as a whole. They were donating for a greater purpose – something beyond their own self-interests and the interests of the candidate trying to win an election. They were convinced that the country was off course, and giving money to their favored candidate would right the ship.&lt;/p&gt;

&lt;p&gt;In that light, maybe the wave of money donated to Diaspora isn’t so surprising. The recent negative attention Facebook has received around privacy and information sharing have left many disenchanted. Some have even gone so far as to delete their accounts. So, when Diaspora comes onto the scene as a direct antidote for those who feel icky about Facebook, people respond. In what may a bit of unintentional brilliance, Diaspora’s Kickstarter Pitch tosses around what are effectively code words in &lt;a href=&quot;http://www.joindiaspora.com/2010/04/27/kickstarter-pitch.html&quot;&gt;“GPG” and “AGPL”&lt;/a&gt;; dog-whistle politicking at its finest.&lt;/p&gt;

&lt;p&gt;In the Ruby world, a similar situation occurred in March, after it was announced that Ruby on Rails would not be a Google Summer of Code project. In fact, no Ruby projects were chosen, in stark contrast with previous years. Many felt that Ruby was being slighted. Within a week, the community rallied around it’s own project, &lt;a href=&quot;http://rubysoc.org&quot;&gt;Ruby Summer of Code&lt;/a&gt;(RubySoC), and raised $100,000 to fund 20 distinct open source Ruby projects over the summer.&lt;/p&gt;

&lt;p&gt;What’s interesting about RubySoC is how the money was raised, because it mirrors political fundraising to an extent. A dozen companies donated the “maximum” of $5,000 to fund a full project, while eleven more chipped in $2,500 to fund half a project. Together, twenty-three companies accounted for $87,500 of the $100,000 the project needed. About 150 more individual contributors (yours truly included) donated the rest, at varying amounts.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.kickstarter.com/projects/196017994/diaspora-the-personally-controlled-do-it-all-distr&quot;&gt;Diaspora contribution page&lt;/a&gt; is a bit more opaque when it comes to exact amounts, but does give a good sense of donation levels. About 4,000 of the 5,000 donors so far have given less than $50, with four donors giving $2,000 or more. The average donation amount to Diaspora is $35, which is the same average donation amount for a presidential campaign. Stretching the campaign analogy further, the Diaspora funding was that of a grassroots model, while RubySoC employed “high-dollar” fundraising from two dozen companies to achieve its goal.&lt;/p&gt;

&lt;p&gt;So a fundraising model can look like this: Identify a serious problem within a community, propose a solution to rectify it, and then target the right audience to fund it. Ruby open source developers, a community numbering in the thousands, could not raise $100,000 from individuals alone. Ruby-centric companies needed to chip in a large share. On the other hand, Diaspora’s community of disenchanted Facebook users is much higher, potentially in the millions. Thus, a large number of donations in relatively small amounts of $35 can be expected.&lt;/p&gt;

&lt;h3 id=&quot;its-all-about-execution&quot;&gt;It’s All About Execution&lt;/h3&gt;

&lt;p&gt;Jaw-dropping fundraising, of course, does not guarantee ultimate success. Just ask Howard Dean and Ron Paul. For half a decade now, Google Summer of Code has employed a model that’s been effective: Provide funding for students to write code for well-established open source projects. Ruby Summer of Code follows the same path, and should be expected to yield similarly fruitful results. For example, it’s expected that by the end of the summer, &lt;a href=&quot;http://ruboto.com&quot;&gt;Ruby on Android&lt;/a&gt; will be a viable development platform. All individuals and companies who funded RubySoC knew exactly what they were getting.&lt;/p&gt;

&lt;p&gt;But Diaspora is a big fat question mark when it comes to execution. Can four college students really build a viable alternative to Facebook? Will the wishes and desires of Diaspora’s donors be fulfilled by the end-product? It seems just as easy to be overly pessimistic about the project as it is to be overly optimistic about it.&lt;/p&gt;

&lt;h3 id=&quot;funding-strategies&quot;&gt;Funding Strategies&lt;/h3&gt;

&lt;p&gt;Running fundraising campaigns isn’t the only way to fund open source software. Up to this point in Sunlight’s history, fundraising has been done primarily through &lt;a href=&quot;http://sunlightfoundation.com/funding/&quot;&gt;very large grants&lt;/a&gt;. Alternatively, figuring how to make the software pay for itself is another option. The Mozilla Foundation best exemplifies this, receiving over $50 million a year from its &lt;a href=&quot;http://en.wikipedia.org/wiki/Mozilla_Foundation#Financing&quot;&gt;search agreement with Google&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What are other means of funding open source software? If Sunlight Labs were to seriously launch a fundraising campaign, what should that look like?&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Fourteen Android Phones in the US since the iPhone 3GS</title>
   <link href="http://luigimontanez.com/2010/fourteen-android-phones-since-iphone-3gs/"/>
   <updated>2010-05-10T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/fourteen-android-phones-since-iphone-3gs/fourteen-android-phones-since-iphone-3gs</id>
   <content type="html">&lt;p&gt;On June 19, 2009, the iPhone 3GS went on sale. On that day, nearly 11 months ago, the Android platform was full of potential, but light on delivery. Only one Android phone was available on the US market – the T-Mobile G1. But on the one-year anniversary of the iPhone 3GS release, we’ll have seen fourteen Android phones hit the US market. The effect of this steady drumbeat of Android phone releases, averaging just over one per month, cannot be overstated. And next month’s announcement of the new iPhone 4 (or maybe “HD”), will do little to stop the Android platform’s momentum.&lt;/p&gt;

&lt;p&gt;Here’s a detailed looked at the US phones released since the iPhone 3GS, courtesy of &lt;a href=&quot;http://en.wikipedia.org/wiki/List_of_Android_devices&quot;&gt;Wikipedia&lt;/a&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Released&lt;/th&gt;
    &lt;th&gt;Carrier&lt;/th&gt;
    &lt;th&gt;Manufacturer&lt;/th&gt; 
    &lt;th&gt;Name&lt;/th&gt;
    &lt;th&gt;UI&lt;/th&gt;
    &lt;th&gt;Screen&lt;/th&gt;
    &lt;th&gt;OS&lt;/th&gt;
    &lt;th&gt;OS Upgrade?&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;July 2009&lt;/td&gt;
    &lt;td&gt;T-Mobile&lt;/td&gt;
    &lt;td&gt;HTC&lt;/td&gt;
    &lt;td&gt;myTouch 3G&lt;/td&gt;
    &lt;td&gt;Google Experience&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.6&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;http://androidandme.com/2010/01/phones/t-mobile-mytouch-3g-users-to-get-android-2-1-this-spring/&quot;&gt;Rumored to 2.1&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;July 2009&lt;/td&gt;
    &lt;td&gt;Sprint&lt;/td&gt;
    &lt;td&gt;Samsung&lt;/td&gt;
    &lt;td&gt;Galaxy&lt;/td&gt;
    &lt;td&gt;Google Experience&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;Despite a &lt;a href=&quot;http://www.petitionspot.com/petitions/samsunggalaxy&quot;&gt;petition&lt;/a&gt;, no.&lt;/td&gt;
  &lt;/tr&gt; 
  &lt;tr&gt;
    &lt;td&gt;October 2009&lt;/td&gt;
    &lt;td&gt;Sprint&lt;/td&gt;
    &lt;td&gt;HTC&lt;/td&gt;
    &lt;td&gt;Hero&lt;/td&gt;
    &lt;td&gt;Sense&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;http://phandroid.com/2010/04/16/htc-hero-samsung-moment-2-1-update-now-coming-early-may/&quot;&gt;2.1&lt;/a&gt; by May 2010&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;October 2009&lt;/td&gt;
    &lt;td&gt;Sprint&lt;/td&gt;
    &lt;td&gt;Samsung&lt;/td&gt;
    &lt;td&gt;Moment&lt;/td&gt;
    &lt;td&gt;Google Experience&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;http://phandroid.com/2010/04/16/htc-hero-samsung-moment-2-1-update-now-coming-early-may/&quot;&gt;2.1&lt;/a&gt; by May 2010&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;November 2009&lt;/td&gt;
    &lt;td&gt;T-Mobile&lt;/td&gt;
    &lt;td&gt;Motorola&lt;/td&gt;
    &lt;td&gt;CLIQ&lt;/td&gt;
    &lt;td&gt;MotoBlur&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;https://supportforums.motorola.com/community/manager/softwareupgrades?view=overview&quot;&gt;2.1&lt;/a&gt; by June 2010&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;November 2009&lt;/td&gt;
    &lt;td&gt;Verizon&lt;/td&gt;
    &lt;td&gt;HTC&lt;/td&gt;
    &lt;td&gt;DROID Eris&lt;/td&gt;
    &lt;td&gt;Sense&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;http://support.vzw.com/information/droid_eris_upgrade.html&quot;&gt;2.1&lt;/a&gt; by May 2010&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;November 2009&lt;/td&gt;
    &lt;td&gt;Verizon&lt;/td&gt;
    &lt;td&gt;Motorola&lt;/td&gt;
    &lt;td&gt;DROID&lt;/td&gt;
    &lt;td&gt;Google Experience&lt;/td&gt;
    &lt;td&gt;3.7&quot;&lt;/td&gt;
    &lt;td&gt;2.0&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;https://supportforums.motorola.com/community/manager/softwareupgrades?view=overview&quot;&gt;2.1&lt;/a&gt; in April 2010&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;November 2009&lt;/td&gt;
    &lt;td&gt;T-Mobile&lt;/td&gt;
    &lt;td&gt;Samsung&lt;/td&gt;
    &lt;td&gt;Behold II&lt;/td&gt;
    &lt;td&gt;TouchWiz&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;None planned.&lt;/td&gt;
  &lt;/tr&gt;  
  &lt;tr&gt;
    &lt;td&gt;January 2010&lt;/td&gt;
    &lt;td&gt;T-Mobile&lt;/td&gt;
    &lt;td&gt;Google/HTC&lt;/td&gt;
    &lt;td&gt;Nexus One&lt;/td&gt;
    &lt;td&gt;Google Experience&lt;/td&gt;
    &lt;td&gt;3.7&quot;&lt;/td&gt;
    &lt;td&gt;2.1&lt;/td&gt;
    &lt;td&gt;--&lt;/td&gt;
  &lt;/tr&gt; 
  &lt;tr&gt;
    &lt;td&gt;March 2010&lt;/td&gt;
    &lt;td&gt;AT&amp;amp;T&lt;/td&gt;
    &lt;td&gt;Motorola&lt;/td&gt;
    &lt;td&gt;Backflip&lt;/td&gt;
    &lt;td&gt;MotoBlur&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;https://supportforums.motorola.com/community/manager/softwareupgrades?view=overview&quot;&gt;2.1&lt;/a&gt; by Q3 2010&lt;/td&gt;
  &lt;/tr&gt; 
  &lt;tr&gt;
    &lt;td&gt;March 2010&lt;/td&gt;
    &lt;td&gt;AT&amp;amp;T&lt;/td&gt;
    &lt;td&gt;Google/HTC&lt;/td&gt;
    &lt;td&gt;Nexus One&lt;/td&gt;
    &lt;td&gt;Google Experience&lt;/td&gt;
    &lt;td&gt;3.7&quot;&lt;/td&gt;
    &lt;td&gt;2.1&lt;/td&gt;
    &lt;td&gt;--&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;March 2010&lt;/td&gt;
    &lt;td&gt;T-Mobile&lt;/td&gt;
    &lt;td&gt;Motorola&lt;/td&gt;
    &lt;td&gt;CLIQ XT&lt;/td&gt;
    &lt;td&gt;MotoBlur&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;https://supportforums.motorola.com/community/manager/softwareupgrades?view=overview&quot;&gt;2.1&lt;/a&gt; by June 2010&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;March 2010&lt;/td&gt;
    &lt;td&gt;Verizon&lt;/td&gt;
    &lt;td&gt;Motorola&lt;/td&gt;
    &lt;td&gt;Devour&lt;/td&gt;
    &lt;td&gt;MotoBlur&lt;/td&gt;
    &lt;td&gt;3.2&quot;&lt;/td&gt;
    &lt;td&gt;1.5&lt;/td&gt;
    &lt;td&gt;&lt;a href=&quot;https://supportforums.motorola.com/community/manager/softwareupgrades?view=overview&quot;&gt;Under evaluation&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;  
  &lt;tr&gt;
    &lt;td&gt;April 2010&lt;/td&gt;
    &lt;td&gt;Verizon&lt;/td&gt;
    &lt;td&gt;HTC&lt;/td&gt;
    &lt;td&gt;DROID Incredible&lt;/td&gt;
    &lt;td&gt;Sense&lt;/td&gt;
    &lt;td&gt;3.7&quot;&lt;/td&gt;
    &lt;td&gt;2.1&lt;/td&gt;
    &lt;td&gt;--&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;June 2010&lt;/td&gt;
    &lt;td&gt;T-Mobile&lt;/td&gt;
    &lt;td&gt;HTC&lt;/td&gt;
    &lt;td&gt;myTouch 3G Slide&lt;/td&gt;
    &lt;td&gt;Sense&lt;/td&gt;
    &lt;td&gt;3.4&quot;&lt;/td&gt;
    &lt;td&gt;2.1&lt;/td&gt;
    &lt;td&gt;--&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Some observations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Not double-counting the Nexus One on T-Mobile and AT&amp;amp;T, that makes for thirteen phones that have been released since the iPhone 3GS launch, and one, the T-Mobile &lt;a href=&quot;http://www.engadget.com/2010/05/04/t-mobile-mytouch-3g-slide-official-android-2-1-qwerty-coming/&quot;&gt;myTouch 3G Slide&lt;/a&gt;, that has been given a June release date.&lt;/li&gt;
  &lt;li&gt;There’s an even mix of mid-level and high-end offerings.&lt;/li&gt;
  &lt;li&gt;AT&amp;amp;T has only released one Android phone, the Motorola Backflip, and it’s not very good. The AT&amp;amp;T Nexus One, sold exclusively by Google, isn’t even available subsidized with a contract.&lt;/li&gt;
  &lt;li&gt;The Motorola Devour is the only Verizon Android phone not using the DROID branding.&lt;/li&gt;
  &lt;li&gt;The vast majority of phones either shipped with or are scheduled to be upgraded to 2.1, but only the Verizon DROID has received the 2.1 upgrade as of today.&lt;/li&gt;
  &lt;li&gt;The 2.1 upgrade is important because a &lt;a href=&quot;http://developer.android.com/resources/dashboard/platform-versions.html&quot;&gt;plurality&lt;/a&gt; of Android phones are still on 1.5. Those 1.5 phones are likely to be either a Sprint Hero or a DROID Eris, which will both see an upgrade in the coming days. When that happens, up to two-thirds of Android phones could be at 2.1.&lt;/li&gt;
  &lt;li&gt;It looks like the early adopters who got a T-Mobile G1 and those few souls who got the lesser Samsung models are SOL when it comes to Android 2.1.&lt;/li&gt;
  &lt;li&gt;The iPhone 3GS sports a 3.5” display. It might be argued that only the Android phones with larger (and higher resolution) displays truly compete with the iPhone 3GS. Most have a smaller 3.2” display.&lt;/li&gt;
  &lt;li&gt;The table above ignores all the &lt;a href=&quot;http://en.wikipedia.org/wiki/List_of_Android_devices&quot;&gt;international phones and other devices&lt;/a&gt; that have been released, as well as &lt;a href=&quot;http://en.wikipedia.org/wiki/List_of_Android_devices#Future&quot;&gt;upcoming efforts&lt;/a&gt; like the Sprint EVO and Dell phones.&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;http://sprint.com/evo&quot;&gt;Sprint EVO&lt;/a&gt; in particular has the potential to be an iPhone 4 killer, even before the iPhone 4 has been officially announced.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Mouseless Monday #2 - Keyboard-Friendly Web Apps</title>
   <link href="http://luigimontanez.com/2010/mouseless-monday-2-keyboard-friendly-web-apps/"/>
   <updated>2010-04-26T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/mouseless-monday-2-keyboard-friendly-web-apps/mouseless-monday-2-keyboard-friendly-web-apps</id>
   <content type="html">&lt;p&gt;Last time for Mouseless Monday, I reviewed the wonders of &lt;a href=&quot;http://luigimontanez.com/2010/mouseless-monday-1-vimium-google-chrome/&quot;&gt;Google Chrome and Vimium&lt;/a&gt;. Vimium is great for bringing keyboard shortcuts to the Web, but it’s a general tool. What if, like on the desktop, we could have site-specific keyboard support? There’s no extension that supports this yet (it would require quite a bit of custom scripting), but the good news is that several popular web apps do natively support keyboard shortcuts.&lt;/p&gt;

&lt;p&gt;For all of these apps, hit the question mark (&lt;code&gt;?&lt;/code&gt; a.k.a. &lt;code&gt;shift+/&lt;/code&gt;) to bring up an explanatory overlay, much like Vimium.&lt;/p&gt;

&lt;h3 id=&quot;gmail&quot;&gt;Gmail&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://gmail.com&quot;&gt;Gmail&lt;/a&gt; was probably the first widely used web app to support keyboard shortcuts, and set the standard for others to follow. Like Vimium, the key bindings are Vim-esque.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Gmail%20Shortcuts.png&quot; alt=&quot;Gmail Shortcuts&quot; width=&quot;600px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For this and other Google products, keyboard shortcuts need to be enabled in the Settings.&lt;/p&gt;

&lt;h3 id=&quot;google-reader&quot;&gt;Google Reader&lt;/h3&gt;

&lt;p&gt;Google’s &lt;a href=&quot;http://google.com/reader&quot;&gt;feed reader&lt;/a&gt; closely followed suit, with many of the same bindings, but added some subtlety with the Shift key:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Google%20Reader%20Shortcuts.png&quot; alt=&quot;Google Reader Shortcuts&quot; width=&quot;600px&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;google-calendar&quot;&gt;Google Calendar&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://google.com/calendar&quot;&gt;Google Calendar&lt;/a&gt; has a very succinct set of shortcuts, but navigation works surprisingly well. However, I have not been able to figure out how to navigate to and edit a single event.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Google%20Calendar.png&quot; alt=&quot;Google Calendar&quot; width=&quot;600px&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;pivotal-tracker&quot;&gt;Pivotal Tracker&lt;/h3&gt;

&lt;p&gt;Moving away from the Google products, I use &lt;a href=&quot;http://pivotaltracker.com&quot;&gt;Pivotal Tracker&lt;/a&gt; to manage agile software projects. The shortcuts are a bit simple, like Google Calendar, so I still find myself using the mouse quite often.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Pivotal%20Tracker.png&quot; alt=&quot;Pivotal Tracker&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;github-issue-tracker&quot;&gt;GitHub Issue Tracker&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;’s issue tracker is also great for managing software projects. Anyone familiar with Gmail’s shortcuts will find the interface familiar.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/GitHub%20Issue%20Tracker.png&quot; alt=&quot;GitHub Issue Tracker&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;excluding-urls-in-vimium&quot;&gt;Excluding URLs in Vimium&lt;/h3&gt;

&lt;p&gt;To take advantage of these keyboard-friendly web apps, you’ll need to exclude their URLs in Vimium Settings from &lt;code&gt;chrome://extensions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Vimium%20Excluded%20URLs.png&quot; alt=&quot;Vimium Excluded URLs&quot; width=&quot;600px&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;rolling-your-own&quot;&gt;Rolling Your Own&lt;/h3&gt;

&lt;p&gt;If you’re a web developer looking to incorporate keyboard shortcuts in your own apps, consider using the &lt;a href=&quot;http://github.com/tzuryby/jquery.hotkeys&quot;&gt;jQuery Hotkeys&lt;/a&gt; plugin.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Mouseless Monday #1 - Vimium on Google Chrome</title>
   <link href="http://luigimontanez.com/2010/mouseless-monday-1-vimium-google-chrome/"/>
   <updated>2010-04-12T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/mouseless-monday-1-vimium-google-chrome/mouseless-monday-1-vimium-google-chrome</id>
   <content type="html">&lt;p&gt;Over the last few months, I’ve made a concerted effort to wean myself off of the mouse (and my MacBook’s trackpad). Why? With a keyboard, we have about a hundred buttons at our disposal, giving us incredible power and opportunity for efficiency. Those buttons are there; we should be using them as much as possible. Learning key combinations and navigating around in modes does require significant practice, but it’s no more difficult than learning to touch type. Touch screens may be the new hotness, but keyboards win when it comes to effectiveness.&lt;/p&gt;

&lt;p&gt;I no longer work with a mouse, but I do find myself reaching down for the trackpad too often. True, the MacBook trackpad, with its multi-touch gestures, can be quite efficient, but the second or two it takes to move my hand down and back up is time wasted, and is almost always unnecessary, as a keyboard analog exists for nearly every action.&lt;/p&gt;

&lt;p&gt;So over the next few months, on Mondays, I’m going to consciously try not to use any pointing device unless it’s absolutely necessary. If your job primarily consists of entering text – you’re a programmer, systems administrator, or writer – I think you should join me.&lt;/p&gt;

&lt;p&gt;When you work in applications that were designed with text entry in mind, like text editors or word processors, they’re usually filled with keyboard-friendly features. But how about the web browser? Websites are filled with links, and to get to those links, they need to be clicked on. Right? &lt;/p&gt;

&lt;p&gt;Well, no. There’s a better way…&lt;/p&gt;

&lt;h3 id=&quot;vimium&quot;&gt;Vimium&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://chrome.google.com/extensions/detail/dbepggeogbaibhgnhhndojpepiihcmeb&quot;&gt;Vimium&lt;/a&gt; is an extension for &lt;a href=&quot;http://dev.chromium.org/getting-involved/dev-channel&quot;&gt;Google Chrome&lt;/a&gt; that makes the point and click nature of web browsing nearly obsolete. As its name implies, Vimium is modeled off the text editor &lt;a href=&quot;http://vim.org&quot;&gt;Vim&lt;/a&gt;, and the extension itself was greatly inspired by &lt;a href=&quot;http://vimperator.org/&quot;&gt;Vimperator&lt;/a&gt; for Firefox. The key concept behind Vimium is that it adds a keyboard navigation mode to Chrome. So when you’re using Chrome, and you’re not currently focused on a form field, you’re in navigation mode (also called normal mode in Vim-speak).&lt;/p&gt;

&lt;p&gt;After installing Vimium, type a question mark, and a help menu pops up:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Vimium%20Help.png&quot; title=&quot;Vimium Help&quot; alt=&quot;Vimium Help&quot; width=&quot;600px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The help menu is pretty straightforward. Use “j” and “k” to scroll down and up. The most important keystroke for going mouseless is the “f”. Hit it, and all links in the browser get their own key combination:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://luigimontanez.com/snaps/Vimium%20Twitter.png&quot; alt=&quot;Vimium Twitter&quot; width=&quot;600px&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It looks overwhelming at first, but your eye is trained on one spot, so in practice it works out. So if I were to type “f”, then “js”, I’d visit my page of Mentions. Lowercase “f” will open the link on the same page, while capital “F” will open it in a new tab. If I wanted to do a search, I’d hit “jj” and then just start typing my query, pressing Enter to submit. Hitting “jj” would put me in Insert mode and I’d type as usual. To get back to Navigation (or Normal) mode from the search box, I’d hit the Esc key.&lt;/p&gt;

&lt;p&gt;With Vimium, I can use the Twitter website more efficiently than any of the desktop Twitter apps. Vimium will change your web browsing forever. Once you get the hang of it, you’ll only be using the mouse for interacting with Flash embeds.&lt;/p&gt;

&lt;h3 id=&quot;google-chrome&quot;&gt;Google Chrome&lt;/h3&gt;

&lt;p&gt;In addition to the goodness that Vimium gives you, I encourage you to learn the key combinations built into Chrome, many of which are shared with Firefox and Safari. Some of my favorites (on the Mac):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  Ctl-Tab         Toggle between open tabs
  Cmd-L           Jump to the Location bar
  Cmd-F           Search (nicer than Vimium's search)
  Cmd-D           Bookmark
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;One annoyance I have is that there’s no easy way to jump from the Location bar back to Navigation mode in Vimium. I’m finding myself hitting Cmd-F for search, typing a dummy string, and then deleting it, all to just get out of the Location bar.&lt;/p&gt;

&lt;h3 id=&quot;up-next&quot;&gt;Up Next&lt;/h3&gt;

&lt;p&gt;In the coming weeks, I’ll be posting more tips for going mouseless. &lt;a href=&quot;http://feeds.feedburner.com/luigimontanez&quot;&gt;Subscribe to my feed&lt;/a&gt; if you’d like to keep up.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Drafting Guidelines for Government Data Catalogs</title>
   <link href="http://luigimontanez.com/2010/drafting-guidelines-government-data-catalogs/"/>
   <updated>2010-03-29T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2010/drafting-guidelines-government-data-catalogs/drafting-guidelines-government-data-catalogs</id>
   <content type="html">&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href=&quot;http://sunlightlabs.com/blog/2010/drafting-guidelines-government-data-catalogs/&quot;&gt;Sunlight Labs blog&lt;/a&gt;. Written with &lt;a href=&quot;http://sunlightlabs.com/people/david&quot;&gt;David James&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A major focus of the Sunlight Labs is to push government to publish its data online. In recent months, we’ve gained in-depth familiarity with government data catalogs through our work on the &lt;a href=&quot;http://nationaldatacatalog.com&quot;&gt;National Data Catalog&lt;/a&gt;. The most prominent example of a data catalog is &lt;a href=&quot;http://data.gov&quot;&gt;data.gov&lt;/a&gt;. Since its launch last year, a handful of states and cities have followed suit with their own efforts. As more data catalogs come online, we want to make sure their contents are open and exchangeable. We want to determine how to best structure the data catalog itself, and we want to ensure that the metadata it contains – the data about the data – exists in the most accessible way possible.&lt;/p&gt;

&lt;p&gt;Last week, Clay posted &lt;a href=&quot;http://sunlightlabs.com/blog/2010/transparencycamp-three-challenges/&quot;&gt;three challenges&lt;/a&gt; for the community to tackle, and this is challenge #3. We’re looking to start this conversation now and move towards consensus within a few months. I was at &lt;a href=&quot;http://transparencycamp.org&quot;&gt;Transparency Camp&lt;/a&gt;, digging deeper into this topic, putting us on the path to make recommendations that governments can adopt quickly.&lt;/p&gt;

&lt;h3 id=&quot;resource-oriented-architecture&quot;&gt;Resource-Oriented Architecture&lt;/h3&gt;

&lt;p&gt;A data catalog lives on the Web, so it makes sense that it embrace the architecture of the Web. A simple Web site with a few pages is good for citizen use, but doesn’t lend itself to being interoperable. As such, we strongly recommend following the &lt;a href=&quot;http://en.wikipedia.org/wiki/Resource_oriented_architecture&quot;&gt;Resource Oriented Architecture&lt;/a&gt; (ROA) guidelines. When applied to the concept of a government data catalog, ROA means:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Resources that represent the data sources, agencies, and jurisdictions (if there are more than one) should exist.&lt;/li&gt;
  &lt;li&gt;Each resource should have a unique URI, so that each one can be addressed individually.&lt;/li&gt;
  &lt;li&gt;Resources should be made available in both human-friendly (HTML) and machine-readable formats (such as XML or JSON).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Content_negotiation&quot;&gt;Content negotiation&lt;/a&gt; should be used to serve the resource correctly depending on the user agent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;defining-a-vocabulary&quot;&gt;Defining a Vocabulary&lt;/h3&gt;

&lt;p&gt;Let’s turn to the metadata that describes a particular government data source. Existing government data catalogs like data.gov have already established some best practices. But going back through the Internet’s history, it’s helpful to contemplate the work of the &lt;a href=&quot;http://dublincore.org/specifications/&quot;&gt;Dublin Core&lt;/a&gt;, which over a decade ago published a set of &lt;a href=&quot;http://dublincore.org/documents/dces/&quot;&gt;fifteen metadata elements&lt;/a&gt; for describing online resources. The Dublin Core spec applies to a wide range of things published online, from videos to academic papers to datasets. The fifteen elements forming the spec give us a good starting point, and remind us how similar online government data is to any other kind of resource published online. Some elements are not fully applicable (Language and Contributor, for example). Others can be broken up into several elements. Coverage can mean a physical geographic area, a political jurisdiction, or a period of time.&lt;/p&gt;

&lt;p&gt;Going from theoretical to practical, let’s look at some sample data pages for existing data catalogs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.data.gov/raw/1358&quot;&gt;data.gov&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://data.dc.gov/Metadata.aspx?id=3&quot;&gt;data.dc.gov&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://data.gov.uk/dataset/absenteeism_from_secondary_schools_in_wales&quot;&gt;data.gov.uk&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.utah.gov/data/state_data_files.html&quot;&gt;utah.gov/data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking at those four examples, we begin to see a lot of similarities among the catalogs and with Dublin Core. From these, we propose a preliminary vocabulary:&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;&lt;strong&gt;Element Name&lt;/strong&gt;&lt;/th&gt;
    &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Title&lt;/td&gt;
    &lt;td&gt;Title of data source.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Description&lt;/td&gt;
    &lt;td&gt;Short description of data source.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;URL&lt;/td&gt;
    &lt;td&gt;Permanent, unique URL that contains this metadata. Can be self-referential.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Type&lt;/td&gt;
    &lt;td&gt;Is the data source a dataset, API, or online database?&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Downloads&lt;/td&gt;
    &lt;td&gt;File format/URL pairs that point to data files.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Created&lt;/td&gt;
    &lt;td&gt;Creation date of the data source.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Released&lt;/td&gt;
    &lt;td&gt;Release date of the data source.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Last Updated&lt;/td&gt;
    &lt;td&gt;Update date of the data source.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Update Frequency&lt;/td&gt;
    &lt;td&gt;How often the data is updated&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Creator&lt;/td&gt;
    &lt;td&gt;Entity (agency, department, or organization) that created the data.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Publisher&lt;/td&gt;
    &lt;td&gt;Entity that published the data.&lt;/td&gt;	
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Maintainer&lt;/td&gt;
    &lt;td&gt;Entity that maintains the data.&lt;/td&gt;	
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Jurisdiction&lt;/td&gt;
    &lt;td&gt;Political jurisdiction of the data.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Time Period&lt;/td&gt;
    &lt;td&gt;The time period the data refers to.&lt;/td&gt;	
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Grouping&lt;/td&gt;
    &lt;td&gt;Can the data be grouped with a larger set of similar data? Recommended for data sets scoped to a time period or jurisdiction.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;License&lt;/td&gt;
    &lt;td&gt;The license under which the data set is released.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Documentation&lt;/td&gt;
    &lt;td&gt;Any documentation, such as a data dictionary, or a reference (URL) to that documentation.&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;This vocabulary forms a base-level set of metadata. Individual data catalogs can and should publish more elements as appropriate, but serious efforts should be put into ensuring that the fifteen elements above are present.&lt;/p&gt;

&lt;h3 id=&quot;the-formats&quot;&gt;The Formats&lt;/h3&gt;

&lt;p&gt;With a vocabulary defined, we can move to the actual data formats to represent an entry in a government data catalog. We don’t need to just choose one. Instead, we can map our general vocabulary to several existing data format standards:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.w3.org/XML/&quot;&gt;XML&lt;/a&gt;: Maps easily to the vocabulary defined above. Loved by the enterprise.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://json.org&quot;&gt;JSON&lt;/a&gt;: XML’s lighter-weight alternative, loved by modern Web developers (and the Sunlight Labs).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://tools.ietf.org/html/rfc4180&quot;&gt;CSV&lt;/a&gt;: A good compromise between machine-friendliness and human-readability.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://microformats.org/&quot;&gt;Microformats&lt;/a&gt;: Can act as an easy-to-implement solution since these can be placed on plain ol’ Web sites with only a little bit of effort.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, and possibly most importantly, we need a data format to represent updates to entries in a data catalog. For that, we recommend the &lt;a href=&quot;http://www.atomenabled.org/developers/syndication/atom-format-spec.php&quot;&gt;Atom Syndication Format&lt;/a&gt;. An individual entry in the Atom feed would contain the unique URL identifier and any updated elements. The entry should use any one of the four formats above, with a bias towards XML, since Atom itself is XML.&lt;/p&gt;

&lt;p&gt;So in summary, the preliminary proposal is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ensure that you have enough metadata to closely follow the vocabulary.&lt;/li&gt;
  &lt;li&gt;If publishing the catalog as a Web site, use the Microformat on the data detail pages.&lt;/li&gt;
  &lt;li&gt;If publishing an API, use XML or JSON in conjunction with Resource-Oriented principles.&lt;/li&gt;
  &lt;li&gt;If publishing the data catalog as a bulk download, use XML, JSON, or CSV.&lt;/li&gt;
  &lt;li&gt;To publish updates of entries in the catalog, use Atom.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll be fleshing out examples of these data formats in the &lt;a href=&quot;http://wiki.sunlightlabs.com/Government_Data_Catalog_Specification&quot;&gt;Sunlight Labs Wiki&lt;/a&gt; over the coming weeks. I’ll be working with the good people of &lt;a href=&quot;http://www.socrata.com/&quot;&gt;Socrata&lt;/a&gt;, who announced their &lt;a href=&quot;http://www.socrata.com/api/docs/&quot;&gt;SODA API&lt;/a&gt; at TransparencyCamp on Saturday, and any other folks interested.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Interview on the Ruby on Rails Podcast</title>
   <link href="http://luigimontanez.com/2010/interview-ruby-on-rails-podcast/"/>
   <updated>2010-03-08T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2010/interview-ruby-on-rails-podcast/interview-ruby-on-rails-podcast</id>
   <content type="html">&lt;p&gt;Geoffrey Grosenbach of &lt;a href=&quot;http://peepcode.com&quot;&gt;Peepcode&lt;/a&gt; fame interviewed me for the &lt;a href=&quot;http://podcast.rubyonrails.com/programs/1/episodes/luigi-montanez-of-sunlight-labs&quot;&gt;Ruby on Rails Podcast&lt;/a&gt;. We talked about civic hacking opportunities for Ruby developers. &lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Sunlight Labs on The Changelog</title>
   <link href="http://luigimontanez.com/2010/sunlight-labs-changelog/"/>
   <updated>2010-02-10T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2010/sunlight-labs-changelog/sunlight-labs-changelog</id>
   <content type="html">&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href=&quot;http://sunlightlabs.com/blog/2010/sunlight-labs-changelog/&quot;&gt;Sunlight Labs&lt;/a&gt; blog.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.sunlightlabs.com/people/jcarbaugh/&quot;&gt;Jeremy&lt;/a&gt; and I are on the newest episode of &lt;a href=&quot;http://thechangelog.com/post/382418778/episode-0-1-3-civic-hacking-with-luigi-montanez-and-jere&quot;&gt;The Changelog&lt;/a&gt;, a terrific podcast about open source development. We talked about the work we do here from our offices in D.C. as well as the great work the entire Sunlight Labs community does across the country. &lt;/p&gt;

&lt;p&gt;You may remember &lt;a href=&quot;http://twitter.com/pengwynn&quot;&gt;Wynn Netherland&lt;/a&gt;, one of the show’s hosts, from &lt;a href=&quot;http://tweetcongress.org&quot;&gt;TweetCongress&lt;/a&gt; and the big splash they made last year. Along with co-host &lt;a href=&quot;http://twitter.com/adamstac&quot;&gt;Adam Stacoviak&lt;/a&gt;, Wynn also interviewed Apps for America winner &lt;a href=&quot;http://thechangelog.com/post/272530971/episode-0-0-5-document-cloud&quot;&gt;Jeremy Ashkenas&lt;/a&gt; back in December.&lt;/p&gt;

&lt;p&gt;Enjoy the show!&lt;/p&gt;
</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>Real Time Disclosure, Technically Speaking</title>
   <link href="http://luigimontanez.com/2010/real-time-disclosure-technically-speaking/"/>
   <updated>2010-01-26T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2010/real-time-disclosure-technically-speaking/real-time-disclosure-technically-speaking</id>
   <content type="html">&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href=&quot;http://sunlightlabs.com/blog/2010/real-time-disclosure-technically-speaking/&quot;&gt;Sunlight Labs&lt;/a&gt; blog.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last week’s &lt;a href=&quot;http://blog.sunlightfoundation.com/2010/01/21/how-the-citizens-united-case-affects-money-politics-and-transparency-as-we-know-it/&quot;&gt;&lt;em&gt;Citizens United v. FEC&lt;/em&gt;&lt;/a&gt; Supreme Court decision was a game-changer in terms of corporate money in politics. In short, corporations will be allowed to freely spend unlimited amounts of money to support or oppose a candidate, just as long as there is no direct coordination with that candidate’s campaign. Unprecedented amounts of corporate money will now flow into our political process. But here at Sunlight, we’re focusing on the disclosure aspects of the decision. The majority opinion stated:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;With the advent of the Internet, prompt disclosure of expenditures can provide shareholders and citizens with the information needed to hold corporations and elected officials accountable for their positions and supporters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the decision doesn’t mandate “prompt disclosure”, it does strongly recommend it. So what does disclosure at Internet speed look like?&lt;/p&gt;

&lt;h3 id=&quot;examples-of-real-time-disclosure&quot;&gt;Examples of Real Time Disclosure&lt;/h3&gt;

&lt;p&gt;Say you contribute $100 to your congressional campaign of choice. The instant your credit card is approved, or your check is processed, the campaign will send a notification to the FEC of the contribution. The FEC’s servers will verify and record it, and instantly broadcast the details of the contribution to any third party who wants to receive it. It should all take place in a matter of seconds.&lt;/p&gt;

&lt;p&gt;Campaign expenditures (and now political expenditures by corporations) would work similarly. For example, when a campaign or corporation decides to spend $25,000 on an ad buy, they would need to disclose that to the FEC within a 24 hour period. Unlike with contributions, disclosing expenditures needs to have a staffer manually enter data, so it would be impractical to demand instant disclosure in this case. But once the FEC receives the data about the expenditure within the 24 hour timeframe, the FEC should instantly broadcast that data to all interested third parties, just like with contributions.&lt;/p&gt;

&lt;h3 id=&quot;proposed-solutions&quot;&gt;Proposed Solutions&lt;/h3&gt;

&lt;p&gt;Real time web technologies have come into their own this past year. Heck, there was even a &lt;a href=&quot;http://www.readwriteweb.com/summit/&quot;&gt;conference&lt;/a&gt; about it. And importantly, real time solutions can be created with open web standards and open source software, two things we strongly want to see government embrace.&lt;/p&gt;

&lt;h4 id=&quot;http&quot;&gt;HTTP&lt;/h4&gt;

&lt;p&gt;One proposed solution would be based on HTTP, the protocol of the Web: An FEC-powered RESTful API with strong querying capabilities, speaking XML and/or JSON, and made available for read and write access. The past few years have proven that well-documented RESTful APIs are the way to go. Twitter, Google, and Sunlight Labs have all embraced this convention. Contributions and expenditures would be POSTed by registered campaigns and corporations, and the public could read all the data via GET.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://s3.amazonaws.com/ember/WkZRsITK2gSqmRqVY8mDc6l1EKVylr2Y_m.png&quot; alt=&quot;HTTP Diagram&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One newer real time technology, based on HTTP and RESTful principles, is &lt;a href=&quot;http://pubsubhubbub.googlecode.com/&quot;&gt;PubSubHubbub&lt;/a&gt;, or PuSH for short. PuSH excels in real-time, event-driven notifications. Usually, when you want to know if a given API has been updated, you need to ask it repeatedly if there’s any new data. This technique, called polling, inefficiently uses up bandwidth because there are a lot of requests made where nothing new is to be found. Instead, PuSH mandates that interested parties subscribe to receive notifications, giving the publishing server a URL to send a notification to, and it’s up to the interested party to take action when they receive that notification at the URL they control. Registering your URL endpoint to receive a notification is known as a &lt;a href=&quot;http://webhooks.pbworks.com/&quot;&gt;Webhook&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;xmpp&quot;&gt;XMPP&lt;/h4&gt;

&lt;p&gt;Unlike HTTP, &lt;a href=&quot;http://xmpp.org/&quot;&gt;XMPP&lt;/a&gt; (eXtensible Messaging and Presence Protocol) was designed for real time applications and asynchronous communication. You’ve used XMPP if you’ve used Google Talk for chatting, or other Jabber IM services. At the simplest level, XMPP is a way to send instant messages around the Internet, with support for extending the definition of those messages to suit your needs. XMPP also defines a &lt;a href=&quot;http://xmpp.org/extensions/xep-0060.html&quot;&gt;publish-subscribe&lt;/a&gt; extension, which would allow third parties to subscribe to a particular set of disclosure data and receive messages from the server instantly.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://s3.amazonaws.com/ember/cFdAlpfrwSI09zLjMubIubqTp4vKBhfE_m.png&quot; alt=&quot;XMPP Diagram&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: For simplicity’s sake, the diagram above ignores XMPP’s &lt;a href=&quot;http://pthree.org/2007/07/15/why-xmpp-part-3-decentralization-is-key/&quot;&gt;decentralization&lt;/a&gt; features.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Either solution is well-supported by solid open source software. HTTP servers like Apache and &lt;a href=&quot;http://wiki.nginx.org/Main&quot;&gt;nginx&lt;/a&gt; are ubiquitous, and frameworks like &lt;a href=&quot;http://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt; and &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;Rails&lt;/a&gt; make creating RESTful APIs a snap. For PuSH, Google has released a &lt;a href=&quot;http://pubsubhubbub.appspot.com/&quot;&gt;reference implementation&lt;/a&gt; running on App Engine. The server of choice for XMPP is &lt;a href=&quot;http://www.ejabberd.im/&quot;&gt;ejabberd&lt;/a&gt;, an Erlang-based project.&lt;/p&gt;

&lt;p&gt;Real time disclosure is possible today. The technology is here, and it’s open. Now, we need to muster the political will to see it through.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Your Input Wanted on Recovery.gov Data</title>
   <link href="http://luigimontanez.com/2009/your-input-wanted-recoverygov-data/"/>
   <updated>2009-09-24T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/your-input-wanted-recoverygov-data/your-input-wanted-recoverygov-data</id>
   <content type="html">&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href=&quot;http://sunlightlabs.com/blog/2009/your-input-wanted-recoverygov-data/&quot;&gt;Sunlight Labs&lt;/a&gt; blog.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here at the Sunlight Labs, we’ve focused a lot on the recent bid on version 2.0 of &lt;a href=&quot;http://recovery.gov&quot;&gt;Recovery.gov&lt;/a&gt;. This morning on the Labs mailing list, Rusty Talbot of Synteractive, one of the winning contractors, &lt;a href=&quot;http://groups.google.com/group/sunlightlabs/browse_thread/thread/51c4ebe3707ea25a?hl=en&quot;&gt;asked for input&lt;/a&gt; on the best way for Recovery.gov to publish its data.&lt;/p&gt;

&lt;p&gt;Rusty wrote:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The Recovery, Accountability, &amp;amp; Transparency Board wishes to have an open discussion with all interested developers about how data should be made available via Recovery.gov.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;As you are all aware, a new version of Recovery.gov will be released soon. From a data standpoint, the initial release of the new site will replicate existing functionality. However, the Board aims to set a new standard of transparency with this site and would therefore like to make the data available in the most convenient and straightforward way (or ways) possible so you can use and analyze official, up-to-date Recovery Act data. We need your input to achieve this goal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Please let us know how the site could best meet your needs in terms of machine-readable data format(s) and standards, APIs, guidance, training, etc.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a great opportunity for all of us who work hard to make government data more open and accessible. Back in April, we at the Sunlight Foundation, as a member of the &lt;a href=&quot;http://www.coalitionforanaccountablerecovery.org/&quot;&gt;Coalition for an Accountable Recovery&lt;/a&gt;, published a &lt;a href=&quot;http://www.coalitionforanaccountablerecovery.org/node/6&quot;&gt;report to the OMB&lt;/a&gt; giving recommendations on data feed publishing (starts on page 8 of the document).&lt;/p&gt;

&lt;p&gt;As one of the project leads for the upcoming &lt;a href=&quot;http://groups.google.com/group/datacatalog&quot;&gt;National Data Catalog&lt;/a&gt;, I’ve been thinking a lot about what makes government data truly useful for software developers, researchers, and journalists. Here’s my more technical take:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;First, publish as much machine-readable raw data as possible. The data should be in a widely-used format, XML or JSON, and should be accessible from predictable, permanent URLs. Documentation clearly describing the schema and data types is essential.&lt;/li&gt;
  &lt;li&gt;As the Recovery Act programs are ongoing, document when, where, and how new data will be published. Set up a regular schedule for updates. Communicating updates could be as simple as setting up a mailing list or feed.&lt;/li&gt;
  &lt;li&gt;After the raw data is made accessible and proves to be useful, consider building an API that complements, rather than duplicates, the raw data sets. APIs are useful for developers who wish to get smaller, discrete sets of data without having to crunch through the entire raw data set. An emphasis should be placed on querying functionality that can be integrated into other apps.&lt;/li&gt;
  &lt;li&gt;The API should also speak XML and/or JSON, while following REST principles. Libraries to consume such APIs exist in all modern programming languages. Again, clear documentation is vitally important.&lt;/li&gt;
  &lt;li&gt;When it comes to data, the RAT Board and Recovery.gov should eat its own dog food. That is, the data used internally by the RAT Board for analysis, tracking, and powering the website should be exactly the same data published to the public. This may not be technically possible right now, but it should be a goal because doing so would be the single best way to ensure that data being published is serving real-world needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So those are my thoughts. &lt;a href=&quot;http://groups.google.com/group/sunlightlabs/browse_thread/thread/51c4ebe3707ea25a?hl=en&quot;&gt;What are yours&lt;/a&gt;?&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Recapping the Ruby Hoedown</title>
   <link href="http://luigimontanez.com/2009/recapping-ruby-hoedown/"/>
   <updated>2009-09-03T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/recapping-ruby-hoedown/recapping-ruby-hoedown</id>
   <content type="html">&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href=&quot;http://sunlightlabs.com/blog/2009/recapping-ruby-hoedown/&quot;&gt;Sunlight Labs&lt;/a&gt; blog.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was in Nashville this past weekend giving a talk at the &lt;a href=&quot;http://rubyhoedown.com&quot;&gt;Ruby Hoedown&lt;/a&gt;, a completely free conference held for the South’s Ruby developers. My talk was titled “Civic Hacking”, and the slides are on &lt;a href=&quot;http://www.slideshare.net/luigimontanez/civic-hacking&quot;&gt;Slideshare&lt;/a&gt;:&lt;/p&gt;

&lt;div style=&quot;width:425px;text-align:left&quot; id=&quot;__ss_1923672&quot;&gt;&lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=hoedown-090829082415-phpapp01&amp;amp;stripped_title=civic-hacking&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot; /&gt;&lt;embed src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=hoedown-090829082415-phpapp01&amp;amp;stripped_title=civic-hacking&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot; /&gt;&lt;/object&gt;&lt;/div&gt;

&lt;p&gt;The conference was one of the best regional Ruby conferences I’ve been to, and a lot of that had to do with the venue, the &lt;a href=&quot;http://www.gaylordhotels.com/gaylord-opryland/&quot;&gt;Gaylord Opryland Hotel&lt;/a&gt;. Essentially a self-contained small town, reminiscent of the Biodome, the hotel provided ample opportunities for running into folks and picking each others brains over a meal or drinks. Visit it if you want to experience how we’ll live on Mars.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090903-c9hak8jtmghftby1epp9rpq3wm.jpg&quot; alt=&quot;opryland&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo credit to Stephen Yeargin on &lt;a href=&quot;http://www.flickr.com/photos/stephenyeargin/3867988503/&quot;&gt;Flickr&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Some solid talks were given as well. &lt;a href=&quot;http://atmos.org/&quot;&gt;Corey Donohue&lt;/a&gt; of &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt; described the importance of breaking up large apps into smaller, RESTful services. &lt;a href=&quot;http://fallenrogue.com/&quot;&gt;Leon Gersing&lt;/a&gt; demoed the features of &lt;a href=&quot;http://www.appcelerator.com/&quot;&gt;Appcelerator Titanium&lt;/a&gt;. While showing off Titanium’s incredible new &lt;a href=&quot;http://www.appcelerator.com/products/titanium-mobile/&quot;&gt;iPhone and Android&lt;/a&gt; support, he was asked “Are you a witch?”, easily the best question of the conference. RSpec lead &lt;a href=&quot;http://github.com/dchelimsky&quot;&gt;David Chelimsky&lt;/a&gt; spoke on the art of mocking, and a kazoo-enhanced lightning talk by &lt;a href=&quot;http://crnixon.org/&quot;&gt;Clinton R. Nixon&lt;/a&gt; on &lt;a href=&quot;http://www.mongodb.org/&quot;&gt;MongoDB&lt;/a&gt; was the most entertaining. Lyle Johnson has posted a &lt;a href=&quot;http://lylejohnson.name/blog/2009/08/31/ruby-hoedown-2009-wrap-up/&quot;&gt;thorough wrap-up&lt;/a&gt; of the weekend as well.&lt;/p&gt;

&lt;p&gt;One day in the Labs, a question was raised as to why one of our developers, &lt;a href=&quot;http://sunlightlabs.com/people/david/&quot;&gt;David&lt;/a&gt;, always seems to be wearing Ruby-related shirts. The answer is because we Rubyists put on &lt;a href=&quot;http://lonestarrubyconf.com/&quot;&gt;a&lt;/a&gt; &lt;a href=&quot;http://gogaruco.com/&quot;&gt;lot&lt;/a&gt; (and &lt;a href=&quot;http://mwrc2009.confreaks.com/&quot;&gt;I&lt;/a&gt; &lt;a href=&quot;http://www.goruco.com/&quot;&gt;mean&lt;/a&gt; &lt;a href=&quot;http://windycityrails.org/&quot;&gt;a&lt;/a&gt; &lt;a href=&quot;http://www.alohaonrails.com/&quot;&gt;lot&lt;/a&gt;) of regional Ruby conferences. The Python crowd, it seems, only have &lt;a href=&quot;http://www.pycon.org/&quot;&gt;PyCon&lt;/a&gt; and &lt;a href=&quot;http://www.djangocon.org/&quot;&gt;DjangoCon&lt;/a&gt;, the latter of which Labs member &lt;a href=&quot;http://sunlightlabs.com/people/james/&quot;&gt;James&lt;/a&gt; is headed to next week.&lt;/p&gt;

&lt;p&gt;So we Rubyists love to organize ourselves and get together, that’s certain. It’s high time that we organize more around making our government more open and more transparent. We’re already off to a good start. &lt;a href=&quot;http://sunlightlabs.com/contests/appsforamerica/&quot;&gt;Apps for America 1&lt;/a&gt; winner &lt;a href=&quot;http://filibusted.us&quot;&gt;Filibusted&lt;/a&gt; is a Rails app, as is &lt;a href=&quot;http://know-thy-congressman.com/&quot;&gt;Know Thy Congressman&lt;/a&gt; , which placed third. &lt;a href=&quot;http://thisweknow.org&quot;&gt;This We Know&lt;/a&gt; and &lt;a href=&quot;http://govpulse.us&quot;&gt;GovPulse&lt;/a&gt;, two of the three finalists in &lt;a href=&quot;&quot;&gt;Apps for America 2&lt;/a&gt; are also Rails apps.&lt;/p&gt;

&lt;p&gt;But I think we Rubyists can do a lot better. Using the new tools we have here at &lt;a href=&quot;http://sunlightlabs.com&quot;&gt;SunlightLabs.com&lt;/a&gt;, let’s go over some Ruby-based projects and ideas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://sunlightlabs.com/projects/congrelate/&quot;&gt;&lt;strong&gt;Congrelate&lt;/strong&gt;&lt;/a&gt; - A project at the Labs headed by &lt;a href=&quot;http://sunlightlabs.com/people/klondike/&quot;&gt;Eric&lt;/a&gt;, powered by Sinatra and jQuery, which focuses on bringing together disparate data sources in powerful ways. We already pull in data from Congress, the Census, OpenSecrets, and GovTrack, but we’d like to bring in more data sources. Check out the code base for instructions on how to build in support for new data sources.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://sunlightlabs.com/projects/tcorps/&quot;&gt;&lt;strong&gt;Transparency Corps&lt;/strong&gt;&lt;/a&gt; - Much like Amazon’s Mechanical Turk, TCorps allows anyone anywhere to have a positive impact on making our government more transparent by aggregating small actions that require human intelligence but not specialized political knowledge. If you have an idea that can benefit from this tool, it’s easy to write your own Task that we can plug into the system.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://sunlightlabs.com/projects/datacatalog/&quot;&gt;&lt;strong&gt;National Data Catalog&lt;/strong&gt;&lt;/a&gt; - Led by David and I, we’re aiming to build a comprehensive catalog of all data sets and APIs published by all levels of government. We’ll soon need help developing parsers that scrape existing data catalogs out there and load that information into our catalog.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;API wrappers for open government web services&lt;/strong&gt; - While we have a Ruby gem for the &lt;a href=&quot;http://github.com/sunlightlabs/ruby-sunlightapi/tree/master&quot;&gt;Sunlight Labs API&lt;/a&gt;, the other APIs out there have been neglected. Let’s get cracking on Ruby wrappers for &lt;a href=&quot;http://sunlightlabs.com/ideas/11/&quot;&gt;OpenSecrets.org&lt;/a&gt;, &lt;a href=&quot;http://sunlightlabs.com/ideas/12/&quot;&gt;GovTrack&lt;/a&gt;, &lt;a href=&quot;http://sunlightlabs.com/ideas/13/&quot;&gt;MAPLight&lt;/a&gt;, and &lt;a href=&quot;http://sunlightlabs.com/ideas/14/&quot;&gt;LittleSis&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let’s get going, Rubyists! Feel free to &lt;a href=&quot;http://sunlightlabs.com/people/luigi/&quot;&gt;contact me&lt;/a&gt; with any questions. And speaking of regional Ruby conferences, I’ll be at &lt;a href=&quot;http://sunlightlabs.com/events/10/&quot;&gt;Ruby DCamp&lt;/a&gt; in two weeks.&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>Google Wave: First Thoughts</title>
   <link href="http://luigimontanez.com/2009/google-wave-first-thoughts/"/>
   <updated>2009-07-19T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/google-wave-first-thoughts/google-wave-first-thoughts</id>
   <content type="html">&lt;p&gt;I received a developer preview invitation for Google Wave this weekend. I’m luigi@wavesandbox.com if you want to add me to your contacts list.&lt;/p&gt;

&lt;p&gt;My initial thoughts can be summed up thusly:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090719-qpnuq9jmeeq79m46bkks7f52h5.png&quot; alt=&quot;Twitter / Luigi Montanez: Google Wave is terrible. B ...&quot; /&gt;&lt;/p&gt;

&lt;p&gt;How bad is it? After about an incredibly frustrating hour or two of trying to wrap my head around things, here are some thoughts…&lt;/p&gt;

&lt;h3 id=&quot;the-wave-discuss-group&quot;&gt;The Wave Discuss Group&lt;/h3&gt;

&lt;p&gt;Apparently in my excitement of signing up, I joined the wave-discuss group, which displays a collective intelligence that can only rival the comment threads to Avril Lavigne videos on YouTube. Click through to see the gory details:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://skitch.com/luigi/b2eb3/chromium&quot;&gt;&lt;img src=&quot;http://img.skitch.com/20090719-tttriidjgy3t1htfifd6umpqy6.preview.jpg&quot; alt=&quot;Chromium&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have no idea how to opt myself out of this group. I’m subject to a mountain of crap in my inbox that I simply don’t want. I tried the Settings option, which appears to be a wave, albeit a broken one speaking Japanese:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090719-bbjge79by4qjpumtxtqk4a681m.png&quot; alt=&quot;Chromium&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-waves-themselves&quot;&gt;The Waves Themselves&lt;/h3&gt;

&lt;p&gt;The Archive and Mute buttons don’t seem to work. Spammers have already struck:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090719-nyxmim3eyawidqnwkqq598afwf.png&quot; alt=&quot;Chromium&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The WYSIWYG interface promotes some truly heinous typography decisions:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090719-1dqmdk2swxs5xphnisdnim1536.png&quot; alt=&quot;Chromium&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Threading seems to be broken. These answers don’t make a lick of sense:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090719-nff9cg1tt3bi7b2reds8yg1qj2.png&quot; alt=&quot;Chromium&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-good&quot;&gt;The Good&lt;/h3&gt;

&lt;p&gt;The live type feature is indeed awesome. But watching the slowness of typing reminds you how much more efficient talking can be. Also, there appear to be live Googlers trying to answer questions as fast as they can, so that’s nice.&lt;/p&gt;

&lt;p&gt;Hopefully, when some people I know get accounts, we can participate is civilized, well-structured waves. But for now, it’s all just too much for me. Using Google Wave results in a sensory overload of low-quality content. Maybe when I figure out how to get off the wave-discuss group, things will be more clear and I can focus on the technology instead of all the chatter.&lt;/p&gt;

&lt;h3 id=&quot;update&quot;&gt;UPDATE&lt;/h3&gt;

&lt;p&gt;I figured out how to opt-out of the annoying wave-discuss group. It involved adding my name to a list (in a wave, naturally) of people who want to be opted-out. Apparently a Googler goes through the list every few days and manually processes the names. There’s no automated system yet. A lose-lose for everyone involved…&lt;/p&gt;
</content>
 </entry>
 
 
 
 <entry>
   <title>On Being a Civic Coder</title>
   <link href="http://luigimontanez.com/2009/on-being-a-civic-coder/"/>
   <updated>2009-06-12T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/on-being-a-civic-coder/on-being-a-civic-coder</id>
   <content type="html">&lt;p&gt;I started working at the &lt;a href=&quot;http://sunlightlabs.com&quot;&gt;Sunlight Labs&lt;/a&gt; this week, and I&amp;#8217;m giving a talk on Being a Civic Coder at &lt;a href=&quot;http://rubynation.org&quot;&gt;RubyNation&lt;/a&gt; today:&lt;/p&gt;
&lt;div style=&quot;width:425px;text-align:left&quot; id=&quot;__ss_1574940&quot;&gt;&lt;a style=&quot;font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;&quot; href=&quot;http://www.slideshare.net/luigimontanez/be-a-civic-coder?type=powerpoint&quot; title=&quot;Be A Civic Coder&quot;&gt;Be A Civic Coder&lt;/a&gt;&lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=beaciviccoder-090612124058-phpapp02&amp;stripped_title=be-a-civic-coder&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=beaciviccoder-090612124058-phpapp02&amp;stripped_title=be-a-civic-coder&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style=&quot;font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;&quot;&gt;View more &lt;a style=&quot;text-decoration:underline;&quot; href=&quot;http://www.slideshare.net/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;PDF&lt;/span&gt; documents&lt;/a&gt; from &lt;a style=&quot;text-decoration:underline;&quot; href=&quot;http://www.slideshare.net/luigimontanez&quot;&gt;luigimontanez&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Some resource links:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://sunlightlabs.com/&quot;&gt;Sunlight Labs&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://sunlightlabs.com/contests/appsforamerica2/&quot;&gt;Apps for America 2&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://groups.google.com/group/sunlightlabs/&quot;&gt;Sunlight Labs Google Group&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://twitter.com/sunlightlabs&quot;&gt;@sunlightlabs on Twitter&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://opensecrets.org/&quot;&gt;Open Secrets&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.followthemoney.org/&quot;&gt;Follow the Money&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://maplight.org/&quot;&gt;MAPLight&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://sunlightlabs.com/contests/appsforamerica/apps/&quot;&gt;Apps for America 1 Submissions&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://tweetcongress.org&quot;&gt;TweetCongress&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://api.dc.gov&quot;&gt;DC &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://appsfordemocracy.org&quot;&gt;Apps for Democracy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Three Videos from RailsConf</title>
   <link href="http://luigimontanez.com/2009/three-videos-from-railsconf/"/>
   <updated>2009-05-29T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/three-videos-from-railsconf/three-videos-from-railsconf</id>
   <content type="html">&lt;p&gt;I attended &lt;a href=&quot;http://railsconf.com&quot;&gt;RailsConf 2009&lt;/a&gt; earlier this month. Overall, it was a good conference, and any commentary on the city to be made has already been made by others.&lt;/p&gt;
&lt;p&gt;I brought my &lt;a href=&quot;http://www.theflip.com/&quot;&gt;Flip Mino HD&lt;/a&gt; with me. While great for shooting outdoor (or very well-lit) scenes, I find the Flip doesn&amp;#8217;t perform as admirably in lower light situations, which is unfortunately the environment of a conference hall. Also, the Flip is optimized to record voice at close distance, so picking up mic audio from a speaker system wasn&amp;#8217;t ideal either.&lt;/p&gt;
&lt;p&gt;That being said, here are three videos I recorded at RailsConf. The TweetCongress video has the best audio quality, while the Gov 2.0 Panel, I&amp;#8217;m sad to say, has the worst.&lt;/p&gt;
&lt;p&gt;&lt;object width=&quot;400&quot; height=&quot;300&quot;&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;movie&quot; value=&quot;http://vimeo.com/moogaloop.swf?clip_id=4584581&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; /&gt;&lt;embed src=&quot;http://vimeo.com/moogaloop.swf?clip_id=4584581&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; allowscriptaccess=&quot;always&quot; width=&quot;400&quot; height=&quot;300&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;a href=&quot;http://vimeo.com/4584581&quot;&gt;Build an App, Start a Movement&lt;/a&gt; from &lt;a href=&quot;http://vimeo.com/user633451&quot;&gt;Luigi Montanez&lt;/a&gt; on &lt;a href=&quot;http://vimeo.com&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;/p&gt;
&lt;p&gt;&lt;object width=&quot;400&quot; height=&quot;300&quot;&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;movie&quot; value=&quot;http://vimeo.com/moogaloop.swf?clip_id=4611379&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; /&gt;&lt;embed src=&quot;http://vimeo.com/moogaloop.swf?clip_id=4611379&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; allowscriptaccess=&quot;always&quot; width=&quot;400&quot; height=&quot;300&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;a href=&quot;http://vimeo.com/4611379&quot;&gt;The Russian Doll Pattern&lt;/a&gt; from &lt;a href=&quot;http://vimeo.com/user633451&quot;&gt;Luigi Montanez&lt;/a&gt; on &lt;a href=&quot;http://vimeo.com&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;/p&gt;
&lt;p&gt;&lt;object width=&quot;400&quot; height=&quot;300&quot;&gt;&lt;param name=&quot;allowfullscreen&quot; value=&quot;true&quot; /&gt;&lt;param name=&quot;allowscriptaccess&quot; value=&quot;always&quot; /&gt;&lt;param name=&quot;movie&quot; value=&quot;http://vimeo.com/moogaloop.swf?clip_id=4589932&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; /&gt;&lt;embed src=&quot;http://vimeo.com/moogaloop.swf?clip_id=4589932&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; allowscriptaccess=&quot;always&quot; width=&quot;400&quot; height=&quot;300&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;a href=&quot;http://vimeo.com/4589932&quot;&gt;Government 2.0 Panel at RailsConf&lt;/a&gt; from &lt;a href=&quot;http://vimeo.com/user633451&quot;&gt;Luigi Montanez&lt;/a&gt; on &lt;a href=&quot;http://vimeo.com&quot;&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>What's with the Wolfram|Alpha Control Room?</title>
   <link href="http://luigimontanez.com/2009/what-s-with-the-wolfram-alpha-control-room/"/>
   <updated>2009-05-18T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/what-s-with-the-wolfram-alpha-control-room/what-s-with-the-wolfram-alpha-control-room</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090519-dtiqecgae5486m263a7724pwgk.png&quot; alt=&quot;control-rm-1.jpg (JPEG Image, 500x331 pixels)&quot;/&gt;&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s no doubt about it, the launch of &lt;a href=&quot;http://www64.wolframalpha.com/input/&quot;&gt;Wolfram|Alpha&lt;/a&gt; has been truly strange.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s the technology itself. All answers get rendered as images, even &lt;a href=&quot;http://www58.wolframalpha.com/input/?i=2%2B2&quot;&gt;when they don&amp;#8217;t need to be&lt;/a&gt;. It doesn&amp;#8217;t handle &lt;a href=&quot;http://www58.wolframalpha.com/input/?i=Standards+%26+Poors&quot;&gt;obvious errors very well&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;They oddly chose to launch on Friday night, a time when even the majority of Battlestar Galactica fans opted to use their DVRs and go out. And they&amp;#8217;ve fed a media hype machine to levels that they cannot possibly live up to.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090519-kmnse2quy725b26bmfubs2rf1e.png&quot; alt=&quot;Wolfram|Alpha Blog : Counting Down&quot;/&gt;&lt;/p&gt;
&lt;p&gt;But the weirdest thing about Wolfram|Alpha is that they have a &lt;a href=&quot;http://blog.wolframalpha.com/2009/05/15/counting-down/&quot;&gt;control room&lt;/a&gt;, like &lt;span class=&quot;caps&quot;&gt;NASA&lt;/span&gt;, or like the villains from 24. Nerds hunch over their laptops in stadium style seating, with huge monitors and projected images on a big wall in front of them. Apparently, launching a web app is &lt;strong&gt;serious business&lt;/strong&gt;. They even have a &lt;a href=&quot;http://www.justin.tv/clip/2dd6b9f07e7f8a4e&quot;&gt;live web feed&lt;/a&gt;, which primarily broadcasts video of some guy standing at the back of the room scratching himself.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090519-heb7ws6mra4w19kapup544akt.png&quot; alt=&quot;Justin.tv - Wolfram|Alpha Launch&quot;/&gt;&lt;/p&gt;
&lt;p&gt;So, if you think this is all incredibly surreal like I do, I invite you to take any of the above images, download &lt;a href=&quot;http://plasq.com/comiclife&quot;&gt;Comic Life&lt;/a&gt;, and have some fun. Here&amp;#8217;s my stab at it:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://img.skitch.com/20090519-qtt27nmn7gmcytp8dp8dpm7nfq.png&quot; alt=&quot;Wolfram|Alpha&quot;/&gt;&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Ruby on Rails != Its Core Team</title>
   <link href="http://luigimontanez.com/2009/ruby-on-rails-its-core-team/"/>
   <updated>2009-04-30T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/ruby-on-rails-its-core-team/ruby-on-rails-its-core-team</id>
   <content type="html">&lt;p&gt;While observing the hullabaloo surrounding the Rails community in recent days, one meme kept popping up that struck me as simply not true: The notion that the Rails community is centered around a group of self-aggrandizing rock star programmers, namely &lt;span class=&quot;caps&quot;&gt;DHH&lt;/span&gt; and his core team. This cannot be further from reality. The strength of Rails lies in the vast, diverse community of developers who have sought time and time again to help each other out, to teach others, and to share code, primarily because it gave them joy to do so.&lt;/p&gt;
&lt;p&gt;As a complete nobody in the Rails community, I&amp;#8217;ve done much more observation and learning than I have done sharing these past few years. As such, I&amp;#8217;d like to share with you a list of people in the Rails world who have established themselves not through their status or through the force of their personality, but through their output.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://pragdave.pragprog.com/&quot;&gt;Dave Thomas&lt;/a&gt; &amp;#8211; The author of the &lt;a href=&quot;http://pragprog.com/titles/ruby3/programming-ruby-1-9&quot;&gt;Programming Ruby/PickAxe&lt;/a&gt; book, and the main author of the first few editions of &lt;a href=&quot;http://pragprog.com/titles/rails3/agile-web-development-with-rails-third-edition&quot;&gt;Agile Web Development with Rails&lt;/a&gt;, Dave was probably the guy who taught you Ruby and Rails.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.rubypal.com/&quot;&gt;David Black&lt;/a&gt; &amp;#8211; The author of the now-classic &lt;a href=&quot;http://www.manning.com/black/&quot;&gt;Ruby for Rails&lt;/a&gt; (&lt;a href=&quot;http://www.manning.com/black2/&quot;&gt;refreshed edition&lt;/a&gt; coming out soon), David provided some essential reading for the Rails developer looking to harness the power of Ruby. Also director of &lt;a href=&quot;http://www.rubycentral.org/&quot;&gt;Ruby Central&lt;/a&gt;, the organization behind &lt;a href=&quot;http://rubyconf.org/&quot;&gt;RubyConf&lt;/a&gt; and &lt;a href=&quot;http://railsconf.com&quot;&gt;RailsConf&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://weblog.jamisbuck.org/&quot;&gt;Jamis Buck&lt;/a&gt; &amp;#8211; A guy who whittles wood in his spare time while living in Idaho, Jamis created the invaluable &lt;a href=&quot;http://capify.org&quot;&gt;Capistrano&lt;/a&gt; deployment tool to help us automate away tedium. He used to be on the Rails Core team, so putting him here may be fudging the list criteria, but his contributions have been so huge (both his projects and his blog posts), that he deserves a mention.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://brainspl.at/&quot;&gt;Ezra Zygmuntowicz&lt;/a&gt; &amp;#8211; Literally &lt;a href=&quot;http://www.pragprog.com/titles/fr_deploy/deploying-rails-applications&quot;&gt;writing the book&lt;/a&gt; on Rails deployment, Ezra did the hard work of figuring out what exactly constituted a solid Rails stack when the existing options left plenty to be desired. He has since worked on a myriad of projects, including &lt;a href=&quot;http://merbivore.com&quot;&gt;Merb&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://yehudakatz.com/&quot;&gt;Yehuda Katz&lt;/a&gt; &amp;#8211; &lt;a href=&quot;http://twitter.com/wycats&quot;&gt;@wycats&lt;/a&gt; may be the man who saves Rails from itself. As the lead driver for Rails 3.0, he&amp;#8217;s already begun sharing the gory details of the Merb/Rails merge to the eagerly waiting masses. He&amp;#8217;s also contributed greatly to &lt;a href=&quot;http://jquery.com&quot;&gt;jQuery&lt;/a&gt;, Merb, and &lt;a href=&quot;http://datamapper.org/&quot;&gt;Datamapper&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://twitter.com/wifelette&quot;&gt;Leah Silber&lt;/a&gt; &amp;#8211; Whenever you go to a regional Ruby conference, you&amp;#8217;ll always see Engine Yard as the top sponsor. While EY may send Ezra, Yehuda, and others to present at these conferences, it&amp;#8217;s the behind-the-scenes help provided by Leah and company that really make a conference successful.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://blog.davidchelimsky.net/&quot;&gt;David Chelimsky&lt;/a&gt; &amp;#8211; Behavior Driven Development is a complete win that we in the Rails community get to enjoy, and as lead developer of RSpec, David has shown a solid and steadfast commitment to continuously improving the tool so that it in turn improves our software.&lt;/li&gt;
	&lt;li&gt;The &lt;a href=&quot;http://giantrobots.thoughtbot.com/&quot;&gt;Thoughtbot&lt;/a&gt; team &amp;#8211; This company&amp;#8217;s work speaks for itself: &lt;a href=&quot;http://www.thoughtbot.com/projects/shoulda/&quot;&gt;Shoulda&lt;/a&gt;, &lt;a href=&quot;http://www.thoughtbot.com/projects/factory_girl/&quot;&gt;Factory Girl&lt;/a&gt;, &lt;a href=&quot;http://www.thoughtbot.com/projects/paperclip/&quot;&gt;Paperclip&lt;/a&gt;, and &lt;a href=&quot;http://www.hoptoadapp.com/&quot;&gt;Hoptoad&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://twitter.com/rbates&quot;&gt;Ryan Bates&lt;/a&gt; &amp;#8211; Putting out one or two &lt;a href=&quot;http://railscasts.com/&quot;&gt;RailsCasts&lt;/a&gt; a week for over two years, Ryan has been amazingly consistent both in the quality of his work and in his dedication to helping us become better Rails programmers.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://railstips.org/&quot;&gt;John Nunemaker&lt;/a&gt; &amp;#8211; RailsTips may be the most consistently helpful of all the Rails blogs.&lt;/li&gt;
	&lt;li&gt;The &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt; team &amp;#8211; Even without considering the contribution the site itself has made, the developers behind GitHub have contributed some fantastic projects to the community, namely &lt;a href=&quot;http://cheat.errtheblog.com/&quot;&gt;Cheat&lt;/a&gt;, &lt;a href=&quot;http://github.com/defunkt/cache_fu&quot;&gt;cache_fu&lt;/a&gt;, &lt;a href=&quot;http://github.com/mojombo/jekyll/&quot;&gt;Jekyll&lt;/a&gt;, and &lt;a href=&quot;http://god.rubyforge.org/&quot;&gt;god&lt;/a&gt;, and they&amp;#8217;ve done plenty of &lt;a href=&quot;http://errtheblog.com/&quot;&gt;helpful&lt;/a&gt; &lt;a href=&quot;http://jointheconversation.org/blog.html&quot;&gt;blogging&lt;/a&gt; &lt;a href=&quot;http://tom.preston-werner.com/&quot;&gt;along&lt;/a&gt; the way.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The people above have written essential libraries, authored books, produced other educational material, and/or helped organize conferences. In other words, they&amp;#8217;ve taken the great technical work of the Rails Core Team, and created a community around it.&lt;/p&gt;
&lt;p&gt;The above list is by no means comprehensive. So if you believe I&amp;#8217;m missing someone, please leave a comment below. Also, in addition to Jamis and Yehuda, there are many of members of the Rails Core team who do it for the music, so to speak, and nothing else. But hopefully the list above conveys the point that Ruby on Rails is so much more than &lt;span class=&quot;caps&quot;&gt;DHH&lt;/span&gt; and its small group of core committers.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Respect the Browser - Lessons from JSConf 2009</title>
   <link href="http://luigimontanez.com/2009/respect-the-browser-lessons-from-jsconf-2009/"/>
   <updated>2009-04-29T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/respect-the-browser-lessons-from-jsconf-2009/respect-the-browser-lessons-from-jsconf-2009</id>
   <content type="html">&lt;p&gt;&amp;#8220;This is the real &lt;a href=&quot;http://events.carsonified.com/fowa/2009/miami/content&quot;&gt;Future of Web Apps&lt;/a&gt; conference,&amp;#8221; I thought to myself during the first day of &lt;a href=&quot;http://jsconf2009.com&quot;&gt;JSConf 2009&lt;/a&gt;, the first Javascript-focused conference. Upon further reflection of the weekend, I realize that my idea of what a web application can be, and more importantly, how it should be created, has been fundamentally altered. The web browser, usually thought of as a dumb, thin client, is actually full of unrealized potential. It&amp;#8217;s time that we, as web developers, tap that well and create a tidal wave of innovation. (This idea was championed by conference organizer &lt;a href=&quot;http://twitter.com/voodootikigod&quot;&gt;Chris Williams&lt;/a&gt; in an impromptu lighting talk during the conference.)&lt;/p&gt;
&lt;p&gt;In short, we should treat the web browser as a first-class development platform, and Javascript as a Serious Language&amp;trade;. No longer just for presentation, a browser can process business logic, and it can talk directly to our data stores. In offline mode, it can talk to its own data store and sync up later. A well-written application for the browser can give our users a markedly better, smoother experience. For developers, browser-centric development can help us deliver better applications faster, continuing on the promise of agile web frameworks like Django and Rails.&lt;/p&gt;
&lt;p&gt;JSConf opened my eyes to the work already under way to accomplishing those goals.&lt;/p&gt;
&lt;h3&gt;The Frameworks&lt;/h3&gt;
&lt;p&gt;The two &amp;#8220;killer&amp;#8221; frameworks out there today are &lt;a href=&quot;http://sproutcore.com&quot;&gt;SproutCore&lt;/a&gt; and &lt;a href=&quot;http://cappuccino.org/&quot;&gt;Cappuccino&lt;/a&gt;. Both aim to give users a Mac OS X-like experience on the Web. SproutCore is what powers Apple&amp;#8217;s &lt;a href=&quot;http://me.com&quot;&gt;MobileMe&lt;/a&gt; and &lt;a href=&quot;http://otherinbox.com&quot;&gt;OtherInbox&lt;/a&gt;, while Cappuccino powers the Apply Keynote-like &lt;a href=&quot;http://280slides.com&quot;&gt;280 Slides&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Francisco Tolmasky of &lt;a href=&quot;http://280north.com&quot;&gt;280 North&lt;/a&gt; kicked off the conference with an overview of Cappuccino and Objective-J (an Objective-C-like superset of Javascript) and a drawdropping demo of the &lt;code&gt;nib2cib&lt;/code&gt; utility, which allows a Mac developer to use XCode&amp;#8217;s Interface Builder to &lt;a href=&quot;http://wiki.github.com/280north/cappuccino/nib2cib&quot;&gt;construct Cappuccino interfaces&lt;/a&gt;. Overall, it appears that Cappuccino is targeted at Cocoa developers.&lt;/p&gt;
&lt;p&gt;SproutCore, on the other hand, is a &lt;a href=&quot;http://www.sproutcore.com/documentation/hello-world-tutorial/&quot;&gt;Ruby gem&lt;/a&gt;, uses &lt;span class=&quot;caps&quot;&gt;ERB&lt;/span&gt; for templating, and supports Rubyish concepts like &lt;a href=&quot;http://wiki.github.com/sproutit/sproutcore/about-mixins&quot;&gt;Mixins&lt;/a&gt;. Mike Subelsky, co-founder of &lt;a href=&quot;http://otherinbox.com&quot;&gt;OtherInbox&lt;/a&gt; and upcoming &lt;a href=&quot;http://chadfowler.com/2009/4/22/railsconf-speaker-interview-mike-subelsky&quot;&gt;speaker at RailsConf&lt;/a&gt;, presented on SproutCore on day 2. He stressed the importance of &lt;a href=&quot;http://wiki.github.com/sproutit/sproutcore/sproutcore-s-modern-model-layer&quot;&gt;Key-Value Coding and Key-Value Observing&lt;/a&gt; in his talk, concepts which I admit I don&amp;#8217;t yet fully grasp. Interestingly, it looks like SproutCore is in the early stages of &lt;a href=&quot;http://www.sproutcore.com/2009/03/15/sproutcore-goes-mobile/&quot;&gt;iPhone support&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Speaking of the iPhone, a mobile framework called &lt;a href=&quot;http://phonegap.com&quot;&gt;PhoneGap&lt;/a&gt; was presented as well. Currently targeting iPhone, Android, and Blackberry (with Palm Pre, Windows Mobile, and Nokia on the way), PhoneGap lets you write your web app (in HTML+Javascript) once, and have it available for all supported platforms (along with proper skinning for the target platform). PhoneGap also comes built in with offline storage support, and does other nice things for you like geolocation and harnessing the accelerometer.&lt;/p&gt;
&lt;p&gt;One final framework worth mentioning is &lt;a href=&quot;http://titaniumapp.com&quot;&gt;Titanium&lt;/a&gt;. This is the easiest to explain: it&amp;#8217;s Adobe Air or Microsoft Silverlight, but using &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;/&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; and Javascript instead of proprietary languages. A &lt;a href=&quot;http://titaniumapp.com/demos&quot;&gt;Tweetie-like&lt;/a&gt; app was demoed by &lt;a href=&quot;http://appcelerator.org/&quot;&gt;Appcelerator &lt;span class=&quot;caps&quot;&gt;CEO&lt;/span&gt;&lt;/a&gt; Jeff Haynie, and it was certainly impressive.&lt;/p&gt;
&lt;p&gt;Something that wasn&amp;#8217;t presented, but I was given a demo of by a Mozilla employee, is &lt;a href=&quot;https://bespin.mozilla.com/&quot;&gt;Bespin&lt;/a&gt;, which is a web-based code editor harnessing the &lt;span class=&quot;caps&quot;&gt;CANVAS&lt;/span&gt; tag in HTML5.&lt;/p&gt;
&lt;h3&gt;Dealing with Data and Processes&lt;/h3&gt;
&lt;p&gt;One of the negatives associated with Javascript has been a lack of options when it comes to data persistence. In recent years, we&amp;#8217;ve seen support for &lt;a href=&quot;http://gears.google.com/&quot;&gt;Gears&lt;/a&gt; and HTML5&amp;#8217;s &lt;a href=&quot;http://dev.w3.org/html5/webstorage/&quot;&gt;WebStorage&lt;/a&gt; implemented in the browser, and these suffice for most use cases. There&amp;#8217;s also been talk of &lt;a href=&quot;http://damienkatz.net/2009/04/couchdb_in_the_browser.html&quot;&gt;CouchDB in the browser&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Gears also supports the notion of a worker pool, and Firefox will soon have &lt;a href=&quot;https://developer.mozilla.org/En/Using_DOM_workers&quot;&gt;Web WWorkers&lt;/a&gt;, both of which allow arbitrary Javascript to be executed in the background. For real-time messaging, Jack Moffitt presented on &lt;a href=&quot;http://code.stanziq.com/strophe/&quot;&gt;Strophe.js&lt;/a&gt;, a library for writing &lt;span class=&quot;caps&quot;&gt;XMPP&lt;/span&gt; clients, which improves on the &lt;a href=&quot;http://en.wikipedia.org/wiki/Comet_(programming)&quot;&gt;Comet&lt;/a&gt; concept that popped up a few years ago.&lt;/p&gt;
&lt;h3&gt;Browsers Almost There&lt;/h3&gt;
&lt;p&gt;With the pending releases of Safari 4, Firefox 3.1, and Google Chrome 2, there&amp;#8217;s an arms race among browser camps to see who can come up with the best and fastest Javascript engine while building in the most comprehensive support for HTML5. That&amp;#8217;s definitely a Good Thing. Who wouldn&amp;#8217;t want to write code for a development platform simultaneously supported by Apple, Mozilla, and Google?&lt;/p&gt;
&lt;p&gt;So, what about Internet Explorer? The latest version (IE8) does &lt;a href=&quot;http://www.sdtimes.com/content/article.aspx?ArticleID=31806&quot;&gt;support some, but not all, of HTML5&lt;/a&gt;, and Gears is available for storage and threading. But I think this is an issue where we developers need to draw a line in the sand and send a clear message: Either Microsoft catches up with the others, or it gets left behind. If we treat Internet Explorer as a dying platform, it will become one. I&amp;#8217;m talking about all versions of IE, not just the oft-maligned IE6.&lt;/p&gt;
&lt;h3&gt;There&amp;#8217;s More&lt;/h3&gt;
&lt;p&gt;For a more comprehensive blow-by-blow, see &lt;a href=&quot;http://www.michaelharrison.ws/weblog/?p=132&quot;&gt;Michael Harrison&amp;#8217;s recap&lt;/a&gt;. Conference organizer Chris Williams &lt;a href=&quot;http://voodootikigod.com/2009/04/28/javascript-the-great-part/&quot;&gt;penned a recap&lt;/a&gt; as well.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Plucking Out Article Content from an Arbitrary Web Page</title>
   <link href="http://luigimontanez.com/2009/plucking-out-article-content-from-an-arbitrary-web-page/"/>
   <updated>2009-03-22T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/plucking-out-article-content-from-an-arbitrary-web-page/plucking-out-article-content-from-an-arbitrary-web-page</id>
   <content type="html">&lt;p&gt;For Defogger, the user should be able to paste in a &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; (or click on a bookmarklet when on another web page) and get back a defogged, enhanced view of the content. Using OpenCalais, Defogger can figure out the important people, organizations, events, and relationships contained in a news article. While &lt;a href=&quot;http://www.opencalais.com/APIcalls#inputcontent&quot;&gt;OpenCalais&lt;/a&gt; does accept &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; as input, it assumes that everything in the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; is fair game. For example, putting &lt;a href=&quot;http://www.google.com/hostednews/ap/article/ALeqM5gd2xGykkCnfLhKopnaeC8-qYjWEAD9735NUG0&quot;&gt;this AP article&lt;/a&gt; hosted on Google through OpenCalais will return &amp;#8220;Google&amp;#8221; as a company mentioned in the article, when in fact Google is only detected because its name is contained in all the extra clutter around the content of the article.&lt;/p&gt;
&lt;p&gt;So I needed a way to remove that extra clutter and pass on exactly what mattered to OpenCalais. Interestingly, I had seen this problem already solved with a bookmarklet called &lt;a href=&quot;http://lab.arc90.com/experiments/readability/&quot;&gt;Readability&lt;/a&gt;, &amp;#8220;a simple tool that makes reading on the Web more enjoyable by removing the clutter around what you&amp;#8217;re reading&amp;#8221;. Try out the bookmarklet on some websites to see for yourself. It seems almost magical, and comes in handy all the time, especially for long articles, or for reading on the iPhone.&lt;/p&gt;
&lt;p&gt;Luckily for me, Readability is open source, with the &lt;a href=&quot;http://code.google.com/p/arc90labs-readability/source/browse/trunk/js/readability.js&quot;&gt;code hosted on Google Code&lt;/a&gt;. It was just up to me to translate the Javascript algorithm into Ruby. So here&amp;#8217;s my version of the code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;open-uri&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;nokogiri&amp;#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;pluck_article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
  &lt;span class=&quot;c1&quot;&gt;# get the raw HTML&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;Nokogiri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:HTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  
  
  &lt;span class=&quot;c1&quot;&gt;# get the paragraphs&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;paragraphs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;p&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# assign points to the parent nodes for each paragraph&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;paragraphs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculate_points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;has_key?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# get the parent node with the highest point total&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;winner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# return the plucked HTML content&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;h1&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;title&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inner_html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;/h1&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;winner&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inner_html&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculate_points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;starting_points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# reward for being a new paragraph&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;starting_points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# look at the id and class of paragraph and parent&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;classes_and_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; 
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; 
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 

  &lt;span class=&quot;c1&quot;&gt;# deduct severely and return if clearly not content&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;classes_and_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/comment|meta|footer|footnote/&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3000&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# reward if probably content&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;classes_and_ids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/post|hentry|entry|article/&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;  
  
  &lt;span class=&quot;c1&quot;&gt;# look at the actual text of the paragraph&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;paragraph&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# deduct if very short&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# reward if long&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    
  &lt;span class=&quot;c1&quot;&gt;# deduct if no periods, question marks, or exclamation points&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;?&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;# reward for periods and commas&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;  
  
  &lt;span class=&quot;n&quot;&gt;points&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;#8217;ve commented the algorithms thoroughly, and Ruby is quite readable, so it should be easy to follow. Essentially, the code takes advantage of several common conventions used on modern websites:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;An article (or blog post or press release) is coded in &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; as a lot of text enclosed in &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tags.&lt;/li&gt;
	&lt;li&gt;Those &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tags are grouped together, usually under a containing &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element.&lt;/li&gt;
	&lt;li&gt;Written English contains a lot of commas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using those observations above, along with a few other tricks, the code assigns points to all elements that contain paragraphs on the page, and the containing element with the highest point value &amp;#8220;wins&amp;#8221;. To use this, it&amp;#8217;s a simple &lt;code&gt;pluck_article('http://www.path.to/some/article')&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve tried the method above out on the sites of the &lt;a href=&quot;http://www.nytimes.com/2009/03/23/business/economy/23toxic.html?_r=1&amp;amp;hp&quot;&gt;New York Times&lt;/a&gt;, &lt;a href=&quot;http://www.google.com/hostednews/ap/article/ALeqM5gd2xGykkCnfLhKopnaeC8-qYjWEAD9735NUG0&quot;&gt;Google AP News&lt;/a&gt;, &lt;a href=&quot;http://online.wsj.com/article/SB123759435215100809.html&quot;&gt;Wall Street Journal&lt;/a&gt;, &lt;a href=&quot;http://www.huffingtonpost.com/robert-kuttner/geithners-last-stand_b_177850.html&quot;&gt;Huffington Post&lt;/a&gt;, &lt;a href=&quot;http://www.athleticsnation.com/2009/3/22/806980/the-case-for-brett-anderso&quot;&gt;Athletics Nation&lt;/a&gt;, and even a press release on &lt;a href=&quot;http://www.house.gov/pelosi/press/releases/March09/cbo.html&quot;&gt;Nancy Pelosi&amp;#8217;s site&lt;/a&gt;. All worked pretty well. The one platform where the algorithm breaks (both for my implementation above and for Readability) is on Scoop, the blogging platform behind &lt;a href=&quot;http://www.dailykos.com/storyonly/2009/3/22/711696/-It-May-Be-Raining-Gold-Already-Because-of-Geithners-Cool-Policies&quot;&gt;Daily Kos&lt;/a&gt; and MyDD. Specifically, the parsing doesn&amp;#8217;t work on blog posts that have a long extended entry (usually diaries). This is because Scoop generates a blog post&amp;#8217;s main entry and extended entry as two separate &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements, and the extended entry &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; ends up &amp;#8220;winning&amp;#8221;. That&amp;#8217;s not at all semantically correct, but I don&amp;#8217;t expect it to ever be fixed. Subsequently, SoapBlox sites (like &lt;a href=&quot;http://openleft.com/showDiary.do;jsessionid=41278F811B4BEAF13A6A6200E3005B12?diaryId=12395&quot;&gt;OpenLeft&lt;/a&gt;) also have the main entry problem, as SoapBlox is a direct port of Scoop.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll sleep on the problem with Scoop/SoapBlox, but I&amp;#8217;m pretty happy with the solution for now. Next up for Defogger: building the page templates using Haml, Sass, and Compass.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Liveblogging the Development of Defogger</title>
   <link href="http://luigimontanez.com/2009/liveblogging-the-development-of-defogger/"/>
   <updated>2009-03-18T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/liveblogging-the-development-of-defogger/liveblogging-the-development-of-defogger</id>
   <content type="html">&lt;p&gt;The &lt;a href=&quot;http://sunlightlabs.com/appsforamerica&quot;&gt;Apps for America&lt;/a&gt; contest put on by the &lt;a href=&quot;http://sunlightfoundation.com&quot;&gt;Sunlight Foundation&lt;/a&gt; is happening right now, and submissions are due on March 31st. Like any respectable software developer, I&amp;#8217;ve put off working on my idea for far too long. With two weeks left to go, I&amp;#8217;m finally getting around to working on it, most recently coming up with some mocks of the home page:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://skitch.com/luigi/begrj/mock1.png-page-1-100-bitmap&quot;&gt;&lt;img src=&quot;http://img.skitch.com/20090319-rd85fqr44tqmqfqh8wqxucik1r.preview.jpg&quot; alt=&quot;mock1.png : Page 1 @ 100% (Bitmap)&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
&lt;a href=&quot;http://skitch.com/luigi/beqhq/defogger-mock-2&quot;&gt;&lt;img src=&quot;http://img.skitch.com/20090319-tndbudbbnmt8th9c2pxd51qihm.preview.jpg&quot; alt=&quot;Defogger Mock 2&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll likely go with the second mock, as the Capitol background is a bit too busy and won&amp;#8217;t work well for the interior, information-heavy pages. In the spirit of transparency, I&amp;#8217;ve decided to &amp;#8220;liveblog&amp;#8221; the entire process of creating the app during these next two weeks. I hope to share design decisions I make, problems I run across, and things I learn. Knowing that I have an audience will hopefully spur me on to create something really good, and maybe will encourage others to attempt an app of their own before the contest is over.&lt;/p&gt;
&lt;p&gt;So what&amp;#8217;s the idea behind Defogger? It&amp;#8217;s a simple app that uses &lt;a href=&quot;http://opencalais.com&quot;&gt;OpenCalais&lt;/a&gt; to semantically mark up a news article (or a blog post or a press release), and enhances the marked up document with transparency-related APIs. So imagine giving Defogger an article about some member of Congress presiding over the groundbreaking of some multi-million dollar project funded with stimulus money. Defogger would answer some of these questions:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;The Politician&lt;/strong&gt;: Which district does he represent, and for how long? Who are his biggest contributors? Are any of them mentioned in the article? Did this member of Congress put in an earmark or otherwise grease the legislative wheels for this project?&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;The Construction Company&lt;/strong&gt;: Does this company employ lobbyists? How much money have they contributed to members of Congress, and are any of those mentioned in this article?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Like any good side project, I&amp;#8217;m using Defogger as a means of learning some new tools and techniques:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://jquery.com&quot;&gt;jQuery&lt;/a&gt;: I don&amp;#8217;t know this Javascript framework nearly well enough, and usually need to defer to other teammates for their expertise. I want to become a jQuery ninja when this is all said and done.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://thoughtbot.com/projects/shoulda/&quot;&gt;Shoulda&lt;/a&gt;, &lt;a href=&quot;http://www.thoughtbot.com/projects/factory_girl/&quot;&gt;Factory Girl&lt;/a&gt;, and &lt;a href=&quot;http://mocha.rubyforge.org/&quot;&gt;Mocha&lt;/a&gt; for Behavior-Driven Development: I&amp;#8217;m comfortable with &lt;a href=&quot;http://rspec.info/&quot;&gt;RSpec&lt;/a&gt;, but I know that Shoulda is what the &amp;#8220;cool kids&amp;#8221; use in the Rails world, and I definitely could do &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; and &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; much better. I hope to build the entire app this way. I employed full &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; with the &lt;a href=&quot;http://sunlight.rubyforge.org&quot;&gt;Sunlight &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; Gem&lt;/a&gt; to great success.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://rubyonrails.org&quot;&gt;New Rails Features&lt;/a&gt; With Rails 2.3 just released, it&amp;#8217;s been far too long (since maybe Rails 2.0) since I did a &lt;code&gt;$ rails my_new_app&lt;/code&gt; on the command line. While Rails has been pretty stable these past two years, there are a lot of goodies that I&amp;#8217;ve never learned and tidbits I have yet to pick up. I hope to fill those gaps with this project.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://haml.hamptoncatlin.com/&quot;&gt;Haml + Sass&lt;/a&gt;, and &lt;a href=&quot;http://compass-style.org/&quot;&gt;Compass&lt;/a&gt;: While I don&amp;#8217;t have the best web design chops, I like to think I can hold my own. However, the process of skinning a site is always painful, and I&amp;#8217;m constantly looking for ways to produce better, more maintainable, front-end code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://37signals.com&quot;&gt;37signals&lt;/a&gt; likes to tell us to &lt;a href=&quot;http://gettingreal.37signals.com/ch03_Embrace_Constraints.php&quot;&gt;embrace constraints&lt;/a&gt;. Hopefully, I&amp;#8217;ll learn that lesson and more throughout these next two weeks. Please consider &lt;a href=&quot;http://feeds.feedburner.com/luigimontanez&quot;&gt;subscribing to my feed&lt;/a&gt; if you&amp;#8217;d like to come along for the ride.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Ruby Sunlight API Gem 0.9 Released</title>
   <link href="http://luigimontanez.com/2009/ruby-sunlight-api-gem-0-9-released/"/>
   <updated>2009-03-15T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2009/ruby-sunlight-api-gem-0-9-released/ruby-sunlight-api-gem-0-9-released</id>
   <content type="html">&lt;p&gt;This release includes support for two new fields on Legislator, a refactoring of the base functionality so that the gem is more compatible within Rails and Merb apps, and support for Lobbyists, Filings, and Issues. There is a new way to set up your Sunlight &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; Key, so this release is not backwards-compatible with releases 0.1. and 0.2.&lt;/p&gt;
&lt;p&gt;This gem is now considered a feature-complete wrapper around the Sunlight &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;, and will be bumped up to 1.0 after being used for a bit in the wild.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/luigi/sunlight&quot;&gt;GitHub&lt;/a&gt; | &lt;a href=&quot;http://sunlight.rubyforge.org&quot;&gt;RubyForge&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Changelog:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Warning: This release is not backwards-compatible!&lt;/li&gt;
	&lt;li&gt;Change loading behavior of base functionality, works better with Rails and Merb&lt;/li&gt;
	&lt;li&gt;Sunlight::SunlightObject is now Sunlight::Base&lt;/li&gt;
	&lt;li&gt;For set up, Sunlight.api_key= is now Sunlight::Base.api_key=&lt;/li&gt;
	&lt;li&gt;For set up, using &amp;#8220;include &amp;#8216;Sunlight&amp;#8217;&amp;#8221; is no longer recommended&lt;/li&gt;
	&lt;li&gt;Correct usage is Sunlight::Legislator.all_for(&amp;#8230;) instead of just Legislator.all_for(&amp;#8230;)&lt;/li&gt;
	&lt;li&gt;Credit to Rue the Ghetto (rughetto on GitHub) and Eric Mill for inspiring the improvements above&lt;/li&gt;
	&lt;li&gt;Add support for senate_class (&amp;#8220;I&amp;#8221;, &amp;#8220;II&amp;#8221;, or &amp;#8220;&lt;span class=&quot;caps&quot;&gt;III&lt;/span&gt;&amp;#8221;) and in_office (0 or 1) on Legislator&lt;/li&gt;
	&lt;li&gt;Add support for Lobbyists, Filings, and Issues&lt;/li&gt;
	&lt;li&gt;Huge credit to mindleak on GitHub for Lobbyist-related functionality&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Ruby Gem for the Sunlight Labs API Updated to 0.2</title>
   <link href="http://luigimontanez.com/2009/ruby-gem-for-the-sunlight-labs-api-updated-to-0-2/"/>
   <updated>2009-03-02T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2009/ruby-gem-for-the-sunlight-labs-api-updated-to-0-2/ruby-gem-for-the-sunlight-labs-api-updated-to-0-2</id>
   <content type="html">&lt;p&gt;Back in August, I released an initial version of a &lt;a href=&quot;http://sunlight.rubyforge.org&quot;&gt;Ruby gem&lt;/a&gt; for the &lt;a href=&quot;http://wiki.sunlightlabs.com/index.php/Sunlight_Labs_API&quot;&gt;Sunlight Labs &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;&lt;/a&gt;. The gem has since been used in many projects, most famously on &lt;a href=&quot;http://tweetcongress.org/&quot;&gt;Tweet Congress&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This weekend at &lt;a href=&quot;http://transparencycamp.org&quot;&gt;Transparency Camp&lt;/a&gt;, I set out to improve several aspects of the gem, including adding a twitter_id field, which wasn&amp;#8217;t there back in August when I made the initial release. Changes include:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Add support for twitter_id and youtube_url on Legislator&lt;/li&gt;
	&lt;li&gt;Add Legislator#search_by_name for fuzzy name searching&lt;/li&gt;
	&lt;li&gt;Add Legislator#all_in_zipcode for better lookups on a five-digit zip code&lt;/li&gt;
	&lt;li&gt;Raise exception when &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; Key isn&amp;#8217;t set&lt;/li&gt;
	&lt;li&gt;Credit for various fixes goes to GitHub users pengwynn, hoverbird, and wilson&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Check it out on &lt;a href=&quot;http://github.com/luigi/sunlight&quot;&gt;GitHub&lt;/a&gt;. Ruby developers participating in &lt;a href=&quot;http://appsforamerica.com&quot;&gt;Apps for America&lt;/a&gt; will hopefully find it indispensable.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Starting Back Up</title>
   <link href="http://luigimontanez.com/2009/starting-back-up/"/>
   <updated>2009-02-28T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2009/starting-back-up/starting-back-up</id>
   <content type="html">&lt;p&gt;Over the last eight months or so, my blog about software development at &lt;a href=&quot;http://salesforceonrails.com&quot;&gt;Salesforce on Rails&lt;/a&gt;, has been criminally neglected. The cause has been twofold. First, I&amp;#8217;ve just been incredibly busy, but that&amp;#8217;s a tired and lame excuse. More significantly, I&amp;#8217;ve largely stopped working with &lt;a href=&quot;http://salesforce.com&quot;&gt;Salesforce.com&lt;/a&gt; and the Force.com development framework, for reasons I&amp;#8217;ll get into later. So Salesforce on Rails is now retired, and I&amp;#8217;ll instead be blogging about software development here at &lt;a href=&quot;http://luigimontanez.com&quot;&gt;LuigiMontanez.com&lt;/a&gt;. Old entries from Salesforce on Rails will be migrated below this one.&lt;/p&gt;
&lt;p&gt;So LuigiMontanez.com is now my place to blog about software development technologies, and also about becoming a better programmer. I&amp;#8217;ve been heavily into the idea of &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_Craftsmanship&quot;&gt;software craftsmanship&lt;/a&gt; lately, facing the harsh reality that I have enormous room for improvement as a software developer. I&amp;#8217;ll still blog about the intersection of potitics and technology at &lt;a href=&quot;http://leftmostbit.com&quot;&gt;Leftmost Bit&lt;/a&gt;, so please do grab that feed if you&amp;#8217;re interested.&lt;/p&gt;
&lt;p&gt;What&amp;#8217;s next for LuigiMontanez.com? Well, in addition to sharing my efforts on becoming a better software developer and project lead, I&amp;#8217;ll be blogging about these technologies that are currently piquing my interest:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Ruby and Rails&lt;/li&gt;
	&lt;li&gt;jQuery&lt;/li&gt;
	&lt;li&gt;CouchDB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;m also planning to participate in the &lt;a href=&quot;http://appsforamerica.com&quot;&gt;Apps for America&lt;/a&gt; contest put on by &lt;a href=&quot;http://sunlightlabs.com&quot;&gt;Sunlight Labs&lt;/a&gt;. My submission will harness &lt;a href=&quot;http://opencalais.com&quot;&gt;Open Calais&lt;/a&gt; and the various government transparency APIs, creating a tool to allow users to clear the fog about some of the non-obvious connections between our elected officials, special interests, and the laws and policies coming out of government. It&amp;#8217;ll be called Defogger.org.&lt;/p&gt;
&lt;p&gt;Compelled by the contest&amp;#8217;s spirit of transparency, I&amp;#8217;ll be blogging the entire app development process right here, from start to finish. With the contest deadline set for March 31, I certainly need to get started on the project sooner than later, and what better way than to force myself to blog about it on a regular basis.&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Accessing Passenger sites from a Vista instance in VMware Fusion</title>
   <link href="http://luigimontanez.com/2009/accessing-passenger-sites-from-a-windows-vista-instance-in-vmware-fusion/"/>
   <updated>2009-02-12T00:00:00-05:00</updated>
   <id>http://luigimontanez.com/2009/accessing-passenger-sites-from-a-windows-vista-instance-in-vmware-fusion/accessing-passenger-sites-from-a-windows-vista-instance-in-vmware-fusion</id>
   <content type="html">&lt;p&gt;This &lt;a href=&quot;http://www.robbyonrails.com/articles/2009/02/11/switch-to-passenger-mod_rails-in-development-on-osx-in-less-than-7-minutes-or-your-money-back&quot;&gt;article by Robby Russell&lt;/a&gt; reminded me of a hopefully helpful post I&amp;#8217;ve been meaning to write for a while. The problem is straightforward: You&amp;#8217;ve got &lt;a href=&quot;http://modrails.com&quot;&gt;Phusion Passenger&lt;/a&gt; set up on your Mac OS X Leopard (see Robby&amp;#8217;s post for details). Your client called, and they say the site you just launched for them looks funky in Internet Explorer. Fun. So now, you want to access your local Passenger site living at &lt;a href=&quot;http://myapp.local&quot;&gt;http://myapp.local&lt;/a&gt; from the copy of Windows Vista living in your &lt;a href=&quot;http://www.vmware.com/products/fusion/&quot;&gt;VMware Fusion&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are two things you need to do in order to access your Passenger sites from Windows Vista via VMware Fusion:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Figure out what Vista thinks is your Mac&amp;#8217;s IP address&lt;/li&gt;
	&lt;li&gt;Create entries in Vista&amp;#8217;s /etc/hosts file (yes, Vista actually has one)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So fire up VMware and Vista, and let&amp;#8217;s begin:&lt;/p&gt;
&lt;h3&gt;Determine Vista&amp;#8217;s Gateway IP&lt;/h3&gt;
&lt;p&gt;When running VMware Fusion, the virtualized OS (in our case Vista) refers to the host system (Mac OS X Leopard) as its IP Gateway and its &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt;. So you want to figure out what that IP address is, and you&amp;#8217;ll be able to access the Apache server running in Leopard. Determine the IP with the following steps:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Open the Control Panel, switch to Classic View, open Network and Sharing Center.&lt;/li&gt;
	&lt;li&gt;Click on Manage Network Connections in the sidebar.&lt;/li&gt;
	&lt;li&gt;Double click on the Local Area Connection, and click on the Details button.&lt;/li&gt;
	&lt;li&gt;Make note of the IPv4 Default Gateway &amp;#8211; that&amp;#8217;s your ticket to accessing your Passenger sites.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;http://skitch.com/luigi/brc94/finding-the-gateway&quot;&gt;&lt;img src=&quot;http://img.skitch.com/20090212-b55errgiwu63xx5ugkq49qxdga.preview.jpg&quot; alt=&quot;Finding the Gateway&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Edit Vista&amp;#8217;s /etc/hosts file&lt;/h3&gt;
&lt;p&gt;I discovered this &lt;a href=&quot;http://maximumpcguides.com/windows-vista/edit-the-windows-vista-hosts-file/&quot;&gt;handy link&lt;/a&gt;, which tells you all you want to know about Vista&amp;#8217;s hosts file. In short, it works pretty much the same as any Unix /etc/hosts file. I followed the instructions to set up a shortcut on my Vista Desktop for quick access, and the screenshot of the Properties dialog for that shortcut is below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://skitch.com/luigi/brc9i/editing-the-hosts-file&quot;&gt;&lt;img src=&quot;http://img.skitch.com/20090212-8m5129pifiqubdy94t1pn25b99.preview.jpg&quot; alt=&quot;Editing the hosts file&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, just edit the file, creating an entry for each Passenger site:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;172.16.160.2 site1.local
172.16.160.2 site2.local
172.16.160.2 site3.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the file saved, you should be able to access your Passenger sites from a browser in Vista (no restart of anything needed).&lt;/p&gt;
&lt;h3&gt;Multiple IEs&lt;/h3&gt;
&lt;p&gt;Now for a bit of a bonus, I highly recommend installing &lt;a href=&quot;http://www.my-debugbar.com/wiki/IETester/HomePage&quot;&gt;IETester&lt;/a&gt; in Vista. IE8 beta 2, IE7, IE6 and IE5.5 will be at your fingertips.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Find this helpful?&lt;/strong&gt; Please consider recommending me on &lt;a href=&quot;http://www.workingwithrails.com/person/13437-luigi-montanez&quot;&gt;Working with Rails&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Custom Fields on Standard Objects in the Force.com IDE</title>
   <link href="http://luigimontanez.com/2008/custom-fields-on-standard-objects-in-the-force-com-ide/"/>
   <updated>2008-06-28T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2008/custom-fields-on-standard-objects-in-the-force-com-ide/custom-fields-on-standard-objects-in-the-force-com-ide</id>
   <content type="html">&lt;p&gt;Browsing through the Force.com Discussion Boards while playing with the &lt;a href=&quot;http://wiki.apexdevnet.com/index.php/Force.com_IDE_Release_Notes#Summer_.2708_Developer_Preview&quot;&gt;new version&lt;/a&gt; of the Force.com &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt; (released June 19), the ever helpful JonP &lt;a href=&quot;http://community.salesforce.com/sforce/board/message?board.id=apex&amp;amp;view=by_date_ascending&amp;amp;message.id=5758#M5758&quot;&gt;explained exactly how&lt;/a&gt; to generate a .object file on standard objects.&lt;/p&gt;
&lt;p&gt;Fire up Eclipse, and in your Force.com project open up src/unpackaged/package.xml. Find the &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; element with the name of &amp;#8220;CustomObject&amp;#8221; and add in some new subelements with the value of the standard object. It should look like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;types&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;members&amp;gt;&lt;/span&gt;*&lt;span class=&quot;nt&quot;&gt;&amp;lt;/members&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;CustomObject&lt;span class=&quot;nt&quot;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;members&amp;gt;&lt;/span&gt;Contact&lt;span class=&quot;nt&quot;&gt;&amp;lt;/members&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;members&amp;gt;&lt;/span&gt;Account&lt;span class=&quot;nt&quot;&gt;&amp;lt;/members&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/types&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, run the &amp;#8220;Refresh from Server&amp;#8221; functionality by right-clicking on src/objects and accessing the Force.com menu. Your standard objects should then appear.&lt;/p&gt;
&lt;p&gt;Alternatively, if you&amp;#8217;re paranoid about too many custom fields being editable (and quickly erasable) in the &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;, you can stick in an entirely new types element named CustomField that looks like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;types&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;members&amp;gt;&lt;/span&gt;Opportunity.SomeCustomField__c&lt;span class=&quot;nt&quot;&gt;&amp;lt;/members&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;CustomField&lt;span class=&quot;nt&quot;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/types&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, you&amp;#8217;re able to use the power and speed of the &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt; to create, edit, and deploy custom fields on your standard objects. It&amp;#8217;s a great productivity win. A big thanks to JonP for explaining all this.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Engine Yard Express: A Production Slice on Your MacBook Pro</title>
   <link href="http://luigimontanez.com/2008/engine-yard-express-a-production-slice-on-your-macbook-pro/"/>
   <updated>2008-06-20T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2008/engine-yard-express-a-production-slice-on-your-macbook-pro/engine-yard-express-a-production-slice-on-your-macbook-pro</id>
   <content type="html">&lt;p&gt;While computing moves more and more to the cloud, it&amp;#8217;s interesting that Ruby web development best practices tend to go in the opposite direction, toward the workstation right in front of you. Running a local web server via &amp;#8216;script/server&amp;#8217; (or my preferred method of &amp;#8216;thin start&amp;#8217;), hosting &lt;a href=&quot;http://salesforceonrails.com/2008/running-a-local-gem-documentation-server-on-mac-os-x&quot;&gt;gem documentation locally&lt;/a&gt;, and using local git branches are all win/win practices because they&amp;#8217;re far more efficient, and frankly, let you do some bonehead moves without your co-workers ever having to know.&lt;/p&gt;
&lt;p&gt;So maybe deployments should be practiced locally as well. &lt;a href=&quot;http://brainspl.at/articles/2008/06/06/engine-yard-express&quot;&gt;Ezra Z.&lt;/a&gt; has announced &lt;a href=&quot;http://express.engineyard.com/&quot;&gt;Engine Yard Express&lt;/a&gt;, a VMware image that&amp;#8217;s essentially an &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt; production slice. The idea is that you run the image via virtualization software on your workstation, so that you can get all the benefits of a virtual server without having to actually connect to one through the Tubes.&lt;/p&gt;
&lt;p&gt;Yes, this really rocks. You&amp;#8217;ll be able practice deployments on the plane!&lt;/p&gt;
&lt;p&gt;So first, you&amp;#8217;ll need to buy &lt;a href=&quot;http://www.vmware.com/products/fusion/&quot;&gt;VMware Fusion&lt;/a&gt; for your Mac. I first purchased Parallels over a year ago, but VMware clearly kicks its ass. Clearly. It actually runs Windows without making the rest of your system unusable.&lt;/p&gt;
&lt;p&gt;Next, &lt;a href=&quot;http://express.engineyard.com/&quot;&gt;download the image&lt;/a&gt; and double-click on it. Before you even realize what happened, you&amp;#8217;ll be presented with a ready, fully-functional slice just waiting for you like an obedient dog:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/luigimontanez/2558712685/&quot; title=&quot;EY Express 0.1.1 by Luigi Montanez, on Flickr&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3170/2558712685_a426c59419.jpg&quot; width=&quot;500&quot; height=&quot;347&quot; alt=&quot;EY Express 0.1.1&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You&amp;#8217;ve been pleasantly provided with randomly generated passwords for the root and express users, and you&amp;#8217;re even given the IP address it&amp;#8217;s chosen.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s create an alias for that address so we don&amp;#8217;t have to memorize it. Open up /etc/hosts in your favorite text editor (requires sudo permission) and stick something like this in there:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;192.168.233.128 express.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, you should probably just leave your VMware window alone. Instead you&amp;#8217;ll want to &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; into the slice as if you were logging into a remote server:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh express@express.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nice! A quick visit to &lt;a href=&quot;http://express.local:81&quot;&gt;http://express.local:81&lt;/a&gt; gives you your Merb start page.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/luigimontanez/2559574162/&quot; title=&quot;EY Express Merb by Luigi Montanez, on Flickr&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3153/2559574162_db7db125f3.jpg&quot; width=&quot;409&quot; height=&quot;500&quot; alt=&quot;EY Express Merb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, in your Capistrano scripts, you can use &amp;#8216;express.local&amp;#8217; as the domain of your servers, and you&amp;#8217;ll be able to practice deployments without ever connecting to a remote server. Bom chicka wa waa!&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Running a Local Gem Documentation Server on Mac OS X</title>
   <link href="http://luigimontanez.com/2008/running-a-local-gem-documentation-server-on-mac-os-x/"/>
   <updated>2008-06-10T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2008/running-a-local-gem-documentation-server-on-mac-os-x/running-a-local-gem-documentation-server-on-mac-os-x</id>
   <content type="html">&lt;p&gt;When I first started playing around with Ruby on Rails, one of the things that struck me was how development was done completely locally. Instead of uploading or synchronizing your source code to a remote web server, you simply fired up a Ruby web server process on your local machine, and the development process seemed to flow more smoothly.&lt;/p&gt;
&lt;p&gt;In that same vein, documentation for Ruby gems can be annoying to hunt down. You have to go to the gem&amp;#8217;s web site, and hope that RDoc exists somewhere. Or, you can navigate to your gem&amp;#8217;s local install directory and poke around in there. Too much work, and it could break your flow. Not anymore:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gem server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, just visit &lt;a href=&quot;http://localhost:8808&quot;&gt;http://localhost:8808&lt;/a&gt;, and you&amp;#8217;re good to go. That easy!&lt;/p&gt;
&lt;p&gt;Also, you may find yourself missing RDoc on updated gems, so make sure to do this when it bothers you:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gem rdoc &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;--all|gem_name&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, it would be great if the server just started automatically on boot up, with no need for a command line directive. In Mac OS X Leopard, the preferred way is to use &lt;a href=&quot;http://developer.apple.com/macosx/launchd.html&quot;&gt;launchd/launchctl&lt;/a&gt;, which is about as obvious to the uninitiated as the rules of Cricket. Luckily, there&amp;#8217;s &lt;a href=&quot;http://lingon.sourceforge.net/&quot;&gt;Lingon&lt;/a&gt;, which wraps all that ugly &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; in a nice &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt;. Make a new entry that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/luigimontanez/2569726390/&quot; title=&quot;Lingon Gem Server by Luigi Montanez, on Flickr&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3002/2569726390_846e749a4b_o.png&quot; width=&quot;547&quot; height=&quot;632&quot; alt=&quot;Lingon Gem Server&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note the full path to the gem command, which I needed for the launch command to work. And that&amp;#8217;s it. Full documentation to all your locally installed gems, available whenever you need them.&lt;/p&gt;
&lt;p&gt;Special thanks to &lt;a href=&quot;http://www.danielfischer.com/2008/05/23/view-rdocs-for-all-local-gems-gem-server-to-the-rescue/&quot;&gt;Daniel Fischer&lt;/a&gt; for the &amp;#8216;gem server&amp;#8217; tip, and &lt;a href=&quot;http://workingwithrails.com/person/7942-brandon-beacher&quot;&gt;Brandon Beacher&lt;/a&gt; for the tip on Lingon.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Essential Force.com Resources</title>
   <link href="http://luigimontanez.com/2008/essential-force-com-resources/"/>
   <updated>2008-04-26T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2008/essential-force-com-resources/essential-force-com-resources</id>
   <content type="html">&lt;p&gt;Because the Force.com developer community is still very small, it&amp;#8217;s important to make the most out of what Salesforce.com (the company) provides for us on the Web. The best site for all things Force.com is of course &lt;a href=&quot;http://developer.force.com&quot;&gt;developer.force.com&lt;/a&gt;, with its invaluable &lt;a href=&quot;https://wiki.apexdevnet.com/index.php/Wiki&quot;&gt;Wiki&lt;/a&gt; and &lt;a href=&quot;http://community.salesforce.com/sforce?category.id=developers&quot;&gt;Discussion Boards&lt;/a&gt;. But sometimes dead-tree versions of knowledge can be helpful too.&lt;/p&gt;
&lt;h3&gt;Ebooks&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;SFDC&lt;/span&gt; has made available two free books, one is an introduction to the platfom and the other is a recipe-style book. If you&amp;#8217;ve been to a Force.com event recently, chances are you received these as actual, bound books. Here are the &lt;span class=&quot;caps&quot;&gt;PDF&lt;/span&gt; ebooks:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://wiki.apexdevnet.com/index.php/Creating_On-Demand_Applications:_An_Introduction_to_the_Force.com_Platform&quot;&gt;Introduction to the Force.com Platform&lt;/a&gt; &amp;#8211; Really a beginner&amp;#8217;s guide, this book takes you on a feature tour of the Force.com platform, and goes over both administrative/declarative features as well as the more programmatic Apex and Visualforce capabilities.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://wiki.apexdevnet.com/index.php/Members:Platform_Cookbook&quot;&gt;Force.com Cookbook&lt;/a&gt; &amp;#8211; I find myself flipping through this problem/solution recipe book often. It&amp;#8217;s very helpful at producing those &amp;#8220;Ah! So that&amp;#8217;s how I&amp;#8217;m supposed to do it!&amp;#8221; moments.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;The APIs&lt;/h3&gt;
&lt;p&gt;The Force.com Application Programmer Interfaces (APIs) allow us developers to integrate our Salesforce instances with external web services, as well build in some powerful customization into those instances. I don&amp;#8217;t print these out, but rather just keep the PDFs quickly accessible for fast keyword searching:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.salesforce.com/us/developer/docs/api/apex_api.pdf&quot;&gt;Apex Web Services &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;&lt;/a&gt; &amp;#8211; Covers the &lt;span class=&quot;caps&quot;&gt;SOAP&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; in all its glory. I personally wish this was &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt;, but &lt;span class=&quot;caps&quot;&gt;SOAP&lt;/span&gt; is better than everything but &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.salesforce.com/us/developer/docs/api_meta/api_meta.pdf&quot;&gt;Apex Metadata &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;&lt;/a&gt; &amp;#8211; A newer &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;, the Metadata &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; allows us to define the structure (fields and relationships) of our custom objects via &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; rather than via the declarative point-and-click interface. Unfortunately there&amp;#8217;s no Metadata &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; available for standard objects (Contacts, Accounts, Opportunities) yet, but I expect that to change this year.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.salesforce.com/us/developer/docs/ajax/apex_ajax.pdf&quot;&gt;Apex &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; Toolkit &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;&lt;/a&gt; &amp;#8211; The &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; Toolkit is primarily used with S-Controls, which are being phased out in favor of Visualforce. To be honest, the &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; Toolkit has always seemed like a workaround hack to me, and hopefully the combination of Visualforce and Apex Code will render it obsolete.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;The Developer Guides&lt;/h3&gt;
&lt;p&gt;These are must-prints. As more thorough extensions to the ebooks above, these guides are the definitive resources for developing with Apex and Visualforce.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.salesforce.com/us/developer/docs/apexcode/salesforce_apex_language_reference.pdf&quot;&gt;Apex Developer&amp;#8217;s Guide&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.salesforce.com/us/developer/docs/pages/salesforce_pages_developers_guide.pdf&quot;&gt;Visualforce Developer&amp;#8217;s Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Frequent Updates&lt;/h3&gt;
&lt;p&gt;Both the APIs and Developer Guides are updated with every release (Spring, Summer, Winter), so make sure to grab the newest versions when you see your org being updated, and please do recycle the old versions if you print them out.&lt;/p&gt;
&lt;p&gt;I suggest bookmarking this post, so you can quickly access these PDFs instead of browsing through the developer.force.com Wiki. Enjoy!&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Opening Gems in Textmate</title>
   <link href="http://luigimontanez.com/2008/opening-gems-in-textmate/"/>
   <updated>2008-04-12T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2008/opening-gems-in-textmate/opening-gems-in-textmate</id>
   <content type="html">&lt;p&gt;Here&amp;#8217;s a problem: you need to look at a gem&amp;#8217;s source code to figure out something, but you need to figure out the path to your gems directory, find the gem in question, and then open it from there. What a pain. Luckily, &lt;a href=&quot;http://drnicutilities.rubyforge.org/svn/find_gem/trunk/website/index.txt&quot;&gt;Dr. Nic&lt;/a&gt; has saved the day:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sudo gem install find_gem
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find_gem activerecord
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This also comes with the wonderful command &amp;#8216;edit_gem&amp;#8217;. Make sure you have your environment &lt;span class=&quot;caps&quot;&gt;EDITOR&lt;/span&gt; variable set in your .bash_login|.bash_profile|.bashrc:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;EDITOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;mate&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Save the file and source it:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; .bash_profile &lt;span class=&quot;c&quot;&gt;# or .bashrc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, &amp;#8220;edit_gem activerecord&amp;#8221; does what you think it should do. Nice little pieces of functionality like these really make the term &amp;#8220;gem&amp;#8221; so appropriate. Hat-tip to &lt;a href=&quot;http://effectif.com/2008/3/29/opening-ruby-gems-in-textmate&quot;&gt;Graham Ashton&lt;/a&gt; for sparking my interest to find a solution.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Presentation on Thin</title>
   <link href="http://luigimontanez.com/2008/presentation-on-thin/"/>
   <updated>2008-04-09T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2008/presentation-on-thin/presentation-on-thin</id>
   <content type="html">&lt;p&gt;Tonight, I&amp;#8217;ll be doing a Lightning Talk for the Atlanta Ruby Users Group on &lt;a href=&quot;http://code.macournoyer.com/thin/&quot;&gt;Thin&lt;/a&gt;, a Ruby web server. Below are my slides, accompanied by several resources:&lt;/p&gt;
&lt;div style=&quot;width:425px;text-align:left&quot; id=&quot;__ss_344581&quot;&gt;&lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=thin-1207766139353517-8&quot;/&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=thin-1207766139353517-8&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style=&quot;font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/?src=embed&quot;&gt;&lt;img src=&quot;http://static.slideshare.net/swf/logo_embd.png&quot; style=&quot;border:0px none;margin-bottom:-5px&quot; alt=&quot;SlideShare&quot;/&gt;&lt;/a&gt; | &lt;a href=&quot;http://www.slideshare.net/luigimontanez/thin-344581?src=embed&quot; title=&quot;View 'Thin' on SlideShare&quot;&gt;View&lt;/a&gt; | &lt;a href=&quot;http://www.slideshare.net/upload?src=embed&quot;&gt;Upload your own&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://github.com/macournoyer/thin/tree/master&quot;&gt;Thin on GitHub&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.garyharan.com/index.php/2008/02/21/rails-development-with-the-thin-web-server/&quot;&gt;Rails Development with Thin&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://blog.ninjahideout.com/posts/busting-a-cap-in-yo-ass&quot;&gt;Using Capistrano with Thin&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://github.com/macournoyer/thin/tree/master/example/thin.god&quot;&gt;Using god with Thin&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.misuse.org/science/2008/04/07/thin-vs-mongrel-a-ruby-on-rails-performance-shootout/&quot;&gt;Thin and Mongrel Performance Test&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thin is in!&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Salesforce Tools of the Trade</title>
   <link href="http://luigimontanez.com/2008/salesforce-tools-of-the-trade/"/>
   <updated>2008-04-07T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2008/salesforce-tools-of-the-trade/salesforce-tools-of-the-trade</id>
   <content type="html">&lt;p&gt;Salesforce.com is billed as Software-as-a-Service: a complete software experience contained in the web browser. While regular users will never have to leave the warm comfort of their browsers, the reality for administrators and developers is much different. We depend on several essential tools to wrangle our data. Luckily, all the following tools are downloadable for free, and versions are available for both Windows and Mac OS X.&lt;/p&gt;
&lt;h3&gt;Apex Data Loader&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://na5.salesforce.com/dwnld/DataLoader/ApexDataLoader.exe&quot;&gt;Windows Installer&lt;/a&gt; | &lt;a href=&quot;http://www.pocketsoap.com/weblog/2008/01/1800.html&quot;&gt;Mac Installer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Originally called LexiLoader (the Mac application is still called this), the Data Loader is the most essential tool for getting data in and out of Salesforce. The Data Loader connects via the Force.com &lt;span class=&quot;caps&quot;&gt;SOAP&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; and understands the ubiquitous format of &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt; (comma-separated values). When exporting data out of Salesforce, you&amp;#8217;ll need to use &lt;span class=&quot;caps&quot;&gt;SOQL&lt;/span&gt;, Salesforce.com&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;-like language for querying your data. &lt;span class=&quot;caps&quot;&gt;SOQL&lt;/span&gt; doesn&amp;#8217;t work exactly like &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;, and at times can be maddeningly confusing. But have no fear, as we have help.&lt;/p&gt;
&lt;h3&gt;Force.com Explorer&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://wiki.apexdevnet.com/index.php/Apex_Explorer&quot;&gt;Windows Installer&lt;/a&gt; | &lt;a href=&quot;http://www.pocketsoap.com/osx/soqlx/&quot;&gt;Mac Installer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Explorer explores your data. With it, you can build and execute &lt;span class=&quot;caps&quot;&gt;SOQL&lt;/span&gt; queries, view the results, and edit the data (one record at a time).&lt;/p&gt;
&lt;p&gt;The Windows version includes a &lt;span class=&quot;caps&quot;&gt;SOSL&lt;/span&gt; Tester, which let&amp;#8217;s you play with results from &lt;span class=&quot;caps&quot;&gt;SOSL&lt;/span&gt;, Salesforce.com&amp;#8217;s search language.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://wiki.apexdevnet.com/images/thumb/b/b4/Main_window.jpg/691px-Main_window.jpg&quot; width=&quot;600px&quot;/&gt;&lt;/p&gt;
&lt;p&gt;The Mac OS X version, SOQLXplorer, doesn&amp;#8217;t include &lt;span class=&quot;caps&quot;&gt;SOSL&lt;/span&gt; support, but does include a nifty graphical view of your data schema:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.pocketsoap.com/osx/soqlx/schema.png&quot; width=&quot;600px&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s say that a city changes it&amp;#8217;s name from Raritan to Edison (&lt;a href=&quot;http://en.wikipedia.org/wiki/Edison,_New_Jersey#Early_history&quot;&gt;it&amp;#8217;s happened before&lt;/a&gt;). So your workflow for updating contact data using the Data Loader and Explorer looks something like this:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Use the Explorer to figure out the correct &lt;span class=&quot;caps&quot;&gt;SOQL&lt;/span&gt; query for all contacts in Raritan&lt;/li&gt;
	&lt;li&gt;Using the Data Loader and your cool query, export the data to a &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt; file&lt;/li&gt;
	&lt;li&gt;Open the &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt; file in Excel, and replace the City column with &amp;#8220;Edison&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Fire up the Data Loader again and update the fields using with the new values in the &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Three different applications, four steps. Whew! If only there was a tool that did all of that in one neat little package&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Mass Update Anything&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://wiki.apexdevnet.com/index.php/Mass_Update_Anything&quot;&gt;Windows/Mac Installation Instructions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mass Update Anything, as the name implies, updates fields in bulk, based on a &lt;span class=&quot;caps&quot;&gt;SOQL&lt;/span&gt; query. In addition, you can choose to delete fields in bulk as well. It&amp;#8217;s a great little tool that does one job very well, and will save you from &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt; hell.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://wiki.apexdevnet.com/images/5/52/Massupdateanything.jpg&quot; width=&quot;600px&quot;/&gt;&lt;/p&gt;
&lt;h3&gt;Force.com &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://wiki.apexdevnet.com/index.php/Force.com_IDE&quot;&gt;Windows/Mac Installation Instructions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Last but not least, the Force.com &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;, based on &lt;a href=&quot;http://eclipse.org&quot;&gt;Eclipse&lt;/a&gt;, is essential if you&amp;#8217;re going to write any custom code for Salesforce. It has more features than I could ever describe in one post, so your best bet is to just &lt;a href=&quot;http://wiki.apexdevnet.com/index.php/Force.com_IDE&quot;&gt;visit the page&lt;/a&gt;. The &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt; also includes an integrated Schema Browser (like the Force.com Explorer), and I&amp;#8217;ve found myself using that rather than the stand-alone app.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;So there you have it. The Data Loader loads data. The Explorer explores data. Mass Update Anything does what it says. And the &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt; provides you with an integrated development environment for Apex Triggers and Classes, S-Controls, Visualforce, and Metadata. These are the tools you need to kick ass, so get &amp;#8217;em and get started!&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Setting a Default Account Using Triggers</title>
   <link href="http://luigimontanez.com/2008/setting-a-default-account-using-triggers/"/>
   <updated>2008-03-28T00:00:00-04:00</updated>
   <id>http://luigimontanez.com/2008/setting-a-default-account-using-triggers/salesforce-triggers</id>
   <content type="html">&lt;p&gt;In Salesforce, every Contact record must be matched to an Account in order to be viewed by your entire organization. Unfortunately, users uploading in new Contacts via data import, or entering a new Contact manually, usually forget to enter in an Account field. Later, when other users search for that Contact, they won&amp;#8217;t be able to find it, as Salesforce considers a Contact to be private (and thus not searchable), if it&amp;#8217;s not linked to an Account.&lt;/p&gt;
&lt;p&gt;Since the Account field on Contacts is standard, we can&amp;#8217;t just modify it to make it a Required Field. Oddly, creating a Workflow to specify an Account when one doesn&amp;#8217;t exist doesn&amp;#8217;t work, for reasons that are a bit of a mystery to me. Enter Triggers: a programmatic way to take some action before or after a record is created, updated, or deleted.&lt;/p&gt;
&lt;p&gt;First, create a generic Account that can function as a catch-all. I suggest &amp;#8220;Individuals&amp;#8221;. Then, use either the &lt;a href=&quot;http://www.salesforce.com/downloads/ApexTools/salesforce_ant.zip&quot;&gt;Apex Deployment Tool&lt;/a&gt; or the &lt;a href=&quot;http://wiki.apexdevnet.com/index.php/Apex_Toolkit_for_Eclipse&quot;&gt;Force.com Toolkit for Eclipse&lt;/a&gt; to create a new trigger (using those tools will be the subject of future posts).&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;trigger&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SetDefaultAccount&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Contact&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;For&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Contact&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;nc:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Trigger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;If&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;AccountId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;nc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;AccountId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Id&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Account&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Individuals&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code basically says: &amp;quot;Before a new Contact is inserted and if it doesn&amp;#8217;t have an Account Id, set the Id to the Account named &amp;#8216;Individuals&amp;#8217;.&lt;/p&gt;
&lt;p&gt;In Eclipse, you&amp;#8217;ll be prompted to provide some test coverage for the trigger before deploying:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;testcontact&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;testmethod&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mytest1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;Contact&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Contact&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Awesome! Now you&amp;#8217;ll never have to worry about anyone in your organization forgetting to link a new Contact to an Account.&lt;/p&gt;
&lt;p&gt;Hat-tip to Mike Rosa @ Salesforce.com for helping me out with this.&lt;/p&gt;</content>
 </entry>
 
 
 
</feed>