<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>
Thomas Mango writes software, has a bulldog, listens to Long Island Hardcore music and eats sandwiches.
He is currently working freelance projects as well as on his own project, Limited Pressing.


var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));

try {
var pageTracker = _gat._getTracker("UA-74018-5");
pageTracker._trackPageview();
} catch(err) {}</description><title>Sliced Software</title><generator>Tumblr (3.0; @slicedsoftware)</generator><link>http://blog.slicedsoftware.com/</link><item><title>Six Weeks Later</title><description>&lt;p&gt;I spent the past six weeks working full time on &lt;a href="http://limitedpressing.com"&gt;Limited Pressing&lt;/a&gt; and I’m really happy with what was accomplished. We teamed up with some big names to host charity auctions (as of this writing we’ve raised almost $15,000 that will be donated to Doctors Without Borders) and rolled out a lot of new features. The biggest feature we launched was our brand new &lt;a href="http://limitedpressing.com/stores"&gt;Stores&lt;/a&gt; infrastructure that I think makes it incredibly easy (not to mention inexpensive) to get a site and store up and running for your label or band.&lt;/p&gt;

&lt;p&gt;Aside from software work, I was also able to get my feet wet over at Amazon with things like EC2 and RDS. Although there were a lot of new things I wanted to spend time learning that got overlooked, I hope to rectify that in the coming weeks.&lt;/p&gt;

&lt;p&gt;Starting today, I begin a brand new project with &lt;a href="http://en.wikipedia.org/wiki/Gary_Culliss"&gt;Gary Culliss&lt;/a&gt; that I’m really looking forward to working on.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/365124683</link><guid>http://blog.slicedsoftware.com/post/365124683</guid><pubDate>Mon, 01 Feb 2010 09:02:54 -0500</pubDate></item><item><title>Why I Spent $60 On An Alarm Clock</title><description>&lt;p&gt;For years, I used one of the original &lt;a href="http://ihomeaudio.com"&gt;iHome&lt;/a&gt; iPod dock alarm clocks. I only docked my iPhone a few times - when I felt like listening to an audiobook without my earphones. Otherwise, I used it as an alarm clock. At least, I attempted to use it as an alarm clock.&lt;/p&gt;

&lt;p&gt;To set the time or set the alarm, you have to spin a wheel. A slow, loud, clicking wheel. Shortly after getting the clock, the wheel started to break. You would spin it one way and the time would start going in the opposite direction. But that wheel wasn’t even the worst part about it - nor the interference with my GSM phone. No, the worst part about it was that it wouldn’t keep time. It would lose a few minutes every month or so. I never knew what time it was and started looking at my phone to double check. I tried resetting it frequently, but gave up. Instead, I began to set my alarm for earlier and earlier to compensate.&lt;/p&gt;

&lt;p&gt;I should have replaced it years ago.&lt;/p&gt;

&lt;h4&gt;What Do Clocks Even Cost?&lt;/h4&gt;

&lt;p&gt;Before I was given the iHome “clock” as a gift, I had a regular alarm clock. I don’t remember how or when it came into my possession. I would say a decade, at least, had gone by since I had actually purchased an alarm clock.&lt;/p&gt;

&lt;p&gt;Not knowing what alarm clocks cost, I &lt;a href="http://www.amazon.com/s/ref=nb_ss?url=search-alias%3Daps&amp;field-keywords=alarm+clock&amp;x=0&amp;y=0"&gt;searched Amazon&lt;/a&gt;. &lt;strong&gt;Wow&lt;/strong&gt;. There are clocks with big numbers, small numbers, weather reports and ceiling projectors. There are clocks that roll off your nightstand and hide. There are clocks with iPod docks. There are fold up clocks. There are wind up clocks. There are clocks with puzzles on top that, when the alarm goes off, forces you to find the pieces that were thrown into the air and put them back together on the top of the clock before the alarm shuts off. There are $5 clocks and there are $105 clocks.&lt;/p&gt;

&lt;h4&gt;Learning My Lesson&lt;/h4&gt;

&lt;p&gt;Page after page, I began to see the problem. Every clock has a gimmick. Every clock does &lt;em&gt;something else&lt;/em&gt;. But I had that clock. I had the &lt;em&gt;do something else&lt;/em&gt; clock and it was horrible. It was so bad, it couldn’t even keep time.&lt;/p&gt;

&lt;p&gt;I tried to find the alarm clocks that were only alarm clocks. Weather reports? I don’t want you. Ceiling projector? Sorry, not for me. The clocks that were left ranged from $5 to $15. Each one had reviews that said something along the lines of “cheap, works well”.&lt;/p&gt;

&lt;p&gt;Unfortunately, these all &lt;em&gt;looked&lt;/em&gt; cheap. I started to think, what if &lt;strong&gt;these&lt;/strong&gt; clocks can’t even keep time. How long would these cheap clocks last? Sure, they were just clocks which is what I wanted, but I don’t want to have to buy another clock next year.&lt;/p&gt;

&lt;p&gt;Then I stumbled on the &lt;a href="http://www.amazon.com/American-Innovative-Neverlate-Executive-Alarm/dp/B0010DX8MI/ref=sr_1_10?ie=UTF8&amp;s=electronics&amp;qid=1262789831&amp;sr=8-10"&gt;Neverlate Execute Alarm Clock&lt;/a&gt;. I am not an executive. Nor do I need 21 separate alarm “banks”. But, something seemed right about this ridiculously expensive alarm clock. It was expensive, but it didn’t do anything &lt;em&gt;else&lt;/em&gt;. Sure, it has separate alarms for each day of the week in addition to seven daily alarms and a quick nap alarm. It also has a gradual wake setting (increasing alarm volume) and a decremental snooze interval (10 minutes first snooze, 5 minutes second snooze, etc).&lt;/p&gt;

&lt;p&gt;It has a lot of features, but each feature is alarm clock related. If there is an alarm clock out there that is actually a good alarm clock, I thought, this must be it. Did I spend too much money on an alarm clock? Yeah, probably. But I will say that I was able to set the clock up in just a couple of minutes and I woke up on time this morning to a nice alarm sound with a gradually increasing volume.&lt;/p&gt;

&lt;p&gt;It doesn’t matter if you’re writing a piece of software or making an alarm clock. Keep your product focused and you won’t end up with a wheel you need to spin 500 times to get from 12:00AM to 7:00AM or a clock that can’t even keep time.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/319928232</link><guid>http://blog.slicedsoftware.com/post/319928232</guid><pubDate>Wed, 06 Jan 2010 10:43:00 -0500</pubDate></item><item><title>One of Those End of The Year Posts</title><description>&lt;p&gt;I suppose waiting until 11PM on December 31st is as good a time as any for an end of the year wrap up post, right?&lt;/p&gt;

&lt;h4&gt;2009&lt;/h4&gt;

&lt;p&gt;The year really started early February for me with my Grandfather passing away. I’ve had relatives pass away before, but this was different. This was someone I was really close to and saw all the time. His death was sudden and was really hard to get past - not only for myself, but for the rest of my family. I don’t think I’m over it yet and I’m not sure I ever will be.&lt;/p&gt;

&lt;p&gt;The rest of the year, I buried myself in work. I would say that my Grandfather’s death was the reason, but to be honest, I’ve been burying myself in work since as far back as I can remember, so maybe this was just an excuse.&lt;/p&gt;

&lt;p&gt;Regardless, 2009 was a year of working hard - maybe too hard.&lt;/p&gt;

&lt;p&gt;The year started wrapping up on December 18th with my last day of new development on &lt;a href="http://gawkk.com"&gt;gawkk&lt;/a&gt;. It’s been a long road. I was first hired by &lt;a href="http://en.wikipedia.org/wiki/Gary_Culliss"&gt;Gary&lt;/a&gt; to work on gawkk at the start of 2007. Working part time, I was able to lay the groundwork. By September of 2007, I had left a software engineering job I had been at for over six years to work full time on gawkk.&lt;/p&gt;

&lt;p&gt;In the past two years, gawkk has grown and changed a lot. Towards the end, we were constantly trimming features and simplifying processes and user interaction. As it stands, I feel that gawkk is a superb video aggregator and discovery engine. Behind the scenes, it scours thousands of video hosting sites and automatically imports and categorizes everything it finds (millions of videos). For our end users, it provides a very simple way to share and discuss videos with their friends. Gawkk suppresses the noise from people you don’t care about, allowing the videos enjoyed by only your friends to surface just for you.&lt;/p&gt;

