<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>ThermalBlog - Home</title>
  <id>tag:blog.thermalcreative.com,2007:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  <link href="http://blog.thermalcreative.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://blog.thermalcreative.com/" rel="alternate" type="text/html"/>
  <updated>2007-12-14T03:36:00Z</updated>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-12-14:342</id>
    <published>2007-12-14T03:10:00Z</published>
    <updated>2007-12-14T03:36:00Z</updated>
    <category term="apple"/>
    <category term="plesk"/>
    <category term="rails"/>
    <link href="http://blog.thermalcreative.com/articles/2007/12/14/new-hosting-server-os" rel="alternate" type="text/html"/>
    <title>New Hosting / Server OS</title>
<content type="html">
            &lt;p&gt;After running nearly two years on a Rimuhosting &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt; with Debian Sarge, we decided to switch over to a Rimuhosting Miro4 on CentOS 5 with Plesk 8.2 and do some hosting. Since it seems that since we&#8217;re the primary tech support contact for our clients regardless of the fact that most of them have direct relationships with their web hosts, we&#8217;ve decided to start hosting client sites ourselves (when appropriate), on our &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt;. VPS hosting for Rails sites is usually a better solution anyway, since nearly every shared host I&#8217;ve attempted to host a Rails app on until now has either been very slow, or very unreliable.&lt;/p&gt;


	&lt;p&gt;Overall, it&#8217;s been a lot of fun getting things up and running, and it&#8217;s been quite painless. Plesk automates a lot of the tasks that I had to do manually on Sarge, a lot of which I really didn&#8217;t want to know about anyway. (Such as editing dovecot config files manually&#8230; ugh)&lt;/p&gt;


	&lt;p&gt;I was a bit concerned about how to host Rails apps with Plesk, and I&#8217;m pleasantly surprised at how easy it is. CentOS5 ships with Apache 2.2, with it&#8217;s awesome mod_proxy_balancer. It&#8217;s definitely not the highest-performance solution available, but it&#8217;s easy to set up, and it integrates well with the Plesk workflow. This blog is running on two mongrels with mongrel_cluster, and balanced with mod_proxy_balancer. I simply had to set up a vhost.conf file based on the setup provided by &lt;a href=&quot;http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/&quot;&gt;Coda Hale&lt;/a&gt; for my subdomain, get mongrel_cluster configured to match, and I was done. There&#8217;s a couple other steps in there, which I&#8217;ll detail in a future post.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;IMAP&lt;/span&gt; Problems&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;The only real problem I&#8217;ve experienced is Apple Mail&#8217;s rebellion against the &lt;span class=&quot;caps&quot;&gt;IMAP&lt;/span&gt; namespace structure of Courier &lt;span class=&quot;caps&quot;&gt;IMAP&lt;/span&gt;, which is the default mail server with Plesk. Apparently under the &lt;span class=&quot;caps&quot;&gt;IMAP&lt;/span&gt; spec mail servers are free to choose a namespace separator as well as a namespace prefix. This can be autodiscovered during the &lt;span class=&quot;caps&quot;&gt;HELO&lt;/span&gt; process with the server, but Mail ignores this. Mail &lt;span class=&quot;caps&quot;&gt;DOES&lt;/span&gt; allow you to set an &lt;span class=&quot;caps&quot;&gt;IMAP&lt;/span&gt; prefix under the Advanced account settings tab, which on Courier servers is &lt;span class=&quot;caps&quot;&gt;INBOX&lt;/span&gt;. Setting that is the first step, which will get Mail to correctly pick up the Sent and Trash folders on the server. However, there is still difficulty when you wish to create new &#8220;Mailboxes&#8221; on the account, which is Mail&#8217;s term for subfolders. In this case, if you wish to create a first-tier subfolder under the account (i.e. Account Name/New Folder) you must specify the mailbox name as &#8220;INBOX.New Folder&#8221; to correctly set it up. However, for subfolders underneath this new folder (i.e. Account Name/New Folder/New Subfolder), you simply add a new Mailbox underneath New Folder as you would expect, with no need to specify any prefix.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-12-07:315</id>
    <published>2007-12-07T17:45:00Z</published>
    <updated>2007-12-07T17:50:51Z</updated>
    <category term="grid server"/>
    <category term="media template"/>
    <category term="rails"/>
    <link href="http://blog.thermalcreative.com/articles/2007/12/7/mediatemple-gs-automated-mongrel-restart" rel="alternate" type="text/html"/>
    <title>MediaTemple (gs) Automated Mongrel Restart</title>
<content type="html">
            &lt;p&gt;I&#8217;ve got a couple of small Rails sites hosted on MediaTemple&#8217;s (gs) product, and I&#8217;m happy to say that it&#8217;s been a positive experience. A lot of people complained about the product early on, but MediaTemple has made a lot of reliability improvements, and I&#8217;ve had nothing but a good experience so far with it.&lt;/p&gt;


	&lt;p&gt;However, the one problem is that the base Rails container, which runs Mongrel, is pretty limited on memory, and it seems that the mongrel process will just get killed if it goes over it&#8217;s limit. I&#8217;ve had this happen a couple of times where the process gets killed without being restarted, and then the site is down until I call &#8220;cap restart&#8221; or restart it via &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt;. This obviously isn&#8217;t an acceptable solution, so I hacked together a little Ruby script that will check your site to see if it&#8217;s alive, and if not it will restart it. Schedule it via cron, and you&#8217;re ready to go!&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;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&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;c&quot;&gt;#!/usr/bin/ruby&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;net/http&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;uri&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;site = &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;your_site_id&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;application = &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;your_application_name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;friendly_name = &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;Your Site's Actual Name (used only for notification)&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;webpath = &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;http://www.yourdomainname.com/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;user = &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;serveradmin%yourdomainname.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;password = &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;yourpassword&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;tt&gt;
