<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Cement Horses - Home</title>
  <id>tag:www.cementhorses.com,2009:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  <link href="http://www.cementhorses.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://www.cementhorses.com/" rel="alternate" type="text/html"/>
  <updated>2008-08-15T15:37:38Z</updated>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>ahaschke</name>
    </author>
    <id>tag:www.cementhorses.com,2008-08-15:20</id>
    <published>2008-08-15T10:37:00Z</published>
    <updated>2008-08-15T15:37:38Z</updated>
    <category term="user experience"/>
    <category term="ux"/>
    <category term="ux week"/>
    <link href="http://www.cementhorses.com/2008/8/15/engineering-happiness" rel="alternate" type="text/html"/>
    <title>Engineering happiness</title>
<content type="html">
            &lt;p&gt;I'm in love.  Thursday's keynote at &lt;a href=&quot;http://www.uxweek.com/&quot;&gt;UX Week&lt;/a&gt; has definitely been the most engaging moment of the conference.  Game designer and researcher &lt;a href=&quot;http://www.uxweek.com/speakers/jane-mcgonigal&quot;&gt;Jane McGonigal&lt;/a&gt; gave a passionate talk about the intersection of gaming and real life, positing that &quot;reality is broken&quot; and games work better.&lt;/p&gt;

&lt;p&gt;Why are games superior to our experience of everyday life? They offer better instructions, better feedback, better emotions ...and a better sense of community.  Jane highlighted the disconnect between game and life feedback with the amusing scenario of wrapping up her keynote note speech and envisioning that her iPhone would ping, alerting her that's she's received 5 speaking credits.  While this is an amusing, but not likely realistic scenario (unless you might be using &lt;a href=&quot;http://www.plusoneme.com/&quot;&gt;Plusoneme,com&lt;/a&gt;), it points out that there are certain experiences that we desire to have, and games give us a way to find satisfaction.&lt;/p&gt;

&lt;p&gt;If not given the experience of being good at something or the chance to be part of something larger, do satisfying work, or find a community that we feel a part of, these become quality of life problems.  The crux of this keynote is that these issues are a user experience challenge that we can address through learning from game interactions.&lt;/p&gt;

&lt;p&gt;While I've been thinking a bit about the future of UX and interaction design during this conference, Jane describes her vision of user experience as being directly related to life satisfaction &amp;ndash; and UX practitioners therefore become the engineers of happiness.  In this view, quality of life can looked at as a quantifiable brand metric.&lt;/p&gt;

&lt;p&gt;For more information on Jane McGonigal's work, take a look at her website at &lt;a href=&quot;http://www.avantgame.com/&quot;&gt;avantgame.com&lt;/a&gt; and her current projects, &lt;a href=&quot;http://www.thelostring.com/&quot;&gt;The Lost Ring&lt;/a&gt; and &lt;a href=&quot;http://superstructgame.org/&quot;&gt;The Superstruct Game&lt;/a&gt;.
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>ahaschke</name>
    </author>
    <id>tag:www.cementhorses.com,2008-08-14:19</id>
    <published>2008-08-14T10:27:00Z</published>
    <updated>2008-08-14T15:27:31Z</updated>
    <category term="user experience"/>
    <category term="ux"/>
    <category term="ux week"/>
    <link href="http://www.cementhorses.com/2008/8/14/the-future-with-gestures" rel="alternate" type="text/html"/>
    <title>The future with gestures</title>
<content type="html">
            &lt;p&gt;The highlight of Wednesday lineup of events at the UX Week conference was, for me, Dan Saffer's workshop on &lt;a href=&quot;http://uxweek.crowdvine.com/talks/show/550&quot;&gt;designing gestural interfaces&lt;/a&gt;.  The overall approach to this session was incredibly tactical, and we focused primarily on on exploring gesture through touch, with fingertips as input device.  After a quick, but comprehensive walkthrough of critical considerations for prototyping a touch-based interface, the room broke into about six groups who each worked through the task of prototyping an installation for a music store who's been losing customers to Amazon and iTunes.  With services like iTunes and &lt;a href=&quot;http://www.last.fm/&quot;&gt;Last.fm&lt;/a&gt; being such an integral part of my hunt for new music, this exercise presented a unique challenge is considering what experiences belong solely to the physical act of flipping through racks of vinyl or CDs that aren't normally replicated in an online experience.&lt;/p&gt;

&lt;p&gt;The one question that I'm left with after this workshop, though, is how gestural interfaces might change how we interface with technology on a daily basis in the future.  Touch-based interfaces already exist in many public locations from airline check-in kiosks to self check-out at the grocery store.  But, with an iPhone in so many people's pockets (and I've never seen such a high penetration of iPhones in a distinct population as at this conference), how will touch and other gestures continue to impact personal computing?&lt;/p&gt;

&lt;p&gt;The overall track of Tuesday's other sessions focused on the experience of service design. While hearing about how Zipcar has approached their business model and embraced experience as being essential &amp;ndash; and exploring how Comedy Central tackled building an extensive archive of tagged clips for &lt;a href=&quot;http://www.thedailyshow.com/&quot;&gt;The Daily Show&lt;/a&gt; &amp;ndash; uncovered interesting approaches to process, this thread didn't produce any lasting &quot;a ha&quot; moments for me to draw from.  However, I did manage to end the day with the most exquisite service experience at &lt;a href=&quot;http://www.masasrestaurant.com/&quot;&gt;Masa's&lt;/a&gt;, a SOMA restaurant that serves up new French cuisine.  I have a feeling, though, that I might encounter some issues passing off the $200 bill as being a &quot;research expense.&quot;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>jperez</name>
    </author>
    <id>tag:www.cementhorses.com,2008-08-14:18</id>
    <published>2008-08-14T09:33:00Z</published>
    <updated>2008-10-15T20:37:59Z</updated>
    <category term="kentico"/>
    <category term="visual studio"/>
    <link href="http://www.cementhorses.com/2008/8/14/debugging-kentico-sites-in-vs-net-2008-05-improve-compilation-time" rel="alternate" type="text/html"/>
    <title>Debugging Kentico sites in vs.net 2008/05 improve compilation time</title>
<content type="html">
            &lt;p&gt;Here is a tip for debugging the massive Kentico sites in vs.net in case you don’t know about it.&lt;/p&gt;
 
&lt;p&gt;By default the website is configured to compile everything in the Kentico site when running F5 (debug) to start app the application in debug mode.&lt;p&gt;
&lt;p&gt;This causes big delays since Kentico websites have lots of code.&lt;/p&gt;
 &lt;p&gt;
Instead what you want to do is compile only the page you are working on.
&lt;/p&gt;
&lt;p&gt;
1)      In vs.net 2008/05 right click on the website node in the tree navigation pane.&lt;br&gt;
2)      Select “Property Pages”.&lt;br&gt;
3)      In the Build page,  Set your project to the following settings&lt;br&gt;
         a.       &lt;b&gt;Build Page&lt;/b&gt; (instead of Website)&lt;br&gt;&lt;b&gt;“Build Web site as part of solution”&lt;/b&gt; option.
