<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
  <title>Saturn Flyer</title>
  <description>Design and Development with Thoughtful Imagination</description>
  <link>http://www.saturnflyer.com/rss/</link>
  <language>en-us</language>
  <ttl>40</ttl>
  
  
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/saturnflyer" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>Cache key for collections in ActiveRecord</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;I&amp;#8217;ve been working on the performance of a Rails application and much of my recent work involves simply caching. It was an application that was an excellent proof-of-concept which quickly turned into a production application.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve got memcached setup and running and now it&amp;#8217;s a speedy little interface.&lt;/p&gt;

&lt;p&gt;But one thing I knew I needed but wasn&amp;#8217;t sure how to do was cache a group of records. Rails fragment caching is super simple for one record:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;% cache [object] do %&amp;gt;
  ... this will be cached based upon your object.cache_key ...
&amp;lt;% end &amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;#8217;s fine and dandy until you want to cache the view for not just one &lt;code&gt;object&lt;/code&gt; in your loop, but the entire rendered view of &lt;code&gt;@objects&lt;/code&gt;. As much as I looked around, I found that nobody has written about this problem. I still wonder if I&amp;#8217;m being naive and there is some obvious way to do this that has simply slipped by me.&lt;/p&gt;

&lt;p&gt;When I first tackled this, I had just a handful of objects in one particular view and would never have more, so I just concatenated the cache_keys of all of them and I was done. In another instance (with a larger number of objects) I tried something different by prepending another object which could be changing and appending a string: &lt;code&gt;cache [user_role, @project_application,'task_lists'] do&lt;/code&gt;. This was painful because it required that I ensure that all the objects down the relationship tree call &lt;code&gt;:touch&lt;/code&gt; and update their &lt;code&gt;belongs_to&lt;/code&gt; parent until finally my &lt;code&gt;@project_application&lt;/code&gt; was updated.&lt;/p&gt;

&lt;p&gt;The task lists in this application don&amp;#8217;t just have tasks, they have attachments and notes too and this just felt like the invalidation of the cache was far too intertwined among the related objects for my liking.&lt;/p&gt;

&lt;p&gt;Finally I realized that it was much simpler than that. What I need here is pretty simple: a &lt;code&gt;cache_key&lt;/code&gt; for a collection.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;group_key&lt;/code&gt; method on a collection would be so much simpler than any convoluted process I attempted. Here&amp;#8217;s what I did:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def self.group_key
  count = ActiveRecord::Base.connection.select_value("select count(*) from widgets").to_s
  timestamp = ActiveRecord::Base.connection.select_value("select max(updated_at) from widgets").to_s.parameterize.wrapped_string
  count+'-'timestamp
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That makes 2 simple calls to the database to get a parameterized representation of the most recent count and &lt;code&gt;updated_at&lt;/code&gt; value for my Widget. If any of my objects change for any reason or if I add a new record, my group_key will be updated.&lt;/p&gt;

&lt;p&gt;I took this and put together a simple gem called &lt;code&gt;group_cache_key&lt;/code&gt; which you may find on &lt;a href="http://gemcutter.org/gems/group_cache_key"&gt;gemcutter.org&lt;/a&gt;. The source is a bit different in that it includes a max &lt;code&gt;updated_at&lt;/code&gt; and max &lt;code&gt;created_at&lt;/code&gt; and it doesn&amp;#8217;t go back to the database for the information:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def cache_key
  if self.empty?
    'empty'
  else
    update_timestamp = max {|a,b| a.updated_at &amp;lt;=&amp;gt; b.updated_at }.updated_at.to_i.to_s
    create_timestamp = max {|a,b| a.created_at &amp;lt;=&amp;gt; b.created_at }.created_at.to_i.to_s
    self.first.class.to_s.underscore+'/'+length.to_s+'-'+create_timestamp+'-'+update_timestamp
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I hope you find it useful. It&amp;#8217;ll give you a cache key value of something like &lt;code&gt;widget/2-1253224342-1253311589&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To use it, grab the gem (&lt;code&gt;gem install group_cache_key&lt;/code&gt;) and add this to your config/environment.rb:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config.gem `group_cache_key`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let me know what you think.&lt;/p&gt;