&lt;/tt&gt;url = &lt;span class=&quot;co&quot;&gt;URI&lt;/span&gt;.parse(webpath)&lt;tt&gt;
&lt;/tt&gt;req = &lt;span class=&quot;co&quot;&gt;Net&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;HTTP&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Head&lt;/span&gt;.new(url.path)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;res = &lt;span class=&quot;co&quot;&gt;Net&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;HTTP&lt;/span&gt;.start(url.host, url.port) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |http|&lt;tt&gt;
&lt;/tt&gt;  http.request(req)&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;unless&lt;/span&gt; res.is_a? &lt;span class=&quot;co&quot;&gt;Net&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;HTTPOK&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  puts &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;Detected Site Down: Restarting &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;friendly_name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;...&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;sh&quot;&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mtr restart &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;application&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; --username &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;user&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; --password &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;password&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;&lt;strong&gt;One More Thing&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;To actually call the script, you have to initialize your &lt;span class=&quot;caps&quot;&gt;PATH&lt;/span&gt; variables, since cron doesn&#8217;t run your .bash_profile script before it runs your job. I created a .sh file to call my ruby script that sets the correct paths before calling the script:&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;&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;c&quot;&gt;#!/bin/sh&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;export &lt;span class=&quot;co&quot;&gt;PATH&lt;/span&gt;=&lt;span class=&quot;gv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;sy&quot;&gt;:/&lt;/span&gt;usr/local/bin/&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;cd &lt;span class=&quot;gv&quot;&gt;$HOME&lt;/span&gt;/data/&lt;tt&gt;
&lt;/tt&gt;./babysitter.rb&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;I called the sh file babysitter.sh, and the ruby script babysitter.rb, chmod +x on both of them, added babysitter.sh as a 5 minute cron job, and forgot about it. Periodically I&#8217;ll get a cron email letting me know that it&#8217;s restarted the app, though it doesn&#8217;t happen very often.&lt;/p&gt;


	&lt;p&gt;Hopefully this will help someone!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-12-06:307</id>
    <published>2007-12-06T04:51:00Z</published>
    <updated>2007-12-06T05:07:44Z</updated>
    <category term="content management"/>
    <category term="drupal"/>
    <link href="http://blog.thermalcreative.com/articles/2007/12/6/thoughts-on-content-management" rel="alternate" type="text/html"/>
    <title>Thoughts on Content Management</title>
<content type="html">
            &lt;p&gt;After developing a few custom &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; apps in Rails, and not being entirely happy with the result, I decided to try Drupal out as a base for a content management app. Now, don&#8217;t get me wrong, I love Rails. I wish I could only &lt;strong&gt;ever&lt;/strong&gt; develop in rails. But the economic reality is that most of the work we get calls for flexible content management, and the &#8216;bespoke&#8217; &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt;&#8217;s that I&#8217;ve built in Rails/PHP/ASP.Net over the years leave a lot to be desired&#8230; Also, as the Rails community seems to be focused more around app development, few actual dedicated content management apps have surfaced. Radiant &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; is one, but I&#8217;m going to give it a bit more time before I try it on a client project. However, reinventing the wheel every time just isn&#8217;t efficient enough to justify building the &#8216;perfect &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; for the situation&#8217;, so I decided to try out some of the open-source heavy-hitters.&lt;/p&gt;


	&lt;h3&gt;Joomla&lt;/h3&gt;


	&lt;p&gt;I built a restricted-access membership site for a client that integrated the user database with their internal enterprise system, and I based that site on Joomla 1.5. Naively, I thought that it was better to base the site on the latest and greatest version of the Joomla framework for forward compatibility. This was indeed a benefit during development, though the documentation on custom module development for version 1.5 was very sparse. Joomla 1.5 uses the &lt;span class=&quot;caps&quot;&gt;MVC&lt;/span&gt; pattern, which is really quite nice since I&#8217;ve done most recent work in Rails with it&#8217;s similar &lt;span class=&quot;caps&quot;&gt;MVC&lt;/span&gt; pattern. However, I found the development of modules to be a painful process that required lots and lots of poking around in the core modules to see how it &#8216;should&#8217; be done, due to the lack of proper documentation.&lt;/p&gt;


	&lt;p&gt;The Joomla community has had quite a bit of drama lately over licensing issues, which has largely halted creation of modules for Joomla 1.5. This has proved to be a major problem for us, since we had recommended Joomla to the client based on it&#8217;s large base of available modules. I&#8217;m hoping that this issue will burn itself out soon, but so far it&#8217;s just another strike against Joomla.&lt;/p&gt;


	&lt;p&gt;Finally, after using the Joomla admin I&#8217;m just not convinced that it&#8217;s nearly powerful and flexible enough to do much more than manage a basic website. The permissions system is quite static, and additional modules seem poorly integrated into the interface. Unlike Drupal, where a module can actually modify the behavior of other modules, each module very much stands alone in Joomla. If you don&#8217;t like the behavior of the core framework, it&#8217;s time to start hacking.&lt;/p&gt;


	&lt;h3&gt;Drupal&lt;/h3&gt;


	&lt;p&gt;So&#8230; after building a membership site in Joomla and being very much underwhelmed by the experience, I decided to give Drupal a whirl. The main features that attracted me to Drupal are the (surprise!) development features, as there is a lot of power to be found in the framework.&lt;/p&gt;


	&lt;p&gt;The default module set is pretty basic. However, when you add Views, &lt;span class=&quot;caps&quot;&gt;CCK&lt;/span&gt;, ImageCache, and Services, you have the ability to build feature-rich sites very quickly. I built a site that allows for full content management by the client with integrated flash interface elements pulling data from Drupal via the &lt;span class=&quot;caps&quot;&gt;AMFPHP&lt;/span&gt; remoting gateway, all in a very few days, most of which were spent writing the Flash elements and building the theme. Very little time was spent on actual module development, since the flexibility provided by the above modules saved me from coding custom modules.&lt;/p&gt;


	&lt;p&gt;The most critical thing with Drupal is to learn which modules are essential. Drupal core is functional, but you really need to add modules to make it useful. The &lt;span class=&quot;caps&quot;&gt;CCK&lt;/span&gt; (Content Construction Kit) allows you to build nodes (types of content) with arbitrary column types. This allows you to construct node types that match all of your content. The Views module lets you create custom views for your content, including &lt;span class=&quot;caps&quot;&gt;RSS&lt;/span&gt; feeds. ImageCache is absolutely fantastic&#8230; It allows you to define resizing presets for images that you can then reference in your templates. When an image is called for, it&#8217;s resized based on the selected template and cached to disk for subsequent use. Should you change the template, just flush the cache and the process starts again! Finally, though I didn&#8217;t use it here, the Services/AMFPHP module is an excellent way to connect Drupal with Flash Remoting. We&#8217;ve got another job coming online that I&#8217;ll mention here once it&#8217;s done that makes use of this.&lt;/p&gt;


	&lt;p&gt;All of this said, Drupal is not for the faint of heart. You need to approach it with a bit of a hacker mentality to really get the most out of it. I&#8217;ve read many comparisons between different &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; options, and one of the most common complaints about Drupal is the varying quality of the modules, the steep learning curve with development, and the less than desirable quality of the Drupal template engine. Many people who complain about these shortfalls find ExpressionEngine an easier &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; to use, due to it&#8217;s ease of skinning. However, I&#8217;m convinced that if you&#8217;re into development and aren&#8217;t too concerned with the skinning issues, Drupal offers a very powerful and flexible base with which to start. Drupal is one of the most extensible platforms I&#8217;ve seen, and offers many ways to plug into nearly every bit of the system to insert your own custom functionality. This alone is it&#8217;s most redeeming feature.&lt;/p&gt;


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


	&lt;p&gt;I&#8217;m definitely going to keep using Drupal for heavy content-management sites. However, whenever I&#8217;m presented with the opportunity to develop an actual web application, I&#8217;ll certainly be going back to Rails.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-12-06:308</id>
    <published>2007-12-06T04:38:00Z</published>
    <updated>2007-12-06T04:51:33Z</updated>
    <category term="drupal"/>
    <link href="http://blog.thermalcreative.com/articles/2007/12/6/it-s-alive" rel="alternate" type="text/html"/>
    <title>It's ALIVE...</title>
