<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>Garbage Burrito! - Latest Blog Entries</title>
    <description>Garbage Burrito! - Latest Blog Entries</description>
    <link>http://www.garbageburrito.com/blog</link>
    <language>en-us</language>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/garbageburrito-blog" /><feedburner:info uri="garbageburrito-blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
      <title>Putting your layouts in a non "layouts" directory in Rails</title>
      <description>&lt;p&gt;
	It&amp;#39;s very easy to tell Rails to look for a layout in a different location from default, example...&lt;/p&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;span style="color:#8b4513;"&gt;render :layout =&amp;gt; &amp;#39;/path/to/layouts/my_layout&amp;#39;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-left: 40px; "&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;p&gt;
	There&amp;#39;s one caveat, the word &amp;quot;layouts&amp;quot; must be in the path. &amp;nbsp;This is probably fine for most cases, but I had a special case. &amp;nbsp;After digging through the Rails source I finally found a solution. &amp;nbsp;This method in the AbstractController is what does the check.&lt;/p&gt;
&lt;p style="margin-left: 40px; "&gt;
	&lt;span style="color:#8b4513;"&gt;def _normalize_layout(value)&lt;br /&gt;
	&amp;nbsp; value.is_a?(String) &amp;amp;&amp;amp; value !~ /\blayouts/ ? &amp;quot;layouts/#{value}&amp;quot; : value&lt;br /&gt;
	end&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
	The solution is to simply override that method in your controller. &amp;nbsp;Here&amp;#39;s my case.&lt;/p&gt;
&lt;p&gt;
	&amp;nbsp;&lt;/p&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;span style="color:#8b4513;"&gt;def _normalize_layout(value)&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;span style="color:#8b4513;"&gt;&amp;nbsp; value =~ /templates/ ? value : &amp;quot;layouts/#{value}&amp;quot;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;span style="color:#8b4513;"&gt;end&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	If the path has &amp;quot;templates&amp;quot; in it, then leave it alone. &amp;nbsp;Otherwise go ahead and prepend &amp;quot;layouts/&amp;quot; for default scenarios. &amp;nbsp;&lt;/div&gt;
&lt;p&gt;
	&amp;nbsp;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=abbsz3Fypc8:8p_GD1SV1g8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=abbsz3Fypc8:8p_GD1SV1g8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=abbsz3Fypc8:8p_GD1SV1g8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=abbsz3Fypc8:8p_GD1SV1g8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=abbsz3Fypc8:8p_GD1SV1g8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=abbsz3Fypc8:8p_GD1SV1g8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=abbsz3Fypc8:8p_GD1SV1g8:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/abbsz3Fypc8" height="1" width="1"/&gt;</description>
      <pubDate>Fri, 04 May 2012 18:41:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/abbsz3Fypc8/putting-your-layouts-in-a-non-layouts-directory-in-rails</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/3156653/putting-your-layouts-in-a-non-layouts-directory-in-rails</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/3156653/putting-your-layouts-in-a-non-layouts-directory-in-rails</feedburner:origLink></item>
    <item>
      <title>New Project - LiveOn.com</title>
      <description>&lt;p&gt;
	&lt;img alt="liveon.png" class="left" src="http://garbageburrito.com/media/AA/AA/ben/images/6376073/thumb/liveon.png" style="width: 80px; height: 80px; " /&gt;I&amp;#39;m really excited about this new project I&amp;#39;m working on. &amp;nbsp;&lt;a href="http://liveon.com"&gt;LiveOn&lt;/a&gt; is a Kansas City based Startup developing a site that helps people capture and share memories with their family today, and preserves them for future generations. Check out the &lt;a href="http://liveon.com"&gt;LiveOn Video&lt;/a&gt; on the homepage. &amp;nbsp;It&amp;#39;s an awesome idea and we&amp;#39;re building some great technology behind it. &amp;nbsp;We&amp;#39;ve already built some cool Flash components to capture webcam video and microphone audio and we&amp;#39;re working with an open source video conversion/repository platform. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;
	I&amp;#39;m still cranking on &lt;a href="http://doodlekit.com"&gt;Doodlekit the Free Website Builder&lt;/a&gt; as well. &amp;nbsp;We&amp;#39;re working on some awesome new features for layout management and doing some ground breaking work with image/color management, dynamic HTML/CSS elements (like menus) and user interface design.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
	We&amp;#39;re using Java as the core language for &lt;a href="http://liveon.com"&gt;LiveOn&lt;/a&gt; (long story), which has actually been kind of nice. &amp;nbsp;I&amp;#39;m realizing again that Java is a great language, it just needs more attention from pragmatic people, instead of &amp;quot;Architects&amp;quot;. &amp;nbsp;My hope is to start with a solid foundation and start to play with some new tech like server side Javascript. &amp;nbsp;I have some ideas around Server Side Dom Manipulation that could revolutionize the view layer (hopefully someone else does it first).&lt;/p&gt;