&lt;h2&gt;Update&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;ve pushed a newer version of the gem out there which creates a hash of the given ids. The hash is created in the order given, so if you&amp;#8217;re doing a sort in your interface, you&amp;#8217;ll get an entirely different cache_key.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/p63jY7bkDKQ" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 27 Oct 2009 16:01:30 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/10/27/cache-key-for-collections-in-activerecord/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/p63jY7bkDKQ/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/10/27/cache-key-for-collections-in-activerecord/</feedburner:origLink></item>
  
    <item>
      <title>Changes in Radiant AdminUI for 0.8.1+</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;There&amp;#8217;s a lot of focus on the visual changes to the Radiant interface, but there are some functional changes that should be discussed too. I&amp;#8217;ve started playing with the new AdminUI as I try to understand the changes (since I haven&amp;#8217;t had time to take part in the development).
The first thing I tackled was figuring out how to rearrange the navigation items and it&amp;#8217;s not too easy to understand what&amp;#8217;s going on.&lt;/p&gt;

&lt;p&gt;First, here&amp;#8217;s the new structure of the tabs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NavTab #=&amp;gt; [NavSubItem, NavSubItem, ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;NavTab&lt;/code&gt; is a subclass of &lt;code&gt;Array&lt;/code&gt; and it&amp;#8217;s accessed via &lt;code&gt;admin.nav&lt;/code&gt; although &lt;code&gt;admin.tabs&lt;/code&gt; will still be available (with a warning of deprecation) for some time.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll be posting details like this on the &lt;a href="http://radiantcms.org/blog"&gt;Radiant blog&lt;/a&gt; once the code is more developed.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s debate about where Snippets ought to go: content or design? Do site editors use them, or do designer/developers use them? So that&amp;#8217;s a good place to start. &lt;/p&gt;

&lt;p&gt;In order to do this, I had to generate an extension. Then, in my extension, I added this to the activate method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;admin.nav['content'].delete_if{ |t| t.name.to_s == 'snippets' }
admin.nav['design'] &amp;lt;&amp;lt; admin.nav_item(:snippets, "Snippets", "/admin/snippets")
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;#8217;s complex, but it moves the &amp;#8220;Snippets&amp;#8221; link from the &amp;#8220;Content&amp;#8221; tab to the &amp;#8220;Design&amp;#8221; tab. It should be simpler; something like this would be nice:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;admin.nav['content']['snippets'].nav_tab = admin.nav['design']
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;but better yet, I&amp;#8217;d rather have:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;admin.nav_items['snippets'].move_to('design', :after =&amp;gt; 'pages')
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It doesn&amp;#8217;t seem too valuable to implement that just to move one thing, but with the new tab/nav structure I would think that there will be a lot more customization by users/developers.&lt;/p&gt;

&lt;p&gt;1) Does that syntax appeal to you? (Why or why not?)&lt;/p&gt;

&lt;p&gt;To make it even simpler, it might be nice to be able to define structure in an initializer or a yaml file somewhere so that Radiant would load it&amp;#8217;s default setup, but then read your changes and rearrange the navigation accordingly. I wouldn&amp;#8217;t want to tackle that until other questions are answered, but it&amp;#8217;s an idea for the future.&lt;/p&gt;

&lt;p&gt;Next, the recent changes only allow you to specify visibility on the main NavTab and not on the NavSubItem.&lt;/p&gt;

&lt;p&gt;2) Do you want to be able to specify visibility on the NavSubItem?&lt;/p&gt;

&lt;p&gt;Using the above example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;admin.nav_items['snippets'].move_to('design', :after =&amp;gt; :pages, :visibility =&amp;gt; :admin)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Personally, I think something like this is a must. I see tabs as a way to organize links and not as much of an authorization mechanism. By that I mean that in order to hide a section to all but a specific role, you&amp;#8217;d need to put it in it&amp;#8217;s own tab even thought it might already make sense in a place like &amp;#8220;Content&amp;#8221;.&lt;/p&gt;