<content type="html">
            &lt;p&gt;Thermal has launched our new website! Well, to be completely honest, it&#8217;s our &lt;span class=&quot;caps&quot;&gt;FIRST&lt;/span&gt; website. Up to this point we&#8217;ve been surviving on a first-round logo draft and no business cards, which I suppose is a testament to the strength of the economy and the demand for people like us.&lt;/p&gt;


	&lt;p&gt;However, we had some time this fall, and decided to get all professional-like and make an actual website.&lt;/p&gt;


	&lt;p&gt;The site is based on Drupal, with a lot of help from Views, &lt;span class=&quot;caps&quot;&gt;CCK&lt;/span&gt;, and ImageCache. My biggest frustration (as mentioned in the previous post) is the difficulty in building themes and customizing the appearance of modules. Shamefully, I did end up hacking the core contact form, after all of my wrangling with hook_form didn&#8217;t produce the desired results. Since Drupal modules often end up outputting &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; (though they should do a minimum of this if they use the theme functions), it seems that some hacking is always required to get the job done.&lt;/p&gt;


	&lt;p&gt;Also included were Javascript support from ThickBox and JCarousel. This was also my first experience with JQuery, and it&#8217;s not bad at all. A lot of similarities to Prototype, though I still like the Prototype coding style a bit better.&lt;/p&gt;


	&lt;p&gt;We&#8217;re still planning for more features in the future for the site, but for now it&#8217;s back to the &#8220;real&#8221; work!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-03-06:35</id>
    <published>2007-03-06T16:22:00Z</published>
    <updated>2007-03-06T16:53:27Z</updated>
    <category term="flash"/>
    <category term="rails"/>
    <link href="http://blog.thermalcreative.com/articles/2007/3/6/xml-load-and-content-encoding" rel="alternate" type="text/html"/>
    <title>XML.load and Content-Encoding</title>
<content type="html">
            &lt;p&gt;I was having a rather perplexing problem with Flash in &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt; the other day, and I found very little to help me until I stumbled upon this &lt;a href=&quot;http://blog.mediacatalyst.com/pivot/entry.php?id=281&quot;&gt;gem&lt;/a&gt;. We have some flash elements on a site that we built that make use of &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; loaded out of a Rails app via ActiveRecord::Base.to_xml. I was using the basic &lt;a href=&quot;http://brainspl.at/nginx.conf.txt&quot;&gt;Nginx config file&lt;/a&gt; put together by &lt;a href=&quot;http://brainspl.at/&quot;&gt;Ezra&lt;/a&gt; for proxying to a mongrel_cluster, which works great overall. However, as mentioned in that blog entry, &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt; doesn&#8217;t like compression or no-cache headers on &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; data.&lt;/p&gt;


	&lt;p&gt;Fortunately Nginx allows you to set the header types that will have gzip compression applied, using the &#8220;gzip_types&#8221; directive in the config file. So, just make sure that your actions that generate xml have the &#8220;Content-Type: text/xml&#8221; header applied, and then remove the &#8220;text/xml&#8221; directive from the list of gzip_types in your Nginx config file.&lt;/p&gt;


	&lt;p&gt;Unfortunately you can&#8217;t use the handy-dandy Rails respond_to function, because Flash fails to correctly set the Request-Type header to text/xml. So, my only solution was to come up with xml actions to parallel with my view actions so that any request to that action would receive xml regardless of the Request-Type.&lt;/p&gt;


	&lt;p&gt;So, make sure that any actions that emit xml for Flash consumption set the following:&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;&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;iv&quot;&gt;@headers&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Content-Type&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&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;text/xml&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;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And you should be good to go!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-02-21:34</id>
    <published>2007-02-21T22:05:00Z</published>
    <updated>2007-02-21T22:29:04Z</updated>
    <category term="prototype"/>
    <category term="rails"/>
    <link href="http://blog.thermalcreative.com/articles/2007/2/21/rails-ajax_options-with" rel="alternate" type="text/html"/>
    <title>Rails AJAX_OPTIONS :with</title>
<content type="html">
            &lt;h2&gt;The Problem&lt;/h2&gt;


	&lt;p&gt;I&#8217;m writing an admin backend for a client, and I wanted to trigger an &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; call based on the value of a &lt;span class=&quot;caps&quot;&gt;SELECT&lt;/span&gt; field. The problem this presents compared to the normal Rails &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; usage is that the value you want to send via &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; isn&#8217;t specified at the time the page is rendered, and I didn&#8217;t want to serialize the entire form to get the correct value of one field.&lt;/p&gt;


	&lt;p&gt;The obvious candidate for a link to fire an &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; call is &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionView/Helpers/PrototypeHelper.html#M000527&quot;&gt;link_to_remote&lt;/a&gt;, but it&#8217;s not entirely obvious how you can specify a request parameter that will be evaluated at the time of the click. Most of the time you set the parameters you wish to send back to the server in the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;, but that won&#8217;t work in this case because I don&#8217;t want to use a static &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;.h2 The solution: &#8221;:with&#8221; 
So, there&#8217;s a handy option to most of the &lt;a href=&quot;http://api.rubyonrails.com/classes/ActionView/Helpers/PrototypeHelper.html&quot;&gt;PrototypeHelper&lt;/a&gt; functions that&#8217;s a bit poorly documented (in my opinion, anyway). :with allows you to specify the &lt;a href=&quot;http://www.prototypejs.org/api/ajax/options&quot;&gt;parameters&lt;/a&gt; part of the &lt;a href=&quot;http://www.prototypejs.org/api/ajax/request&quot;&gt;Ajax.Request&lt;/a&gt; call. This will be evaluated on the fly when the onclick is fired, and is submitted via &lt;span class=&quot;caps&quot;&gt;POST&lt;/span&gt;. (Unless you are setting the postBody parameter as well.) The best part is that Prototype will serialize standard JavaScript object notation (read: &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt;) into a &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;-encoded &lt;span class=&quot;caps&quot;&gt;POST&lt;/span&gt; body. Not too clear? Try this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
link_to_remote(&quot;Set Position&quot;, 
           :url =&amp;gt; {:action =&amp;gt; &quot;load_map&quot;, :id =&amp;gt; @listing},
           :with =&amp;gt; &quot;{map_id:$F('listing_map_id')}&quot;)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will yield the following &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;/JavaScript:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&amp;lt;a href=&quot;#&quot; onclick=&quot;new Ajax.Request('/property/show_map/1', 
           {asynchronous:true, evalScripts:true, 
           parameters:{map_id:$F('listing_map_id')}}); 
           return false;&quot;&amp;gt;Set Position&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Which will, when clicked, generate an &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; call with the following &lt;span class=&quot;caps&quot;&gt;POST&lt;/span&gt; body:&lt;/p&gt;


	&lt;p&gt;map_id=1&lt;/p&gt;


	&lt;p&gt;(assuming the value of my dropdown is 1.) Also, note that $F is a Prototype shortcut that allows you to grab the value of a form field based on the ID you pass in. An extremely handy function&#8230;&lt;/p&gt;


	&lt;p&gt;So, this is a really great way to add an arbitrary number of parameters to an &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; call using any Javascript variable, which could be the position of an element, value of a form field, the list goes on!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-02-10:32</id>
    <published>2007-02-10T19:16:00Z</published>
    <updated>2007-02-10T19:45:44Z</updated>
    <category term="General Tech"/>
    <category term="apple"/>
    <link href="http://blog.thermalcreative.com/articles/2007/2/10/adventures-in-mac-ownership" rel="alternate" type="text/html"/>
    <title>Adventures in Mac Ownership...</title>