&lt;p&gt;
	Anyway, sorry for the rambling, I&amp;#39;m really just trying to get the phrase &lt;a href="http://liveon"&gt;LiveOn&lt;/a&gt; with a link to the site in here as much as possible. ;) &amp;nbsp;So yeah, &lt;a href="http://liveon.com"&gt;LiveOn&lt;/a&gt;!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=4zo3kqoX28c:CXvh6LMEkh4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=4zo3kqoX28c:CXvh6LMEkh4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=4zo3kqoX28c:CXvh6LMEkh4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=4zo3kqoX28c:CXvh6LMEkh4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=4zo3kqoX28c:CXvh6LMEkh4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=4zo3kqoX28c:CXvh6LMEkh4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=4zo3kqoX28c:CXvh6LMEkh4:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/4zo3kqoX28c" height="1" width="1"/&gt;</description>
      <pubDate>Wed, 15 Jun 2011 16:27:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/4zo3kqoX28c/new-project-liveoncom</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/1910173/new-project-liveoncom</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/1910173/new-project-liveoncom</feedburner:origLink></item>
    <item>
      <title>Organizing Large Rails Projects, the Simple Way</title>
      <description>One thing that Rails isn't particularly good at is organization of large projects.&amp;nbsp; There's one controllers directory, one models directory, etc.&amp;nbsp; As Doodlekit started to grow I tried to find ways to keep this in check. &amp;nbsp;&lt;br /&gt;&lt;br /&gt;I've been using Engines for a couple of years and I've found it way to cumbersome for just organizing code.&amp;nbsp; I looked into Namespacing, but I don't want to have the namespaces in the URLs.&amp;nbsp; All I want is to be able to organize code into subdirectories.&lt;br /&gt;&lt;br /&gt;Right now I just need one extra subdirectory for Addons. Here's what my directory structure looks like.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;app&lt;br /&gt;-- controllers&lt;br /&gt;---- sites_controller.rb&lt;br /&gt;---- ...&lt;br /&gt;---- addons&lt;br /&gt;------ forms_controller.rb&lt;br /&gt;------ ...&lt;br /&gt;-- models&lt;br /&gt;---- site.rb&lt;br /&gt;---- ...&lt;br /&gt;---- addons&lt;br /&gt;------ form.rb&lt;br /&gt;------ ...&lt;br /&gt;-- views&lt;br /&gt;---- sites&lt;br /&gt;---- ...&lt;br /&gt;---- addons&lt;br /&gt;------ forms&lt;br /&gt;------ ....&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Just like you would have with namespacing, but I'm not actually namespacing.&amp;nbsp; To get this to work you only need to add a few lines to your environment.rb file.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Rails::Initializer.run do |config|&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;....&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.load_paths += %W(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; #{RAILS_ROOT}/app/controllers/addons&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; #{RAILS_ROOT}/app/models/addons&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; #{RAILS_ROOT}/app/helpers/addons&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.controller_paths += %W(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; #{RAILS_ROOT}/app/controllers/addons&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .....&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;ActionController::Base.view_paths.insert(1, "app/views/addons")&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=E9-Ra5b4GbI:KRZ9O-AWcyU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=E9-Ra5b4GbI:KRZ9O-AWcyU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=E9-Ra5b4GbI:KRZ9O-AWcyU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=E9-Ra5b4GbI:KRZ9O-AWcyU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=E9-Ra5b4GbI:KRZ9O-AWcyU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=E9-Ra5b4GbI:KRZ9O-AWcyU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=E9-Ra5b4GbI:KRZ9O-AWcyU:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/E9-Ra5b4GbI" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 07 Dec 2010 15:48:00 +0200</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/E9-Ra5b4GbI/organizing-large-rails-projects-the-simple-way</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/1326901/organizing-large-rails-projects-the-simple-way</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/1326901/organizing-large-rails-projects-the-simple-way</feedburner:origLink></item>
    <item>
      <title>Re-order Multiple Items by Number</title>
      <description>&lt;img  src="http://garbageburrito.com/media/AA/AA/ben/images/4318971/Screen_shot_2010-11-18_at_12.05.22_AM.png " align="right" alt="" style="margin-top: 10px; margin-right: 10px; margin-bottom: 10px; margin-left: 10px; " /&gt;We're working on some cool new image management tools for &lt;a href="http://www.doodlekit.com"&gt;Doodlekit&lt;/a&gt; and one small feature we wanted to add was number re-ordering, like you can do in your Netflix queue.&lt;br /&gt;&lt;br /&gt;Maybe I'm dense but it took me quite a while to get the logic down for this and I went through a number of different revisions before I nailed it. &amp;nbsp;I thought I'd post it here just incase anyone is looking for it, and for feedback&lt;br /&gt;&lt;br /&gt;The algorithm I settled on is very simple. Get the elements that you want to change, remove all of them from the array, reinsert them at their new positions in the array (in ascending order), and reindex the entire array. &amp;nbsp;This is all done before saving anything and you should only save what changed. &amp;nbsp;&lt;br /&gt;&lt;br /&gt; &lt;script src="https://gist.github.com/704674.js?file=gistfile1.rb"&gt;&lt;/script&gt; &lt;br /&gt;The example is from a Ruby on Rails controller, but it's simple enough that sans some Ruby magic it should easily translate to other languages. &amp;nbsp;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=P-r3m6AOK6g:oiS5zzyVTjk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=P-r3m6AOK6g:oiS5zzyVTjk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=P-r3m6AOK6g:oiS5zzyVTjk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=P-r3m6AOK6g:oiS5zzyVTjk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=P-r3m6AOK6g:oiS5zzyVTjk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=P-r3m6AOK6g:oiS5zzyVTjk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=P-r3m6AOK6g:oiS5zzyVTjk:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/P-r3m6AOK6g" height="1" width="1"/&gt;</description>
      <pubDate>Sun, 21 Nov 2010 14:30:00 +0200</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/P-r3m6AOK6g/reorder-multiple-items-by-number</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/1252411/reorder-multiple-items-by-number</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/1252411/reorder-multiple-items-by-number</feedburner:origLink></item>
    <item>
      <title>Center Elements Horizontally and Vertically with Prototype</title>
      <description>Wanted to share this little snippet that lets you easily center Elements vertically and horizontally in the viewport.&lt;br /&gt;&lt;br /&gt;Once you add the code you can call it like so...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$('my_div').centerVertically();&lt;br /&gt;$('my_div').centerHorizontally();&lt;/pre&gt;&lt;br /&gt;The code is paste below and &lt;a href="http://gist.github.com/630462"&gt;also on Gist&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;script src="http://gist.github.com/630462.js?file=center-prototype.js"&gt;&lt;/script&gt; 