&lt;p&gt;These recent changes are going to cause a bit of pain for developers to upgrade the &lt;a href="http://ext.radiantcms.org"&gt;numerous extensions&lt;/a&gt; out there, but it&amp;#8217;ll be well worth it in the long run; especially if it&amp;#8217;s easy to move things around.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Updates in Radiant have been causing some pain do to the major changes being made recently and if you&amp;#8217;re not well-versed in the core application it can be difficult to keep up. Please post your questions to the &lt;a href="http://radiantcms.org/mailing-list/"&gt;mailing list&lt;/a&gt; where people are generally very helpful. Although we&amp;#8217;d all like to avoid upgrade problems, they sometimes comes from changes in Radiant or changes in Rails, and we are doing what we can to create problem free upgrade paths. But this doesn&amp;#8217;t mean that the creators or maintainers of the particular extension that you use are yet aware of your problem. Hence, the &lt;a href="http://radiantcms.org/mailing-list/"&gt;mailing list&lt;/a&gt; is your best option for help.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thanks very much to &lt;a href="http://recursivecreative.com/"&gt;John&lt;/a&gt; and &lt;a href="http://prime-motif.com/"&gt;Sean&lt;/a&gt; for hacking away and getting this into the master branch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; There&amp;#8217;s plenty of discussion going on about this on the development email list, and I&amp;#8217;ve got some related changes that I hope to add   to the core here &lt;a href="http://github.com/saturnflyer/radiant/commits/tab"&gt;http://github.com/saturnflyer/radiant/commits/tab&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/_2Uo1iibBuw" height="1" width="1"/&gt;</description>
      <pubDate>Sat, 19 Sep 2009 19:00:53 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/09/19/changes-in-radiant-adminui-for-0-8-1/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/_2Uo1iibBuw/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/09/19/changes-in-radiant-adminui-for-0-8-1/</feedburner:origLink></item>
  
    <item>
      <title>Fat Free CRM on Heroku</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;&lt;a href="http://heroku.com/"&gt;Heroku&lt;/a&gt; is an excellent way to &lt;strong&gt;easily&lt;/strong&gt; deploy Rails applications. But there&amp;#8217;s a trick to doing it: it&amp;#8217;s a read-only file system.&lt;/p&gt;

&lt;p&gt;To some, this may be old news, but to others who have come across a project using SASS, you might feel like your out of luck. &lt;a href="http://fatfreecrm.com/"&gt;Fat Free CRM&lt;/a&gt;, for example is a great new project, and it uses SASS. Try running it on Heroku and you&amp;#8217;ll start getting frustrated. If you&amp;#8217;re not familiar with SASS, it automatically generates static CSS files for you in production, meaning it needs write access to the file system.&lt;/p&gt;

&lt;p&gt;So, what do you do? The good thing is &lt;a href="http://github.com/heroku/sass_on_heroku/tree/master"&gt;Heroku has a plugin to help with SASS&lt;/a&gt;. &lt;strong&gt;But&lt;/strong&gt;, in this instance, it doesn&amp;#8217;t seem to work. I&amp;#8217;ve installed it with Fat Free CRM and have pushed up to Heroku, but I get errors so rather than debug the issue you can try another option: &lt;a href="http://github.com/mooktakim/heroku_sass_and_cache/tree/master"&gt;http://github.com/mooktakim/heroku&lt;em&gt;sass&lt;/em&gt;and_cache/tree/master&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s a step-by-step. First, if you don&amp;#8217;t have a Heroku account, signup and install the gem:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem install heroku
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, get the Fat Free CRM code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git://github.com/michaeldv/fat_free_crm.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And turn it into a Heroku project&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd fat_free_crm
$ heroku create
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;#8217;ll need to install a plugin to manage the location for SASS files.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ script/plugin install git://github.com/mooktakim/heroku_sass_and_cache.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Read the documentation for the plugin, but you&amp;#8217;ll need to add this to &lt;code&gt;config/routes.rb&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;map.heroku_sass_and_cache
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just drop that on the first line of your &lt;code&gt;routes.rb&lt;/code&gt; file and commit all of your changes.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git add .
$ git commit -m "feeling sassy"
$ git push heroku master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That last bit will deploy your application to Heroku. Fat Free CRM requires that you run the &lt;code&gt;rake crm:setup&lt;/code&gt; task.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ heroku rake crm:setup USERNAME=myusername PASSWORD=mypass EMAIL=my@email.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After that, you should have a working Fat Free CRM on Heroku. Try &lt;code&gt;heroku open&lt;/code&gt; and you&amp;#8217;ll land at your new login screen.&lt;/p&gt;