<content type="html">
            &lt;p&gt;Well, I just learned my biggest lesson about Mac Ownership&#8230; Buy AppleCare.&lt;/p&gt;


	&lt;p&gt;I&#8217;ve had my MacBookPro (MBP) for almost a year now, and I&#8217;ve been giddy about it most of the time. It&#8217;s my first Mac, and I couldn&#8217;t be happier for switching. (My name is Matt White, and I&#8217;m a &lt;a href=&quot;http://www.youtube.com/watch?v=hGtJeWJ0HRw&#38;mode=related&quot;&gt;switcher&lt;/a&gt; !)&lt;/p&gt;


	&lt;p&gt;This summer I participated in the &lt;span class=&quot;caps&quot;&gt;MBP&lt;/span&gt; battery recall, and congratulated myself for purchasing a computer from a company so addicted to quality that they sent me a new battery because the original didn&#8217;t &#8220;live up to expectations&#8221;. Take &lt;span class=&quot;caps&quot;&gt;THAT&lt;/span&gt;, Dell!&lt;/p&gt;


	&lt;p&gt;However, while I was based out of New Zealand last fall (about a month after getting my new battery), my computer started having hardware problems. When used on battery, it would randomly lose power without warning. No shutdown, just dead. The problem started getting worse and worse, to the point where I couldn&#8217;t even use the machine without being on AC power. Needless to say, this is ultra lame when you&#8217;re talking about a laptop. (Or &#8220;portable&#8221;, as Apple likes to call the ultra-hot &lt;span class=&quot;caps&quot;&gt;MBP&lt;/span&gt;)&lt;/p&gt;


	&lt;p&gt;I was in New Zealand, which meant that I had to live with it. However, when I got back to the &lt;span class=&quot;caps&quot;&gt;US I&lt;/span&gt; was looking forward to exercising my 1-year hardware warranty to fix an obvious hardware problem. I didn&#8217;t need tech support or troubleshooting, I just wanted it &lt;span class=&quot;caps&quot;&gt;FIXED&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Well, lo and behold, there is &lt;span class=&quot;caps&quot;&gt;NO WAY&lt;/span&gt; to get service under your hardware warranty without calling Apple, where you will have to speak to a tech who will explain to you that even though you have a 1-year hardware warranty, he can&#8217;t actually talk to you about your problem unless you buy AppleCare, or pay a single-time service fee of $49. Excuse me, but how else am I supposed to get service?!&lt;/p&gt;


	&lt;p&gt;After shouting at two techs, I finally got one who would help me. Though the problem began suspiciously close to my battery replacement, they still wanted me to send in my whole computer. If you&#8217;re a tech guy, you realize that sending in your computer is like being a truck driver and having to send in your truck for two weeks while your customers wait for you to get back on the road. Not good when you have deadlines. (And when do &lt;span class=&quot;caps&quot;&gt;I NOT&lt;/span&gt; have deadlines?)&lt;/p&gt;


	&lt;p&gt;Meanwhile, in addition to the battery problem, my MagSafe power connector began having problems. I had a difficult time getting a good connection between it and the computer, and it would randomly lose connection while I was working. This coupled with the fact that my battery was now not working at all meant that when it disconnected on it&#8217;s own, everything went black. How&#8217;s that for enticing you to &#8220;save often&#8221;?&lt;/p&gt;


	&lt;p&gt;Apple sent me a box to send my machine back, and I debated and debated about doing it. Should I buy another Mac to use while waiting for this one to be fixed? No, definitely not. Local service wasn&#8217;t an option, so I opted to buy AppleCare and hope that the service level would increase enough from Apple Tech Support to actually allow me to get it fixed without taking a two-week &#8220;vacation&#8221;.&lt;/p&gt;


	&lt;p&gt;What a difference&#8230; Buying AppleCare was like the difference between a rude taxi driver and a limo driver. (I&#8217;m just assuming here. I&#8217;ve never ridden in a limo, and probably never will.) While I&#8217;m still pretty irritated about the manhandling at the hands of AppleCare when I still had a legitimate one-year warranty issue to solve, at least they would help me now&#8230; After talking to another tech, we decided to replace the battery instead. I had since tried my machine with my co-worker&#8217;s battery, and it worked just fine. When we tried my battery in &lt;span class=&quot;caps&quot;&gt;HIS&lt;/span&gt; computer, it wouldn&#8217;t even turn on without AC power.&lt;/p&gt;


	&lt;p&gt;After explaining this to Apple, they overnighted me a new battery, a new MagSafe, and life is now good as gold&#8230;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;The Moral of the Story&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;If you&#8217;re Apple, please have your techs stop being jackasses with people when they have a legitimate hardware issue. I did &lt;span class=&quot;caps&quot;&gt;NOT&lt;/span&gt; appreciate how I was treated.&lt;/p&gt;


	&lt;p&gt;If you&#8217;re a Mac owner, and you don&#8217;t have AppleCare but still have your hardware warranty, be very pushy when you call them on the phone. If it&#8217;s a legitimate hardware failure, they should fix it without charging you a dime. If you don&#8217;t want to be pushy, just buy AppleCare. Then they treat you like royalty&#8230; Either way, the peace of mind of knowing that, barring my own stupidity, my machine will last a solid three years because Apple will &lt;span class=&quot;caps&quot;&gt;HAVE&lt;/span&gt; to keep it going is still worth at least $349.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-02-09:31</id>
    <published>2007-02-09T23:46:00Z</published>
    <updated>2007-02-10T19:16:21Z</updated>
    <category term="Rails"/>
    <category term="capistrano"/>
    <category term="site5"/>
    <link href="http://blog.thermalcreative.com/articles/2007/2/9/site5-deployment-problems-with-latest-capistrano" rel="alternate" type="text/html"/>
    <title>Site5 Deployment Problems with Capistrano &gt; 1.2</title>