&lt;div firebugversion="1.5.4" style="display: none;" id="_firebugConsole"&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_SglH3uOhNo:yRzvQcsM7r4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_SglH3uOhNo:yRzvQcsM7r4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=_SglH3uOhNo:yRzvQcsM7r4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_SglH3uOhNo:yRzvQcsM7r4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=_SglH3uOhNo:yRzvQcsM7r4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_SglH3uOhNo:yRzvQcsM7r4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_SglH3uOhNo:yRzvQcsM7r4:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/_SglH3uOhNo" height="1" width="1"/&gt;</description>
      <pubDate>Sun, 17 Oct 2010 00:27:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/_SglH3uOhNo/center-elements-horizontally-and-vertically-with-prototype</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/1151251/center-elements-horizontally-and-vertically-with-prototype</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/1151251/center-elements-horizontally-and-vertically-with-prototype</feedburner:origLink></item>
    <item>
      <title>Calling for a better HTML File Input</title>
      <description>&lt;img  alt="" style="margin: 2px;" src="http://garbageburrito.com/media/AA/AA/ben/images/3867081/fileinputwin.png" align="right" /&gt;New features coming in HTML5 and CSS3 represent a sigh of relief for people using kludgey code and hacks to get things working the way you want.&amp;nbsp; However, there's one element that you can find on almost every single web app that's getting no attention, the File Input. In particular there's no standardization on what it should look like or how you can style it.&amp;nbsp; It seems it's time for the W3C to take care of this.&lt;br /&gt;&lt;br /&gt;As I'm sure you're aware, the file input looks different in different browsers.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;img  alt="" src="http://garbageburrito.com/media/AA/AA/ben/images/3867111/main/fileinputsafari.png" /&gt;&lt;br /&gt;To make matters worse it's impossible to style it like other controls, as it's actually two elements in one.&amp;nbsp; For example, stetting the background and border does this...&lt;br /&gt;&lt;br /&gt;&lt;img  alt="" src="http://garbageburrito.com/media/AA/AA/ben/images/3867141/main/fileinputstyled.png" /&gt;&lt;br /&gt;You can't even set the button text!&lt;br /&gt;&lt;br /&gt;And, as if to deliberately put you into a browser war fueled rage, there are inconsistencies in how the input reacts to JavaScript calls.&amp;nbsp; What I mean is, a hypothetical solution would be to hide the actual file input and have a button that controls it.&amp;nbsp; In theory the fake button would just call the click() method on the file input opening the browse dialog.&amp;nbsp; The problem is this works in Safari and IE, but not Firefox (I didn't test Opera or Chrome).&amp;nbsp; Furthermore, IE will not let you submit the form through JavaScript if you call the click() method, only through a submit button.&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://garbageburrito.com//media/AA/AA/ben/images/3867151/huge/mobileme.png"&gt;&lt;img  style="margin: 1px;" alt="" src="http://garbageburrito.com/media/AA/AA/ben/images/3867151/mobileme.png" align="right" /&gt;&lt;/a&gt;The only solution available is a nasty hack that requires you to put an &lt;a href="http://www.quirksmode.org/dom/inputfile.html"&gt;invisible input in front of a styled button&lt;/a&gt;. No offense to the people that thought of it, it's clever, but it makes me cringe.&amp;nbsp; It seems to be the accepted practice now, even Apple uses it in MobileMe Mail.&lt;br /&gt;&lt;br /&gt;Recently my Partner in Crime &lt;a href="http://heathbits.com"&gt;Heath Huffman&lt;/a&gt; tweeted to Jeremy Keith (Author of the amazing HTML5 for web designers) that HTML5 needs to have a way to style the file input, to which &lt;a href="http://twitter.com/adactio/status/24962916283"&gt;he replied&lt;/a&gt; "That's a job for CSS, not HTML.". Looking at the &lt;a href="http://www.w3.org/TR/css3-ui/"&gt;CSS3 spec&lt;/a&gt; I found...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;em&gt;In addition, this document does not attempt to solve all user interface related issues / features that can be found in modern user interfaces. Perhaps future versions may attempt to solve these. For example:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Complex or composite controls (e.g. the HTML4 &amp;lt;INPUT type="file"&amp;gt; and the &amp;lt;ISINDEX&amp;gt; elements). &lt;br /&gt;&lt;/em&gt;&lt;/blockquote&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;Looks like neither side wants to touch it.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;I'm not sure what the solution is.&amp;nbsp; Could be extending CSS to recognize these composite elements, or it could be simplifying the HTML component itself.&amp;nbsp; Maybe HTML could let you have a class for each of the sub components (textbox and button).&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Either way this is a design problem many run into and the only workable solution leaves a lot to be desired.&amp;nbsp; Now's the time to do something about it.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xDX1_aU-pM8:W_v9Ekpio2Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xDX1_aU-pM8:W_v9Ekpio2Y:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=xDX1_aU-pM8:W_v9Ekpio2Y:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xDX1_aU-pM8:W_v9Ekpio2Y:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=xDX1_aU-pM8:W_v9Ekpio2Y:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xDX1_aU-pM8:W_v9Ekpio2Y:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xDX1_aU-pM8:W_v9Ekpio2Y:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/xDX1_aU-pM8" height="1" width="1"/&gt;</description>
      <pubDate>Mon, 27 Sep 2010 18:09:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/xDX1_aU-pM8/calling-for-a-better-html-file-input</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/1107721/calling-for-a-better-html-file-input</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/1107721/calling-for-a-better-html-file-input</feedburner:origLink></item>
    <item>
      <title>Table Editor for YUI's Rich Text Editor</title>
      <description>&lt;img  alt="" src="http://garbageburrito.com/media/AA/AA/ben/images/3729661/main/table-editor.png" align="right" /&gt;We've been beta testing our new implementation of YUI's Rich Text Editor in &lt;a href="http://doodlekit.com"&gt;DoodleKit &lt;/a&gt;and almost instantly we received complaints of the missing Table Editor.&amp;nbsp; So I made one.&lt;br /&gt;&lt;br /&gt;It's pretty basic so far and uses the "Insert then Edit" pattern that's already used in existing YUI RTE components.&amp;nbsp; You can edit table properties like width and border, and there's a context menu for inserting and removing rows and columns.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://static.garbageburrito.com/yui-rte-tables/table-editor.html"&gt;Check out an example here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I've &lt;a href="http://github.com/bgkittrell/yui-rte-tables"&gt;put it up on GitHub&lt;/a&gt;, and installing it is super easy.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Copy table-editor.js, table-editor.css and table-editor.png to your desired locations.&lt;/li&gt;&lt;li&gt;Include the table-editor.js and table-editor.css in your HTML.&lt;/li&gt;&lt;li&gt;Modify table-editor.css to point to table-editor.png&lt;/li&gt;&lt;li&gt;After your Editor has been instantiated, initialize the table editor.&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;myEditor.initTableEditor();&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add a button with a value of 'inserttable' to your toolbar.&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;br /&gt;You can check out the table-editor.html file for example usage.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://github.com/bgkittrell/yui-rte-tables"&gt;YUI RTE Table Editor on GitHub&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=fwP8QBs5wjA:bcdnUXBSZKM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=fwP8QBs5wjA:bcdnUXBSZKM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=fwP8QBs5wjA:bcdnUXBSZKM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=fwP8QBs5wjA:bcdnUXBSZKM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=fwP8QBs5wjA:bcdnUXBSZKM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=fwP8QBs5wjA:bcdnUXBSZKM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=fwP8QBs5wjA:bcdnUXBSZKM:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/fwP8QBs5wjA" height="1" width="1"/&gt;</description>
      <pubDate>Fri, 10 Sep 2010 19:42:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/fwP8QBs5wjA/table-editor-for-yuis-rich-text-editor</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/1070621/table-editor-for-yuis-rich-text-editor</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/1070621/table-editor-for-yuis-rich-text-editor</feedburner:origLink></item>
    <item>
      <title>Custom Editor Stylesheet for YUI RTE</title>
      <description>&lt;img  alt="" style="margin: 3px;" src="http://garbageburrito.com/media/AA/AA/ben/images/2908321/editor-css.png" align="right" /&gt;One of the first things I wanted to get working with YUI's Rich Text Editor was to make the editor area styled appropriately.&amp;nbsp; There is an example out there that basically waits for the editor to finish loading and then dynamically adds a link tag to the head of the iframe.&amp;nbsp; It works, but there's a moment where you can see the un-styled content then it switches.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Then I found that you can set the initial HTML that's loaded into the iframe, so I figured why not just load it there?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;var html = "&amp;lt;html&amp;gt;\n&amp;lt;head&amp;gt;\n&amp;lt;title&amp;gt;{TITLE}&amp;lt;/title&amp;gt;\n&amp;lt;meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /&amp;gt;\n" +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;base href=\"http://" + document.domain + "/\"&amp;gt;\n" +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;style&amp;gt;\n{CSS}\n&amp;lt;/style&amp;gt;\n" +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;style&amp;gt;\n{HIDDEN_CSS}\n&amp;lt;/style&amp;gt;\n" + &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;style&amp;gt;\n {EXTRA_CSS}\n&amp;lt;/style&amp;gt;\n" +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;link rel=\"stylesheet\" type=\"text/css\" href=\"/assets/editor_css\"&amp;gt;\n" +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;/head&amp;gt;\n" + &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;lt;body onload=\"document.body._rteLoaded = true;\"&amp;gt;\n{CONTENT}\n&amp;lt;/body&amp;gt;\n&amp;lt;/html&amp;gt;\n";&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;editor = new YAHOO.widget.Editor(container, {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; animate: true,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; collapse: false,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; markup: 'xhtml',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; css: '',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; html: html,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; toolbar: {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; buttons: button_config&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;Working great so far.&amp;nbsp; &lt;br /&gt;&lt;div firebugversion="1.5.4" style="display: none;" id="_firebugConsole"&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=q5B_WQAsv2E:sLyZp7p8pIo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=q5B_WQAsv2E:sLyZp7p8pIo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=q5B_WQAsv2E:sLyZp7p8pIo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=q5B_WQAsv2E:sLyZp7p8pIo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=q5B_WQAsv2E:sLyZp7p8pIo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=q5B_WQAsv2E:sLyZp7p8pIo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=q5B_WQAsv2E:sLyZp7p8pIo:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/q5B_WQAsv2E" height="1" width="1"/&gt;</description>
      <pubDate>Mon, 07 Jun 2010 12:11:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/q5B_WQAsv2E/custom-editor-stylesheet-for-yui-rte</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/730571/custom-editor-stylesheet-for-yui-rte</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/730571/custom-editor-stylesheet-for-yui-rte</feedburner:origLink></item>
    <item>
      <title>Bitchin: Easy Key/Value Fields for Rails Using Bit Fields or Hashes</title>
      <description>Document databases are definitely hot right now, and for good reason.&amp;nbsp; I've thought relational databases were wasted on most web apps for a long time and I'm seriously considering switching &lt;a href="http://doodlekit.com"&gt;Doodlekit &lt;/a&gt;to something like MongoDB.&lt;br /&gt;&lt;br /&gt;In the meantime (ie. while I get my ass caught up) I wrote a simple plugin to make it super easy to add properties to your ActiveRecord models without needing table columns for all of them. &lt;br /&gt;&lt;br /&gt;Nothing earth-shattering, just a cool little plugin I wanted to share.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I call it &lt;a href="http://github.com/bgkittrell/bitchin"&gt;Bitchin&lt;/a&gt;.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There are two parts to it, &lt;strong&gt;Bitchin &lt;/strong&gt;and &lt;strong&gt;Hashed&lt;/strong&gt;.&amp;nbsp; The only difference is that &lt;strong&gt;Bitchin&lt;/strong&gt; uses a Bit Field so it can only store boolean fields which means it's much faster.&amp;nbsp; As long as you have an Integer called bit_flag in your table you just need to do this...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;class User &amp;lt; ActiveRecord::Base
 &lt;br /&gt;&amp;nbsp; bitchin :active, :banned, :stupid&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And the accessors are automatically created for you...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;user.stupid = true