&lt;p&gt;This will get you going, but you&amp;#8217;ll find that minor things like storing avatars won&amp;#8217;t work because they expect to be stored on the file system. Missing avatars aren&amp;#8217;t an application deal-breaker and I imagine that there might be some options in the future for separate storage options, or even just using &lt;a href="http://gravatar.com/"&gt;Gravatar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have any luck with the &lt;a href="http://github.com/heroku/sass_on_heroku/tree/master"&gt;official Sass support on Heroku&lt;/a&gt;, leave a comment and I&amp;#8217;ll update the post.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/ulCMIcQCcnQ" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 08 Sep 2009 11:46:24 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/09/08/fat-free-crm-on-heroku/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/ulCMIcQCcnQ/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/09/08/fat-free-crm-on-heroku/</feedburner:origLink></item>
  
    <item>
      <title>Why you should use Devver</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;For good reason, developers share concern over not only a well-tested application, but also a regularly tested application. If you are managing a group of developers and are responsible for the outcome, wouldn&amp;#8217;t you first find a solution to allow your developers to run the test suite whenever they want? If your team members are running tests whenever they want on your massive application it&amp;#8217;ll probably slow them down, so of course you&amp;#8217;ll implement a continuous integration server. But then you&amp;#8217;re left with the requirement that they checkin their code. That could be a painful situation if they checkin some feature breaking hack. Enter &lt;a href="http://devver.net"&gt;Devver&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m participating in the &lt;a href="http://devver.net/"&gt;Devver&lt;/a&gt; beta. When I got my invitation I immediately starting testing out the RadiantCMS source. While the code base is relatively simple, Radiant has some great test coverage including Cucumber features.&lt;/p&gt;

&lt;p&gt;Radiant is a bit of a strange bird when it comes to Rails apps since it has it&amp;#8217;s own Radiant::Initializer rather than a Rails::Initializer. Devver wasn&amp;#8217;t quite expecting this, but &lt;a href="http://devver.net/about"&gt;Dan, Ben, and Avdi&lt;/a&gt; were extremely quick to respond to my requests.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s been a good deal of development around the problem of running a massive test suite for an application. There&amp;#8217;s &lt;a href="http://cruisecontrol.sourceforge.net/"&gt;CruiseControl&lt;/a&gt; or &lt;a href="http://cruisecontrolrb.thoughtworks.com/"&gt;CruiseControl.rb&lt;/a&gt;, and &lt;a href="http://integrityapp.com/"&gt;Integrity&lt;/a&gt; or &lt;a href="http://github.com/felipegiotto/Inotegration/"&gt;Inotegration&lt;/a&gt;, or &lt;a href="http://runcoderun.com/radiant/radiant"&gt;RunCodeRun&lt;/a&gt; and plenty of others that I&amp;#8217;m missing. It seems to me that the problem with those approaches is that you need to checkin your code. In some respects, it&amp;#8217;s too late to run your tests when you&amp;#8217;ve already checked in the code.&lt;/p&gt;