<content type="html">
            &lt;p&gt;So, I&#8217;ve dutifully upgraded my copy of Capistrano to the latest version, and then updated one of the apps I have running on Site5. The only one, actually, and it will probably stay that way. After feeling the Mongrel love with a little Nginx/Pound/Pen/mod_proxy_balancer sprinkled on top I don&#8217;t think I&#8217;ll &lt;span class=&quot;caps&quot;&gt;EVER&lt;/span&gt; use FastCGI again. Anyway&#8230;&lt;/p&gt;


	&lt;p&gt;Apparently in the latest versions of Capistrano, all permissions on the new releases are set chmod g+w, something that doesn&#8217;t fly on most (if not all) shared hosts. The biggest problem, however, is how this problem is manifested on such hosts as Site 5. In this case, the app would simply refuse to spawn &lt;span class=&quot;caps&quot;&gt;ANY&lt;/span&gt; FastCGI processes, and would return a completely empty request. No &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; status code, nothing. Apache would still serve static files, but anything that fell through to the dispatcher would fail.&lt;/p&gt;


	&lt;p&gt;Of course, there we NO log messages in either the production.log or the fastcgi.crash.log. Nothing. Nada. Nothing to work with. Not even a 500 response in the browser.&lt;/p&gt;


	&lt;p&gt;After tearing my hair out, I talked to Site5 support and they suggested permissions as the culprit. However, they suggested that I set 755 on the whole app, which failed to rectify the Capistrano-set permissions. At this point I didn&#8217;t realize what Capistrano was doing, so I resumed emptying my follicles.&lt;/p&gt;


	&lt;p&gt;After reading a post by &#8220;Josh on Rails&#8221; on the RoR message board about the same problem, I found out what Capistrano was doing. Thankfully, in version 1.4.0 of Capistrano, Jamis added a :set_permissions task, allowing you to override the task in your deploy.rb. So, I just did the following:&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;task &lt;span class=&quot;sy&quot;&gt;:set_permissions&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:except&lt;/span&gt; =&amp;gt; { &lt;span class=&quot;sy&quot;&gt;:no_release&lt;/span&gt; =&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt; } &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# do nothing&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;in my deploy.rb, and voila, no more problem. Simple fix, but since there is really zero diagnostic info available it&#8217;s almost impossible to figure out what&#8217;s going on. (At least for me with my seemingly never-ending shallow knowledge of the &lt;span class=&quot;caps&quot;&gt;UNIX&lt;/span&gt; domain&#8230; Curse my days as an &lt;span class=&quot;caps&quot;&gt;ASP&lt;/span&gt;.Net user! Curse them!)&lt;/p&gt;


	&lt;p&gt;Hope this saves someone a few hours&#8230; I wasted far too many on it.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>Matt White</name>
    </author>
    <id>tag:blog.thermalcreative.com,2007-01-24:29</id>
    <published>2007-01-24T23:38:00Z</published>
    <updated>2007-01-24T23:44:20Z</updated>
    <category term="blogging"/>
    <link href="http://blog.thermalcreative.com/articles/2007/1/24/migrated-to-mephisto" rel="alternate" type="text/html"/>
    <title>Migrated to Mephisto</title>
<content type="html">
            &lt;p&gt;Well, I&#8217;ve migrated the blog to &lt;a href=&quot;http://www.mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt;... A rather oddly-named blogging package, but it&#8217;s definitely the best thing going for Rails blogging apps these days. Sadly &lt;a href=&quot;http://www.typosphere.org&quot;&gt;Typo&lt;/a&gt; has fallen off the map, and Typo was always something of a dog from a performance perspective.&lt;/p&gt;


	&lt;p&gt;So, thanks to &lt;a href=&quot;http://octopod.info/2006/6/12/converting-typo-to-mephisto&quot;&gt;this article&lt;/a&gt;, the migration was pretty easy and Mephisto seems &lt;span class=&quot;caps&quot;&gt;MUCH&lt;/span&gt; snappier than Typo. It&#8217;s also much less memory-intensive, and has an excellent caching implementation that allows you to expire the cache on command.&lt;/p&gt;


	&lt;p&gt;Finally, as the new &lt;a href=&quot;http://www.prototypejs.org/&quot;&gt;Prototype&lt;/a&gt; site seems to be using Mephisto as a &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; with little difficulty, I think we&#8217;re going to check out using Mephisto as a low-end simple &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; for sites that don&#8217;t require a ton of bells and whistles. We shall see&#8230;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>matt</name>
    </author>
    <id>tag:blog.thermalcreative.com,2006-10-31:7</id>
    <published>2006-10-31T00:11:00Z</published>
    <updated>2007-01-24T22:56:29Z</updated>
    <category term="General"/>
    <link href="http://blog.thermalcreative.com/articles/2006/10/31/the-importance-of-inspiration" rel="alternate" type="text/html"/>
    <title>The Importance of Inspiration</title>
<content type="html">
            &lt;p&gt;I have recently been having a difficult time being productive&#8230; I don&#8217;t know if it&#8217;s the nice weather or the fact that I&#8217;m in New Zealand, but the lines of code haven&#8217;t been exactly gushing forth.&lt;/p&gt;


	&lt;p&gt;However, I read &lt;a href=&quot;http://www.37signals.com/svn/posts/72-inspiration-is-magical&quot;&gt;something&lt;/a&gt; the other day that made me feel a bit better. I&#8217;ve noticed that when I&#8217;m &#8220;inspired&#8221;, I can be at least 10 times more productive than when I&#8217;m not. The problem is that I can&#8217;t control when I&#8217;m inspired. So, I just have to take the bull by the horns when I am!&lt;/p&gt;


	&lt;p&gt;So, when you&#8217;re inspired, take advantage of it. Don&#8217;t go to bed, don&#8217;t go to lunch, don&#8217;t answer the phone. Take advantage of it, because it&#8217;s worth far more than all the mornings where you sit dutifully at your chair and can&#8217;t get anything worthwhile done. Who knows, it might just be better to go skiing on those unproductive days and wait for inspiration to strike!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>matt</name>
    </author>
    <id>tag:blog.thermalcreative.com,2006-10-29:6</id>
    <published>2006-10-29T06:48:00Z</published>
    <updated>2007-01-24T22:56:46Z</updated>
    <category term="General Tech"/>
    <category term="development"/>
    <category term="textmate"/>
    <link href="http://blog.thermalcreative.com/articles/2006/10/29/textmate-musical-instrument" rel="alternate" type="text/html"/>
    <title>TextMate ~= Musical Instrument?</title>