&lt;br /&gt;user.stupid? #=&amp;gt; true
&lt;br /&gt;user.stupid #=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;&lt;strong&gt;Hashed&lt;/strong&gt; works the same way but it relies on ActiveRecord's built-in hash serialization so you can basically store any scalar value.&lt;br /&gt;&lt;br /&gt;More about configuration options and how to use &lt;a href="http://github.com/bgkittrell/bitchin"&gt;in the README&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This plugin is under the Do Whatever The Fuck You Want With It License (WTFYWL)&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=zRXllNqdRNA:SIs8LWL46a8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=zRXllNqdRNA:SIs8LWL46a8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=zRXllNqdRNA:SIs8LWL46a8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=zRXllNqdRNA:SIs8LWL46a8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=zRXllNqdRNA:SIs8LWL46a8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=zRXllNqdRNA:SIs8LWL46a8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=zRXllNqdRNA:SIs8LWL46a8:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/zRXllNqdRNA" height="1" width="1"/&gt;</description>
      <pubDate>Sun, 06 Jun 2010 02:38:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/zRXllNqdRNA/bitchin-easy-keyvalue-fields-for-rails-using-bit-fields-or-hashes</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/727781/bitchin-easy-keyvalue-fields-for-rails-using-bit-fields-or-hashes</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/727781/bitchin-easy-keyvalue-fields-for-rails-using-bit-fields-or-hashes</feedburner:origLink></item>
    <item>
      <title>YUI Editor Spell Checker with Rails</title>
      <description>Dav Glass has a &lt;a href="http://blog.davglass.com/files/yui/editor42/"&gt;great spell checker example&lt;/a&gt; on his blog, and it's pretty easy to get it working with Ruby on Rails and Aspell.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Rails&lt;br /&gt;&lt;/h3&gt;First you'll need to &lt;a href="http://blog.evanweaver.com/files/doc/fauna/raspell/files/README.html"&gt;install Raspell and it's dependencies&lt;/a&gt;. &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Next you'll need an action to call this.&amp;nbsp; I already had an Editor controller for other stuff like image browsing, so I just added this action.&lt;br /&gt;&lt;br /&gt;