&lt;p&gt;With that said, the time has come to let gawkk do its thing and focus attention elsewhere.&lt;/p&gt;

&lt;p&gt;Other than working on gawkk full time through 2009, I’ve worked on a handful of very small freelance projects - all from clients I first did work for many years ago. I’ve released a &lt;a href="http://github.com/tsmango"&gt;few simple plugins&lt;/a&gt; and worked on a bunch of new side projects that have taken up most of my nights and weekends.&lt;/p&gt;

&lt;h4&gt;Twenty Ten&lt;/h4&gt;

&lt;p&gt;I’ll be starting the new year with an entire month of not doing any paid work. Instead, I will spend most days and nights slaving away on a couple of my side projects and reading every technical book I can get my hands on. Another one of my goals for this month is to completely refactor my mornings in an attempt to get a better work-at-home routine down. Lastly, I hope to squeeze in a couple of snowboarding day trips here and there, because there is nothing more relaxing to me than sitting at the top of a snow covered mountain.&lt;/p&gt;

&lt;p&gt;I hope to have my new morning routine all straightened out when February comes, because I’m lucky enough to be starting a brand new project with Gary. We’re completely changing direction with this project and I’m really excited to get rolling. It’s going to be really fun to use some of the new things in the Rails ecosystem that I’ve had my eye on as well as just getting to start a new, fresh project (I’m looking at you, &lt;a href="http://github.com/rails/rails"&gt;Rails 3&lt;/a&gt;!). In addition to new Rails specific things, we plan on using AWS for our entire infrastructure. Everything from EC2 and RDS to S3 and CloudFront. I honestly can’t wait to get my hands on that infrastructure. Everything Amazon has been doing with their Web Services continues to impress me. Just the other day they released &lt;a href="http://developer.amazonwebservices.com/connect/ann.jspa?annID=579"&gt;object versioning&lt;/a&gt; for S3 - really neat stuff.&lt;/p&gt;

&lt;p&gt;Aside from my plan, I hope that the Rails community continues to thrive and that, for everyone’s sake, this economy picks up in 2010.&lt;/p&gt;

&lt;p&gt;Happy New Year!&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/310667348</link><guid>http://blog.slicedsoftware.com/post/310667348</guid><pubDate>Thu, 31 Dec 2009 22:44:00 -0500</pubDate></item><item><title>A Look Back At Staples</title><description>&lt;p&gt;In early 2007, I was contracted to implement a document management web application for Staples Digital Copy Services. Customers can register and upload documents for very large jobs to Staples’ regional copy centers. The app handles documents for about ten locations. The only non-rails part was a multi-file uploader I wrote as a Java applet. Staples wanted drag and drop file uploading that also supported dropping multiple files at once, which I was able to do with Java.&lt;/p&gt;

&lt;p&gt;Certain privileged Staples employees can log in and download documents, read descriptions and manage which jobs have been completed.&lt;/p&gt;

&lt;p&gt;I was contacted a few days ago for a quote to work on a new feature for the application and was happy to see the app has been running smoothly these past few years. They keep adding locations to the system and it’s quickly closing in on managing 100,000 documents.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/287042632</link><guid>http://blog.slicedsoftware.com/post/287042632</guid><pubDate>Wed, 16 Dec 2009 23:37:52 -0500</pubDate></item><item><title>Automatically Resizing a Textarea's Height</title><description>&lt;p&gt;Here is a simple Javascript method that can be used to automatically resize the height of a textarea based on the amount of content inside.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://prototypejs.org"&gt;Prototype&lt;/a&gt; is used in this example.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.slicedsoftware.com/post/191242481/automatically-resizing-a-textareas-height"&gt;Click through&lt;/a&gt; if you don’t see the code snippet below.&lt;/p&gt;

&lt;div id="gist-189275" class="gist"&gt;
  
  
    
      
      &lt;div class="gist-file"&gt;
        &lt;div class="gist-data gist-syntax"&gt;
          
          
          
            &lt;div class="gist-highlight"&gt;&lt;pre&gt;&lt;div class="line" id="LC3"&gt;
&lt;span class="nt"&gt;&lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"comment"&lt;/span&gt; &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;cols=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt;&lt;span class="nt"&gt;&gt;&lt;/textarea&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC4"&gt; &lt;/div&gt;&lt;div class="line" id="LC5"&gt;
&lt;span class="nt"&gt;&lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&gt;&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC6"&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;autoResize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fieldId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC7"&gt;    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fieldId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC8"&gt;    &lt;/div&gt;&lt;div class="line" id="LC9"&gt;    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC10"&gt;      &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fieldId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fieldId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC11"&gt;    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC12"&gt;      &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fieldId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC13"&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC14"&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC15"&gt; &lt;/div&gt;&lt;div class="line" id="LC16"&gt;  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'comment'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'keyup'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="nx"&gt;autoResize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'comment'&lt;/span&gt;&lt;span class="p"&gt;);});&lt;/span&gt;
&lt;/div&gt;&lt;div class="line" id="LC17"&gt;&lt;span class="nt"&gt;&lt;/script&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
          
        &lt;/div&gt;

        &lt;div class="gist-meta"&gt;
          &lt;a href="http://gist.github.com/raw/189275/0dc7304a21ac471a1eb6c076e18d0a8dcbb7058a/gistfile1.htm" style="float:right;"&gt;view raw&lt;/a&gt;
          &lt;a href="http://gist.github.com/189275"&gt;This Gist&lt;/a&gt; brought to you by &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;.
        &lt;/div&gt;
      &lt;/div&gt;
        
  
&lt;/div&gt;</description><link>http://blog.slicedsoftware.com/post/191242481</link><guid>http://blog.slicedsoftware.com/post/191242481</guid><pubDate>Fri, 18 Sep 2009 17:05:00 -0400</pubDate></item><item><title>I have been slowly building my record collection for a while,...</title><description>&lt;img src="http://26.media.tumblr.com/tumblr_kpzr3pKOFl1qzto1xo1_500.jpg"/&gt;&lt;br/&gt; Silent Majority - Life of a Spectator&lt;br/&gt;&lt;br/&gt; &lt;img src="http://28.media.tumblr.com/tumblr_kpzr3pKOFl1qzto1xo3_500.jpg"/&gt;&lt;br/&gt; The Movielife - Self Destruct&lt;br/&gt;&lt;br/&gt; &lt;img src="http://25.media.tumblr.com/tumblr_kpzr3pKOFl1qzto1xo2_500.jpg"/&gt;&lt;br/&gt; The Movielife - This Time Next Year&lt;br/&gt;&lt;br/&gt; &lt;img src="http://30.media.tumblr.com/tumblr_kpzr3pKOFl1qzto1xo4_500.jpg"/&gt;&lt;br/&gt; The Movielife Has A Gambling Problem&lt;br/&gt;&lt;br/&gt; &lt;p&gt;I have been slowly building my record collection for a while, but recently it seems like I’ve been making more moves to pick up the things I always knew I’d want. This weekend, I was able to get my hands on 4 of the records that I’ve been really looking forward to getting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.slicedsoftware.com/images/2009/09/sm-life-of-a-spectator.jpg" target="_blank"&gt;Silent Majority - Life of a Spectator (out of 300)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.slicedsoftware.com/images/2009/09/movielife-self-destruct.jpg" target="_blank"&gt;The Movielife - Self Destruct (Black out of 750)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.slicedsoftware.com/images/2009/09/movielife-next-year.jpg" target="_blank"&gt;The Movielife - This Time Next Year (Blue out of 750)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.slicedsoftware.com/images/2009/09/movielife-gambling-problem.jpg" target="_blank"&gt;The Movielife Has A Gambling Problem (Clear #95/1000)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was able to get the Silent Majority because, amazingly, &lt;a href="http://en.wikipedia.org/wiki/Indecision_(band)"&gt;Artie Phillie&lt;/a&gt; was selling it for a friend on eBay.&lt;/p&gt;

&lt;p&gt;The Movielife records came into my possession because a good friend recently started selling off some of his collection. &lt;strong&gt;Has A Gambling Problem&lt;/strong&gt; was purchased new by him and never even removed from the sleeve.&lt;/p&gt;