&lt;p&gt;Of course you can use things like &lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;ZenTest&lt;/a&gt; with autotest. And there&amp;#8217;s &lt;a href="http://github.com/timcharper/spork/tree/master"&gt;spork&lt;/a&gt; for speeding up your tests as well. But a massive test suite that takes a while to run is something you might like to avoid running locally. Offload that to a server! Run &lt;code&gt;rake devver:spec&lt;/code&gt; or &lt;code&gt;rake devver:test&lt;/code&gt;. &lt;a href="http://devver.net/documentation/how_it_works"&gt;It&amp;#8217;s a very simple process&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You could, of course use &lt;a href="http://github.com/brynary/testjour/tree/master"&gt;testjour&lt;/a&gt; if it&amp;#8217;s a viable option in your development environment, but Devver is still probably much simpler to setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://devver.net/documentation/install"&gt;Installation is simple&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download and install the Devver gem&lt;/li&gt;
&lt;li&gt;Download and install the Devver Rakefile&lt;/li&gt;
&lt;li&gt;Configure Devver to use your API key&lt;/li&gt;
&lt;li&gt;Declare your gem dependencies&lt;/li&gt;
&lt;li&gt;Run it!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;I&amp;#8217;ve not been compensated in any way by Devver. They&amp;#8217;ve taken a great idea (run tests &lt;strong&gt;before&lt;/strong&gt; a code checkin) and made it easy and fast; and I thought you should know about it.&lt;/em&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/CuQNZLEdHtM" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 28 Jul 2009 19:21:48 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/07/28/why-you-should-use-devver/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/CuQNZLEdHtM/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/07/28/why-you-should-use-devver/</feedburner:origLink></item>
  
    <item>
      <title>Textpattern on Github</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;I&amp;#8217;m a former user of &lt;a href="http://textpattern.com/"&gt;Textpattern&lt;/a&gt; and I&amp;#8217;m glad to see it more easily accessible on &lt;a href="http://github.com/textpattern/textpattern/"&gt;github&lt;/a&gt;. I hope it&amp;#8217;ll be easier for other users out there to contribute to the project.&lt;/p&gt;

&lt;p&gt;My path to abandonment began when I built a real estate management interface on top of Textpattern. It was an interesting experience to say the least. The system is built to provide clear methods like &lt;code&gt;graf()&lt;/code&gt; which I&amp;#8217;m sure you would guess is a way to display an HTML paragraph element&amp;#8230;&lt;/p&gt;

&lt;p&gt;And of course, for your &lt;a href="http://github.com/textpattern/textpattern/blob/7dfe341b90617557dcf704685d0a13f1ed27bb76/textpattern/lib/txplib_html.php"&gt;developing delight&lt;/a&gt; there are other methods like &lt;code&gt;sLink()&lt;/code&gt;, &lt;code&gt;eLink()&lt;/code&gt;, &lt;code&gt;wLink()&lt;/code&gt;, &lt;code&gt;dLink()&lt;/code&gt;, and &lt;code&gt;aLink()&lt;/code&gt;. I&amp;#8217;ll leave it to you to guess what features they implement. &lt;a href="http://github.com/textpattern/textpattern/blob/7dfe341b90617557dcf704685d0a13f1ed27bb76/textpattern/lib/txplib_html.php#L423"&gt;My favorite&lt;/a&gt; is listed in there too.&lt;/p&gt;

&lt;p&gt;I am glad, however, that in the very unfortunate event where I might need to use Textpattern again it&amp;#8217;ll be much more accessible to track other forks and branches. Cheers to the Textpattern community, from a thankful but recovering user.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/3cFIK2N8CnU" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 28 Jul 2009 17:34:11 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/07/28/textpattern-on-github/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/3cFIK2N8CnU/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/07/28/textpattern-on-github/</feedburner:origLink></item>
  
    <item>
      <title>External website resources</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;I wrote a recent post about &lt;a href="http://www.saturnflyer.com/blog/jim/2009/06/18/managing-all-of-your-content/"&gt;managing ALL of your content&lt;/a&gt; where I discuss the idea that your content is not just the content on your site.&lt;/p&gt;