&lt;/p&gt;
&lt;img src=&quot;http://cementhorses.com/assets/2008/8/14/vs.net_debug.jpg&quot; /&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>ahaschke</name>
    </author>
    <id>tag:www.cementhorses.com,2008-08-13:16</id>
    <published>2008-08-13T11:00:00Z</published>
    <updated>2008-08-13T15:59:09Z</updated>
    <category term="user experience"/>
    <category term="ux"/>
    <category term="ux week"/>
    <link href="http://www.cementhorses.com/2008/8/13/resistance-is-a-good-thing" rel="alternate" type="text/html"/>
    <title>Resistance ...is a good thing?</title>
<content type="html">
            &lt;p&gt;I've been spending the week away from the office at &lt;a href=&quot;http://www.uxweek.com/&quot;&gt;UX Week&lt;/a&gt; in San Fran, a conference for user experience practitioners that Adaptive Path hosts every year.  This year's event has taken good strides towards making sure that attendees aren't sitting in a dim ballroom listening to talking heads for a majority of the day, and the programming has a healthy mix of lectures, working sessions and even field trips.&lt;/p&gt;

&lt;p&gt;Day one of UX Week kicked off on Tuesday around the theme of &quot;Fundamentals of User Experience.&quot;   Interestingly, one thread that continued to surface throughout the day was the idea of resistance or constraints being a necessary part of the creative process.  &lt;a href=&quot;http://www.uxweek.com/speakers/jensen-harris&quot;&gt;Jensen Harris&lt;/a&gt; from Microsoft was the first speaker to more directly speak about how finding resistance was an integral part of his team's progress in redeveloping the interface for Word 2007, and he referenced this quote from Igor Stravinsky:&lt;/p&gt; 

&lt;p&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3030/2757484557_d62733c77c.jpg?v=0&quot; alt=&quot;Quote - Igor Stravinsky&quot;&gt;&lt;/p&gt;

&lt;p&gt;The notion of resistance as a tool for propelling projects forward presented itself again in an afternoon working session on, well, &lt;a href=&quot;http://uxweek.crowdvine.com/talks/show/544&quot;&gt;designing effective work sessions&lt;/a&gt;.  Pulling from Adaptive Path's collective experience with structured ideation sessions (translation = &quot;brainstorming&quot;), it's critical to build a framework of resistance to help shape the direction of a group discussion and give participants something to react against.&lt;/p&gt;

&lt;p&gt;I'll continue to post more followups as the conference continues, and day two delves into the theme of media and service design.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>shinji kuwayama</name>
    </author>
    <id>tag:www.cementhorses.com,2008-08-01:12</id>
    <published>2008-08-01T16:12:00Z</published>
    <updated>2008-07-23T16:18:08Z</updated>
    <link href="http://www.cementhorses.com/2008/8/1/managing-dashboard-widgets-on-various-external-displays" rel="alternate" type="text/html"/>
    <title>Managing dashboard widgets on various external displays</title>