&lt;p&gt;So there you have it, 4 records from 2 of my favorite bands and &lt;strong&gt;proof&lt;/strong&gt; that I actually have interests other than writing software (admittedly, not many).&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/188187495</link><guid>http://blog.slicedsoftware.com/post/188187495</guid><pubDate>Mon, 14 Sep 2009 22:33:00 -0400</pubDate></item><item><title>A Cacheable Hash That Stays Synced</title><description>&lt;p&gt;Rails.cache freezes values in hashes that are cached directly. &lt;a href="http://github.com/tsmango/cacheable_hash/tree/master"&gt;CacheableHash&lt;/a&gt; is a wrapper for Hash objects that prevents that from happening. Changes to the Hash being wrapped are automatically persisted back to the cache store so that everything stays in sync.&lt;/p&gt;

&lt;p&gt;You can clone (or fork) my new MIT licensed plugin over at &lt;a href="http://github.com/tsmango/cacheable_hash/tree/master"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Example&lt;/h3&gt;

&lt;p&gt;An instance of CacheableHash is used like any other hash. A cache key is the only thing required.&lt;/p&gt;

&lt;div style="background-color: #eaeaea; border: 1px solid #dedede; overflow-y:auto;"&gt;&lt;code&gt;&lt;pre style="background-color: #eaeaea;color: #666;font-size: 95%;padding: .5em;"&gt;&gt;&gt; fruit = CacheableHash.new('fruit_hash_key', :hash =&gt; {:apple =&gt; 'red', :banana =&gt; 'yellow'}, :expires_in =&gt; 1.week)
&gt;&gt; fruit[:banana]
=&gt; "yellow"&lt;/pre&gt;&lt;/code&gt;&lt;/div&gt;

&lt;p&gt;Changes are automatically persisted.&lt;/p&gt;

&lt;div style="background-color: #eaeaea; border: 1px solid #dedede; overflow-y:auto;"&gt;&lt;code&gt;&lt;pre style="background-color: #eaeaea;color: #666;font-size: 95%;padding: .5em;"&gt;&gt;&gt; fruit = Rails.cache.read('fruit_hash_key')
&gt;&gt; fruit[:apple]
=&gt; "red"

&gt;&gt; fruit[:apple] = 'green'

&gt;&gt; Rails.cache.read('fruit_hash_key')[:apple]
=&gt; "green"&lt;/pre&gt;&lt;/code&gt;&lt;/div&gt;

&lt;h3&gt;About Synchronicity&lt;/h3&gt;

&lt;p&gt;Whenever a method is called on an instance of CacheableHash, that instance automatically writes itself back to the cache store. Often, this is unnecessary. If you call .keys, for example, there is no reason to write back to the cache store. Only when reading a value from the hash using [], is the copy in the cache store not specifically updated. But, rather than worrying about the specific methods that change the contents of the hash, it’s safer to just update the instance in the cache store whenever not specifically reading values.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/182158868</link><guid>http://blog.slicedsoftware.com/post/182158868</guid><pubDate>Mon, 07 Sep 2009 14:53:14 -0400</pubDate></item><item><title>Updated: Mobile Twitter Trends Application (2.1)</title><description>&lt;div style="float:right;"&gt;
&lt;a href="http://www.slicedsoftware.com/images/wtt/trends-v2dot1-0.jpg"&gt; &lt;img style="border:1px solid #E5E5E5;margin:0 0 5px 10px;" src="http://www.slicedsoftware.com/images/wtt/trends-v2dot1-0.thumb.jpg"/&gt;&lt;/a&gt;&lt;br/&gt;&lt;a href="http://www.slicedsoftware.com/images/wtt/trends-v2dot1-1.jpg"&gt; &lt;img style="border:1px solid #E5E5E5;margin:0 0 5px 10px;" src="http://www.slicedsoftware.com/images/wtt/trends-v2dot1-1.thumb.jpg"/&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;I wasn’t able to add all of the polish and features to my &lt;a href="http://trends.slicedsoftware.com"&gt;Trends&lt;/a&gt; application that I really felt was necessary last night, so I’ve just rolled out a quick update. This is definitely the last update for a while on this app.&lt;/p&gt;

&lt;h3&gt;Version 2.1&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The front page now lists not only the &lt;em&gt;currently&lt;/em&gt; trending topics on Twitter, but it also shows topics that have trended in the past day and the past week.&lt;/li&gt;
&lt;li&gt;Hashtag topics are now working (they were broken in v2).&lt;/li&gt;
&lt;li&gt;The timestamp on the topic page now more accurately states when the topic was &lt;em&gt;first seen&lt;/em&gt; trending.&lt;/li&gt;
&lt;li&gt;Added some protection against strange (and actually kind of frequent) errors thrown by the Twitter API when requesting the list of trends.&lt;/li&gt;
&lt;li&gt;If What the Trend doesn’t know about a particular topic, rather than throwing an error, you’re now redirected back to the trends list and a dialog is displayed telling you what happened.&lt;/li&gt;
&lt;li&gt;Fixed a visual bug in TankEngine related to the top 1px border of the toolbar (it used to be a dark line, it now matches the actual iPhone toolbar element).&lt;/li&gt;
&lt;li&gt;Updated the default loading image used for the fullscreen Trends application (accessed through the home screen shortcut) so that the toolbar matches the updated toolbar.&lt;/li&gt;
&lt;/ul&gt;</description><link>http://blog.slicedsoftware.com/post/180883749</link><guid>http://blog.slicedsoftware.com/post/180883749</guid><pubDate>Sun, 06 Sep 2009 00:08:00 -0400</pubDate></item><item><title>Mobile Twitter Trends Application</title><description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="http://blog.slicedsoftware.com/post/180883749/updated-mobile-twitter-trends-application-2-1"&gt;Version 2.1 has been released&lt;/a&gt;.&lt;/p&gt;

&lt;div style="float:right;"&gt;
&lt;a href="http://www.slicedsoftware.com/images/wtt/wtt-v2-0.jpg"&gt; &lt;img style="border:1px solid #E5E5E5;margin:0 0 5px 10px;" src="http://www.slicedsoftware.com/images/wtt/wtt-v2-0.thumb.jpg"/&gt;&lt;/a&gt;&lt;br/&gt;&lt;a href="http://www.slicedsoftware.com/images/wtt/wtt-v2-1.jpg"&gt; &lt;img style="border:1px solid #E5E5E5;margin:0 0 5px 10px;" src="http://www.slicedsoftware.com/images/wtt/wtt-v2-1.thumb.jpg"/&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Just over a month ago, I released a &lt;a href="http://trends.slicedsoftware.com"&gt;mobile web application&lt;/a&gt; that used the API from &lt;a href="http://www.whatthetrend.com"&gt;whatthetrend.com&lt;/a&gt; to present a list of recently trending topics on Twitter, along with their explanations. This little application turned out to be pretty handy, but for a while I’ve wanted to change it a bit. Most importantly, I wanted to have the front page of the application be the list of &lt;em&gt;currently&lt;/em&gt; trending topics on Twitter.&lt;/p&gt;

&lt;h3&gt;Trends: Version 2&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The interface has been re-implemented from the ground up (actually the entire application was rewritten from scratch) and is now styled like a normal list-based iPhone application.&lt;/li&gt;
&lt;li&gt;When you first load the application, it shows you a list of the topics that are currently trending on Twitter.&lt;/li&gt;
&lt;li&gt;Clicking on a topic will bring you to that topic’s page. The explanation as to why that topic is trending is pulled in from What the Trend? and displayed here.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will be adding lists for the daily trending topics as well as the trending topics for the week - for now, only the current trending topics are available.&lt;/p&gt;

&lt;p&gt;Please visit &lt;a href="http://trends.slicedsoftware.com"&gt;Trends&lt;/a&gt; on your iPhone and add it to your home screen for the best experience.&lt;/p&gt;

&lt;h3&gt;Sweat the Details&lt;/h3&gt;

&lt;p&gt;For this project, I used Noel Rappin’s &lt;a href="http://github.com/noelrappin/tank-engine/tree/master"&gt;TankEngine&lt;/a&gt; plugin for the iPhone’s user interface. I ended up having to hack it a bit so that it would run in fullscreen mode without breaking out into Safari when clicking links, but overall it was very enjoyable to use. You can run the Trends application in fullscreen mode by tapping the + button in MobileSafari and then tapping ‘Add to Home Screen’. When you launch Trends from the new icon on your home screen, it will launch in fullscreen mode.&lt;/p&gt;

