<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>dibson.net &#187; Computing</title>
	<atom:link href="http://www.dibson.net/category/computing/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dibson.net</link>
	<description>by Dibson T Hoffweiler</description>
	<lastBuildDate>Mon, 23 Jan 2012 19:00:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Rails&#8217;s DB-Insensitive Case Insensitivity</title>
		<link>http://www.dibson.net/2011/03/22/railss-db-insensitive-case-insensitivity/</link>
		<comments>http://www.dibson.net/2011/03/22/railss-db-insensitive-case-insensitivity/#comments</comments>
		<pubDate>Tue, 22 Mar 2011 20:00:31 +0000</pubDate>
		<dc:creator>Dibson</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.dibson.net/?p=1219</guid>
		<description><![CDATA[I&#8217;ve been working with Rails for the past few weeks. But seriously, folks, it&#8217;s been great. Anyway, what are we all here for? To hear about my first big trouble with Rails. We had a simple request at work to &#8230; <a href="http://www.dibson.net/2011/03/22/railss-db-insensitive-case-insensitivity/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working with Rails for the past few weeks.  But seriously, folks, it&#8217;s been great.  Anyway, what are we all here for?  To hear about my first big trouble with Rails.</p>
<p>We had a simple request at work to make a database field case-insensitive.  Which is all to say, we had to make this touch field&#8217;s once defaultly true case sensitivity:</p>
<pre name="code" class="ruby">validates_uniqueness_of :a_touchy_field</pre>
<p>into a blatant lie:</p>
<pre name="code" class="ruby">validates_uniqueness_of :a_touchy_field, :case_sensitive =&gt; false</pre>
<p>And this is why Rails is so great.  We&#8217;re done!</p>
<p>BUT WAIT.  WHAT ABOUT THE BIG TROUBLE?</p>
<p>Oh right!  Well, this field is very touchy.  Touchy like&#8230; millions of rows touchy.  And it didn&#8217;t like all this insensitivity we we&#8217;re giving it.  And neither did MySQL.  There&#8217;s <a href="https://rails.lighthouseapp.com/projects/8994/tickets/2503-validates_uniqueness_of-is-horribly-inefficient-in-mysql">a lighthouse ticket</a> all about it.</p>
<p>The issue is that to keep things DB-neutral, Rails is having MySQL perform a <code>LOWER()</code> on that field on each row to do a binary comparison for the uniqueness validation.  How unkind to our conveniently indexed database field.</p>
<p>By default, MySQL does a case-insensitive string comparison.  So we rolled our own uniqueness validation&#8230;</p>
<pre name="code" class="ruby">def TouchyModel &lt; ActiveRecord::Base
  validate :ensure_unique_case_insensitive_touchy_field

  def ensure_unique_case_insensitive_touchy_field
    if new_record? || a_touchy_field_changed?
      if TouchyModel.exists?(:a_touchy_field =&gt; a_touchy_field)
        errors.add(:a_touchy_field, "must be alone, or else it'll get whiny")
      end
    end
  end
end</pre>
<p>This lets us tip-toe around the call to <code>LOWER()</code> and get on with our validations using the default MySQL comparison.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dibson.net/2011/03/22/railss-db-insensitive-case-insensitivity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hard drive backups</title>
		<link>http://www.dibson.net/2010/12/02/hard-drive-backups/</link>
		<comments>http://www.dibson.net/2010/12/02/hard-drive-backups/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 20:32:34 +0000</pubDate>
		<dc:creator>Dibson</dc:creator>
				<category><![CDATA[Computing]]></category>

		<guid isPermaLink="false">http://www.dibson.net/?p=1197</guid>
		<description><![CDATA[My reliable-so-far computer has been making a &#8220;tick tick&#8221; sound in the fan recently. I&#8217;ve never been one to keep backups of my personal work, but doing freelance work for the past year and a half has made me a &#8230; <a href="http://www.dibson.net/2010/12/02/hard-drive-backups/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My reliable-so-far computer has been making a &#8220;tick tick&#8221; sound in the fan recently.  I&#8217;ve never been one to keep backups of my personal work, but doing freelance work for the past year and a half has made me a bit paranoid about losing my personal and work data.  Time to backup!</p>
<p><a href="http://www.jwz.org/doc/backups.html">Jamie Zawinski&#8217;s backup PSA</a> is my favorite document about backing up data.  So I ordered one of the new <a href="http://www.codinghorror.com/blog/2010/09/revisiting-solid-state-hard-drives.html">hybrid drives mentoned on Coding Horror</a> and got it in the mail a few days ago.</p>
<p>I&#8217;ve copied disks using <tt>dd</tt> in the past, but it&#8217;s silent output always leaves me concerned.  This time I went with <a href="http://clonezilla.org/clonezilla-live/">Clonezilla Live</a>, a simple-to-use Debian-based live CD whose sole purpose is to duplicate disks.  Easy!</p>
<p>My next little hurdle was when I put in my hybrid drive and put the old drive into an external enclosure.  My machine booted fine, but when I plugged in the external disk, it wouldn&#8217;t mount.  Ubuntu 10.10 was attempting to mount the external disk to the root of the filesystem.  This line in <tt>/etc/fstab</tt> was the culprit:</p>
<pre name="code">
# &lt;file system&gt;  &lt;mount point&gt;   &lt;type&gt;  &lt;options&gt;         &lt;dump&gt;  &lt;pass&gt;
# / was on /dev/sda1 during installation
UUID=&lt;some-uuid&gt; /               ext4    errors=remount-ro 0       1
</pre>
<p>The first change I had to make was to change the UUID on the external disk.  I used the following command to do so:</p>
<pre name="code">
tune2fs -U random /dev/sdb1
</pre>
<p>Then, I updated the fstab like so:</p>
<pre name="code">
# &lt;file system&gt; &lt;mount point&gt;   &lt;type&gt;  &lt;options&gt;                         &lt;dump&gt;  &lt;pass&gt;
UUID=<em>&lt;new-uuid&gt;</em> /<em>media/backup</em>   ext4    <em>user,nobootwait,</em>errors=remount-ro 0       <em>2</em>
</pre>
<p>The external now mounts to <tt>/media/backup</tt>, is mountable automatically by ubuntu since the <tt>user</tt> option is set, and <tt>fsck</tt> will check the drive last since <tt>pass</tt> is now set to <tt>2</tt>.  <tt>nobootwait</tt> prevents the machine from booting if the disk is not present.</p>
<p>I dropped this in a file, and now I have an easy command to backup to a bootable drive!</p>
<pre name="code" class="sh">
#!/bin/sh
sudo rsync -vaxE --delete --ignore-errors / /media/backup/
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dibson.net/2010/12/02/hard-drive-backups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sort Criteria not used in Drupal View</title>
		<link>http://www.dibson.net/2010/06/30/sort-criteria-not-used-in-drupal-view/</link>
		<comments>http://www.dibson.net/2010/06/30/sort-criteria-not-used-in-drupal-view/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 19:18:45 +0000</pubDate>
		<dc:creator>Dibson</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[sort]]></category>
		<category><![CDATA[views]]></category>

		<guid isPermaLink="false">http://www.dibson.net/?p=1091</guid>
		<description><![CDATA[I was having trouble with the Drupal Views module. I have a view of a CCK Node, and I wanted to sort the view by one of the CCK data fields. The view was sorting on node id by default. &#8230; <a href="http://www.dibson.net/2010/06/30/sort-criteria-not-used-in-drupal-view/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was having trouble with the Drupal Views module.  I have a view of a CCK Node, and I wanted to sort the view by one of the CCK data fields.  The view was sorting on node id by default.</p>
<p>Adding the CCK content field to the &#8220;Sort Criteria&#8221; gave no change in the SQL query.  I struggled with this for a good hour before deciding to create my view from scratch.</p>
<p>Once I recreated the view, I found that <strong>sorting by columns is handled in the table style settings</strong>.  The not correctly sorted view was using the table style; I went back to my original view&#8217;s table settings and was able to sort by other columns by default.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dibson.net/2010/06/30/sort-criteria-not-used-in-drupal-view/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Multiple Images for Ubercart Products</title>
		<link>http://www.dibson.net/2010/06/25/multiple-images-for-ubercart-products/</link>
		<comments>http://www.dibson.net/2010/06/25/multiple-images-for-ubercart-products/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 19:44:17 +0000</pubDate>
		<dc:creator>Dibson</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[cck]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[ubercart]]></category>

		<guid isPermaLink="false">http://www.dibson.net/?p=1063</guid>
		<description><![CDATA[I&#8217;m working on a Drupal site with the Ubercart package. I&#8217;m learning both at the same time, which is a challenge since they each offer so many options. Below I&#8217;ve listed some troubles I came across while I fighting to &#8230; <a href="http://www.dibson.net/2010/06/25/multiple-images-for-ubercart-products/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on a <a href="http://www.drupal.org/">Drupal</a> site with the <a href="http://www.ubercart.org/">Ubercart</a> package.  I&#8217;m learning both at the same time, which is a challenge since they each offer so many options.  Below I&#8217;ve listed some troubles I came across while I fighting to get multiple images for the UC Product content type.</p>
<h2>Don&#8217;t Change Product&#8217;s Display Field &#8220;Image&#8221;</h2>
<p>Well, you can if you know what you&#8217;re doing.  But I had mistakenly updated the display fields for the <em>product</em> content type at <a href="http://www.example.org/admin/content/node-type/product/display">Home › Administer › Content management › Product › Display Fields</a> to be &#8216;product_full image linked to image&#8217; for &#8216;full node&#8217;.  The reason I shouldn&#8217;t have done this is because UberCart handles the images itself.  Head over to <a href="http://www.example.org/admin/store/settings/products/edit">Home › Administer › Store administration › Configuration › Product Settings</a> to choose a <em>Product Image Widget</em>.</p>
<p>None available?  Install one off the <a href="http://drupal.org/project/lightbox2">Lightbox2</a> or <a href="http://drupal.org/project/thickbox">Thickbox</a> modules to have an option.</p>
<h2>Uploading Multiple Images</h2>
<p>Oh! the pains of learning.  Months ago I attempted to add another Image field to the Product content type.  It led nowhere and took up a lot of my time.  Today I learned that the CCK Image Field offers the option of multiple images.  Simple!</p>
<p>Head over to <a href="http://www.example.org/admin/content/node-type/product/fields/field_image_cache">Home › Administer › Content management › Product › Manage Fields › Image</a>.  Under &#8220;Global Settings&#8221; there is an option for number of images to allow.</p>
<h2>Contemplates for UberCart Products</h2>
<p>Now: my image fields are hidden from the product pages.  I have an image widget set for UberCart.  I&#8217;m using <a href="http://drupal.org/project/contemplate">the Contemplate module</a> for product node rendering.  How do I show the image widget?</p>
<p>There is probably a better way, but I found it by using the <em>get_defined_vars()</em> function.  Reviewing the output of that function from my product node template revealed the image widget to be in <em>$content['image']['#value']</em>.  I dropped that in the template and had the lightbox triggering widget showing all product images.</p>
<p>For easier review of <em>get_defined_vars</em> output, install the <a href="">Devel</a> module, and use this line of code:</p>
<pre lang="php">&lt;?php dpm(get_defined_vars()); ?&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dibson.net/2010/06/25/multiple-images-for-ubercart-products/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sierpinski&#8217;s Carpet Animation</title>
		<link>http://www.dibson.net/2009/11/19/sierpinskis-carpet-animation/</link>
		<comments>http://www.dibson.net/2009/11/19/sierpinskis-carpet-animation/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 08:00:18 +0000</pubDate>
		<dc:creator>Dibson</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[fractal]]></category>
		<category><![CDATA[sierpinski]]></category>

		<guid isPermaLink="false">http://www.dibson.net/?p=377</guid>
		<description><![CDATA[A few weeks ago I wrote a little script (code below the fold) to generate the frames of the following animation. It&#8217;s an animation of different iterations of Sierpinski&#8217;s Carpet. To generate the carpet, take a square. Divide it into &#8230; <a href="http://www.dibson.net/2009/11/19/sierpinskis-carpet-animation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A few weeks ago I wrote a little script (code below the fold) to generate the frames of the following animation.  It&#8217;s an animation of different iterations of <a href="http://en.wikipedia.org/wiki/Sierpinski_carpet">Sierpinski&#8217;s Carpet</a>.</p>
<div id="attachment_376" class="wp-caption aligncenter" style="width: 739px"><a href="http://www.dibson.net/wp-content/uploads/2009/11/carpet-729px-0-6.gif"><img src="http://www.dibson.net/wp-content/uploads/2009/11/carpet-729px-0-6.gif" alt="7 Iterations of the Carpet" title="Sierpinski&#039;s Carpet Animation" width="300" height="300" class="size-full wp-image-376" /></a><p class="wp-caption-text">7 Iterations of the Carpet</p></div>
<p>To generate the carpet, take a square.  Divide it into nine squares (3&#215;3) and remove the center one.  Then, for each of the remaining 8 squares, repeat ad infinitum.</p>
<p>If you get bored doing it an infinite number of times, take a break and eat <a href="http://www.evilmadscientist.com/article.php/fractalcookies">Sierpinski&#8217;s Cookie</a>.</p>
<p><span id="more-377"></span></p>
<h4>The Code &#8211; SierpinskisCarpenter.py</h4>
<p>Sorry for the crappy box this is in.  Copy and paste for reading.</p>
<pre lang="python">
#!/usr/bin/python

#
# SierpinskisCarpenter.py
#
# Author: Dibson T Hoffweiler <dibson@hoffweiler.com>
# WWW:    http://www.dibson.net/
#
#             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
#                     Version 2, December 2004
#
#  Everyone is permitted to copy and distribute verbatim or modified
#  copies of this license document, and changing it is allowed as long
#  as the name is changed.
#
#             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
#    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
#   0. You just DO WHAT THE FUCK YOU WANT TO.
#

import Image

class SierpinskisCarpenter:

    def __init__(self):
        """ Prepare the Carpenter """
        self.color = (0, 0, 255)

    def getCounter(self):
        """ Return current counter value, increment it. """
        c = self.counter
        self.counter += 1
        return c

    def getFrameFilename(self):
        """ Return filename for next frame. """
        return "carpet-frame-%02d-%06d.gif" % (self.itr_start, self.getCounter())

    def getCarpetImage(self, itr, size, init=True):
        """ Return an image object of Sierpinski's Carpet

            itr - int - how many iterations deep to go
            size - int - width of carpet in pixels
            init - bool - if True, clear counters - must set False when recursing! (default True)
        """

        if (init):
            # Prepare to lay the carpet out
            self.counter = 0

        if (0 == itr):
            # No need to iterate, return the part
            part = Image.new("RGB", (size, size), self.color)
            return part
        else:
            # Get smaller carpet, and paste it in 8 times

            third = size / 3

            partSmall = self.getCarpetImage(itr - 1, third, False)

            im = Image.new("RGB", (size, size), (255, 255, 255))

            # top left
            tl_start = (0, 0)
            im.paste(partSmall, tl_start)

            # top center
            tc_start = (third, 0)
            im.paste(partSmall, tc_start)

            # top right
            tr_start = (2 * third, 0)
            im.paste(partSmall, tr_start)

            # middle right
            mr_start = (2 * third, third)
            im.paste(partSmall, mr_start)

            # bottom right
            br_start = (2 * third, 2 * third)
            im.paste(partSmall, br_start)

            # bottom center
            bc_start = (third, 2 * third)
            im.paste(partSmall, bc_start)

            # bottom left
            bl_start = (0, 2 * third)
            im.paste(partSmall, bl_start)

            # middle left
            ml_start = (0, third)
            im.paste(partSmall, ml_start)

            return im

    def animateCarpet(self, itr, size, start=None):
        """ A recursive function to generate an animation of drawing Sierpinski's Carpet.

        - itr - int - how many iterations to do
        - size - int - image size will be a square with lengths this many pixels
        - start - 2dim tuple - top left corner of carpet to draw

        Example:

          sc = SierpinskisCarpenter()
          itr = 3
          size = (3 ** itr, 3 ** itr)
          im = sc.animateCarpet(itr, size)
          im.show()

        """

        if (None == start):
            # Init the animation
            start = (0,0)
            self.counter = 0
            self.im = Image.new("RGB", (size, size), (255, 255, 255))
            self.itr_start = itr
            self.im.save(self.getFrameFilename())

        # tab for clean debug output
        tab = "\t" * itr

        #print tab + "MAKE CARPET ITR %s" % (itr)
        #print "%sStart %s" % (tab, start)

        if (0 == itr):
            # LAST ITERATION - PAINT IT!
            #print "%sPAINTING: Start %s" % (tab, start)
            self.im.paste(self.color, (start[0], start[1], start[0] + size, start[1] + size))
            self.im.save(self.getFrameFilename())
        else:
            # NEED TO ITERATE, DO ALL 8 SQUARES

            third = size / 3

            # top left
            tl_start = (start[0], start[1])
            self.im = self.animateCarpet(itr-1, size/3, tl_start)

            # top center
            tc_start = (start[0] + third, start[1])
            self.im = self.animateCarpet(itr-1, size/3, tc_start)

            # top right
            tr_start = (start[0] + 2 * third, start[1])
            self.im = self.animateCarpet(itr-1, size/3, tr_start)

            # middle right
            mr_start = (start[0] + 2 * third, start[1] + third)
            self.im = self.animateCarpet(itr-1, size/3, mr_start)

            # bottom right
            br_start = (start[0] + 2 * third, start[1] + 2 * third)
            self.im = self.animateCarpet(itr-1, size/3, br_start)

            # bottom center
            bc_start = (start[0] + third, start[1] + 2 * third)
            self.im = self.animateCarpet(itr-1, size/3, bc_start)

            # bottom left
            bl_start = (start[0], start[1] + 2 * third)
            self.im = self.animateCarpet(itr-1, size/3, bl_start)

            # middle left
            ml_start = (start[0], start[1] + third)
            self.im = self.animateCarpet(itr-1, size/3, ml_start)

        return self.im

cm = SierpinskisCarpenter()

# EXAMPLE: saves 6 iterations of Sierpinski's Carpet
#topItr = 6
#size = 3 ** topItr
#for itr in range(topItr+1):
#    im = cm.getCarpetImage(itr, size)
#    im.save("carpet-%spx-%s.gif" % (size, itr))

# EXAMPLE: dumps out frames for drawing out carpet
#cm.animateCarpet(3, 27)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dibson.net/2009/11/19/sierpinskis-carpet-animation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