<content type="html">
            &lt;p&gt;Like everyone else at Cement Horses, I use a MacBook for daily work, along with an external monitor. When leaving the office, I take the Macbook and leave the monitor, naturally.&lt;/p&gt;

&lt;p&gt;Dashboard widgets aren't like ordinary windows -- when I disconnect the external display, the Mac doesn't automatically move them all to the primary display. They simply stay positioned way offscreen, and inaccessible. I can tell you that logging in or restarting doesn't help, and here's the solution I've found.&lt;/p&gt;

&lt;p&gt;Widget locations are kept in this plist:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;~&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;Preferences&lt;/span&gt;/com.apple.dashboard.plist&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;If you have &lt;a href=&quot;http://developer.apple.com/&quot;&gt;Apple's developer tools&lt;/a&gt; installed, you can open this in Property List Editor and simply edit each widget's pos-x and pos-y values. (You can just make them zero; as long as they're visible in the Dashboard, you can rearrange them that way.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://cementhorses.com/assets/2008/7/16/Picture_2.png&quot; alt=&quot;screen cap&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once saved, you can reload/activate the plist from the Terminal, like so:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;killall &lt;span class=&quot;co&quot;&gt;Dock&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;If you switch displays regularly, you can try maintaining separate profiles:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;~&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;Preferences&lt;/span&gt;/com.apple.dashboard.plist.home&lt;tt&gt;
&lt;/tt&gt;~&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;Preferences&lt;/span&gt;/com.apple.dashboard.plist.work&lt;tt&gt;
&lt;/tt&gt;~&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;Preferences&lt;/span&gt;/com.apple.dashboard.plist.no&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;A bash function like this one:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;resetdash () { &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; [ &lt;span class=&quot;er&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# -ne 2 ] &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;then&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    echo &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Usage: resetdash [current] [other]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  echo &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Saves your current widget profile, and then activates the profile of your other (specified) setup.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  mv &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$HOME/Library/Preferences/com.apple.dashboard.plist&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$HOME/Library/Preferences/com.apple.dashboard.plist.$1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;; &lt;tt&gt;
&lt;/tt&gt;  mv &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$HOME/Library/Preferences/com.apple.dashboard.plist.$2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$HOME/Library/Preferences/com.apple.dashboard.plist&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;  killall &lt;span class=&quot;co&quot;&gt;Dock&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;  echo &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Widget profile saved and reactivated.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;  fi&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Means you can run &lt;em&gt;resetdash work none&lt;/em&gt; to change over to your no-external-display profile. (I'm not a pro at bash scripting, so you may have better ideas.)&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>shinji kuwayama</name>
    </author>
    <id>tag:www.cementhorses.com,2008-07-28:10</id>
    <published>2008-07-28T16:11:00Z</published>
    <updated>2008-07-23T16:17:11Z</updated>
    <category term="Stuff You Already Know"/>
    <category term="css"/>
    <link href="http://www.cementhorses.com/2008/7/28/counting-in-css" rel="alternate" type="text/html"/>
    <title>Counting in CSS</title>
<content type="html">
            &lt;p&gt;One of the best things you can do as a Rails developer is remember to utilize &lt;em&gt;everything&lt;/em&gt; at your disposal. Last week, I had this front-end task to set up dynamic footnotes; I initially assumed I would be doing this in Ruby, until i found this &lt;strong&gt;choice&lt;/strong&gt; CSS2 &#8220;counter&#8221; support:&lt;/p&gt;


&lt;pre&gt;
body { counter-reset: footnote; }
.footnote:before {
  content: counter(footnote);    
  counter-increment: footnote 1;  
}
&lt;/pre&gt;

	&lt;p&gt;No kidding! It&#8217;s a good reminder&#8212;&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; is quite evolved and mature, and it contains a lot of little-discussed functionality. Remember to exploit it as much as possible (IE6 notwithstanding)…&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>shinji kuwayama</name>
    </author>
    <id>tag:www.cementhorses.com,2008-07-23:11</id>
    <published>2008-07-23T16:13:00Z</published>
    <updated>2008-07-23T16:15:18Z</updated>
    <category term="Stuff You Already Know"/>
    <link href="http://www.cementhorses.com/2008/7/23/take-control-of-your-server-configuration-with-capistrano" rel="alternate" type="text/html"/>
    <title>Take control of your server configuration with Capistrano</title>
<content type="html">
            &lt;p&gt;A typical Rails deployment involves configuring a number of services via configuration files. Common examples include httpd.conf, nginx.conf, memcached.conf, monitrc, my.cnf, haproxy.conf, et al. These little files are the laces that hold your app together; the tiniest mistake or misconfiguration will usually take your whole operation down. On top of this, if you&#8217;ve got multiple servers, you&#8217;ve got to make sure that every server is configured correctly.&lt;/p&gt;


	&lt;p&gt;So why don&#8217;t we put these under version control, and then use Capistrano to deploy configuration changes to one or more servers? Here&#8217;s one way to do it.&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://cementhorses.com/assets/2008/6/25/app_cap.png&quot; alt=&quot;screenshot of a Rails app containing server config files&quot; /&gt;
First, config files go in config/server.&lt;/p&gt;


	&lt;p&gt;In this example, the target servers are running Debian (Etch), and config/server/ corresponds to the root directory of the server&#8212;so we&#8217;ve got /var, /etc, and so on.&lt;/p&gt;


	&lt;p&gt;With this under version control along with the rest of the app, you can now roll back to earlier &#8220;known-good&#8221; configurations lickety-split.&lt;/p&gt;


	&lt;p&gt;As an added benefit, this increases transparency for your team, since developers can see how the deployment works without having to actually visit the servers.&lt;/p&gt;


	&lt;p&gt;And here&#8217;s where it gets even better&#8212;you can now use Capistrano to deploy configs!&lt;/p&gt;


	&lt;p&gt;Dig on this:&lt;/p&gt;


&lt;strong&gt;rake deploy:config&lt;/strong&gt;
&lt;pre&gt;
desc &quot;Deploy server configurations&quot; 
  task :config,:roles=&amp;gt;:app do
    # Export to a temp directory, to avoid uploading .svn directories.
    temp_dir = &quot;/tmp/capistrano-#{Time.now.strftime(&quot;%Y%m%d%H%M%S&quot;)}&quot; 
    system &quot;svn export config/server #{temp_dir}&quot; 
    system &quot;scp -r #{temp_dir}/* #{user}@#{host}:/&quot; 
    system &quot;rm -rf #{temp_dir}&quot; 
    sudo &quot;chmod 700 /etc/monitrc&quot; 
    sudo &quot;chmod 600 /etc/mysql/my.cnf&quot; 
    sudo &quot;chmod -R a+wx /var/service/*&quot; 
    sudo &quot;chmod +x /home/deploy/backup_db&quot; 
    deploy::reload_monit
    deploy::restart_mysql
    deploy::restart_mongrels
    deploy::restart_apache
  end
&lt;/pre&gt;

	&lt;ul&gt;
	&lt;li&gt;This happens to be a subversion environment; if you&#8217;re on git you can probably just omit the exporting step. &lt;/li&gt;
		&lt;li&gt;Make sure you completely understand how &#8220;scp&#8221; works&#8212;if this is new to you, bone up, because a mistake here can really ruin your day.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Please note that this code snippet will almost certainly &lt;strong&gt;not&lt;/strong&gt; work for you as-is; you will have to adjust, rewrite, and optimize this for your unique situation.&lt;/p&gt;


	&lt;p&gt;One last tip: If you run into problems at first, make sure that permissions are reset correctly; these are idiosyncratic and tend to get wrecked in transition. It&#8217;s a simple/best practice to explicitly reset the permissions in your deployment.&lt;/p&gt;


	&lt;p&gt;You&#8217;ll thank yourself later&#8212;enjoy!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>scelis</name>
    </author>
    <id>tag:www.cementhorses.com,2008-07-23:9</id>
    <published>2008-07-23T16:11:00Z</published>
    <updated>2008-07-23T16:14:47Z</updated>
    <category term="Open Source"/>
    <link href="http://www.cementhorses.com/2008/7/23/time-parseable" rel="alternate" type="text/html"/>
    <title>Time Parseable</title>
<content type="html">
            &lt;p&gt;Nobody likes dropdowns. &lt;code&gt;datetime_select&lt;/code&gt; and &lt;code&gt;date_select&lt;/code&gt;? Ugly troupes of unwieldy elements, each of them. They form a line and rudely spit lists of numbers at you. Who wants that? I know how to type a date. Rails knows how to parse a date. &lt;code&gt;Time.parse&lt;/code&gt;, let&#8217;s be friends!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ script/plugin install git://github.com/cementhorses/time_parseable.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, let&#8217;s say we have this object filled with timestamp attributes that we need to manage&#8230;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# create_table do |t|
#   t.timestamp :published_at, :archived_at
# end
class NewsItem &amp;lt; ActiveRecord::Base
  time_parseable
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What? NewsItem now has &lt;code&gt;published_at_string&lt;/code&gt; and &lt;code&gt;archived_at_string&lt;/code&gt;? Yup. And on assignment, they are automatically parsed with &lt;code&gt;Time.parse&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;news_item.published_at_string = 'April 30, 2008'
news_item.published_at # =&amp;gt; Wed Apr 30 00:00:00 -0000 2008
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you&#8217;re only parsing the &lt;code&gt;published_at&lt;/code&gt; column, and magic is looking a bit too expensive for you, scope things down.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;time_parseable :published_at
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wonderful.&lt;/p&gt;

&lt;p&gt;Wait a second! &lt;code&gt;Time.parse&lt;/code&gt;, you&#8217;re a good friend, but what are you doing?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Time.parse('Cement Horses') == Time.now # =&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yes, &#8220;Cement Horses&#8221; is &lt;em&gt;now&lt;/em&gt;, but I only want dates for dates. &lt;code&gt;time_parseable&lt;/code&gt;, please work this out.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;news_item.archived_at_string = 'Cement Horses'
news_item.archived_at # =&amp;gt; nil
news_item.errors.on(:archived_at) # =&amp;gt; 'is invalid'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&#8217;s just throw things in a &lt;code&gt;form_for&lt;/code&gt;, and &lt;code&gt;time_parseable&lt;/code&gt; will do the rest.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;%= f.label :published_at_string %&amp;gt;
&amp;lt;%= f.text_field :published_at_string %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The field, once assigned, will return a &lt;code&gt;strftime&lt;/code&gt;-formatted result. We can choose the format (but we must choose wisely—it should be able to parse to the same result).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;time_parseable :format =&amp;gt; '%I:%M %p on %b %d, %Y'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&#8217;s it for now. Cutting down the form fields, one time at a time.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>shinji kuwayama</name>
    </author>
    <id>tag:www.cementhorses.com,2008-06-23:8</id>
    <published>2008-06-23T14:46:00Z</published>
    <updated>2008-07-23T16:28:53Z</updated>
    <category term="Stuff You Already Know"/>
    <link href="http://www.cementhorses.com/2008/6/23/an-ssh-one-liner-to-authorize-via-public-key" rel="alternate" type="text/html"/>
    <title>An SSH one-liner to authorize via public-key</title>
<content type="html">
            &lt;p&gt;Here's a two-part tip on SSH productivity--you can use public-key authentication and SSH's built-in configuration options to save some time every day.&lt;/p&gt;

&lt;p&gt;1) Authorize your public key. 
If you're like me, it's a bother to remember each little step -- here's the one-liner I use for convenience.&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;  &amp;gt; ssh someuser&lt;span class=&quot;iv&quot;&gt;@remotehost&lt;/span&gt;.com &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;echo `cat ~/.ssh/id_rsa.pub` &amp;gt;&amp;gt; ~/.ssh/authorized_keys&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This will append your key to the remote host's list of authorized keys. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't have a public key yet? You can generate one with:&lt;/em&gt;&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt; &amp;gt; ssh-keygen &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;&lt;em&gt;You'll find a brand-new keypair in your ~/.ssh directory. Read up on &lt;a href=&quot;http://en.wikipedia.org/wiki/Public-key_cryptography&quot;&gt;public-key cryptography&lt;/a&gt; if it's new to you.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;2) Now add the remote host to your (local) .ssh/config file:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;Host&lt;/span&gt; rh&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;Hostname&lt;/span&gt; remotehost.com&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;User&lt;/span&gt; someuser&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The SSH config file can contain many entries; just add this to the list. &quot;Host&quot; is an alias/nickname/shortcut of your choosing.&lt;/p&gt;

&lt;p&gt;So, you can now SSH to your remote host with:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt; &amp;gt; ssh rh&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This will save you a little typing. Public-key authentication is a &quot;best practice&quot; anyway -- it's good to develop the habit. For example, this is the only way to SSH into Amazon EC2 instances, and for administrators, it means you can share access to a SSH account (say, a deployer) without floating the password around. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bonus tip:&lt;/em&gt;
If you find Capistrano and Net::SSH behaving quirkily, make sure you have the latest versions of both. Recent updates to Net::SSH have included various updates and fixes relevant to public-key authentication.&lt;/p&gt;

&lt;p&gt;cf. &lt;a href=&quot;http://net-ssh.rubyforge.org/ssh/v2/api/files/CHANGELOG_rdoc.html&quot;&gt;http://net-ssh.rubyforge.org/&lt;/a&gt;
&lt;br /&gt;
cf. &lt;a href=&quot;http://groups.google.com/group/capistrano/browse_thread/thread/1102208ff925d18&quot;&gt;http://groups.google.com/group/capistrano/&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>dustin anderson</name>
    </author>
    <id>tag:www.cementhorses.com,2008-06-17:5</id>
    <published>2008-06-17T18:50:00Z</published>
    <updated>2008-06-17T19:19:21Z</updated>
    <category term="Stuff You Already Know"/>
    <category term="microapp"/>
    <category term="microframeworks"/>
    <category term="ruby"/>
    <category term="sinatra"/>
    <link href="http://www.cementhorses.com/2008/6/17/microapps-or-little-ditties-with-sinatra" rel="alternate" type="text/html"/>
    <title>MicroApps (or little ditties) with Sinatra</title>
<content type="html">
            &lt;p&gt;Me and one of the other horses left the stables recently and went to RailsConf.  Of all the sessions I attended, my favorite one was by far Erik Kastner&#8217;s talk entitled &lt;a href=&quot;http://www.slideshare.net/guesta2b753/microapps-for-fun-and-sprofits&quot;&gt;MicroApps for Fun and Profit.&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://metaatem.net/&quot;&gt;Erik Kastner&lt;/a&gt; explained that MicroApps are small apps that you can write the bulk of the code in a day&#8230; or get completely done in one sitting (one day).&lt;/p&gt;


	&lt;p&gt;They can be simply &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;/CSS/JavaScript&#8230; they can be written in Camping, they can be &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; mashups, you could use Yahoo! Pipes, it could be just text on a page.  You could use Ruby on Rails, you can use a blog engine&#8230; it doesn&#8217;t really matter, it just has to be done in one sitting.&lt;/p&gt;


	&lt;p&gt;The app he demoed (called &lt;a href=&quot;http://github.com/kastner/jeff4good/tree/master&quot;&gt;Jeff4Good&lt;/a&gt; ) is a one-page web form that takes &#8220;donations&#8221; of stuff or money to help his friend Jeff who needed money for a hospital trip that cost him a bunch of money.&lt;/p&gt;


	&lt;p&gt;The Jeff4Good app uses the relatively new ruby microframework, &lt;a href=&quot;http://www.sinatrarb.com&quot;&gt;Sinatra&lt;/a&gt;.  He wrote it within one day.
Personally, I have ideas for web apps all the time &#8211; it&#8217;s rare that I have time to actually get something out there, but the MicroApp &#8220;philosopy&#8221; that Erik Kastner proposes (along with things like the Sinatra framework) makes it seem so much more possible to get stuff out there.  I love the idea of getting something completely done in one sitting &#8211; I&#8217;ve got waaaay too many ideas that haven&#8217;t been implemented right now.&lt;/p&gt;


	&lt;p&gt;Erik pointed out that the title of the talk should be &#8220;MicroApps for fun and Micro Profit&#8221; because most of the MicroApps that he has written were not profitable &#8211; or if they were, the profit wasn&#8217;t much.&lt;/p&gt;


	&lt;p&gt;The profit that you do gain, however, is that you get to learn something new and you build your portfolio.  You can play around with ActiveRecord or DataMapper in new ways.  You can start hacking on &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt;&#8217;s that you haven&#8217;t played with before.  You also get to build your portfolio of successful web apps.  That can lead to promotions or job offers.&lt;/p&gt;


	&lt;p&gt;Erik also pointed out that he&#8217;s been able to work with some high profile developers and designers because he didn&#8217;t need a big commitment from them&#8230; you might be able to get a great designer to help out on a fun little project and make your MicroApp look super sweet.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Some examples of MicroApps:&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://metaatem.com/words&quot;&gt;metaatem.com/words&lt;/a&gt; (Spell your name in pictures from Flickr)&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://twistori.com/&quot;&gt;Twistori&lt;/a&gt; (twitter mashup)&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://foamee.com/&quot;&gt;Foamee&lt;/a&gt; (twitter mashup &#8211; tracks who you owe beer or coffee to)&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://crocspotting.com/&quot;&gt;CrocSpotting&lt;/a&gt; (a phoblog (photo blog) that uses Yahoo! Pipes &#38; a Flickr feed of Crocs (you know those shoe things))&lt;/p&gt;


	&lt;p&gt;Learn more about the Sinatra Microframework at &lt;a href=&quot;http://www.sinatrarb.com&quot;&gt;sinatrarb.com&lt;/a&gt; and &lt;a href=&quot;http://www.gittr.com/&quot;&gt;gittr.com&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;em&gt;Write your first &#8220;hello world&#8221; Sinatra app in less than 60 seconds:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;gv&quot;&gt;$sudo&lt;/span&gt; gem install sinatra&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


Then, start writing your code in a *.rb file (e.g. frank.rb).
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rubygems&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sinatra&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;get &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OMG, like, hey world!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Save your 5 lines of code and then run the app:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;gv&quot;&gt;$ruby&lt;/span&gt; frank.rb&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then, it should say:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;frank takes the stage on port 4567&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Go to localhost:4567 in your browser.&lt;/p&gt;


	&lt;p&gt;&#8220;OMG, like, hey world!&#8221;&lt;/p&gt;


	&lt;p&gt;See &#8211; fun&#8230; and easy!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>dbora</name>
    </author>
    <id>tag:www.cementhorses.com,2008-05-29:4</id>
    <published>2008-05-29T20:30:00Z</published>
    <updated>2008-06-17T15:26:47Z</updated>
    <category term="Open Source"/>
    <category term="calendar"/>
    <category term="plugin"/>
    <category term="rails"/>
    <category term="ruby"/>
    <category term="schedule"/>
    <link href="http://www.cementhorses.com/2008/5/29/ror-schedulable" rel="alternate" type="text/html"/>
    <title>RoR: Schedulable</title>
<content type="html">
            &lt;h3&gt;What it is.&lt;/h3&gt;

&lt;p&gt;If you have data that must go live on a specific date; If you have a model object you would like to query for it&#8217;s published state; If you would like the functions of publishing and un-publishing content to be precise and understandable, the Schedulable plugin may be for you.  In short, adding Schedulable to your models will allow you to manage the publishing of your data through the liberal use of semantic sugar.  The goal of the Schedulable plugin is to be intuitive, concise and easy while solving an often necessary and crucial business need: Scheduling your content.&lt;/p&gt;

&lt;h3&gt;How it works.&lt;/h3&gt;

&lt;p&gt;Calling &lt;code&gt;schedulable&lt;/code&gt; automatically hooks a few methods to a published_at column:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;scheduled?&lt;/code&gt; (&lt;code&gt;true&lt;/code&gt; if the item is scheduled to be published but isn&#8217;t yet)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;published?&lt;/code&gt; (&lt;code&gt;true&lt;/code&gt; if the item is published)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real power is when expiration is a question&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;schedulable :end =&amp;gt; :archived_at
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;schedulable :published_at, :archived_at
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;does a little more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;scheduled? :archived_at&lt;/code&gt; (&lt;code&gt;true&lt;/code&gt; if &lt;code&gt;archived_at&lt;/code&gt; is set in the future)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;archived?&lt;/code&gt; (&lt;code&gt;true&lt;/code&gt; if the item has been archived)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;with a note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;published?&lt;/code&gt; returns &lt;code&gt;false&lt;/code&gt; when &lt;code&gt;archived?&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It&#8217;s all semantic sugar:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;schedulable :activated_at, :terminated_at, :end_required =&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;therefore creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;activated?&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terminated?&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that last option? It just adds a validation requiring the end to be set if the start is.&lt;/p&gt;

&lt;p&gt;We have your other validations taken care of, too. We&#8217;re just more comfortable with things when they&#8217;re chronological.&lt;/p&gt;

&lt;h3&gt;How can I get it&lt;/h3&gt;

&lt;p&gt;On Edge:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ script/plugin install git://github.com/cementhorses/schedulable.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&#8230;otherwise &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git@github.com:cementhorses/schedulable.git vendor/plugins/schedulable
&lt;/code&gt;&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>dustin anderson</name>
    </author>
    <id>tag:www.cementhorses.com,2008-05-08:2</id>
    <published>2008-05-08T19:31:00Z</published>
    <updated>2008-05-08T20:30:55Z</updated>
    <category term="Stuff You Already Know"/>
    <link href="http://www.cementhorses.com/2008/5/8/less-work-more-be-ing" rel="alternate" type="text/html"/>
    <title>Less work, more be-ing with quick shell aliasing</title>
<content type="html">
            &lt;p&gt;This weekend, after working an endless &lt;a href=&quot;http://www.amazon.com/4-Hour-Workweek-Escape-Live-Anywhere/dp/0307353133&quot;&gt;5 hour work week&lt;/a&gt;, I decided that I want to implement new ways for me to continue to be even &lt;a href=&quot;http://www.hhhh.org/wiml/virtues.html&quot;&gt;lazier&lt;/a&gt; than I already am&#8230;&lt;/p&gt;


	&lt;p&gt;After laboriously lifting my heavy 4&#8221; long fingers to ssh into another server that I couldn&#8217;t remember the IP address for, I started to think there has to be a better way.&lt;/p&gt;


	&lt;p&gt;Why am I always repeatedly type long lines of ssh logins, rake tasks, etc. into the command line?  I&#8217;m always trying to stay &lt;a href=&quot;http://en.wikipedia.org/wiki/Don't_repeat_yourself&quot;&gt;&lt;span class=&quot;caps&quot;&gt;DRY&lt;/span&gt;&lt;/a&gt; in my application code, and it&#8217;s got me thinking, how can I sort of stay &#8220;DRY&#8221; at the command line and limit the amount of work that I do?&lt;/p&gt;


	&lt;p&gt;Why don&#8217;t I create time saving aliases more often?&lt;/p&gt;


	&lt;p&gt;One big reason that I don&#8217;t create time saving aliases more often is because it&#8217;s not brain-dead-easy enough for me to edit my .bash_profile&#8230; so, I created an alias to quickly edit my .bash_profile:&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; 'be' (for &amp;quot;bash edit&amp;quot;)&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; be&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;mate ~/.bash_profile&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

The really sweet version that re-sources your .bash_profile after you save your changes is:
&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; be&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;mate -w ~/.bash_profile;source ~/.bash_profile&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Then, I decided to take a look at where I could reduce repetitive tasks, so I executed the &lt;code&gt;history&lt;/code&gt; command to see what are some of the longer commands that I&#8217;ve written repetitively.&lt;/p&gt;


&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;~&lt;/span&gt; $ history
   &lt;span class=&quot;Constant&quot;&gt;10&lt;/span&gt;  ssh deploy&lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;myserver&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;railsmachina&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;com&lt;/span&gt;
   &lt;span class=&quot;Constant&quot;&gt;13&lt;/span&gt;  cd &lt;span class=&quot;Variable&quot;&gt;Projects2&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;/&lt;/span&gt;
   &lt;span class=&quot;Constant&quot;&gt;55&lt;/span&gt;  rake db&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;migrate&lt;/span&gt;
   &lt;span class=&quot;Constant&quot;&gt;57&lt;/span&gt;  rake db&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;migrate&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;RAILS_ENV&lt;/span&gt;&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;test
   &lt;span class=&quot;Constant&quot;&gt;88&lt;/span&gt;  rake ultrasphinx&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;bootstrap&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;I see that I&#8217;m typing a lot of long rake tasks like &lt;code&gt;rake db:migrate, rake ultrasphinx:bootstrap, cd Projects/post_it, cd Projects/my_project&lt;/code&gt;&lt;/p&gt;


So, I&#8217;m going to add those&#8230; 
&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; rdb&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rake db:migrate&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; rub&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rake ultrasphinx:bootstrap&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; my_project&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;cd Projects/my_project/trunk/&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

I don&#8217;t want to go crazy in one day and add &lt;span class=&quot;caps&quot;&gt;EVERYTHING&lt;/span&gt;, I&#8217;d rather fine tune this over time and make the process of adding and editing my bash_profile easier&#8230; So, by just adding the &lt;code&gt;be&lt;/code&gt; alias, I now have an easier way to create shortcuts and it makes me a much happier programmer:
&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; be&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;mate ~/.bash_profile&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;We discussed the possibility of writing a function (let&#8217;s call it &lt;code&gt;balias&lt;/code&gt;) that could automatically add an alias to your bash_profile (e.g. &lt;code&gt;balias myserver &quot;ssh live@8.23.456.78&quot;&lt;/code&gt;).  My only hesitation with doing that is it could make your .bash_profile a disorganized mess&#8230;  But, it would be very nice to just add new aliases via command line.&lt;/p&gt;


The other challenge is how do you remember all these shortcuts?  Type &lt;code&gt;alias&lt;/code&gt; in your command line to remember what aliases you have added.
&lt;pre class=&quot;blackboard&quot;&gt;
&lt;span class=&quot;Keyword&quot;&gt;~&lt;/span&gt; $ &lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; be&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;mate -w ~/.bash_profile;source ~/.bash_profile&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; ett&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;mate app config lib db public test vendor/plugins &amp;amp;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; gd&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;git diff | mate&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; app_live_1&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;ssh live@8.22.345.67&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; app_live_2&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;ssh live@8.22.345.99&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; app_live_db&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;ssh live@8.22.345.222&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; app_sandbox&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;ssh sandbox@8.22.43.243&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; app_staging&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;ssh staging@8.22.43.244&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; rdb&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rake db:migrate&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; rdbt&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;rake db:migrate RAILS_ENV=test&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;alias&lt;/span&gt; td&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;mate ~/Documents/todo.txt&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;

Footnotes:
	&lt;ul&gt;
	&lt;li&gt;See other people&#8217;s .bash_profiles here: http://dotfiles.org/&lt;/li&gt;
		&lt;li&gt;You can also edit your .ssh/config, but I find it just as good to put them in the .bash_profile. &lt;/li&gt;
		&lt;li&gt;You can set up autocomplete for ssh as well &#8211; using this &lt;a href=&quot;http://drawohara.com/post/6584031&quot;&gt;Life changing shell function&lt;/a&gt;, I&#8217;m probably missing something about setting up .ssh/config, but right now, it&#8217;s not working well for me since all my logins are always &lt;code&gt;ssh username@8.34.56.123&lt;/code&gt; and not simply &lt;code&gt;ssh domain_name&lt;/code&gt;.&lt;/li&gt;
	&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://www.cementhorses.com/">
    <author>
      <name>jjones</name>
    </author>
    <id>tag:www.cementhorses.com,2008-05-07:1</id>
    <published>2008-05-07T19:28:00Z</published>
    <updated>2008-05-08T20:00:53Z</updated>
    <category term="Stuff You Already Know"/>
    <category term="rails"/>
    <category term="ruby"/>
    <link href="http://www.cementhorses.com/2008/5/7/interceptor-methods" rel="alternate" type="text/html"/>
    <title>Interceptor Methods</title>
<content type="html">
            Let's say we have a class in a plugin or module somewhere, and we want to override one of its methods to handle more cases, without losing the original functionality.  For example, maybe we've got a login module that checks for the user record in a database.  We want to make it check an LDAP first, then check the database if the user is not found in the LDAP.

Using an &quot;interceptor&quot; pattern can help here.  We'll alias the original method, storing a copy of it under a new name.  Then we redefine the method to handle the new feature and conditionally call the old method.

Here's an example:

&lt;pre class=&quot;blackboard&quot;&gt;
    &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Unicorn&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;climate&lt;/span&gt;

      &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;frolic&lt;/span&gt;
        puts &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;Frolic in a meadow, enchant other forest creatures with majesty&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;    &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; this class definition is locked away somewheres&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;    &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; now let's reopen the class and add the interceptor&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Unicorn&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;      &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; copy the original method so we can still call it&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;alias_method&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;old_frolic&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;frolic&lt;/span&gt; 
      
&lt;span class=&quot;Comment&quot;&gt;      &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; let's intercept calls to frolic method&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;frolic&lt;/span&gt;
        &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;climate&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;tundra&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; new functionality&lt;/span&gt;
          puts &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;Frolic on a glittering glacier, under the Aurora Borealis&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;Keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; conditionally default to old method definition&lt;/span&gt;
          old_frolic
        &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
          </content>  </entry>
</feed>