&lt;h3&gt;heroku&lt;/h3&gt;

&lt;p&gt;In addition to wanting to update this application a bit, I’ve been really wanting a reason to try &lt;a href="http://heroku.com/"&gt;heroku&lt;/a&gt; and I thought this was the perfect application to use as my test run. heroku is a service that allows you to deploy ruby applications quickly and easily. You know what? Saying it allows you to deploy ruby applications quickly and easily is an &lt;em&gt;understatement&lt;/em&gt; – heroku is, by far, the most wonderful service I have used in recent memory. I set out tonight to rewrite my mobile Trends application from scratch. Once I had a working version, I went to heroku not knowing anything of how it worked, signed up and in less than two minutes my application was deployed to heroku and running perfectly.&lt;/p&gt;

&lt;p&gt;If you have a simple application that you’re planning to host on your own server, I highly suggest taking a minute to deploy it over at heroku. It’s free for small applications and I guarantee you will immediately see what an incredible service it is. I honestly can’t say enough.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;I don’t sleep enough and heroku is awesome.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/180267415</link><guid>http://blog.slicedsoftware.com/post/180267415</guid><pubDate>Sat, 05 Sep 2009 04:08:00 -0400</pubDate></item><item><title>Rails Rumble Reflections</title><description>&lt;p&gt;I competed in &lt;a href="http://r09.railsrumble.com/"&gt;Rails Rumble&lt;/a&gt; 2009 over the weekend. It was my first time competing, so I wanted to share some of what I learned while working on a project from start to finish with other people in a 48 hour window.&lt;/p&gt;

&lt;h3&gt;Get a real designer&lt;/h3&gt;

&lt;p&gt;Our team consisted of three developers and no designers. We could all write HTML and CSS and develop front ends, but we weren’t designers. We didn’t possess the talent necessary to develop a really stunning interface, while actually developing the rest of the application in the time allotted.&lt;/p&gt;

&lt;p&gt;Although we produced a full featured application that ended up looking halfway decent, there is no doubt in my mind that we would have benefited immensely if we had a real designer. And by designer, I mean someone who actually makes a living doing design work for web applications.&lt;/p&gt;

&lt;h3&gt;Be opinionated, but be flexible&lt;/h3&gt;

&lt;p&gt;Any project with multiple engineers is bound to bring about disagreements. People are going to discuss and argue their points. I believe that when it comes to software development, you must be opinionated to develop good software. Having strong opinions about something means you are passionate about it. When you’re constrained by a 48 hour window, being opinionated is even more important. You don’t have the luxury of having an entire discussion about every little thing that comes up.&lt;/p&gt;

&lt;p&gt;The problem is that when opinionated people disagree, they spend a lot of time in heated discussion. Normally, these discussions will lead to a better overall implementation and everyone benefits, but when you’re constrained by time, you must not only be opinionated, you must also be flexible. You have to pick your battles and make concessions.&lt;/p&gt;

&lt;h3&gt;Working with people you trust&lt;/h3&gt;

&lt;p&gt;Being able to make concessions is related to another point I have. You should work with people you trust. If you don’t trust the people you are working with, you are going to have a hard time giving in when the other person yells louder. You aren’t going to be able to sit back and say:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I’m working with this person for a reason. I have to trust them, they are very passionate about this.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Being able to trust your team members is not only important during a competition like this one, it’s always important. The difference with a competition, though, is that you just don’t have the time to spend on every disagreement.&lt;/p&gt;

&lt;h3&gt;Don’t write tests&lt;/h3&gt;

&lt;p&gt;Nowadays a lot of people talk about test drive development. Write tests for code that doesn’t exist yet. When you write the code, you know you’re done because it passes the tests. The problem with &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt; is that it can be time consuming. Additionally, because you only have a 48 hour window, the scope of your application must be small enough to complete. If it’s small enough to complete, it will probably be small enough to manually test throughout the competition.&lt;/p&gt;

&lt;p&gt;I spoke to some other contestants who feel the same way. Some even went into the project doing tests and quickly abandoned them because they were too time consuming. Even &lt;a href="http://lowdownapp.com"&gt;Lowdown&lt;/a&gt;, a Rails Rumble entry specifically built to help developers, designers and managers collaborate on &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt; feature stories &lt;a href="http://seancribbs.com/tech/2009/08/24/lowdown-our-rails-rumble-09-application/"&gt;said&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ironically – especially considering the purpose of our application - we didn’t test, spec, or write features. There were times we could have benefitted from TDD, but many other times it would have just slowed us down. We considered the app to be a prototype/proof-of-concept anyway, not a polished and hardened work of craftsmanship.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think this is the key. Testing is good, but testing during the competition could prove fatal. If you only finish a third of your application because you were busy writing tests, you don’t get more points - even if that third is really perfect. It’s better to get to a feature complete state as early as possible and then iterate and iterate and iterate until the last moments of the competition.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;As you can probably tell, I am &lt;em&gt;very&lt;/em&gt; opinionated when it comes to software development. Being opinionated can also leak into the rest of my life. This article, these reflections, are &lt;em&gt;my&lt;/em&gt; reflections. I’m sure many other participants, possibly even my own teammates, don’t agree with me - I’m okay with that. The fact is, nothing I said here (other than having a real designer on your team) is necessarily “right”. It is, however, right for me and probably a lot of other people.&lt;/p&gt;

&lt;p&gt;In the end, I was lucky enough to work with smart people and smart people can work through differences to deliver something they are proud of. And despite our differences, the three of us were really happy that we were able to deliver the application we set out to develop. Being proud of that accomplishment is something we could all agree on.&lt;/p&gt;

&lt;p&gt;I’m really looking forward to Rails Rumble 2010.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/170966735</link><guid>http://blog.slicedsoftware.com/post/170966735</guid><pubDate>Mon, 24 Aug 2009 23:03:00 -0400</pubDate></item><item><title>Making Your Existing User Base Play Nice With Your Facebook User Base</title><description>&lt;p&gt;&lt;em&gt;This is the second article in a series dedicated to getting your existing rails application on Facebook without clawing your eyes out. You should read the &lt;a href="http://blog.slicedsoftware.com/post/166959450/getting-your-existing-rails-app-on-facebook"&gt;first article&lt;/a&gt; if you haven’t already.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the previous article, I talked about how to use facebooker to extend your existing rails application with Facebook only views. Requests that came into your application &lt;em&gt;from&lt;/em&gt; Facebook, were authenticated by facebooker to be genuine Facebook requests, the Facebook user was required to add your application and all of your Facebook specific .fbml.erb views and layouts were automatically used instead of your standard .html.erb views. While all of this was happening for requests coming from Facebook, your regular application kept chugging along, doing its own thing, unaware you were cheating on it with that blue haired girl from your Calc class.&lt;/p&gt;

&lt;p&gt;Chances are however, your application has users (at least you hope it does). What you really want, is for users on your existing Rails app and new users coming in through Facebook to be treated like equal citizens. Sure you may email one and you may notify another, but aside from how you communicate with them, the content they generate in your application should be shared by everyone. If data generated by regular users and Facebook users couldn’t be seen or accessed by one another, there would be no reason to having a single action with two different views (html, fbml).&lt;/p&gt;

&lt;p&gt;
	There are a few things we need to get our different types of users to play nicely.
	&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A place to store a user’s Facebook user id and last session key.&lt;/li&gt;
		&lt;li&gt;A way to catch authenticated Facebook sessions for new users to our application.&lt;/li&gt;
		&lt;li&gt;A way to automatically log in an existing user who has authenticated via a Facebook request.&lt;/li&gt;
	&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Tracking Facebook account details in your users table.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you only plan on doing Facebook related stuff (you have no interest in having Twitter oauth support in your app in the future), the easiest thing to do is just add a couple of fields to your User model. We can just pull these migration lines from what facebooker does:&lt;/p&gt;

&lt;div style="background-color: #eaeaea; border: 1px solid #dedede; overflow-y:auto;"&gt;&lt;code&gt;&lt;pre style="background-color: #eaeaea;color: #666;font-size: 95%;padding: .5em;"&gt;
add_column :users, :facebook_id, :integer, :limit =&gt; 20, :null =&gt; false 
add_column :users, :session_key, string
&lt;/pre&gt;&lt;/code&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Tracking Facebook account details in a separate object.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Alternatively, if you plan on having not only Facebook authentication, but Twitter oauth at some point, you may want to create a new model called FacebookAccount to store your user’s Facebook account details (as well as a foreign key back to the User it belongs to). Then you can add a TwitterAccount object as well and do what you have to do.&lt;/p&gt;