<content type="html">
            &lt;p&gt;My software/web development tool of choice is the excellent TextMate from &lt;a href=&quot;http://www.macromates.com/&quot;&gt;Macromates&lt;/a&gt;. I am one of the contingent that bought a $2535 copy of TextMate: TextMate + the Mac to run it on. Of course I had other reasons for going to the Mac, but TextMate certainly helped!&lt;/p&gt;


	&lt;p&gt;I must admit, though, that after coming from my Visual Studio days, TextMate seems like a bit more work than I&#8217;m used to. Visual Studio has a wonderful (some would call it a crutch) feature called Intellisense&amp;trade;. Since Visual Studio is designed to work with a specific set of languages, it does so very well&#8230; The flip side is, it&#8217;s only on Windows, it&#8217;s not as customizable, it only does certain languages, and Microsoft makes it.&lt;/p&gt;


	&lt;p&gt;TextMate&#8217;s creator, Allan Odgaard, says that though TextMate isn&#8217;t an &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;, it does provide many features that most &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;&#8217;s do not. These include it&#8217;s powerful Bundle system, powered by Snippets, Commands,  Macros, and Languages. That said, I&#8217;ve been using TextMate for several months now and I&#8217;m ashamed to admit that I&#8217;ve been using my development Lamborghini to drive around my subdivision&#8230;&lt;/p&gt;


	&lt;p&gt;I&#8217;ve been reading the TextMate manual out of boredom amidst a torrential downpour in Southland, New Zealand, and I&#8217;m absolutely shocked to see what I&#8217;ve missed. If TextMate was a musical instrument, I&#8217;ve been using it to play scales for the past few months and missing out on the amazing music that is possible with it. This brings us to the comparison in the title of this post&#8230;&lt;/p&gt;


	&lt;p&gt;I&#8217;m a drummer, and I&#8217;ve spent quite a few years practicing and trying to improve my playing&#8230; Playing a musical instrument is something impossible to do perfectly, as there are just too many techniques to master. However, practice does make &#8220;almost perfect&#8221;. Learning TextMate actually reminds me of learning to play a musical instrument. You can play a few basic tunes after just a few hours of practice, but it takes long hours (and a lot of talent) to truly master an instrument.&lt;/p&gt;


	&lt;p&gt;One of the most productive ways to improve your playing is to pick one aspect of a technique to focus on at a time. After practicing that one skill for a while it will become committed to muscle memory, and then it will be &#8220;second nature&#8221;. If you try to tackle too many elements at once, it will be difficult to remember them all, much less to do them well.&lt;/p&gt;


	&lt;p&gt;A tool like TextMate is really an extension of your mind, which means that the more it becomes second nature the faster and more efficient you become. This is opposed to the &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;, which can sometimes actually become a substitute for thinking by allowing you to forget how certain things are done.&lt;/p&gt;


	&lt;p&gt;So, as I have done many times in trying to improve my musical skill, I am going to choose one feature of TextMate a day to apply in my development process. The next day I&#8217;ll choose another, and so on. I&#8217;m hoping that by focusing on one at a time I will be better able to remember and apply all of them without having to open the bundle editor every time I&#8217;m wondering about a tab trigger or a hotkey. In fact, I would like eliminate the &#8220;what&#8217;s the hotkey again?&#8221; pauses that too often interrupt my workflow.&lt;/p&gt;


	&lt;p&gt;So, I&#8217;ll see how it goes. I&#8217;ll try to post updates on how it&#8217;s going, and see how much I&#8217;m able to improve my workflow. It should be an interesting experiment.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>matt</name>
    </author>
    <id>tag:blog.thermalcreative.com,2006-08-23:5</id>
    <published>2006-08-23T16:48:00Z</published>
    <updated>2007-02-28T21:10:24Z</updated>
    <category term="General"/>
    <category term="General Tech"/>
    <category term="css"/>
    <category term="html"/>
    <category term="ie"/>
    <link href="http://blog.thermalcreative.com/articles/2006/8/23/fun-with-sprites" rel="alternate" type="text/html"/>
    <title>Fun With Sprites</title>
<content type="html">
            &lt;p&gt;or: More IE Hell&lt;/p&gt;


	&lt;p&gt;Well, I may be in an anti-IE rut, but this is where I&#8217;ve been tearing my hair out lately&#8230; Once again, I&#8217;ve developed a site top-to-bottom on my Mac, and am only now testing it in IE. Fortunately, IE really only seems to require &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; tweaks (i.e. lots of &#8221;* html&#8221; selectors), but I just ran into a problem that is particularly intriguing.&lt;/p&gt;


	&lt;p&gt;I&#8217;m using &lt;a href=&quot;http://www.alistapart.com/articles/sprites/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; sprites&lt;/a&gt; as a way around the usual image slicing required for rollovers. It usually works great, but it didn&#8217;t work so well on my latest site. I&#8217;m doing the usual:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
div#nav a:hover img, div#nav a.sel img { margin-top: -40px; }
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This simply pulls the image up behind the mask created by the containing anchor set for overflow:hidden. This &#8220;masks&#8221; the image, and allows you to pull it up by half it&#8217;s height to do the rollover. Pretty slick.&lt;/p&gt;


	&lt;p&gt;However, in IE for some reason it doesn&#8217;t want to re-draw the image, so it appears that the :hover state never gets fired. However, on pages that have the &#8220;sel&#8221; class applied to the active nav element, the pullout works fine. Bear in mind that this doesn&#8217;t require a re-draw, because it&#8217;s already there when the page is initially rendered. So&#8230; why won&#8217;t IE re-draw in response to the :hover?&lt;/p&gt;


	&lt;p&gt;Well, to be honest, I&#8217;m not sure. I&#8217;ve done some experimenting with how the nav bar is positioned to see if it&#8217;s a page layout issue, but that doesn&#8217;t seem to be it. The code is almost identical to previous times I&#8217;ve done this, so I&#8217;m somewhat at a loss. However, I did find a workaround:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
div#nav a:hover { border: 0px solid black; }
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The non-border border seems to trigger a re-draw in IE, and then the rollovers work just fine. I&#8217;m going to continue investigating what might be causing this particular instance, but for now this solves the issue.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>matt</name>
    </author>
    <id>tag:blog.thermalcreative.com,2006-07-30:4</id>
    <published>2006-07-30T23:55:00Z</published>
    <updated>2007-01-24T22:57:22Z</updated>
    <category term="Design"/>
    <category term="css"/>
    <category term="suckerfish"/>
    <link href="http://blog.thermalcreative.com/articles/2006/7/30/ie-suckerfish-hell" rel="alternate" type="text/html"/>
    <title>IE Suckerfish Hell</title>