&lt;p&gt;In my continuing research for better ways to manage content I came across a real gem. &lt;a href="http://github.com/bluemonk/net-dns/tree/master"&gt;Net::DNS&lt;/a&gt; which is a helpful tool for resolving DNS and gives you a different perspective than Ruby&amp;#8217;s &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/resolv/rdoc/index.html"&gt;Resolv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to check if a domain is valid then something as simple as this might do the trick:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Net::DNS::Resolver.start("google.com").answer.size &amp;gt; 0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But of course, there&amp;#8217;s much more to it than that. &lt;a href="http://marcoceresa.com/net-dns/"&gt;Check it out!&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/PLEeVzBvwaM" height="1" width="1"/&gt;</description>
      <pubDate>Fri, 03 Jul 2009 01:15:36 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/07/03/external-website-resources/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/PLEeVzBvwaM/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/07/03/external-website-resources/</feedburner:origLink></item>
  
    <item>
      <title>Ruby FuzzyHash</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;I came across an interesting way to use a Hash at &lt;a href="http://github.com/joshbuddy/fuzzyhash/tree/master"&gt;http://github.com/joshbuddy/fuzzyhash/tree/master&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I may look into this further for &lt;a href="http://github.com/saturnflyer/radiant-vapor-extension/tree/master"&gt;Vapor&lt;/a&gt; since this is basically what that RadiantCMS extension needs to do.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve altered the sample code but it does all the explaining:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;hash = FuzzyHash.new&lt;br/&gt;
        hash[/^\d+$/] = &amp;#8216;number&amp;#8217;&lt;br/&gt;
        hash[/.*/] = &amp;#8216;something&amp;#8217;&lt;br/&gt;
        hash[&amp;#8216;chunky&amp;#8217;] = &amp;#8216;bacon&amp;#8217;&lt;br/&gt;
        hash[&amp;#8216;foo&amp;#8217;] = &amp;#8216;vader&amp;#8217;&lt;/p&gt;
        
        &lt;p&gt;hash[&amp;#8216;foo&amp;#8217;] #=&gt; &amp;#8216;vader&amp;#8217;&lt;br/&gt;
        hash[&amp;#8216;food&amp;#8217;] #=&gt; &amp;#8216;something&amp;#8217;&lt;br/&gt;
        hash[&amp;#8216;123&amp;#8217;] #=&gt; &amp;#8216;number&amp;#8217;&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/iKGN2R17fik" height="1" width="1"/&gt;</description>
      <pubDate>Thu, 02 Jul 2009 12:44:22 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/07/02/ruby-fuzzyhash/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/iKGN2R17fik/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/07/02/ruby-fuzzyhash/</feedburner:origLink></item>
  
    <item>
      <title>Rails Metal in RadiantCMS</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;Radiant edge now supports loading Rails Metal from extensions!&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m really excited to announce that. I had been working on it before the release of 0.8.0, but hadn&amp;#8217;t had the time to hammer it out before the release. Admittedly, I push some sloppy commits into the main repo, and I should have rebased them and cleaned them up. This was the first opportunity I&amp;#8217;d had to look around at the way Rack middlewares are loaded in Rails, so a lot of my effort was just poking around. Gregg Pollack&amp;#8217;s &lt;a href="http://www.railsenvy.com/2009/6/11/rack-metal-and-rails-middleware"&gt;screencast on Rack &amp;amp; Metal&lt;/a&gt; had some helpful tips in it. Check it out if you want to try out the new features in Radiant.&lt;/p&gt;

&lt;p&gt;This will make things like checking a login status (like we&amp;#8217;re doing with &lt;a href="http://www.practicegreenhealth.org"&gt;Practice Greenheath&lt;/a&gt; and the &lt;a href="http://github.com/saturnflyer/radiant-header_authorize-extension/"&gt;Header Authorize extension&lt;/a&gt;) much faster.&lt;/p&gt;

&lt;p&gt;More importantly, &lt;a href="http://github.com/saturnflyer/radiant-vapor-extension/"&gt;Vapor&lt;/a&gt;(the extension to allow users to write their own redirect rules which also caches all the rules so its nice and speedy) will be &lt;a href="http://github.com/saturnflyer/radiant-vapor-extension/commit/15add081b72046bf02e65286aa458d37b9a3c66f"&gt;moving to metal&lt;/a&gt;. I&amp;#8217;ve created a separate branch for this, but I&amp;#8217;m considering backward compatibility so that if you&amp;#8217;ve got an older version of Radiant, it&amp;#8217;ll still operate the same old way (by catching the requests in the SiteController). I&amp;#8217;ll need to re-evaluate the code before it goes into the master branch, but it works!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/f2HUqwX5hRg" height="1" width="1"/&gt;</description>
      <pubDate>Thu, 25 Jun 2009 12:27:49 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/06/25/rails-metal-in-radiantcms/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/f2HUqwX5hRg/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/06/25/rails-metal-in-radiantcms/</feedburner:origLink></item>
  
    <item>
      <title>Managing ALL of Your Content</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;We&amp;#8217;ve been working hard to provide great features to our customers that are using Radiant and we&amp;#8217;ve been pushing a lot of that work out &lt;a href="http://ext.radiantcms.org/authors/3"&gt;into the community&lt;/a&gt;. We&amp;#8217;ve still got plenty more in store for our extension development and of course a lot more to contribute to Radiant.&lt;/p&gt;

&lt;p&gt;One of the problems any organization might face is the task of keeping track of your content. Of course, you&amp;#8217;d look to a content management system like Radiant, but even beyond your content is the content from others. Many organizations have relationships with others and their content is often linked back and forth. As the content changes, some things may get stale and we&amp;#8217;re working on a way to keep track of that.&lt;/p&gt;

&lt;p&gt;Your content isn&amp;#8217;t just your content. Your site depends on its environment and you&amp;#8217;ll need to react to any changes in it.&lt;/p&gt;

&lt;p&gt;When you&amp;#8217;re writing content for your site, you shouldn&amp;#8217;t just be worried about what you&amp;#8217;ve got. You also need to make sure that your target sites (or sites on which you might comment or to which you might send your visitors) are up and running too. &lt;a href="http://github.com/saturnflyer/radiant-site_watcher-extension"&gt;Site Watcher&lt;/a&gt; is a great way to keep track of what&amp;#8217;s happening on your own site and we&amp;#8217;ll be adding more features there, but there will be more to come for tracking the rest of the world too.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll be posting more about this in the future as we get ready to release our upcoming projects.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/In7Ry_xF4mo" height="1" width="1"/&gt;</description>
      <pubDate>Thu, 18 Jun 2009 14:47:19 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/06/18/managing-all-of-your-content/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/In7Ry_xF4mo/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/06/18/managing-all-of-your-content/</feedburner:origLink></item>
  
    <item>
      <title>Pretending to Be Different</title>
      <dc:creator>Jim Gay</dc:creator>
      <description>&lt;p&gt;It seems to be very common to &lt;em&gt;say&lt;/em&gt; in many ways that you are different, but when it comes to showing it, many companies must be too afraid to actually &lt;em&gt;*be&lt;/em&gt;* different.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve seen a TV commercial for the Audi Q5 which claims that it is unmistakable. From the behavior of the actors in the ad I would guess that it&amp;#8217;s supposed to be unmistakably different, but when it comes time to show how different it is you are shown that it is&amp;#8230; black. The other cars, you see, are &lt;strong&gt;beige&lt;/strong&gt;. Never mind that they look the same in every other way.&lt;/p&gt;

&lt;p&gt;This ad just plain confuses the point:&lt;/p&gt;

&lt;p&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/z066zR0hYaI&amp;amp;hl=en&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x3a3a3a&amp;amp;color2=0x999999"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/z066zR0hYaI&amp;amp;hl=en&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x3a3a3a&amp;amp;color2=0x999999" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;Are you doing this? Is your company claiming to be different but not showing your differences? &lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/saturnflyer/~4/lFPDSmpPDEw" height="1" width="1"/&gt;</description>
      <pubDate>Wed, 17 Jun 2009 00:17:12 GMT</pubDate>
      <guid isPermaLink="false">http://www.saturnflyer.com/blog/jim/2009/06/17/pretending-to-be-different/</guid>
      <link>http://feedproxy.google.com/~r/saturnflyer/~3/lFPDSmpPDEw/</link>
    <feedburner:origLink>http://www.saturnflyer.com/blog/jim/2009/06/17/pretending-to-be-different/</feedburner:origLink></item>
  
  
</channel>
</rss>