&lt;p&gt;For this example, I’ll assume you just added some fields to your User.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hey, do I know you?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now that we have a place to store Facebook account details, we need a way to make a new User for a new Facebook user. Let me preface this by saying that there are probably a hundred different ways to do this. What I’m going to detail, however, is the approach that worked well for me.&lt;/p&gt;

&lt;p&gt;Let’s go back to our &lt;code&gt;application_controller&lt;/code&gt; and see how we left it:&lt;/p&gt;

&lt;div style="background-color: #eaeaea; border: 1px solid #dedede; overflow-y:auto;"&gt;&lt;code&gt;&lt;pre style="background-color: #eaeaea;color: #666;font-size: 95%;padding: .5em;"&gt;
before_filter :require_login_for_facebook

def require_login_for_facebook
  if params[:format] == 'fbml'
    ensure_authenticated_to_facebook

    if !session[:facebook_session].nil?
      # we'll do something with users
      # here in the next post about fb
    end
  end
end
&lt;/pre&gt;&lt;/code&gt;&lt;/div&gt;

&lt;p&gt;If you follow a Facebook request coming into our application, you’ll see that it hits the &lt;code&gt;require_login_for_facebook&lt;/code&gt; before filter, it should pass the &lt;code&gt;(params[:format] == 'fbml')&lt;/code&gt; test because facebooker will have forced the format to be fbml because it already verified the request came from Facebook. Next, the famous &lt;code&gt;ensure_authenticated_to_facebook&lt;/code&gt; method is called to make sure we get a &lt;code&gt;Facebooker::Session&lt;/code&gt;. After that, I do one more test to ensure we really do have a &lt;code&gt;Facebooker::Session&lt;/code&gt; sitting in &lt;code&gt;session[:facebook_session]&lt;/code&gt; and we can be on our way.&lt;/p&gt;

&lt;p&gt;Inside of the if statement checking if &lt;code&gt;!session[:facebook_session].nil?&lt;/code&gt;, we’re going to want something along the lines of:&lt;/p&gt;

&lt;div style="background-color: #eaeaea; border: 1px solid #dedede; overflow-y:auto;"&gt;&lt;code&gt;&lt;pre style="background-color: #eaeaea;color: #666;font-size: 95%;padding: .5em;"&gt;
unless user_logged_in? or (controller_name == 'facebook' and action_name == 'connect')
  facebook_session = session[:facebook_session]
  if user = User.find(:first, :conditions =&gt; {:facebook_id =&gt; facebook_session.user.uid})
    session[:user_id] = user.id
  else
    redirect_to :controller =&gt; 'facebook', :action =&gt; 'connect'
  end
end
&lt;/pre&gt;&lt;/code&gt;&lt;/div&gt;

&lt;p&gt;I should probably mention that I don’t use &lt;a href="http://github.com/technoweenie/restful-authentication/tree/master"&gt;restful-authentication&lt;/a&gt;. I generally roll my own. Please, take a minute to yell and scream about what a horrible person I am. Blah blah blah. Okay, done? Despite not using the norm, you can see some of the same basic things here. First up, I have a helper method called &lt;code&gt;user_logged_in?&lt;/code&gt;. Can you guess what that does? Good. I’m sure you have the same kind of method. Just make sure there isn’t already someone logged in. Don’t worry about that next part of the unless statement ensuring we aren’t in &lt;code&gt;FacebookController#connect&lt;/code&gt;, you’ll understand that soon.&lt;/p&gt;

&lt;p&gt;So, after we ensure we have a &lt;code&gt;Facebooker::Session&lt;/code&gt;, we make sure there isn’t someone already logged in. Next, we try and locate the User in our users table that has a &lt;code&gt;facebook_id&lt;/code&gt; that matches the user id of the Facebook authenticated user (&lt;code&gt;session[:facebook_session].user.uid&lt;/code&gt;). If we find someone with that &lt;code&gt;facebook_id&lt;/code&gt;, we can automatically log them in. For me, I set &lt;code&gt;session[:user_id]&lt;/code&gt;, for everyone else in the world, do what you normally do to log someone in.&lt;/p&gt;

&lt;p&gt;The reason we can automatically log this person in is because that user already had to log into Facebook and when Facebook made a request to us, facebooker did the heavy lifting to ensure that this was &lt;em&gt;a real Facebook&lt;/em&gt; request. We wouldn’t have gotten this far if it wasn’t a real Facebook request. And, since this &lt;strong&gt;is&lt;/strong&gt; a real Facebook request, we can assume the uid of the user inside of the &lt;code&gt;Facebooker::Session&lt;/code&gt; is really who they say they are. Thus, they are sufficiently authenticated.&lt;/p&gt;

&lt;p&gt;But how do we actually get a user object with a &lt;code&gt;facebook_id&lt;/code&gt; into the database so that we actually have someone to automatically log in? It’s actually pretty easy. First, generate a controller called &lt;code&gt;FacebookController&lt;/code&gt;. Inside of this controller, create a method called &lt;code&gt;connect&lt;/code&gt;. I know, I know, Facebook Connect! Although I won’t be talking about it in this article, this is actually in preparation for allowing users to add your Facebook app inside of Facebook, then go out to your existing external application and log in using Facebook Connect while still retaining the same user object they used from your Facebook applicaiton.&lt;/p&gt;

&lt;p&gt;Inside of the &lt;code&gt;FacebookController#connect&lt;/code&gt; method, you’re going to want to prepare a new User model. This method is going to act like a &lt;code&gt;Users#new&lt;/code&gt; and &lt;code&gt;Users#create&lt;/code&gt; method. The idea is that we need this user to essentially register for our site. User’s in our existing rails app register, so why not Facebook users? The difference, however, is that we want to ask for as little information as possible while still being able to have full fledged accounts for Facebook users that can be shown on our existing site. For me, that means I need a username. Just pick a username and I’ll be happy. Oh, and don’t forget to add an &lt;code&gt;app/views/facebook/connect.fbml.erb&lt;/code&gt; view for this method (for Facebook Connect, we’d have a connect.html.erb - get it?).&lt;/p&gt;