<content type="html">
            &lt;p&gt;So, we&#8217;ve got a pretty new client site that I finished work on this weekend, and I experienced the curse of all Mac-based web developers: you can&#8217;t test in IE. So, I&#8217;d been developing and testing in Firefox and Safari, all in &lt;span class=&quot;caps&quot;&gt;XHTML 1&lt;/span&gt;.0 Strict, hoping that whatever I was doing wasn&#8217;t so whacky that I&#8217;d have problems later. Overall, the whole site was pretty straightforward&#8230;until the end.&lt;/p&gt;


	&lt;p&gt;The designer (our own Bill Edmonson) had designed some slick looking dropdown menus:&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;/files/BBsubnav.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;As you&#8217;ll notice, there&#8217;s some space between the menu items. I&#8217;m a big fan of &lt;a href=&quot;http://alistapart.com/articles/dropdowns/&quot;&gt;suckerfish dropdowns&lt;/a&gt;, mainly because of the pretty markup, and also because they&#8217;re pretty easy to create. So, in this instance, all you need to do is add some margin to your LI&#8217;s to create the spacing between the nav elements.&lt;/p&gt;


	&lt;p&gt;This works brilliantly in all the standards-complient browsers (SCBs), because the transparent space between the items is still &#8220;contained&#8221; within the UL that is the subnav. Thus the onmouseout shouldn&#8217;t get fired in IE, because you&#8217;re over the menu even when you&#8217;re not over an individual item. In the SCBs, you&#8217;re still hovering the contents of the parent LI, so the menu will stay open.&lt;/p&gt;


	&lt;p&gt;No problem. Except that IE fires onmouseout prematurely, because it treats the lack of a background (the transparent space between the nav elements) as if it&#8217;s &#8220;punched out&#8221; of the parent UL. Thus, the menu closes as soon as your mouse wanders over one of the gaps, which you will immediately do as  soon as you try to select anything but the top element.&lt;/p&gt;


	&lt;p&gt;The solution? A transparent &lt;span class=&quot;caps&quot;&gt;GIF&lt;/span&gt; background on the parent UL. Thus, a menu with the following html:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;item1&quot;&gt;Menu Item 1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;item2&quot;&gt;Menu Item 2&lt;/a&gt;
     &lt;ul&gt;
       &lt;li&gt;&lt;a href=&quot;item2/sub1&quot;&gt;Sub Item 1&lt;/a&gt;&lt;/li&gt;
       &lt;li&gt;&lt;a href=&quot;item2/sub2&quot;&gt;Sub Item 2&lt;/a&gt;&lt;/li&gt;
     &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Would have the following background to eliminate the problem, excluding all of the usual suckerfish stuff, which can be had at &lt;a href=&quot;http://www.alistapart.com/articles/dropdowns&quot;&gt;&lt;span class=&quot;caps&quot;&gt;ALA&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
  ul#nav ul { background: url(/images/common/spacer.gif) };
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This has the effect of filling the background, but it&#8217;s still transparent, so you still get the desired effect. However, IE treats the element as if it were &#8220;opaque&#8221;, instead of &#8220;punched out&#8221;. Thus, onmouseout only fires when it should, and not when you mouseover one of the gaps.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>matt</name>
    </author>
    <id>tag:blog.thermalcreative.com,2006-07-14:3</id>
    <published>2006-07-14T15:03:00Z</published>
    <updated>2007-01-24T22:57:38Z</updated>
    <category term="General Tech"/>
    <category term="Rails"/>
    <link href="http://blog.thermalcreative.com/articles/2006/7/14/server-configuration" rel="alternate" type="text/html"/>
    <title>Final (For Now) Server Configuration</title>
<content type="html">
            &lt;p&gt;So, I&#8217;ve decided to be a wuss&#8230; Unfortunately, Apache2.2 isn&#8217;t available as a Debian package at this point, and there&#8217;s very little information about when it will become available. I don&#8217;t want to roll my own install, I&#8217;d just rather wait for the Apache2.2 package to come out and I&#8217;ll upgrade then. That way I can stick with my friendly, clean apt-get goodness.&lt;/p&gt;


	&lt;p&gt;So, in the meantime, I&#8217;ve settled on this solution:&lt;/p&gt;


	&lt;p&gt;1. Apache 2.0 with mod_proxy