&lt;pre&gt;def spellcheck&lt;br /&gt;&amp;nbsp; spell = Aspell.new&lt;br /&gt;&amp;nbsp; spell.set_option("mode", "html")&lt;br /&gt;&amp;nbsp; words = spell.list_misspelled([params[:text]])&lt;br /&gt;&lt;br /&gt;&amp;nbsp; checked = { :check =&amp;gt; :spelling,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; :data =&amp;gt; words.map { |word|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :word =&amp;gt; word,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :suggestions =&amp;gt; spell.suggest(word)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; render :json =&amp;gt; checked.to_json&lt;br /&gt;end
&lt;/pre&gt;
&lt;br /&gt;&lt;br /&gt;Fairly straightforward.&amp;nbsp; It looks for misspelled words and returns a JSON object with the results.&amp;nbsp; The set_option("mode", "html") is important because it makes Aspell ignore text that's part of an HTML tag.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;JavaScript&lt;/h3&gt;I modified Dav's script slightly, you can &lt;a href="/media/AA/AA/ben/downloads/65071/spellcheck.js"&gt;grab my version here&lt;/a&gt;.&amp;nbsp; There are three main differences.&amp;nbsp; First I made the script a function of the Editor object, so that it could be initialized on command.&amp;nbsp; I'll show how to do that later.&lt;br /&gt;&lt;br /&gt;Then I changed the Ajax request to POST the HTML back to the action for checking.&lt;br /&gt;&lt;br /&gt;
&lt;pre&gt;this._conn = YAHOO.util.Connect.asyncRequest('POST', '/editor/spellcheck', {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; success: this._checkSpelling,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; failure: function() {},&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; scope: this&lt;br /&gt;}, 'text=' + escape(this.getEditorHTML())); 
&lt;/pre&gt;
&lt;br /&gt;&lt;br /&gt;Finally I changed the replacement regular expression to ingore text inside HTML tags and to look for word boundaries. &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;html = html.replace(new RegExp('\\b' + data.data[i].word + '(?![^&amp;lt;]*&amp;gt;)\\b', 'g'), '&amp;lt;span class="yui-spellcheck"&amp;gt;' + data.data[i].word + '&amp;lt;/span&amp;gt;');&lt;/pre&gt;&lt;br /&gt;So to get the Javascript side working just copy my script into a .js file and load that in the HTML.&amp;nbsp; Some time after the editor is initialized call...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;editor.initSpellChecker();&lt;/pre&gt;&lt;br /&gt;Make sure to add a button...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;{ type: 'push', label: 'Check Spelling', value: 'spellcheck' }&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;... and add the Highlight CSS to your main editor config ....&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;extracss: '.yui-spellcheck { background-color: yellow; }'&lt;/pre&gt;&amp;nbsp;&lt;div firebugversion="1.5.4" style="display: none;" id="_firebugConsole"&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=PKnmGL5emCw:y5arPNBktBI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=PKnmGL5emCw:y5arPNBktBI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=PKnmGL5emCw:y5arPNBktBI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=PKnmGL5emCw:y5arPNBktBI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=PKnmGL5emCw:y5arPNBktBI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=PKnmGL5emCw:y5arPNBktBI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=PKnmGL5emCw:y5arPNBktBI:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/PKnmGL5emCw" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 01 Jun 2010 15:34:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/PKnmGL5emCw/yui-editor-spell-checker-with-rails</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/718091/yui-editor-spell-checker-with-rails</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/718091/yui-editor-spell-checker-with-rails</feedburner:origLink></item>
    <item>
      <title>Moving Towards a More Segmented Internet</title>
      <description>&lt;p&gt;I've been feeling a lot of anxiety about the Web recently and I just figured out why. The iPad, Facebook and the aging platform that is web development are all pointing to big changes for the Internet. Read on for my semi-coherent ramblings.&lt;/p&gt;

&lt;p&gt;The iPad has been hugely successful in just a few weeks. I'm holding out for a 3g but I knew from the keynote that it is a "Magical" device. However to me as a web developer the iPad, iPhone and the App Store represent a shift away from technologies I've been specializing in for over a decade. Yes it still has a browser and you can make awesome web apps for the iPhone platform, but in reality the native apps are so much better. This presents a dilemma for me. The notion of developing a app that works on only one platform seems so limiting and constraining to me, but it's so hot right now.&lt;/p&gt;

&lt;p&gt;Last night my wife and I were chatting. I was telling her about the Facebook hubub and how I think everyone is blowing it out of proportion. People like Jeffery Zeldman are saying "But most of us, if we think about it, have seen Big Things like this come and go on the web". That's how I want to feel, but as I was talking I could tell that I really felt like this time is different. The fact is that that Facebook has almost 500 million users. There are only 230 million Internet users in the US, and &lt;a href="http://www.google.com/publicdata?ds=wb-wdi&amp;met=it_net_user&amp;idim=country:USA&amp;dl=en&amp;hl=en&amp;q=Internet+Users#met=it_net_user&amp;idim=country:USA&amp;tdim=true"&gt;1.6 billion on the planet&lt;/a&gt;. That's 30% of the Net. You can keep saying "I've seen this come and go" but that at some point something is going to stick.&lt;/p&gt;

&lt;p&gt;If it does stick it represents a fundamental change in how we interact with the Web. If everyone thinks they need a Facebook account to get around on the Web that means you do too. As a business you need to make sure you're Facebook compatible, just like we bend over for Google Page Rank. Google has been a discovery engine to an existing web of sites. Facebook wants to be the web. This sort of corporate controlled web, however you feel about it, will be rejected by large amounts of Internet users. It already has been.&lt;/p&gt;

&lt;p&gt;This left me thinking what's next? What comes after the Web? Until now I couldn't imagine the Web not being the go-to platform for information sharing, communication and entertainment. &lt;/p&gt;

&lt;p&gt;When I learned HTML I read HTML4, A Visual Quickstart Guide from the Peachpit Press. HTML4, 13 years ago. HTML5 is only just now looking like we may get to use it sometime soon. IE9 is the big question, and it's still being developed. In other words the fundamental tools we use as web developers are stagnant. Every once in a while we find a gem that's supported by all like Ajax, dragndrop, etc. By and large I feel like the solutions we're coming up with to take it to the next level, while extremely clever, are hackish. We now have 5 browsers to contend with, Firefox, Safari, IE, Chrome and Opera. I can imagine how much of a relief it must be to go to a single platform like iPhone or Android.&lt;/p&gt;

&lt;p&gt;All of these things, the Facebook Web, the success of App Stores and the stagnation of web development represent a split in the way people will use the Internet in the future. Computing in general is moving away from a single desktop sitting under your desk to a multitude of devices that have their own specific purpose. Cars are getting Net connections, appliances have WiFi, hell my treadmill has an Ethernet port. As beautiful and elegant as the Web Browser as a single platform is, it's holding us back. &lt;/p&gt;

&lt;p&gt;As this story unfolds more segments will be created. More devices, more platforms, more markets. This is a good thing. Niche markets will thrive and individuals will be able to create profitable businesses. But it does mean that I'm probably going to have to learn Objective-C.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=aJlZRFM3mdQ:PKeZ94nF9eM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=aJlZRFM3mdQ:PKeZ94nF9eM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=aJlZRFM3mdQ:PKeZ94nF9eM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=aJlZRFM3mdQ:PKeZ94nF9eM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=aJlZRFM3mdQ:PKeZ94nF9eM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=aJlZRFM3mdQ:PKeZ94nF9eM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=aJlZRFM3mdQ:PKeZ94nF9eM:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/aJlZRFM3mdQ" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 27 Apr 2010 10:46:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/aJlZRFM3mdQ/moving-towards-a-more-segmented-internet</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/645201/moving-towards-a-more-segmented-internet</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/645201/moving-towards-a-more-segmented-internet</feedburner:origLink></item>
    <item>
      <title>Custom Captcha System Using Static Images</title>
      <description>&lt;p&gt;For awhile I had a Javascript bot blocker that did a good job keeping spammers from flinging crap at our blogs, but apparently they got smarter. Go Figure. Even though I hate them, I figured the best option would be to add a Captcha system. I looked into systems like Snook and Askimet and really didn't think they were right for our customers at this point. At least not for a first line of defense.&lt;/p&gt;&lt;p&gt;Before you get much further, this is not a plugin, and I'm not even going to provide full examples. One of the chief benefits of a custom system is the obscurity. However, I do think the general approach is sound and worth sharing. IMO, creating a captcha plugin is kind of like selling every lock with the same key.&lt;/p&gt;&lt;p&gt;I looked at hosted solutions like Re-Captcha, but didn't want to be reliant on a third party. I also looked at the Simple Captcha Rails plugin. The problem I had with it is that it generated the images on the fly, which seemed like it could turn into a resource nightmare with all the requests we get.&lt;/p&gt;&lt;p&gt;I wanted to create a system that used static pre-generated images so it would be super fast.&lt;/p&gt;&lt;h2 class="header2"&gt;The Gist of It&lt;/h2&gt;&lt;p&gt;I generated a set of images using ImageMagick. Here's an example of the code I used to do that...&lt;/p&gt;&lt;pre&gt;
words = %w{ sack river space }&lt;br /&gt;for word in words&lt;br /&gt;    `convert xc:#FFF -resize 110x35! -frame '1x1' -family Helvetica -pointsize 13 -gravity &amp;quot;Center&amp;quot; -draw &amp;quot;text 0,0 '#{word}'&amp;quot; #{word}.jpg`&lt;br /&gt;end
&lt;/pre&gt;&lt;p&gt;Notice the text is the name of the file. I put those images in a directory in my app. Then I created a table with a key, filename, and created date.&lt;/p&gt;&lt;p&gt;Here's some psuedo code.&lt;/p&gt;&lt;pre&gt;
image = getRandomCaptchaFile()

captcha = findCaptcha(filename = image, createdDate &amp;gt; expireInterval)
&lt;br /&gt;if captcha == nil&lt;br /&gt;    captcha = new Captcha&lt;br /&gt;    captcha.filename = image&lt;br /&gt;    captcha.key = getRandomKey()&lt;br /&gt;    captcha.created_date = now()&lt;br /&gt;    captcha.save&lt;br /&gt;end

deleteAllCaptchas(created_date &amp;lt; 1.day.ago)

return captcha
&lt;/pre&gt;&lt;p&gt;This is the crux of the system. Basically I get a random image file, check to see if a captcha record has been created within a set interval, if not create a new one with a new key (such as a GUID), and delete all the old captchas. For doodlekit I also have some code to take into account the multi-site environment.&lt;/p&gt;&lt;p&gt;Once you have this you can create a controller or action to accept the random key. This will look up the image from the captcha table and return the image data. The random key breaks the link between the URL and the actual image.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=t99yn2q6eQw:17PefugC038:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=t99yn2q6eQw:17PefugC038:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=t99yn2q6eQw:17PefugC038:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=t99yn2q6eQw:17PefugC038:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=t99yn2q6eQw:17PefugC038:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=t99yn2q6eQw:17PefugC038:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=t99yn2q6eQw:17PefugC038:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/t99yn2q6eQw" height="1" width="1"/&gt;</description>
      <pubDate>Wed, 20 Jan 2010 00:05:00 +0200</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/t99yn2q6eQw/custom-captcha-system-using-static-images</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/449991/custom-captcha-system-using-static-images</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/449991/custom-captcha-system-using-static-images</feedburner:origLink></item>
    <item>
      <title>Adding Pagination to Twitter API Calls with will_paginate</title>
      <description>&lt;p&gt;First of all, if you're not using &lt;a href="http://wiki.github.com/mislav/will_paginate"&gt;will_paginate&lt;/a&gt; for all of your pagination then you should be. It's well known that the built in pagination in Rails is slow and clunky. &lt;a href="http://wiki.github.com/mislav/will_paginate"&gt;will_paginate&lt;/a&gt; will easily replace your ActiveRecord pagination, but it can paginate just about anything else.&lt;/p&gt;&lt;p&gt;&lt;a href="http://twitter.rubyforge.org/"&gt;John Nunemaker's Twitter Plugin&lt;/a&gt; makes short work of hooking your app up to the Twitter API. With a few strokes of code you can be pulling statuses down like mad. Now if you want to list a bunch of statuses you'll likely want to have some kind of pagination.&lt;/p&gt;&lt;p&gt;First there's the standard Auth&lt;/p&gt;&lt;pre&gt;
httpauth = Twitter::HTTPAuth.new(username, password)&lt;br /&gt;client = Twitter::Base.new(httpauth)
&lt;/pre&gt;&lt;p&gt;Then setup some pagination defaults, and grab some tweets.&lt;/p&gt;&lt;pre&gt;
current_page = params[:page] || 1&lt;br /&gt;per_page = 100&lt;br /&gt;tweets = client.user_timeline(:count =&amp;gt; per_page, :page =&amp;gt; current_page)
&lt;/pre&gt;&lt;p&gt;Then just wrap the paginator around your collection and the deed is done.&lt;/p&gt;&lt;pre&gt;
if !tweets.empty?&lt;br /&gt;  @tweets = WillPaginate::Collection.create(current_page, per_page, tweets.first.user.statuses_count) do |pager|&lt;br /&gt;    pager.replace(tweets)&lt;br /&gt;  end&lt;br /&gt;end
&lt;/pre&gt;&lt;p&gt;Finally, insert the pagination links in the view.&lt;/p&gt;&lt;pre&gt;
&amp;lt;%= will_paginate @tweets %&amp;gt;
&lt;/pre&gt;&lt;p&gt;That's it. A marriage of two great plugins indeed.&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=QVPPxP3hNUk:WgPNZT1UPso:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=QVPPxP3hNUk:WgPNZT1UPso:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=QVPPxP3hNUk:WgPNZT1UPso:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=QVPPxP3hNUk:WgPNZT1UPso:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=QVPPxP3hNUk:WgPNZT1UPso:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=QVPPxP3hNUk:WgPNZT1UPso:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=QVPPxP3hNUk:WgPNZT1UPso:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/QVPPxP3hNUk" height="1" width="1"/&gt;</description>
      <pubDate>Fri, 18 Sep 2009 00:54:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/QVPPxP3hNUk/adding-pagination-to-twitter-api-calls-with-will_paginate</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/261661/adding-pagination-to-twitter-api-calls-with-will_paginate</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/261661/adding-pagination-to-twitter-api-calls-with-will_paginate</feedburner:origLink></item>
    <item>
      <title>Lessons From Home Renovation - Nothing is That Complicated</title>
      <description>&lt;p&gt;&lt;img alt="Plumber or Serial Killer?  You decide." class="right" height="400" src="http://garbageburrito.com/media/AA/AA/ben/images/1021591/main/5299490-800x358.jpg" width="179" /&gt;When people find out I've been renovating my house for 7 years they always ask, &amp;quot;where did you learn how to do all that stuff?&amp;quot; &amp;#160;The truth is that I learned it all as I was doing it. &amp;#160;I've replaced copper and PVC plumbing, run gas lines, rebuilt door and window frames, installed kitchen cabinets, sinks and countertops, dry walled, floored, painted, electrified as well as many other things I had no idea how to do before we moved in. &amp;#160;It's not because I'm a super awesome dude, it's because I shed my fear of learning new things. &lt;/p&gt;&lt;p&gt;When you think about it, companies make products that are easy to use. &amp;#160;Just because you're a professional plumber doesn't mean you want to spend hours putting together an unnecessarily complex system. &amp;#160;&amp;#160;Sure there are things best left to the professionals. &amp;#160;I wasn't about to rent a backhoe and dig up my own sewer line, or get up on 30 foot scaffolding to hang siding.&lt;/p&gt;&lt;p&gt;I constantly think about this in my career. &amp;#160;Sometimes I avoid adding a new feature, or trying a new tool because I'm afraid that it will be too complicated or take too much time. &amp;#160;This reminds me of when XML was just a buzzword. &amp;#160;For a long time I just heard descriptions of it and I was so afraid that it was some crazy complex system that I would never understand. &amp;#160;Then when I actually saw what they were talking about I was like &amp;quot;That's it?!&amp;quot;.&lt;/p&gt;&lt;p&gt;Most things in this world are much more simple than they look from the outside. &amp;#160;If you just jump in, it's really not too bad.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=CqjRUJ3LWzA:UXV9nevf2FI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=CqjRUJ3LWzA:UXV9nevf2FI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=CqjRUJ3LWzA:UXV9nevf2FI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=CqjRUJ3LWzA:UXV9nevf2FI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=CqjRUJ3LWzA:UXV9nevf2FI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=CqjRUJ3LWzA:UXV9nevf2FI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=CqjRUJ3LWzA:UXV9nevf2FI:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/CqjRUJ3LWzA" height="1" width="1"/&gt;</description>
      <pubDate>Thu, 03 Sep 2009 13:44:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/CqjRUJ3LWzA/lessons-from-home-renovation-nothing-is-that-complicated</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/240451/lessons-from-home-renovation-nothing-is-that-complicated</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/240451/lessons-from-home-renovation-nothing-is-that-complicated</feedburner:origLink></item>
    <item>
      <title>Outsource Your E-Mail Notifications With MadMimi's Mailer API</title>
      <description>&lt;p&gt;I recently got the E-Mail Marketing itch. I realized we have a great email list that we haven't tapped into at all. The thing is I don't want to just blast the same email to everyone, I want the email to be semi-intelligent, ie. 2 days after someone signs up they get an email with helpful tips.&lt;/p&gt;&lt;p&gt;Enter &lt;a href="http://developer.madmimi.com/"&gt;Mad Mimi's new Mailer API&lt;/a&gt;. This is just brilliant IMO, exactly what I was looking for. Basically they have a simple API to send out one-off or "Transactional" emails through their system. What are the benefits?&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Create Beautiful E-Mails through their awesome promotion builder&lt;/li&gt;&lt;li&gt;Track Views, Clicks, Bounces, etc.&lt;/li&gt;&lt;li&gt;Automatically adds new E-Mails to your audience for other promotions&lt;/li&gt;&lt;li&gt;Ability to change your emails live, without deploying&lt;/li&gt;&lt;li&gt;Offload Mail Server resources to their systems&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Now when a customer signs up, or their credit card is declined or whatever, instead of getting dry ugly text they get a rich friendly looking email. Plus I can track what's happening and improve the emails as time goes by.&lt;/p&gt;&lt;p&gt;I can also create a system where I choose when to send other promotions based on the user's behavior. This sort of personalized response is the best way to get through with E-Mail Marketing these days.&lt;/p&gt;&lt;p&gt;It's not necessary to go into a full-tutorial here, simply because Mad Mimi's developer center covers it well, and it's not that complicated in the first place. But I will cover the basics.&lt;/p&gt;&lt;p&gt;First install the gem. Make sure you've added github to your list of gem repositories.&lt;/p&gt;&lt;pre&gt;$ gem sources -a http://gems.github.com (you only have to do this once)&lt;br /&gt;$ sudo gem install mad_mimi_mailer
&lt;/pre&gt;&lt;p&gt;I had a version conflict with ActiveSupport so I froze the gem, but that's up to you.&lt;/p&gt;&lt;p&gt;What they've done is extend ActionMailer, so changing your emails to Mad Mimi is stupid simple. Essentially you put in your api creds, change the base class and add mimi_ to the front of all the methods. You'll also need to specify the name of the promotion.&lt;/p&gt;&lt;pre&gt;MadMimiMailer.api_settings = {&lt;br /&gt; :username =&amp;gt; 'ben@doodlekit.com',&lt;br /&gt; :api_key =&amp;gt; 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'&lt;br /&gt;}

class BillerMailer &amp;lt; MadMimiMailer
def mimi_suspended(customer_site)&lt;br /&gt; settings = SystemSetting.find(:first)&lt;br /&gt; promotion "Account Suspended"&lt;br /&gt; @subject = 'Doodlekit Alert - Your Website Has Been Suspended'&lt;br /&gt; @body = {}&lt;br /&gt; @recipients = customer_site.email_address&lt;br /&gt; @from = settings.admin_email

 @body[:customer_name] = customer_site.full_name&lt;br /&gt; @body[:site_title] = customer_site.site_name&lt;br /&gt; @body[:site_url] = customer_site.url &lt;br /&gt;end
&lt;/pre&gt;&lt;p&gt;This mailer is using a promotion called "Account Suspended", so there must be a promotion with that name in my Mad Mimi account. The elements in the @body hash are mapped to variables in your Mad Mimi Promotion. :customer_name maps to {customer_name}.&lt;/p&gt;&lt;p&gt;Then just change your deliver call to include mimi_&lt;/p&gt;&lt;pre&gt;BillerMailer.deliver_mimi_suspended(customer_site)
&lt;/pre&gt;&lt;p&gt;That's it!&lt;/p&gt;&lt;p&gt;One quick helpful tip. If your having issues and would like to see what's going on between you and the API you can enable HTTP debugging by adding the following line in the post_request method in mad_mimi_mailer.rb.&lt;/p&gt;&lt;pre&gt;http.set_debug_output $stdout
&lt;/pre&gt;&lt;p&gt;Kind of Hackish, but good if you're in a bind.&lt;/p&gt;&lt;p&gt;I'm super happy about how this turned out, and plan to explore the other area's of &lt;a href="http://developer.madmimi.com/developer/api"&gt;Mad Mimi's API&lt;/a&gt;. And of course it's always great for sending out regular promotions to your email list.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_KJkbjVVoGA:2_oRpSxia-A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_KJkbjVVoGA:2_oRpSxia-A:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=_KJkbjVVoGA:2_oRpSxia-A:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_KJkbjVVoGA:2_oRpSxia-A:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=_KJkbjVVoGA:2_oRpSxia-A:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_KJkbjVVoGA:2_oRpSxia-A:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=_KJkbjVVoGA:2_oRpSxia-A:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/_KJkbjVVoGA" height="1" width="1"/&gt;</description>
      <pubDate>Mon, 31 Aug 2009 11:36:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/_KJkbjVVoGA/outsource-your-email-notifications-with-madmimis-mailer-api</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/235921/outsource-your-email-notifications-with-madmimis-mailer-api</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/235921/outsource-your-email-notifications-with-madmimis-mailer-api</feedburner:origLink></item>
    <item>
      <title>Rails, Mysql and Snow Leopard Issues - Missing Ruby Headers</title>
      <description>&lt;p&gt;Tried starting my development environement after installing Snow Leopard and got this error about the MySql gem not being included with Rails anymore.&lt;/p&gt;&lt;pre&gt;
!!! The bundled mysql.rb driver has been removed from Rails 2.2. Please install the mysql gem and try again: gem install mysql.
&lt;/pre&gt;&lt;p&gt;Tried to install the gem and got this.&lt;/p&gt;&lt;pre&gt;
ERROR: Error installing mysql:&lt;br /&gt;   ERROR: Failed to build gem native extension.
&lt;br /&gt;/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config&lt;br /&gt;mkmf.rb can't find header files for ruby at /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/ruby.h
&lt;/pre&gt;&lt;p&gt;Found a post that said to install the latest 64-bit MySql, got the same error. Found &lt;a href="http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/c80246746b73989d/58ed8255599a3a15?lnk=raot"&gt;this thread&lt;/a&gt; that said to install XCode from the Snow Leopard disk and run this command and we're back in business.&lt;/p&gt;&lt;pre&gt;
sudo env ARCHFLAGS=&amp;quot;-arch x86_64&amp;quot; gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
&lt;/pre&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=5r_aYHtRPKE:3faXbpslNZo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=5r_aYHtRPKE:3faXbpslNZo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=5r_aYHtRPKE:3faXbpslNZo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=5r_aYHtRPKE:3faXbpslNZo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=5r_aYHtRPKE:3faXbpslNZo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=5r_aYHtRPKE:3faXbpslNZo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=5r_aYHtRPKE:3faXbpslNZo:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/5r_aYHtRPKE" height="1" width="1"/&gt;</description>
      <pubDate>Sat, 29 Aug 2009 02:04:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/5r_aYHtRPKE/rails-mysql-and-snow-leopard-issues-missing-ruby-headers</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/232001/rails-mysql-and-snow-leopard-issues-missing-ruby-headers</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/232001/rails-mysql-and-snow-leopard-issues-missing-ruby-headers</feedburner:origLink></item>
    <item>
      <title>Lessons From Home Renovation: The Right Tool</title>
      <description>&lt;p&gt;One of the earlier projects we did was replacing the old cast iron sewer stack. For those not familiar, this is a 4&amp;quot; diameter cast iron pipe. My Dad came up to help with this one. &lt;/p&gt;&lt;p&gt;The first question was, how are we going to cut through this stuff? After deciding a hacksaw wasn't going to work we went to the Home Depot rental department so see what we could find. We came looking for a sawzall, but thankfully the guy there asked what we needed it for. After we told him he said &amp;quot;No no, I have what you need&amp;quot;. He brought out what looked like a giant bicycle chain attached to a handle. He explained how you wrap the chain around the pipe, which had little sharp disks on it, and tightened it until the pipe snapped.&lt;/p&gt;&lt;p&gt;It worked beautifully. Aside from the pipe being heavy as crap, the job was super easy thanks to this tool. That's all the tool was made for, that one specific purpose.&lt;/p&gt;&lt;p&gt;That's when I realized how incredibly important it is to have the right tool for the right job. It can save you time, money, effort and most importantly sanity. Time and time again I've found ways to make projects easier just by looking for a better tool.&lt;/p&gt;&lt;p&gt;I've carried this over into my professional career as well. Java and Ruby both have their place in my toolbox, as well as many other tools I find make my job easier.&lt;/p&gt;&lt;p&gt;If you find yourself beating your head against the wall, take a step back and make sure you're using the right tool.&lt;br /&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xuxw10PSrOQ:NIVD786dDjo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xuxw10PSrOQ:NIVD786dDjo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=xuxw10PSrOQ:NIVD786dDjo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xuxw10PSrOQ:NIVD786dDjo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=xuxw10PSrOQ:NIVD786dDjo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xuxw10PSrOQ:NIVD786dDjo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=xuxw10PSrOQ:NIVD786dDjo:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/xuxw10PSrOQ" height="1" width="1"/&gt;</description>
      <pubDate>Fri, 28 Aug 2009 19:43:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/xuxw10PSrOQ/lessons-from-home-renovation-the-right-tool</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/231251/lessons-from-home-renovation-the-right-tool</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/231251/lessons-from-home-renovation-the-right-tool</feedburner:origLink></item>
    <item>
      <title>New Doodlekit Billing System Upgrade Complete</title>
      <description>&lt;p&gt;Yesterday we pushed out the new Doodlekit Billing System that consolidated our user accounts. Before we had one user account for every website. Now a user account can have multiple websites. This allows them to use a single credit card for all their websites, or to use multiple cards to separate charges (if they had a business website and a personal website for example). Read more about Doodlekit's &lt;a href="http://doodlekit.com/blog/entry/220091/user-consolidation-project-complete" onclick="window.open(this.href);return false;" onkeypress="window.open(this.href);return false;"&gt;User Consolidation Project&lt;/a&gt; on our blog.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=KU8TCFJBVz0:ewuDQB6_FhI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=KU8TCFJBVz0:ewuDQB6_FhI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=KU8TCFJBVz0:ewuDQB6_FhI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=KU8TCFJBVz0:ewuDQB6_FhI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=KU8TCFJBVz0:ewuDQB6_FhI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=KU8TCFJBVz0:ewuDQB6_FhI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=KU8TCFJBVz0:ewuDQB6_FhI:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/KU8TCFJBVz0" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 25 Aug 2009 13:43:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/KU8TCFJBVz0/new-doodlekit-billing-system-upgrade-complete</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/224261/new-doodlekit-billing-system-upgrade-complete</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/224261/new-doodlekit-billing-system-upgrade-complete</feedburner:origLink></item>
    <item>
      <title>Google, Please Implement Plugins in Gmail Too...</title>
      <description>&lt;p&gt;Google Wave looks awesome. If you haven't seen the demo, &lt;a href="http://wave.google.com/"&gt;check it out&lt;/a&gt;, this is definitely the future of Internet communication. The operative word being Future. Most people that come across this blog may be ready, but the general public is not. This is to be expected of course.&lt;/p&gt;&lt;p&gt;When I was watching the demo and they showed the Google Search plugin, a &amp;quot;wave&amp;quot; of ideas hit me. I thought of all the things I could do, especially for Doodlekit. But the thing is all of these things could be helpful in GMail too.&lt;/p&gt;&lt;p&gt;The problem is that I don't expect that 90% of our customer base will know what Wave is for at least a year. This plugin functionality could be so powerful in GMail.&lt;/p&gt;&lt;p&gt;I'm excited about the possibilities with Wave, but I hope it doesn't draw attention away from the best email client on the Net.&lt;/p&gt;&lt;p&gt; &lt;span class="wrappedobject"&gt;
  &lt;script type="text/javascript"&gt;&lt;!--
  document.write(" \n\n &lt;object width=\"425\" height=\"344\"&gt;&lt;param name=\"movie\" value=\"http:\/\/www.youtube.com\/v\/v_UyVmITiYQ&amp;rel=0&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en&amp;feature=player_embedded&amp;fs=1\"&gt;&lt;\/param&gt;&lt;param name=\"allowFullScreen\" value=\"true\"&gt;&lt;\/param&gt;&lt;param name=\"allowScriptAccess\" value=\"always\"&gt;&lt;\/param&gt;&lt;embed src=\"http:\/\/www.youtube.com\/v\/v_UyVmITiYQ&amp;rel=0&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en&amp;feature=player_embedded&amp;fs=1\" type=\"application\/x-shockwave-flash\" allowfullscreen=\"true\" allowScriptAccess=\"always\" width=\"425\" height=\"344\"&gt;&lt;\/embed&gt;&lt;\/object&gt; ");
  //--&gt;&lt;/script&gt;&lt;/span&gt; &lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=mJKumD2wxho:EZC-08Ujdzo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=mJKumD2wxho:EZC-08Ujdzo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=mJKumD2wxho:EZC-08Ujdzo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=mJKumD2wxho:EZC-08Ujdzo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=mJKumD2wxho:EZC-08Ujdzo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=mJKumD2wxho:EZC-08Ujdzo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=mJKumD2wxho:EZC-08Ujdzo:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/mJKumD2wxho" height="1" width="1"/&gt;</description>
      <pubDate>Mon, 24 Aug 2009 15:45:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/mJKumD2wxho/google-please-implement-plugins-in-gmail-too</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/220271/google-please-implement-plugins-in-gmail-too</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/220271/google-please-implement-plugins-in-gmail-too</feedburner:origLink></item>
    <item>
      <title>Paypal Website Payments Pro on Rails - Take 2</title>
      <description>&lt;h2 class="header2"&gt;Problem&lt;/h2&gt;&lt;p&gt;We've been using Paypal's Website Payments Pro for a few years and the ROR::Paypal has been working just fine for our purposes, until I changed things up a bit. I wanted to make the signup more atomic in case of a failure but had trouble when I tried to use the DoCapture method. Looking at the code it actually says in the comments that they couldn't get it to work, awesome right?&lt;/p&gt;&lt;p&gt;First I tried out &lt;a href="http://www.activemerchant.org/"&gt;ActiveMerchant&lt;/a&gt;. It looked great and was super easy to implement. Unfortunately it did not work in my app for reasons that are too embarrassing to publicly admit.&lt;/p&gt;&lt;h2 class="header2"&gt;Solution&lt;/h2&gt;&lt;p&gt;After effin around for awhile I found an alternate solution. Apparently there's a &lt;a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&amp;amp;content_ID=developer/library_download_sdks"&gt;Paypal Ruby SDK&lt;/a&gt; that uses their NVP or Name Value Pair protocol. I didn't even know the used NVP until now. What a relief, SOAP is so crappy.&lt;/p&gt;&lt;p&gt;The best part is it's super easy to implement. The SDK download is a sample Rails app. To use it yourself all you need to do is copy the PayPalSDK plugin from the vendor directory and paypal.yml from config.&lt;/p&gt;&lt;p&gt;If your currently using a certificate you'll want to switch to a signature, another welcome change. The signature is just a string you pass to the web service, instead of a stupid cert file you have to load up. You can get the signature from the API Settings in your Paypal account. Once you have that info copy the API Username, Password and Signature into the paypal.yml file.&lt;/p&gt;&lt;p&gt;Then look at the controllers in the sample app for examples of how to call it. The basic gist is something like this.&lt;/p&gt;&lt;pre&gt;
require 'caller'
caller =  PayPalSDKCallers::Caller.new
transaction = caller.call(
  {&lt;br /&gt;    :method          =&amp;gt; 'DoDirectPayment',&lt;br /&gt;    :amt             =&amp;gt; total.to_s,&lt;br /&gt;    :currencycode    =&amp;gt; 'USD',&lt;br /&gt;    :paymentaction   =&amp;gt; 'Authorization',&lt;br /&gt;    :creditcardtype  =&amp;gt; card.type_code,&lt;br /&gt;    :acct            =&amp;gt; card.card_number,&lt;br /&gt;    :firstname       =&amp;gt; name[0],&lt;br /&gt;    :lastname        =&amp;gt; name[1],&lt;br /&gt;    :street          =&amp;gt; address.address1,&lt;br /&gt;    :city            =&amp;gt; address.city,&lt;br /&gt;    :state           =&amp;gt; address.state,&lt;br /&gt;    :zip             =&amp;gt; address.zipcode.to_s,&lt;br /&gt;    :countrycode     =&amp;gt; address.country,&lt;br /&gt;    :expdate         =&amp;gt; card.card_expiration.strftime(&amp;quot;%m%Y&amp;quot;),&lt;br /&gt;    :cvv2            =&amp;gt; TEST_MODE ? &amp;quot;000&amp;quot; : card.security_code&lt;br /&gt;  }&lt;br /&gt;)       &lt;br /&gt;if transaction.success?       &lt;br /&gt;  return transaction.response[&amp;quot;TRANSACTIONID&amp;quot;]&lt;br /&gt;else&lt;br /&gt;  raise PaymentException, transaction.response[&amp;quot;L_LONGMESSAGE0&amp;quot;]&lt;br /&gt;end
&lt;/pre&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;I really like this approach because it's a super thin layer that just does what it needs.&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=8AhHegtOdqM:rJhI1qXqbh0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=8AhHegtOdqM:rJhI1qXqbh0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=8AhHegtOdqM:rJhI1qXqbh0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=8AhHegtOdqM:rJhI1qXqbh0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?i=8AhHegtOdqM:rJhI1qXqbh0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=8AhHegtOdqM:rJhI1qXqbh0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/garbageburrito-blog?a=8AhHegtOdqM:rJhI1qXqbh0:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/garbageburrito-blog?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/garbageburrito-blog/~4/8AhHegtOdqM" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 18 Aug 2009 16:47:00 +0300</pubDate>
      <link>http://feedproxy.google.com/~r/garbageburrito-blog/~3/8AhHegtOdqM/paypal-website-payments-pro-on-rails-take-2</link>
      <guid isPermaLink="false">http://garbageburrito.com/blog/entry/212901/paypal-website-payments-pro-on-rails-take-2</guid>
    <feedburner:origLink>http://garbageburrito.com/blog/entry/212901/paypal-website-payments-pro-on-rails-take-2</feedburner:origLink></item>
  </channel>
</rss>