&lt;div style="background-color: #eaeaea; border: 1px solid #dedede; overflow-y:auto;"&gt;&lt;code&gt;&lt;pre style="background-color: #eaeaea;color: #666;font-size: 95%;padding: .5em;"&gt;
def connect
	if request.get?
		# Lets collect some information about this user
		@facebook = Hash.new
		@facebook[:id] = facebook_session.user.uid
		@facebook[:name] = facebook_session.user.name
		@facebook[:description] = facebook_session.user.about_me
		@facebook[:image_small] = facebook_session.user.pic_square_with_logo
		@facebook[:image_large] = facebook_session.user.pic_big
		@facebook[:profile_url] = facebook_session.user.profile_url.gsub(/^http:\/\/www\.facebook\.com\//, '')

		# We're going to want this later, no point in hitting the API again
		session[:facebook_credentials] = @facebook

		# To make things easier, I like to suggest a username.
		# I won't do it here, but generally I run the suggested username
		# through a unique_username? check about 3 times, appending a 
		# random integer on the end to try and make it unique.
		# If I can't find a unique username quickly, I let the user worry about it.

		@user = User.new
		if !@facebook[:profile_url].blank? and !@facebook[:profile_url][/^profile.php/]
			# This user has a new vanity url so that is a preferred username
			@user.username = @facebook[:profile_url].first(15).gsub(/\s/, '').gsub(/\./, '')
		elsif !@facebook[:name].blank?
			# This user doesn't have a vanity url, just use their name
			@user.username = @facebook[:name].first(15).gsub(/\s/, '').gsub(/\./, '')
		end
	else
		@facebook = session[:facebook_credentials]

		# Create the new User object from params[:user]
		# Make sure to store the @facebook[:id] and session key (see facebooker docs)
		# Fetch and store their avatar locally (Facebook likes you to use their (x)fbml
		# tags to display a user's current profile picture, you could do that instead.)

		# Log the user in
		session[:user_id] = @user.id

		redirect_to path_to_front_page
	end
end
&lt;/pre&gt;&lt;/code&gt;&lt;/div&gt;

&lt;p&gt;I know it looks like there’s a lot going on in the &lt;code&gt;connect&lt;/code&gt; method, but it’s pretty straight forward and the inline documentation should really explain everything. Obviously, you’ll want a form in your &lt;code&gt;app/views/facebook/connect.fbml.erb&lt;/code&gt; view. You’ll need a username field and you’ll probably want to display the image in &lt;code&gt;@facebook[:image_small]&lt;/code&gt; on the page somewhere.&lt;/p&gt;

&lt;p&gt;Now, whenever an existing Facebook user comes back to your application, they will automatically be logged in with their full fledged account. They never have to worry about logging in or the fact that they “registered”. In fact, I tell my user’s they are just picking a username. That &lt;em&gt;is&lt;/em&gt; technically all they’re doing. Having to “register” scares people off. Picking a username is easy.&lt;/p&gt;

&lt;p&gt;I may write another article that explains how you can setup Facebook Connect to allow your existing Facebook users to log in directly at your main external rails app (outside of Facebook), using Facebok Connect. Doing this would actually allow you to get users to sign up using Facebook Connect directly from your main site as well. After the post connect callback from Facebook Connect, you’d just the same kind of the check in the application controller to see if you have the user with that &lt;code&gt;facebook_id&lt;/code&gt;, either log them in automatically or send them off to your &lt;code&gt;FacebookController#connect&lt;/code&gt; method (only it will be the .html.erb version this time) to finish the account sign up. It’s really very similar to what we do here.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/167766187</link><guid>http://blog.slicedsoftware.com/post/167766187</guid><pubDate>Thu, 20 Aug 2009 21:40:00 -0400</pubDate></item><item><title>Getting Your Existing Rails App on Facebook</title><description>&lt;p&gt;There’s a ton of information already out there about writing a new Facebook app with Ruby on Rails. You use &lt;a href="http://github.com/mmangino/facebooker/tree/master"&gt;facebooker&lt;/a&gt;, you call a method at the top of your &lt;code&gt;application_controller&lt;/code&gt; and you’re done. It’s pretty easy. The problem is that when you have an existing Rails app and you want to extend it to support alternate fbml views for a Facebook application, things are a bit trickier.&lt;/p&gt;

&lt;p&gt;Here’s how I did it:&lt;/p&gt;

&lt;p&gt;
	You’ll have to start with the usual setup:
	&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a Facebook app from the &lt;a href="http://www.facebook.com/developers"&gt;Developer Application&lt;/a&gt;
&lt;/li&gt;
		&lt;li&gt;Install the &lt;a href="http://github.com/mmangino/facebooker/tree/master"&gt;plugin&lt;/a&gt;
&lt;/li&gt;
		&lt;li&gt;Setup your ssh tunnel for development&lt;/li&gt;
		&lt;li&gt;Setup your config/facebook.yml&lt;/li&gt;
	&lt;/ul&gt;
	I won’t bother explaining how to do all of this stuff. There are &lt;a href="http://www.pragprog.com/titles/mmfacer/developing-facebook-platform-applications-with-rails"&gt;tons&lt;/a&gt; of &lt;a href="http://www.pragprog.com/screencasts/v-mmfacer/rails-development-for-the-facebook-platform"&gt;resources&lt;/a&gt; out &lt;a href="http://peepcode.com/products/rails-on-facebook"&gt;there&lt;/a&gt;.


&lt;p&gt;After you get that done, it’s time to start serving authenticated fbml views for requests coming from Facebook. In the facebooker world, you need to call &lt;code&gt;ensure_authenticated_to_facebook&lt;/code&gt;. Unfortunately, if you do that in your &lt;code&gt;application_controller&lt;/code&gt;, it will try and do a Facebook authentication for every request coming into your application, not just the ones actually coming from Facebook. Since you are trying to extend your existing application with Facebook views, this isn’t what you want.&lt;/p&gt;

&lt;p&gt;It turns out that facebooker does two very important things for you by just having the plugin configured in your application. The first is that it forces the format of all of the Facebook requests to be fbml. Next, it adds an object to &lt;code&gt;session[:facebook_session]&lt;/code&gt;. It’s safe to say that if your request has a format of fbml and there is something in &lt;code&gt;session[:facebook_session]&lt;/code&gt;, you’ve got yourself a Facebook request.&lt;/p&gt;

&lt;p&gt;To catch and authenticate just the requests coming from Facebook, you’ll want to add the next bit of code to your &lt;code&gt;application_controller&lt;/code&gt;:&lt;/p&gt;

&lt;code&gt;&lt;pre style="background-color: #eaeaea;border: 1px solid #dedede;color: #666;font-size: 95%;padding: .5em;"&gt;
before_filter :require_login_for_facebook

def require_login_for_facebook
  if params[:format] == 'fbml'
    ensure_authenticated_to_facebook
    
    if !session[:facebook_session].nil?
      # we'll do something with users
      # here in the next post about fb
    end
  end
end
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;Now, let’s say you have a &lt;code&gt;movies_controller&lt;/code&gt; that uses an &lt;code&gt;app/views/layouts/movies.html.erb&lt;/code&gt; layout. You’ll want to add an &lt;code&gt;app/views/layouts/movies.fbml.erb&lt;/code&gt; layout for requests coming from Facebook. Next, you want a Facebook specific view for your &lt;code&gt;index&lt;/code&gt; action. You already have an &lt;code&gt;app/views/movies/index.html.erb&lt;/code&gt; right? Well, just add an &lt;code&gt;app/views/movies/index.fbml.erb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That’s it, you’re done! Now, when a request comes into your regular application for &lt;code&gt;/movies&lt;/code&gt;, the regular &lt;code&gt;index.html.erb&lt;/code&gt; view will be rendered inside of your regular &lt;code&gt;movies.html.erb&lt;/code&gt; template. But, when a request comes in from your Facebook application to &lt;code&gt;/fb-app-name/movies&lt;/code&gt;, it’s authenticated with facebooker, the facebook user will have to have added your application and your new &lt;code&gt;index.fbml.erb&lt;/code&gt; view will automatically be rendered inside of your &lt;code&gt;movies.fbml.erb&lt;/code&gt; layout.&lt;/p&gt;

&lt;p&gt;I will post another article soon talking about how to approach integrating your existing user base with a Facebook user base.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Like this article? Be sure to read the &lt;a href="http://blog.slicedsoftware.com/post/167766187/making-your-existing-user-base-play-nice-with-your"&gt;second article&lt;/a&gt; in this series titled: “Making Your Existing User Base Play Nice With Your Facebook User Base”.&lt;/em&gt;&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/166959450</link><guid>http://blog.slicedsoftware.com/post/166959450</guid><pubDate>Wed, 19 Aug 2009 22:07:00 -0400</pubDate></item><item><title>Consume At Will - RSS Feed Changed</title><description>&lt;p&gt;The RSS feed for this blog has been changed. It now lives at &lt;a href="http://feeds.feedburner.com/SlicedSoftware"&gt;&lt;a href="http://feeds.feedburner.com/SlicedSoftware"&gt;http://feeds.feedburner.com/SlicedSoftware&lt;/a&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I would appreciate it if you updated your subscription.&lt;/p&gt;
&lt;p&gt;Carry on.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/164869432</link><guid>http://blog.slicedsoftware.com/post/164869432</guid><pubDate>Mon, 17 Aug 2009 09:23:00 -0400</pubDate></item><item><title>This Economy Sucks - Do Your Job Better!</title><description>&lt;p&gt;In this economy, it’s difficult to go a day without hearing someone say “in this economy”. Aren’t you sick of hearing that phrase? Well I sure am and I work from home where most of my talking is to my dog, &lt;a target="_blank" href="http://farm3.static.flickr.com/2466/3801957555_0c2f3fb2ac_o.jpg"&gt;Napoleon&lt;/a&gt;. What better way is there to get people to stop saying “in this economy” than to do your job better? The better everyone does their job, the faster we get this economy to stop sucking so much, right? I think it works something like that.&lt;/p&gt;
&lt;p&gt;So, if you work with databases all the time and &lt;a href="http://www.slicedsoftware.com/programs/pgnj"&gt;PGnJ&lt;/a&gt; helps you do your job better, do yourself a favor and &lt;a href="http://www.slicedsoftware.com/programs/pgnj#donate"&gt;donate to the project&lt;/a&gt;. Keep PGnJ going and feel good about yourself with a just a few clicks!&lt;/p&gt;
&lt;p&gt;Disclaimer: I have not taken economics since high school.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/158850870</link><guid>http://blog.slicedsoftware.com/post/158850870</guid><pubDate>Sat, 08 Aug 2009 21:33:00 -0400</pubDate></item><item><title>Keeping Text Fields and Text Areas Consistent With CSS</title><description>&lt;p&gt;Let me just start by saying that I don’t claim to be good at design at all, but as I don’t work with a designer, I have had to fend for myself over the years. I’d say I “get by” in the design department by sticking to things that aren’t overly complicated. It’s probably also worth noting that I can be a perfectionist at times. I care a lot about the code I produce - whether it’s 5 lines of code that can be written more simply or a few pixels lining up better (admittedly, I’m way better at refactoring code than I am at interfaces).&lt;/p&gt;
&lt;p&gt;What I’d like to explain is a very simple thing I do to keep my text fields and text areas looking consistent with just a couple lines of CSS.&lt;/p&gt;
&lt;p&gt;By default, most browsers like Safari and Firefox render text fields with a simple 3D type depth. It makes the field stand out. Text areas, on the other hand, are usually rendered without that 3D type effect. They are given a simple, flat border. This is what 2 text fields look like compared to a text area, by default, without any CSS:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.slicedsoftware.com/images/2009/08/no-border.png"/&gt;&lt;/p&gt;
&lt;p&gt;The first step to keeping things consistent looking is to simply set the border of text fields and text areas with CSS. Now both widgets are at a level playing field.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.slicedsoftware.com/images/2009/08/border.png"/&gt;&lt;/p&gt;
&lt;p&gt;Just setting the border is a nice first step, but that slight 3D depth given to text fields by default is actually pretty useful to indicate to the user that she can click and type into the area. To do this, you can simply set the border-top of the text fields and text areas to be slightly darker than the border you set in the last step.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.slicedsoftware.com/images/2009/08/border-with-depth.png"/&gt;&lt;/p&gt;
&lt;p&gt;I suspect that most users looking at this form wouldn’t even think twice about this subtle tweak, and that’s the beauty of it. It’s so simple yet still does such a great job of making your forms look way, way sexier.&lt;/p&gt;
&lt;p&gt;Sample CSS:&lt;/p&gt;
&lt;pre style="background-color: #eaeaea;border: 1px solid #dedede;color: #666;font-size: 85%;padding: .5em;"&gt;&lt;code&gt;.textfield, textarea {
  border: 1px solid #c9c2c1;
  border-top: 1px solid #999999;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;
&lt;p&gt;Maybe the word for me is neurotic.&lt;/p&gt;
&lt;/code&gt;&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/158650936</link><guid>http://blog.slicedsoftware.com/post/158650936</guid><pubDate>Sat, 08 Aug 2009 13:42:00 -0400</pubDate></item><item><title>PGnJ 1.1 - Free For Good, QuickJoin, Crasher Fix</title><description>&lt;p&gt;After 8 months of being on sale, I would like to announce that &lt;a href="http://www.slicedsoftware.com/programs/pgnj"&gt;PGnJ 1.1&lt;/a&gt; is now available and that it is completely free (and that it will absolutely stay free).&lt;/p&gt;
&lt;p&gt;It comes down to the fact that the vast majority of PGnJ’s user base decided to stay on 0.8 (the last free version). There wasn’t huge interest in a pay version of PGnJ and because of that, interaction with customers along with feedback totally dropped off the map. But I still had things I wanted to add to PGnJ. I still use PGnJ every day. I wanted people to get those new features. So, the PGnJ-for-pay experiment is officially over.&lt;/p&gt;
&lt;p&gt;What’s new in 1.1? The &lt;a href="http://www.slicedsoftware.com/files/PGnJ/changes.txt"&gt;changelog&lt;/a&gt; may look pretty slim but it comes with a couple of very major improvements as well as a fix for a crashing bug that came about in the past couple of weeks.&lt;/p&gt;
&lt;p&gt;Changelog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PGnJ is now &lt;b&gt;free&lt;/b&gt;. Enjoy!&lt;/li&gt;
&lt;li&gt;When using the DataBrowser (double click a table from the database tree in the sidebar), you can how double click any cell to edit the contents (PostgreSQL and MySQL only).&lt;/li&gt;
&lt;li&gt;Developed a brand new, one of a kind feature that I call QuickJoin. When you open the DataBrowser, it will automatically add a QuickJoin bar to the top of the window with a list of all foreign keys for the current table. Clicking a foreign key will bring up a drop down list of all fields in the referenced table. Selecting a column (you can select as many as you want, across as many referenced tables as you want) will automatically generate JOINs under the hood and display the selected column right inline next to the fk column. See below for a quick demonstration.&lt;/li&gt;
&lt;li&gt;Fixed a major crashing bug that came about with OS X Java Update 4. Essentially, the application must be run in 32 bit mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align:center;"&gt;&lt;a href="http://blog.slicedsoftware.com/post/157711510/pgnj-1-1-free-for-good-quickjoin-crasher-fix"&gt;Watch a short demo of PGnJ’s innovative new feature called QuickJoin!&lt;/a&gt;&lt;/p&gt;
&lt;p style="text-align:center;"&gt;&lt;a href="http://www.slicedsoftware.com/programs/pgnj"&gt;Download PGnJ 1.1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;object height="325" width="415" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"&gt;
&lt;param name="quality" value="high"&gt;
&lt;param name="bgcolor" value="#FFFFFF"&gt;
&lt;param name="flashVars" value="thumb=http://content.screencast.com/users/tsmango/folders/Jing/media/353fbe71-cea8-4121-aa55-0d9ae6a1e36a/FirstFrame.jpg&amp;containerwidth=415&amp;containerheight=325&amp;showbranding=false&amp;content=http://content.screencast.com/users/tsmango/folders/Jing/media/353fbe71-cea8-4121-aa55-0d9ae6a1e36a/00000430.mp4"&gt;
&lt;param name="allowFullScreen" value="true"&gt;
&lt;param name="scale" value="showall"&gt;
&lt;param name="allowScriptAccess" value="always"&gt;
&lt;param name="base" value="http://content.screencast.com/users/tsmango/folders/Jing/media/353fbe71-cea8-4121-aa55-0d9ae6a1e36a/"&gt;
&lt;param name="src" value="http://content.screencast.com/users/tsmango/folders/Jing/media/353fbe71-cea8-4121-aa55-0d9ae6a1e36a/jingh264player.swf"&gt;
&lt;embed height="325" width="415" src="http://content.screencast.com/users/tsmango/folders/Jing/media/353fbe71-cea8-4121-aa55-0d9ae6a1e36a/jingh264player.swf" base="http://content.screencast.com/users/tsmango/folders/Jing/media/353fbe71-cea8-4121-aa55-0d9ae6a1e36a/" allowscriptaccess="always" scale="showall" allowfullscreen="true" flashvars="thumb=http://content.screencast.com/users/tsmango/folders/Jing/media/353fbe71-cea8-4121-aa55-0d9ae6a1e36a/FirstFrame.jpg&amp;containerwidth=415&amp;containerheight=325&amp;showbranding=false&amp;content=http://content.screencast.com/users/tsmango/folders/Jing/media/353fbe71-cea8-4121-aa55-0d9ae6a1e36a/00000430.mp4" bgcolor="#FFFFFF" quality="high" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/157711510</link><guid>http://blog.slicedsoftware.com/post/157711510</guid><pubDate>Fri, 07 Aug 2009 01:51:00 -0400</pubDate></item><item><title>Using Partials as Reusable Inner Layouts</title><description>&lt;p&gt;You may find this pretty basic, but it’s useful nonetheless.&lt;/p&gt;

&lt;p&gt;Using partials in Rails is a wonderful example of code reuse. For example, you may have comments that use polymorphism so that you can attach comments to different models in your system. If you always want your comments to display using the same UI (and why wouldn’t you) on not only Project Messages but also To Do items, you can create a /comments/_comment partial and render these partials from either the Project Message page or the To Do item page. But, we all knew that.&lt;/p&gt;

&lt;p&gt;Sometimes, however, you may want to use a partial like an inner layout inside of your page’s layout.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; If you have problems seeing the code snippet below, just &lt;a href="http://blog.slicedsoftware.com/post/156640294/using-partials-as-reusable-inner-layouts"&gt;click through&lt;/a&gt;.&lt;/p&gt;

&lt;div id="gist-162703" class="gist"&gt;
      &lt;div class="gist-file"&gt;
        &lt;div class="gist-data gist-syntax"&gt;
            &lt;div class="gist-highlight"&gt;&lt;pre&gt;&lt;div class="line" id="LC1"&gt;&lt;!-- /dashboard/_container.html.erb - This partial is used as a template --&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt; &lt;/div&gt;&lt;div class="line" id="LC3"&gt;&lt;table id="dashboard"&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;  &lt;tr&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;    &lt;td id="tabs"&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;      &lt;!-- Links to different areas of the dashboard --&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;    &lt;/td&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;    &lt;td id="main"&gt;&lt;/div&gt;&lt;div class="line" id="LC9"&gt;      &lt;%= yield %&gt;&lt;/div&gt;&lt;div class="line" id="LC10"&gt;    &lt;/td&gt;&lt;/div&gt;&lt;div class="line" id="LC11"&gt;  &lt;/tr&gt;&lt;/div&gt;&lt;div class="line" id="LC12"&gt;&lt;/table&gt;&lt;/div&gt;&lt;div class="line" id="LC13"&gt; &lt;/div&gt;&lt;div class="line" id="LC14"&gt; &lt;/div&gt;&lt;div class="line" id="LC15"&gt;&lt;!-- /messages/_inbox.html.erb - This partial uses the dashboard _container as a wrapper --&gt;&lt;/div&gt;&lt;div class="line" id="LC16"&gt; &lt;/div&gt;&lt;div class="line" id="LC17"&gt;&lt;% render(:layout =&gt; "/dashboard/container", :locals =&gt; {:selected =&gt; 'inbox'}) do -%&gt;&lt;/div&gt;&lt;div class="line" id="LC18"&gt;  &lt;div id="messages"&gt;&lt;/div&gt;&lt;div class="line" id="LC19"&gt;    &lt;%= render @messages %&gt;&lt;/div&gt;&lt;div class="line" id="LC20"&gt;  &lt;/div&gt;&lt;/div&gt;&lt;div class="line" id="LC21"&gt;&lt;% end -%&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
        
        &lt;/div&gt;

        &lt;div class="gist-meta"&gt;
          &lt;a href="http://gist.github.com/raw/162703/f8e649be5e3ea92c4f66c9eadc9ed2c1339ddd0f/inner_layout_example.html.erb" style="float:right;"&gt;view raw&lt;/a&gt;
          &lt;a href="http://gist.github.com/162703"&gt;This Gist&lt;/a&gt; brought to you by &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt;.
        &lt;/div&gt;
      &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Above is a really simple example, demonstrating how you can use a partial as an “inner layout”. Essentially this allows you to have a reusable partial with contextual, custom view code somewhere inside that reusable template - just like you’d use a regular page layout, except now you can have them scattered about your application.&lt;/p&gt;

&lt;p&gt;Yes, this example in particular is really simple, but if you’ve never seen partials used this way, your brain is probably already cranking on how immensely useful this can be.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/156640294</link><guid>http://blog.slicedsoftware.com/post/156640294</guid><pubDate>Wed, 05 Aug 2009 16:56:00 -0400</pubDate></item><item><title>Updated: iPhone Optimized What The Trend App</title><description>&lt;p&gt;I rolled out a few updates to my &lt;a target="_blank" href="http://www.slicedsoftware.com/wtt"&gt;iPhone optimized What The Trend? webapp&lt;/a&gt; last week.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the app is added to the home screen using the + in Mobile Safari, the application will launch in full screen mode rather than in Mobile Safari with the top location bar and bottom bookmark bar.&lt;/li&gt;
&lt;li&gt;What The Trend?’s &lt;a target="_blank" href="http://www.mattmayer.com/"&gt;Matt Mayer&lt;/a&gt; graciously allowed me to use his graph icon as the app’s home screen icon.&lt;/li&gt;
&lt;li&gt;Improved the design of the trend list on the front page.&lt;/li&gt;
&lt;li&gt;Tapping a trend goes to the trend’s single page explanation and gives a link out to the whatthetrend.com single trend page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align:center;"&gt;&lt;a href="http://www.slicedsoftware.com/images/wtt/wtt-0.png"&gt; &lt;img style="border:1px solid #E5E5E5;" src="http://www.slicedsoftware.com/images/wtt/wtt-0.thumb.png"/&gt;&lt;/a&gt; &lt;a href="http://www.slicedsoftware.com/images/wtt/wtt-1.png"&gt; &lt;img style="border:1px solid #E5E5E5;" src="http://www.slicedsoftware.com/images/wtt/wtt-1.thumb.png"/&gt;&lt;/a&gt; &lt;a href="http://www.slicedsoftware.com/images/wtt/wtt-2.png"&gt; &lt;img style="border:1px solid #E5E5E5;" src="http://www.slicedsoftware.com/images/wtt/wtt-2.thumb.png"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What’s coming in the future?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Matt of WTT has recently added the ability to update trend explanations from the API. Soon, I will extend this mobile webapp to utilize this new API method.&lt;/li&gt;
&lt;li&gt;I will add an additional link on the single trend explanation page that will do a Google News search on the selected trend.&lt;/li&gt;
&lt;li&gt;I’m going to juggle some things around. The front page of the app will be replaced with a list of &lt;i&gt;current&lt;/i&gt; Twitter trends. You’ll be able to quickly change to the daily and weekly trend lists as provided by Twitter’s search API.&lt;/li&gt;
&lt;li&gt;Each Trend on these new trend lists, when clicked, will send you over to the single trend page to explain what the trend is about.&lt;/li&gt;
&lt;li&gt;There will be a link out to the current full trend explanation list as provided by WTT (which is used on the front page of the app now) so you can see more than just the top current, daily and weekly trends.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please feel free to send me feedback, feature suggestions or questions (you can use the contact link in the sidebar).&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/153323849</link><guid>http://blog.slicedsoftware.com/post/153323849</guid><pubDate>Fri, 31 Jul 2009 21:46:00 -0400</pubDate></item><item><title>A Mobile What the Trend? Application</title><description>&lt;p&gt;I’ve just released a &lt;a target="_blank" href="http://www.slicedsoftware.com/wtt"&gt;simple little iPhone optimized webapp&lt;/a&gt; that hooks into the API of the awesome &lt;a target="_blank" href="http://whatthetrend.com/"&gt;What the Trend?&lt;/a&gt; site. Enjoy!&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/145156016</link><guid>http://blog.slicedsoftware.com/post/145156016</guid><pubDate>Mon, 20 Jul 2009 01:39:00 -0400</pubDate></item><item><title>Updated: Mobile LIRR Schedule Application</title><description>&lt;p&gt;I have just released an update to my iPhone optimized, &lt;a target="_blank" href="http://www.slicedsoftware.com/lirr"&gt;mobile LIRR scheduling application&lt;/a&gt;. Most importantly, this update brings the service back online after being off for a couple of months due to underlying system changes on the MTA sites.&lt;/p&gt;
&lt;p&gt;Full Changelog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Entirely re-written to work with the MTA’s new website.&lt;/li&gt;
&lt;li&gt;Each schedule now notes whether it is a peak or off peak trip.&lt;/li&gt;
&lt;li&gt;Each schedule now includes the total trip duration.&lt;/li&gt;
&lt;li&gt;Each transfer in a schedule now notes what time the train at the transfer station leaves.&lt;/li&gt;
&lt;li&gt;If a transfer is not direct (meaning if the first train is late, the following train may not wait) it is noted with an * and a message at the bottom of the page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Shoot me an email with the contact link in the sidebar if you have any problems, questions or other feedback.&lt;/p&gt;
&lt;p&gt;I plan on adding some quick reference materials, including station orderings on each branch line, maps and links out to the standard HTML train schedules in the near future.&lt;/p&gt;</description><link>http://blog.slicedsoftware.com/post/145092357</link><guid>http://blog.slicedsoftware.com/post/145092357</guid><pubDate>Sun, 19 Jul 2009 23:40:24 -0400</pubDate></item></channel></rss>