2. Pound
3. mongrel_cluster
4. Mongrel&lt;/p&gt;


	&lt;p&gt;The biggest change from my previous post is the order that these appear in&#8230; Previously, I had been fronting the whole setup with Pound, routing to Apache or Mongrel based on which domain was requested. According to the author of Pound, vohsting in Pound is somewhat of a hack. I agree, and I think that Apache&#8217;s vhosting implementation is much easier and more elegant than request header-based routing in Pound. So, I flipped the order, and did this:&lt;/p&gt;


	&lt;p&gt;Apache -&amp;gt; mod_proxy -&amp;gt; Pound (listening on 127.0.0.1:8080) =&amp;gt; Mongrel(s) (Listening on 127.0.0.1:8000 &#8211; 8003)&lt;/p&gt;


	&lt;p&gt;This way vhosting is managed through Apache, and requests for Rails applications get handled with Pound. Requests for static content (or my SquirrelMail install) get handled by Apache directly. An additional benefit is that Pound now only listens on local loopback, instead of externally. This is one less open port, which my daddy always said is a good thing. The tradeoff is that Apache is now handling all inbound requests, and I&#8217;m sure that Pound is probably a quicker overall solution than Apache fronting for Pound. However, unless I become a world-famous blogger with millions of hits a day, I don&#8217;t expect this to be much of an issue.&lt;/p&gt;


	&lt;p&gt;So, you want to know how to do this yourself? Well, read on&#8230;&lt;/p&gt;


	&lt;p&gt;First off, I&#8217;m using Debian Sarge for all of this. Commands may be different on your particular flavor of OS. I&#8217;m also assuming that you&#8217;ve got an existing Rails stack installed. If you haven&#8217;t done this yet, I&#8217;d recommend Ezra&#8217;s excellent &lt;a href=&quot;http://www.brainspl.at/rails_stack.html&quot;&gt;Rails stack tutorial&lt;/a&gt;. Also, a plug for &lt;a href=&quot;http://www.rimuhosting.com&quot;&gt;Rimuhosting&lt;/a&gt; is that they have developed a script version of the Rails-specific part of Ezra&#8217;s tutorial, and they&#8217;ll auto-install it for you if you get a &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt; from them. A note of caution: Ezra&#8217;s tutorial assumes you&#8217;ll be using LigHTTPD, which we won&#8217;t be using. Thus, you&#8217;ll also need to install Apache2 using apt-get.&lt;/p&gt;


	&lt;p&gt;Next, install Mongrel and mongrel_cluster:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
    sudo gem install mongrel --include-dependencies
    sudo gem install mongrel_cluster
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;While we&#8217;re installing our lovely open-source software (free&#8230;ALL &lt;span class=&quot;caps&quot;&gt;FREE&lt;/span&gt;! WAHAHAHA! Sorry&#8230;I&#8217;m an old &lt;span class=&quot;caps&quot;&gt;ASP&lt;/span&gt;/ASP.Net developer. I&#8217;m still giddy about free software), let&#8217;s go ahead and install Pound.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
    sudo apt-get install pound
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now we&#8217;ve got all of our software, we just need to configure it. First, we need to apply mongrel_cluster to our Rails app. I&#8217;m not going to cover any Capistrano-specific info here, this will just be the bare bones coverage of Mongrel configuration. If you need more info, there&#8217;s lots of good documentation available at &lt;a href=&quot;http://mongrel.rubyforge.org/&quot;&gt;the Mongrel site&lt;/a&gt;.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
    cd /var/www/myrailsapp
    sudo /usr/sbin/adduser -r mongrel
    sudo chown -R mongrel:mongrel /var/www/myrailsapp
    sudo mongrel_rails cluster::configure -e production \
        -p 8000 -N 3 -c /var/www/apps/testapp -a 127.0.0.1 \
        --user mongrel --group mongrel
    sudo mongrel_rails cluster::start
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;example from &lt;a href=&quot;http://mongrel.rubyforge.org/docs/mongrel_cluster.html&quot;&gt;mongrel_cluster documentation&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Now mongrel_cluster is configured to start three mongrels on 127.0.0.1:8001, :8001, :8002, and those three mongrels have been started. Redirecting requests to each will require a simple load balancer/reverse proxy. Enter Pound! The Pound configuration files are stored in /etc/pound/pound.cfg, and /etc/default/pound. Open /etc/pound/pound.cfg in your favorite editor (I like pico), and add the following to the end of the file:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
    ListenHTTP 127.0.0.1:8080

    UrlGroup &quot;.*&quot; 
        BackEnd 127.0.0.1:8000,1
        BackEnd 127.0.0.1:8001,1
        BackEnd 127.0.0.1:8002,1
    EndGroup
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Then edit /etc/default/pound, and change startup=0 to startup=1. Finally:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
    sudo /etc/init.d/pound start
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Almost there! Now pound is running on port 8080 waiting to balance requests across your three Mongrels. The last step is to tell Apache to proxy requests for that particular vhost to Mongrel. To do this, we need to enable mod_proxy and set the appropriate vhost to be a reverse proxy:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
    sudo a2enmod mod_proxy
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Finally, edit your /etc/apache2/apache2.conf file and edit the vhost entry that you want to forward to Mongrel. For more info on vhosting setup, please refer to the &lt;a href=&quot;http://httpd.apache.org/docs/&quot;&gt;Apache2 docs&lt;/a&gt;. Mine looks like:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
    &amp;lt;virtualhost&gt;
        ServerName blog.thermalcreative.com
        ProxyPass / http://127.0.0.1:8080
        ProxyPassReverse / http://127.0.0.1:8080
    &amp;lt;/virtualhost&gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Save your changes, and then:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
    sudo /etc/init.d/apache2 reload
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will forward all requests for blog.thermalcreative.com through Apache to Pound, which will in turn balance those requests across my cluster of Mongrels. Pretty cool, eh? Possible enhancements would include configuring Mongrel to listen on multiple ports, thus enabling you to run multiple Rails apps. Alternatively, you could configure mod_proxy to pass requests for certain subdirectories to Mongrel, this giving the appearance of running apps in subdirectories (e.g. http://www.thermalcreative.com/blog/) while actually serving them via Mongrel. This has &lt;span class=&quot;caps&quot;&gt;SEO&lt;/span&gt;  implications for those of you who are way into that&#8230; I personally like the cleanliness of subdomains. Also, you need to set up mongrel_cluster to start all of your clusters on boot. There&#8217;s some excellent info on how to do that over at the &lt;a href=&quot;http://mongrel.rubyforge.org/docs/mongrel_cluster.html&quot;&gt;mongrel_cluster documentation&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;That&#8217;s all for now&#8230;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.thermalcreative.com/">
    <author>
      <name>matt</name>
    </author>
    <id>tag:blog.thermalcreative.com,2006-07-13:2</id>
    <published>2006-07-13T02:34:00Z</published>
    <updated>2007-01-24T22:57:49Z</updated>
    <category term="Rails"/>
    <link href="http://blog.thermalcreative.com/articles/2006/7/13/rimuhosting-rocks-again" rel="alternate" type="text/html"/>
    <title>Rimuhosting Rocks Again</title>
<content type="html">
            &lt;p&gt;So, we&#8217;re starting our brand-new little company, and of course we&#8217;re paranoid about cash flow. So, in the interests of keeping fixed costs low, I got the cheapest &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt; possible from Rimuhosting. I&#8217;ve had some previous projects hosted with them, and their support is second to none.&lt;/p&gt;


	&lt;p&gt;Well, as I should have expected all along, running a Rails app under Apache just isn&#8217;t feasible under 96Mb of memory. So, of course this blog was painfully slow, and I also couldn&#8217;t even compile a new version of Apache from the command line without running out of memory.&lt;/p&gt;


	&lt;p&gt;Cash flow be damned. I want more memory.&lt;/p&gt;


	&lt;p&gt;So, I email the friendly folks @ Rimu and ask them to bump me to the next hosting plan so that my shiny Typo install can breathe. Ten minutes later, they email me back and inform me that not only have they already added memory, but they bumped me from the 96MB plan to the 192MB plan, for the price of the 128MB plan! $50 worth of hosting for $26.95!&lt;/p&gt;


	&lt;p&gt;And why do they rock &#8220;again&#8221;?&lt;/p&gt;


	&lt;p&gt;I have a client with a demanding Rails app that does lookups and updates against a 500k DB of voters. I had the site running on a 192MB &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt;, and it seemed to be doing just fine. Without warning me, he brought on another 40-50 data entry people, thus hammering my poor Rails app into heavy swapping and poor performance.&lt;/p&gt;


	&lt;p&gt;&#8220;It&#8217;s running slow, can you reboot it or something?&#8221; &#8220;No, this is &lt;span class=&quot;caps&quot;&gt;YOUR FAULT&lt;/span&gt;&#8221;, I thought. I emailed Rimu and asked them if they could bump me to the 320MB memory level. 20 minutes later, I get an email telling me that they bumped me, rebooted, and that I didn&#8217;t have to pay for it if I didn&#8217;t need to keep it! What?! I don&#8217;t have to pay???&lt;/p&gt;


	&lt;p&gt;Four days later the storm had passed&#8230; I asked them to bump me back down again, which they once again did immediately. No charge. Happy client, happy developer.&lt;/p&gt;


	&lt;p&gt;Rimuhosting rocks. Again.&lt;/p&gt;
          </content>  </entry>
</feed>
