<?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>Postpostmodern &#187; Instructional</title>
	<atom:link href="http://postpostmodern.com/category/instructional/feed/" rel="self" type="application/rss+xml" />
	<link>http://postpostmodern.com</link>
	<description>Speaking of web development.</description>
	<lastBuildDate>Tue, 08 Jun 2010 18:46:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Slicehost (and Linode) LAMP Cheatsheet</title>
		<link>http://postpostmodern.com/instructional/slicehost-and-linode-lamp-cheatsheet/</link>
		<comments>http://postpostmodern.com/instructional/slicehost-and-linode-lamp-cheatsheet/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 23:51:35 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[LAMP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Postfix]]></category>
		<category><![CDATA[Slicehost]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=120</guid>
		<description><![CDATA[A quick list of steps I use to set up a LAMP server on Slicehost or Linode.]]></description>
			<content:encoded><![CDATA[<p>I have set up several <a href="http://slicehost.com">Slicehost</a> slices as Ubuntu LAMP servers, but since I&#8217;m not a server admin, I always have to reference the tutorials to remember the steps. So, I&#8217;ve compiled the list of steps here, as concisely as possible. This process sets up everything you need for hosting multiple sites on a single server, and it works equally well for most servers running Ubuntu including <a href="http://slicehost.com">Slices</a> and <a href="http://linode.com">Linodes</a>.</p>

<dl>
  <dt>Disclaimer</dt>
  <dd>Please use these only if you already know the whys and wherefores. If you don&#8217;t generally understand one or more of these steps, <strong><em>consult the <a href="http://articles.slicehost.com/ubuntu-intrepid">Slicehost Articles</a> or the <a href="http://library.linode.com/lamp-guides/">Linode Articles</a> before asking questions here</em></strong>. Most of the information here comes from the <a href="http://articles.slicehost.com/ubuntu-intrepid">Slicehost Articles for Ubuntu</a>. I have also added a few extra steps from sources cited in the footnotes.</dd>
  <dt>Helping Me Out</dt>
  <dd>If you need to sign up for a Slicehost or Linode account, and you plan on using this article as a guide to configure your server, please use these referral links:
    <ul>
      <li><a href="https://manage.slicehost.com/customers/new?referrer=a65ed663fdc3b50a3d32cb06fee151d1">Sign up for a Slicehost account</a></li>
      <li><a href="http://www.linode.com/?r=1eadb325010c5678e5e5af3cd16505bf6bb5be00">Sign up for a Linode account</a></li>
    </ul>
  </dd>
  <dd>Corrections to this article are also appreciated. Please note, however, that corrections != personal preference. If you have a different way of doing something, you&#8217;ll need to present a convincing case as to why it is better.</dd>
  <dt>Assumptions</dt>
  <dd>This guide/cheatsheet assumes you have already created a virtual server with Ubuntu installed.</dd>
  <dd>You should also set up your DNS. If you&#8217;re using Slicehost, my <a href="http://github.com/postpostmodern/slicehost-dns">Slicehost DNS</a> script will help.</dd>
  <dt>Conventions</dt>
  <dd>For this article, I&#8217;m using:
    <ul>
      <li><code>xxx.xxx.xxx.xxx</code> to indicate the IP address of your server</li>
      <li><code>bob</code> as the server&#8217;s name (hostname)</li>
      <li><code>example.com</code> as the domain name</li>
      <li><code>demo</code> as the admin user</li>
      <li><code>nano</code> as my editor because I have no vi skills.</li>      
    </ul>
  </dd>
</dl>

<h2>Configure Server for Terminal.app (Mac users only)</h2>

<p>Terminal.app behaves as dtterm, but Ubuntu doesn&#8217;t have the dtterm entry in its terminfo database. This fixes that.<sup><a href="#footnote-1-120" id="footnote-link-1-120" title="See the footnote.">1</a></sup></p>

<h3>Save Terminal Info to a File</h3>

<p><em>On your Mac (local machine)&#8230;</em></p>

<ol>
<li><kbd class="block">infocmp > /tmp/dtterm</kbd></li>
<li><kbd class="block">scp /tmp/dtterm root@xxx.xxx.xxx.xxx:/tmp</kbd></li>
</ol>

<h3>Import Terminal Info</h3>

<ol>
<li>Log into your server as root</li>
<li><kbd class="block">tic /tmp/dtterm</kbd></li>
</ol>

<h2>Some Basic Package Setup</h2>

<h3>Aptitude Upgrade</h3>

<p><em>Still logged in as root&#8230;</em></p>

<ol>
<li>Make sure you have access to the universe repositories
<kbd class="block">nano /etc/apt/sources.list</kbd>
and uncomment the universe repositories</li>
<li>Update<br />
<kbd class="block">aptitude update</kbd></li>
<li>Upgrade<br />
<kbd class="block">aptitude safe-upgrade 
aptitude full-upgrade</kbd></li>
</ol>

<h3>Install Build Essentials</h3>

<ol>
<li>Install<br />
<kbd class="block">aptitude install build-essential</kbd></li>
</ol>

<h3>Install CURL</h3>

<ol>
<li>Install<br />
<kbd class="block">aptitude install curl</kbd></li>
<li>Install ca-certificates for ssl connections
<kbd class="block">aptitude install ca-certificates</kbd></li>
</ol>

<h2>SSH and Users</h2>

<h3>Create New User and Allow sudo</h3>

<p><em>Still logged in as root&#8230;</em></p>

<ol>
<li>Change root password, if desired
<kbd class="block">passwd</kbd></li>
<li>Add user<br />
<kbd class="block">adduser demo</kbd></li>
<li>Set up sudo config<br />
<kbd class="block">visudo</kbd> and add <code>demo ALL=(ALL) ALL</code> to the end</li>
<li>Log out or switch to your local machine</li>
</ol>

<h3>Set up SSH Keys</h3>

<ol>
<li><em>On your local machine</em>, copy local public ssh key to server (assuming you have already created your public key on your local machine)
<kbd class="block">scp ~/.ssh/id_rsa.pub demo@xxx.xxx.xxx.xxx:/home/demo/</kbd></li>
<li>Switch back to your server or log back in as root</li>
<li>Create authorized_keys file<br />
<kbd class="block">cd /home/demo
mkdir .ssh 
mv id_rsa.pub .ssh/authorized_keys</kbd></li>
<li>Set permissions
<kbd class="block">chown -R demo:demo .ssh
chmod 700 .ssh
chmod 600 .ssh/authorized_keys
</kbd></li>
</ol>

<h3>Configure sshd</h3>

<ol>
<li>Open sshd_config  
<kbd class="block">nano -w /etc/ssh/sshd_config</kbd></li>
<li>Set these:  
<pre><code lang="bash">Port 30000 (change to a port of your choosing)
Protocol 2
PermitRootLogin no
PasswordAuthentication no
X11Forwarding no
UsePAM no
UseDNS no
AllowUsers demo</code></pre>
</li>
</ol>

<h3>Setup iptables</h3>

<ol>
<li>Dump existing rules  
<kbd class="block">cd /etc 
iptables-save > iptables.up.rules</kbd></li>
<li>Copy rules file from Slicehost example  
<kbd class="block">curl -o iptables.test.rules http://articles.slicehost.com/assets/2007/9/4/iptables.txt</kbd></li>
<li>Edit it and set port number for sshd
<kbd class="block">nano -w iptables.test.rules</kbd></li>
<li>Load it  
<kbd class="block">iptables-restore < iptables.test.rules</kbd></iptables>
<li>Check the new rules  
<kbd class="block">iptables -L</kbd></li>
<li>Save the new rules  
<kbd class="block">iptables-save > iptables.up.rules</kbd></li>
<li>Make sure the new rules are read every time  
<kbd class="block">nano -w network/interfaces</kbd> and make it look like this:  
<pre><code lang="bash">...
auto lo
iface lo inet loopback
pre-up iptables-restore < /etc/iptables.up.rules

# The primary network interface
...</code></pre>
</li>
</ol>

<h3>Restart and Test sshd</h3>

<ol>
<li>Reload sshd<br />
<kbd class="block">/etc/init.d/ssh reload</kbd></li>
<li>Try to log in from another terminal</li>
<li>If successful, logout</li>
</ol>

<h2>User Config</h2>

<p><em>Logged in as demo...</em></p>

<h3>Configure Nano</h3>

<ol>
<li>Set some configuration
<kbd class="block">cp /etc/nanorc ~/.nanorc
nano -w ~/.nanorc</kbd></li>
<li>Uncomment these lines:<br />
<code># set brackets ""')&gt;]}"</code><br />
<code># set nowrap</code>  (should be set by default in recent versions)
<code># set tabsize 8</code></li>
<li>Change tabsize to 2 or 4 or something:<br />
<code>set tabsize 4</code></li>
</ol>

<h3>Add Bash Aliases</h3>

<ol>
<li>Create aliases file <kbd class="block">nano -w .bash_aliases</kbd> and add:
<pre><code lang="bash">alias lo='logout'
alias mksite='sudo /usr/local/a2mksite/a2mksite.sh'
alias free='free -m'
alias ag='sudo apache2ctl graceful'
if [ "$TERM" != "dumb" ] &#038;&#038; [ -x /usr/bin/dircolors ]; then
    eval "`dircolors -b`"
    alias ls='ls -la --color=auto'
fi

# Git
alias gst='git status'
# alias gl='git pull'
alias ga='git add'
alias gp='git push'
alias gd='git diff | mate'
alias gc='git commit -v'
alias gca='git commit -v -a'
alias gb='git branch'
alias gba='git branch -a'
alias gco='git checkout'
alias glog='git log --pretty=format:"# %aD : %an%n%n* %s%n%n%b%n"'
alias glt='glog --since=yesterday'
alias gly='glog --since="2 days ago" --until="1 day ago"'</code></pre>
</li>
<li>If necessary, activate aliases in .bashrc <kbd class="block">nano -w .bashrc</kbd> and uncomment the part that loads .bash_aliases</li>
<li>Get the aliases working <kbd class="block">source ~/.bashrc</kbd></li>
</ol>

<h2>Basic Server Config</h2>

<h3>Set Hostname<sup><a href="#footnote-2-120" id="footnote-link-2-120" title="See the footnote.">2</a></sup></h3>

<ol>
<li>Name your server by setting a short hostname in /etc/hostname 
<kbd class="block">sudo nano /etc/hostname</kbd>
and type <code>bob.example.com</code></li>
<li>Set the fully-qualified domain name in hosts<br />
<kbd class="block">sudo nano /etc/hosts</kbd> 
and add <code>xxx.xxx.xxx.xxx    bob.example.com    bob</code><br />
below the <code>127.0.0.1 localhost</code> entry</li>
<li>Reboot
<kbd class="block">sudo reboot</kbd></li>
<li>Check hostname<br />
<kbd class="block">hostname</kbd></li>
<li>Check FQDN<br />
<kbd class="block">hostname -f</kbd></li>
</ol>

<h3>Set Locale</h3>

<ol>
<li>Generate locale info<br />
<kbd class="block">sudo locale-gen en_US.UTF-8</kbd></li>
<li>Update locale<br />
<kbd class="block">sudo /usr/sbin/update-locale LANG=en_US.UTF-8</kbd></li>
</ol>

<h3>Set Timezone</h3>

<ol>
<li>Start up timezone configurator and follow instructions<br />
<kbd class="block">sudo dpkg-reconfigure tzdata</kbd></li>
</ol>

<h2>Git</h2>

<h3>Install Git</h3>

<ol>
<li>Install<br />
<kbd class="block">sudo aptitude install git-core</kbd></li>
</ol>

<h2>Subversion</h2>

<h3>Install svn</h3>

<ol>
<li>Install<br />
<kbd class="block">sudo aptitude install subversion</kbd></li>
</ol>

<h2>Web Server</h2>

<h3>Install a2mksite</h3>

<p>a2mksite is a script that I wrote that allows you to create an Apache virtual host with one command (including the document root, config files, log rotation, etc). One thing you should know is that it creates a directory structure for multiple web sites (virtual hosts), placing each site's public and log directories in its own directory like so: <code>/var/www/sites/example.com</code></p>

<p>Read the <a href="http://github.com/postpostmodern/a2mksite">description here</a> to learn more about what it does.</p>

<ol>
<li>Clone a2mksite from Github
<kbd class="block">git clone git://github.com/postpostmodern/a2mksite.git</kbd></li>
<li>Move it to /usr/local
<kbd class="block">sudo mv a2mksite /usr/local</kbd></li>
<li>CHOWN it to root
<kbd class="block">sudo chown 0:0 /usr/local/a2mksite</kbd></li>
<li>Make sure you have the script aliased as <code>mksite</code> in your <code>.bash_aliases</code> file (see Bash Aliases snippet earlier in this post).</li>
</ol>

<h3>Install Logrotate</h3>

<ol>
<li>Install<br />
<kbd class="block">sudo aptitude install logrotate</kbd></li>
</ol>

<h3>Install Apache</h3>

<ol>
<li>Install
<kbd class="block">sudo aptitude install apache2 apache2.2-common apache2-mpm-prefork apache2-utils libexpat1 ssl-cert</kbd></li>
<li>Set up basic config using <a href="http://gist.github.com/236374">my httpd.conf</a> as an example
<kbd class="block">wget http://gist.github.com/raw/236374/8542ce36a24f2c653b023e83e85d29fda74072f3/httpd.conf
sudo mv httpd.conf /etc/apache2/httpd.conf
sudo nano /etc/apache2/httpd.conf</kbd></li>
<li>Enable Modules<br />
<kbd class="block">sudo a2enmod auth_digest dav dav_lock rewrite</kbd></li>
<li>Create errors dir<br />
<kbd class="block">sudo mkdir /var/www/errors</kbd></li>
<li>Create maintenance dir<br />
<kbd class="block">sudo mkdir /var/www/maintenance</kbd></li>
<li>CHOWN them<br />
<kbd class="block">sudo chown -R demo:demo /var/www/errors /var/www/maintenance</kbd></li>
<li>Create global 404<br />
<kbd class="block">nano -w /var/www/errors/404.html</kbd></li>
<li>Create maintenance page<br />
<kbd class="block">nano -w /var/www/maintenance/index.html</kbd></li>
<li>Make default site<br />
<kbd class="block">mksite default</kbd>
and overwrite the original default</li>
</ol>

<h2>MySQL</h2>

<h3>Install MySQL</h3>

<ol>
<li>Install<br />
<kbd class="block">sudo aptitude install mysql-server mysql-client libmysqlclient15-dev</kbd></li>
<li>Set root password (follow instructions during installation)</li>
</ol>

<h2>PHP</h2>

<h3>Install PHP</h3>

<ol>
<li>Install PHP
<kbd class="block">sudo aptitude install libapache2-mod-php5 php5 php5-common php5-curl php5-dev php5-gd php5-imagick php5-mcrypt php5-memcache php5-mhash php5-mysql php5-pspell php5-snmp php5-sqlite php5-xmlrpc php5-xsl php5-xcache</kbd></li>
<li>Edit xcache.ini
<kbd class="block">sudo nano /etc/php5/apache2/conf.d/xcache.ini</kbd>
and set <code>xcache.var_size</code> to something other than zero</li>
<li>Edit php.ini
<kbd class="block">sudo nano /etc/php5/apache2/php.ini</kbd>
and set error output, max upload size, etc.</li>
<li>Restart Apache
<kbd class="block">sudo /etc/init.d/apache2 restart</kbd></li>
</ol>

<h2>Mail (for sending via PHP)</h2>

<h3>Reverse DNS</h3>

<ol>
<li>Set Reverse DNS in SliceManager or Linode Manager to your server's FQDN, i.e. what you see when you type <kbd>hostname -f</kbd></li>
<li>Check it<br />
<kbd class="block">sudo aptitude install dnsutils</kbd>
<kbd class="block">dig -x xxx.xxx.xxx.xxx</kbd></li>
</ol>

<h3>Postfix</h3>

<ol>
<li>Install Postfix<br />
<kbd class="block">sudo aptitude install postfix mailx</kbd></li>
<li>Test Postfix<br />
<kbd class="block">mail someone@somewhereelse.com</kbd> and send a message. Don't forget: <kbd>ctrl-d</kbd> ends the message.</li>
<li>Optionally continue configuration as described <a href="http://articles.slicehost.com/2008/7/31/postfix-basic-settings-in-main-cf">here</a></li>
</ol>

<h2>A Backup Solution</h2>

<p>The following is my own backup solution for my web sites. It backs up the MySQL databases and web site files. Then, it sends a copy to Amazon S3.</p>

<h3>Install Ruby for S3Sync</h3>

<ol>
<li>Install Ruby
<kbd class="block">sudo aptitude install ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 irb1.8 libreadline-ruby1.8 libruby1.8 libopenssl-ruby sqlite3 libsqlite3-ruby1.8</kbd></li>
<li>Symlink locations
<kbd class="block">sudo ln -s /usr/bin/ruby1.8 /usr/bin/ruby
sudo ln -s /usr/bin/ri1.8 /usr/bin/ri
sudo ln -s /usr/bin/rdoc1.8 /usr/bin/rdoc
sudo ln -s /usr/bin/irb1.8 /usr/bin/irb</kbd></li>
<li>Install Ruby Gems (optional)
<kbd class="block">wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz
tar xzvf rubygems-1.3.7.tgz
cd rubygems-1.3.7
sudo ruby setup.rb
cd ..
rm -R rubygems-1.3.7*
sudo ln -s /usr/bin/gem1.8 /usr/bin/gem</kbd></li>
<li>Update gems
<kbd class="block">sudo gem update
sudo gem update --system</kbd></li>
</ol>

<h3>Install S3Sync</h3>

<ol>
<li>Download and move S3Sync
<kbd class="block">wget http://s3.amazonaws.com/ServEdge_pub/s3sync/s3sync.tar.gz
tar xvzf s3sync.tar.gz
sudo mv s3sync /usr/local/
sudo chown 0:0 /usr/local/s3sync/
rm s3sync.tar.gz</kbd></li>
<li>Make sure you installed the ca-certificates package earlier (see "Install CURL" above)</li>
</ol>

<h3>Install Web Server Backup Script</h3>

<ol>
<li>Clone it from Github
<kbd class="block">sudo git clone git://github.com/postpostmodern/web-server-backup.git /usr/local/web-server-backup
</kbd></li>
<li>Configure it according to the README
<kbd class="block">sudo nano /usr/local/web-server-backup/backup.sh</kbd></li>
<li>Test Run
<kbd class="block">sudo /usr/local/web-server-backup/backup.sh</kbd></li>
</ol>

<h3>Schedule the Backup with Cron</h3>

<ol>
  <li>Create a cron job
    <kbd class="block">sudo nano /etc/cron.d/web_server_backup</kbd>
  </li>
  <li>Make it look something like this:
    <pre><code lang="cron">SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
MAILTO=demo@example.com
HOME=/root

30 4 * * * root /usr/local/web-server-backup/backup.sh > /dev/null</code></pre>
  </li>
</ol>

<h2>There is no step 54.</h2>

<p>Okay. That was a lot of steps, but everything should be running properly now. Though this article is mostly for my own reference, your comments are welcome.<br /></p>

<ol class="footnotes"><li id="footnote-1-120"><a href="http://hans.fugal.net/blog/2008/02/12/os-x-terminal-emulation-woes/">OS X Terminal Emulation Woes</a>  <a href="#footnote-link-1-120">&#8593; back up there</a></li><li id="footnote-2-120"><a href="http://jblevins.org/computing/linux/hostname">Linux Hostname Configuration</a>  <a href="#footnote-link-2-120">&#8593; back up there</a></li></ol>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/slicehost-and-linode-lamp-cheatsheet/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Terminal Tip: Prevent Creation of Mac Dot Files</title>
		<link>http://postpostmodern.com/instructional/terminal-tip-prevent-creation-of-mac-dot-files/</link>
		<comments>http://postpostmodern.com/instructional/terminal-tip-prevent-creation-of-mac-dot-files/#comments</comments>
		<pubDate>Fri, 07 Aug 2009 12:59:04 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=412</guid>
		<description><![CDATA[An environment variable can prevent creation of ._filename files.]]></description>
			<content:encoded><![CDATA[<p>I had no idea until recently that you can actually prevent creation of the <code>._filename</code> files when using tar (and other commands, I assume) by setting an environment variable. On Leopard, it&#8217;s called COPYFILE_DISABLE.</p>

<p>So, put this in your .bash_profile: <code>export COPYFILE_DISABLE=true</code> and you can avoid having to do <a href="http://postpostmodern.com/instructional/terminal-tip-delete-those-mac-dot-files/">this</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/terminal-tip-prevent-creation-of-mac-dot-files/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Terminal Tip: Delete Those Mac Dot Files</title>
		<link>http://postpostmodern.com/instructional/terminal-tip-delete-those-mac-dot-files/</link>
		<comments>http://postpostmodern.com/instructional/terminal-tip-delete-those-mac-dot-files/#comments</comments>
		<pubDate>Mon, 08 Jun 2009 16:40:32 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Terminal]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=396</guid>
		<description><![CDATA[Use the find command to delete all of the ._* and .DS_Store files.]]></description>
			<content:encoded><![CDATA[<p>Unzipping/untaring an archive that was created on a Mac can produce a lot of ._blah and .DS_Store files. Rid yourself of them with:</p>

<p><kbd class="block">find . &#92;( -name '._*' -o -name '.DS_Store' &#92;)  -exec rm {} \;</kbd></p>

<p>or, if you&#8217;re using GNU find (e.g. on Ubuntu) you can use <code>-delete</code>:</p>

<p><kbd class="block">find . &#92;( -name '._*' -o -name '.DS_Store' &#92;)  -delete</kbd></p>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/terminal-tip-delete-those-mac-dot-files/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A Body with Class</title>
		<link>http://postpostmodern.com/instructional/a-body-with-class/</link>
		<comments>http://postpostmodern.com/instructional/a-body-with-class/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 23:07:12 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=228</guid>
		<description><![CDATA[Ease section-specific styling by adding classes to your body tag.]]></description>
			<content:encoded><![CDATA[<h2>This Short Version</h2>

<p>Add a class attribute to your <body> tag for each part of the page&#8217;s path in the URL. E.g.: The page <em>http://example.com/about/history</em> should have a body tag that looks like <code>&lt;body class="about history"&gt;</code>. It makes styling those sections of your site nice and simple.</p>

<h2>The Explanation</h2>

<p>Often times, specific styling/formatting is shared between similar pages. The traditional way to deal with this is to include additional CSS files when special formatting is needed. I&#8217;ve found body classing to be more useful and more efficient.<sup><a href="#footnote-1-228" id="footnote-link-1-228" title="See the footnote.">1</a></sup></p>

<p>Since the pages that share styling often also share a path in the url, it&#8217;s really simple to add the path parts as classes to the body tag. For example, say the <strong><em>about</em></strong> section of a web site needs special formatting because it has an extra sidebar or maybe some sort of widget. I would add the class &#8216;about&#8217; to the body tag of all of the about pages. This method continues down the hierarchy. The page at <strong><em>/about/history</em></strong> would have a body class of &#8216;about history&#8217;, and so on. It&#8217;s very simple and very handy.</p>

<p>It&#8217;s also very simple to add this functionality to your layouts whether you&#8217;re using Rails or any other framework. My PHP framework, <a href="http://github.com/postpostmodern/phooey/tree">Phooey</a>, does it for you automatically.</p>

<p>For Rails, you can include this in your layout:</p>

<p><code>&lt;body class="&lt;%= controller_name -%&gt; &lt;%= action_name -%&gt;"&gt;</code></p>

<p>&#8230;or, if you&#8217;re using Haml (which I highly recommend):</p>

<p><code>%body{:class =&gt; "#{controller_name} #{action_name}"}</code></p>

<p>Agree? Disagree? Confused? Let me know down there in the comments.<br /></p>

<ol class="footnotes"><li id="footnote-1-228">I am of the opinion that you should only include <em>one CSS file per media type</em> in any page of your site (except for the IE stylesheets). I usually include only the following stylesheets in every page of every site: all.css, screen.css, print.css. And each one of those is minified. More on this in my forthcoming article on Sass.  <a href="#footnote-link-1-228">&#8593; back up there</a></li></ol>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/a-body-with-class/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pseudo Pseudo Classes</title>
		<link>http://postpostmodern.com/instructional/pseudo-pseudo-classes/</link>
		<comments>http://postpostmodern.com/instructional/pseudo-pseudo-classes/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 05:16:19 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=384</guid>
		<description><![CDATA[Simple jQuery snippet to get some pseudo-classes]]></description>
			<content:encoded><![CDATA[<p>The <code>:first-child</code> and <code>:last-child</code> pseudo classes in CSS are super-handy for stying things like lists. For example, if you want a horizontal line between list items, you can set:</p>

<pre><code>ul li {
  border-bottom: solid 1px #e0e0e0;
}
ul li:last-child {
  border: none;
}
</code></pre>

<p>Unfortunately, most current browsers can&#8217;t stomach <code>:first-child</code> and <code>:last-child</code>. :(</p>

<p>But just a teaspoon of jQuery will make that pseudo-class medicine go right down:</p>

<pre><code lang='javascript'>function firstLast()
{
  $('ul li:first-child').addClass('first');
  $('ul li:last-child').addClass('last');
}
jQuery(firstLast);
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/pseudo-pseudo-classes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Git Yr Remote Set Up</title>
		<link>http://postpostmodern.com/instructional/git-yr-remote-set-up/</link>
		<comments>http://postpostmodern.com/instructional/git-yr-remote-set-up/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 01:46:02 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=323</guid>
		<description><![CDATA[Set up a remote git repo and git user on Ubuntu.]]></description>
			<content:encoded><![CDATA[<h2>Last week&#8230;</h2>

<dl>
<dt>Jason</dt>
<dd>I started using Unfuddle for <em>[redacted]</em></dd>

<dd>I like it so far.</dd>

<dt><a href="http://treypiepmeier.com">Trey</a></dt>
<dd>it&#8217;s a good service</dd>

<dd>I&#8217;m going to move all my private repos there</dd>

<dt>Jason</dt>
<dd>if you just want online repo storage, why not just use your Slice?</dd>

<dt><a href="http://treypiepmeier.com">Trey</a></dt>
<dd>I should do that</dd>

<dt>Jason</dt>
<dd>It&#8217;s super easy</dd>

<dt><a href="http://treypiepmeier.com">Trey</a></dt>
<dd>yeah?</dd>

<dd>you should blog it</dd>

<dt>Jason</dt>
<dd>ok.</dd>
</dl>

<h2>So here is how to get your remote git up and go</h2>

<h3>Setting up a remote Git repo and connecting via ssh in a nutshell:</h3>

<p>First, we install git on the server. I&#8217;m using aptitude on Ubuntu for this. Next, we have two options: we can just set up a bare git repo and push to it using an existing user; or, if we want to be able to safely share the repo with others, we can set up a git user. After setting up the git user, we create the bare git repo, chown it to the git user, and push to it from our local machine.</p>

<h3>On your slice&#8230;</h3>

<ol>
<li><p>Install Git</p>

<p><kbd class="block">sudo aptitude git-core</kbd></p></li>
<li><p>Add the Git User (If you want to use an existing user, skip to step #7.)</p>

<p><kbd class="block">sudo adduser git</kbd></p></li>
<li><p>Set up ssh key (standard procedure)</p>

<p><kbd class="block">su - git</kbd>
<kbd class="block">mkdir .ssh</kbd>
<kbd class="block">chmod 700 .ssh</kbd>
<kbd class="block">nano -w ~/.ssh/authorized_keys</kbd></p>

<p>(Yes, I use nano. What of it?)</p>

<p><em>[ paste in public key and save the file ]</em></p></li>
<li><p>Exit su</p>

<p><kbd class="block">exit</kbd></p></li>
<li><p>Give the Git User a special shell that only allows git commands</p>

<p><kbd class="block">sudo nano /etc/passwd</kbd></p>

<p><em>[ Change git&#8217;s shell from <code>/bin/sh</code> to <code>/usr/bin/git-shell</code> ]</em></p>

<p><em>[ Save /etc/passwd ]</em></p></li>
<li><p>If you have set up your sshd_config to only allow specific users, you&#8217;ll need to add git</p>

<p><kbd class="block">sudo nano /etc/ssh/sshd_config</kbd></p>

<p><em>[ Add git to AllowUsers (near the end of the file), e.g.: AllowUsers jason git ]</em></p></li>
<li><p>Reload sshd</p>

<p><kbd class="block">sudo /etc/init.d/ssh reload</kbd></p></li>
<li><p>Create a dir for your repos</p>

<p><kbd class="block">sudo mkdir /var/git</kbd></p>

<p><kbd class="block">sudo chown &#96;whoami&#96; /var/git</kbd></p></li>
<li><p>Create your first bare repo (<code>--bare</code> means no working dir; i.e. just the contents of .git)</p>

<p><kbd class="block">cd /var/git</kbd>
<kbd class="block">mkdir test.git</kbd>
<kbd class="block">cd test.git</kbd>
<kbd class="block">git --bare init</kbd>
<kbd class="block">sudo chown -R git .</kbd></p></li>
</ol>

<h3>Back on your local machine&#8230;</h3>

<ol>
<li><p>Go to there</p>

<p><kbd class="block">cd /path/to/test</kbd></p></li>
<li><p>Add your remote (just as if it were somewhere like Github)</p>

<p><kbd class="block">git remote add origin ssh://git@slice1.example.com/var/git/test.git</kbd></p></li>
<li><p>Push all your branches</p>

<p><kbd class="block">git push --all</kbd></p></li>
</ol>

<h2>N.B.</h2>

<ul>
<li>If you use something other than Ubuntu and aptitude, your git-shell may be located somewhere else. Try <kbd>which git-shell</kbd> to find it.</li>
<li>If you&#8217;ve changed your ssh port to something other than 22, you&#8217;ll need to do something like this: 
<kbd class="block">git remote add origin ssh://git@slice1.example.com:8822/var/git/test.git</kbd></li>
<li>To allow others to contribute, put their public key in <code>/home/git/.ssh/authorized_keys</code>, but remember, you can&#8217;t log in as git; so, you&#8217;ll need to edit it as root with sudo.</li>
</ul>

<p>Questions? Comments? Recommendations? Let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/git-yr-remote-set-up/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Global AJAX Cursor Change</title>
		<link>http://postpostmodern.com/instructional/global-ajax-cursor-change/</link>
		<comments>http://postpostmodern.com/instructional/global-ajax-cursor-change/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 22:08:54 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[UI]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=290</guid>
		<description><![CDATA[Two snippets to let users know when your web app is busy AJAXing.]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t know if I&#8217;ve ever mentioned this before, but in case I haven&#8217;t:</p>

<h2>Something to this effect should be used on all AJAX web pages:</h2>

<pre><code lang='javascript'>function globalAjaxCursorChange() 
{
  $("html").bind("ajaxStart", function(){
     $(this).addClass('busy');
   }).bind("ajaxStop", function(){
     $(this).removeClass('busy');
   });
}
</code></pre>

<p>Along with this CSS:</p>

<pre><code lang='css'>html.busy, html.busy * {
  cursor: wait !important;
}
</code></pre>

<p>The javascript above is jQuery, but I used to do the same type of thing back when I used Prototype.</p>

<p>Developers sometimes go to great lengths to supplement the native behavior of a system with custom &#8216;busy&#8217; indicators. And that&#8217;s great, but don&#8217;t forget what&#8217;s built-in. Users instinctively know that something&#8217;s working when they see the old hourglass/watch cursor.</p>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/global-ajax-cursor-change/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Rails Tip: Default Scope</title>
		<link>http://postpostmodern.com/instructional/rails-tip-default-scope/</link>
		<comments>http://postpostmodern.com/instructional/rails-tip-default-scope/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 16:27:30 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[named_scope]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=221</guid>
		<description><![CDATA[An easy way to designate default options for find(:all)]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve started using the <a href="http://www.railsbrain.com/api/rails-2.1.2/doc/index.html?a=M003687&#038;name=all"><strong>all</strong></a> method instead of <strong>find(:all)</strong> for fetching records – mainly because it&#8217;s shorter to type, but it&#8217;s also easy to override with a named scope. Just create a named_scope called <strong>all</strong> to set whatever default conditions and order you want. You can always use <strong>find(:all)</strong> if you want the non-scoped records.</p>

<pre><code lang="ruby">named_scope :all, { 
  :order => 'last_name',
  :conditions => 'activated_at IS NOT NULL'
}</code></pre>

<p>Thoughts, corrections and objections welcome in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/rails-tip-default-scope/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Smarter MAMP</title>
		<link>http://postpostmodern.com/instructional/a-smarter-mamp/</link>
		<comments>http://postpostmodern.com/instructional/a-smarter-mamp/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 16:08:44 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[BIND]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=170</guid>
		<description><![CDATA[Create a whole new site on your Mac just by creating a new folder thanks to BIND and Apache's dynamic virtual hosts.]]></description>
			<content:encoded><![CDATA[<p>This past weekend, I was cleaning up my ~/Sites folder, and I started thinking, &#8220;There&#8217;s got to be a better way!&#8221; And I wasn&#8217;t referring to <a href="http://www.adultswim.com/video/?episodeID=8a25c3921a8130c6011a8249afab001b">baby hammock</a>. I was talking about having to set up all those virtual hosts and whatnot. Well, a little research quickly brought me to the <em>&#8220;how did I not know this before?!&#8221;</em> point. And now, I will share it with you.</p>

<p>(Editor&#8217;s Note: <em>This article turned out to be a little longer than I expected. The whole process is really quite simple. It should only take about 10 minutes, at the most.</em>)</p>

<p>The first thing I didn&#8217;t realize is that Apache supports something called dynamic virtual hosts. That means you don&#8217;t have to create a virtual host in your conf files and restart Apache every time you want to create a new site. This is incredibly handy for development. Combine that with a real DNS server (BIND), and you have a much smarter system. I can now create a whole new site on my MacBook just by creating a new folder! Much simpler than the old way.</p>

<h2>The Old Way?</h2>

<p>To put this in context, let&#8217;s quickly review the old way. For years, I&#8217;ve developed websites on Mac OS X using the standard &#8216;MAMP&#8217; setup: Mac/Apache/MySQL/PHP. When starting a new site, the first thing I do is set up a virtual host for Apache. If you&#8217;re like me, you know this as a 4-step process:</p>

<ol>
<li><p>Create a directory for the site&#8217;s files. Something like:</p>

<p><kbd class="block">mkdir -p ~/Sites/domain.com/public</kbd></p></li>
<li><p>Create a line in /etc/hosts for the domain:</p>

<p><kbd class="block">127.0.0.1 domain.dev</kbd></p></li>
<li><p>Add a few lines to my Apache conf file to configure the virtual host:</p>

<pre><code>&lt;VirtualHost *&gt;
  ServerName domain.dev
  DocumentRoot /Users/jason/Sites/domain.com/public
&lt;/VirtualHost&gt;
</code></pre></li>
<li><p>Restart Apache:</p>

<p><kbd class="block">sudo apachectl graceful</kbd></p></li>
</ol>

<h2>The New Way!</h2>

<ol>
<li><p>Create a directory for the site&#8217;s files. Something like:</p>

<p><kbd class="block">mkdir -p ~/Sites/domain.com/public</kbd></p></li>
</ol>

<p>Done.</p>

<p>Not only that, but I also decided to set up a few TLDs to separate my sites. I use <strong>.ppm</strong> for my personal and freelance sites, <strong>.dev</strong> for my experimental stuff, and <strong>.bsi</strong> for my company work. This allows me to separate sites like so:</p>

<pre><code>Sites
|-- bsi
|   |-- this
|   |-- that
|   `-- theother
|-- dev
|   |-- experiment1
|   |-- experiment2
|   |-- youget
|   `-- thepoint
`-- ppm
    |-- postpostmodern
    `-- littlebeestudio
</code></pre>

<p>These would be:</p>

<ul>
<li>this.bsi</li>
<li>that.bsi</li>
<li>theother.bsi</li>
<li>postpostmodern.ppm</li>
<li>littlebeestudio.ppm</li>
<li>experiment1.dev</li>
<li>experiment2.dev</li>
<li>youget.dev</li>
<li>thepoint.dev</li>
</ul>

<h2>First, let&#8217;s talk about the hosts file.</h2>

<p>The first thing you need for an Apache virtual host is a unique hostname. As can be seen in step 2, above, this is usually accomplished via the /etc/hosts file. The only problem is the hosts file doesn&#8217;t support any wildcards. So, you can&#8217;t say:</p>

<pre><code>127.0.0.1    *.dev
</code></pre>

<p>Instead, you have to have this:</p>

<pre><code>127.0.0.1    postpostmodern.dev
127.0.0.1    littlebeestudio.dev
...
...
</code></pre>

<p>&#8230;and eventually, you end up with a hosts file a mile long.</p>

<h2>Enter BIND — the built-in, but inactive DNS server</h2>

<p><a href="http://en.wikipedia.org/wiki/BIND">BIND (named)</a> comes with Mac OS X. We just need to configure it and turn it on.</p>

<p><em>I should mention here that DNS server stuff falls outside of my comfort zone. I just followed a few articles (on <a href="http://www.macosxhints.com/article.php?story=2005110220352084">macosxhints</a> and <a href="http://ubuntuforums.org/showpost.php?p=2220686&#038;postcount=20">Ubuntu Forums</a>) to get this working. I&#8217;m not sure how it impacts the vulnerability of your Mac from a security standpoint.</em> All I know is that it works and provides a few advantages over the hosts file:</p>

<ul>
<li>You can set up TLDs to resolve to your local IP address. So, anything.dev and anything.test will automatically stay local.</li>
<li>Apparently, since BIND will be caching DNS info, it will make web browsing faster. I haven&#8217;t formally tested this, but if it&#8217;s true, it&#8217;s a nice bonus. It does seem a little quicker.</li>
</ul>

<h3>Setting up rndc</h3>

<p>This creates a configuration file and key for rndc, which controls named.</p>

<p>Get into sudo, and make it stick.</p>

<p><kbd class="block">sudo -s</kbd></p>

<p>Generate the conf file.</p>

<p><kbd class="block">rndc-confgen > /etc/rndc.conf</kbd></p>

<p>Copy the key to the key file.</p>

<p><kbd class="block">head -n 6 /etc/rndc.conf > /etc/rndc.key</kbd></p>

<p>Exit sudo.</p>

<p><kbd class="block">exit</kbd></p>

<h3>Creating your DNS zone files</h3>

<p>DNS zones are created via files in /var/named. Create a new file in there called dev.zone and fill it with this:</p>

<pre><code>;
; BIND data file for dev sites
;
$TTL    604800
@       IN      SOA     dev. root.dev. (
                     2008101920         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      dev.
@       IN      A       127.0.0.1
*.dev.  14400   IN      A       127.0.0.1
</code></pre>

<p>Repeat the above for each TLD you want to set up, replacing &#8216;dev&#8217; of course.</p>

<h3>Configuring named.conf</h3>

<p>Now, open /etc/named.conf. The first thing you want to do here is to show named where to get its DNS info (for the rest of the internet), i.e. forwarding servers. Let&#8217;s use OpenDNS. Add these lines in the <strong>options</strong> section of named.conf (after &#8216;directory &#8220;/var/named&#8221;;&#8217;):</p>

<pre><code>forwarders {
    208.67.222.222;
    208.67.220.220;
};
</code></pre>

<p>Now, we just need to let named know about those zone files we created a minute ago. For each of the zone files, create a section like this:</p>

<pre><code>zone "dev" IN {
  type master;
  file "dev.zone";
};
</code></pre>

<p>You&#8217;ll see where to put it. There&#8217;s a &#8216;localhost&#8217; section already there. Just put yours below that.</p>

<h3>Configuring and loading the LaunchDaemon</h3>

<p>Okay. One last thing. Tell Mac OS X to activate named. Open the LaunchDaemon plist file for named (I had to use Textmate because Property List Editor didn&#8217;t let me save a file belonging to root.):</p>

<p><kbd class="block">/System/Library/LaunchDaemons/org.isc.named.plist</kbd></p>

<p>Change &#8216;disabled&#8217; from true to false, and save the file.</p>

<p>Now, load it:</p>

<p><kbd class="block">sudo launchctl load /System/Library/LaunchDaemons/org.isc.named.plist</kbd></p>

<p>If everything went well, your DNS server should be up and running, and your personalized TLDs should resolve to your local machine. Try visiting something.dev and see if it resolves correctly. You might want to comment out all those custom lines from your /etc/hosts file too.</p>

<h2>Now for the Apache Magic!</h2>

<p>Now that the DNS stuff is out of the way, it&#8217;s just a matter of setting that magic directive in your Apache conf file. The directive is called <a href="http://httpd.apache.org/docs/2.2/mod/mod_vhost_alias.html">VirtualDocumentRoot</a>.</p>

<p>I don&#8217;t know how you have your Apache configured, but personally, I like to keep all of my custom configuration in my own file (the one in /etc/apache2/users). Here is what my /etc/apache2/users/jason.conf file looks like:</p>

<pre><code>DocumentRoot "/Users/jason/Sites/default/public/"

NameVirtualHost 127.0.0.1

&lt;VirtualHost 127.0.0.1&gt;
    VirtualDocumentRoot /Users/jason/Sites/%-1/%-2+/public
&lt;/VirtualHost&gt;
</code></pre>

<p>The DocumentRoot directive is for the default site — the site that comes up when you visit http://localhost. The NameVirtualHost should be the reverse IP for your local machine. Finally, the VirtualDocumentRoot is an interpolated path for finding your sites. &#8216;%-1&#8217; means the last part of the domain name (the TLD). &#8216;%-2+&#8217; means everything before that. So, http://example.dev/ would load files from /Users/jason/Sites/dev/example/public. If you want a different scheme, read more about <a href="http://httpd.apache.org/docs/2.2/mod/mod_vhost_alias.html#interpol">directory name interpolation on Apache&#8217;s web site</a>.</p>

<p>Now, restart Apache!</p>

<p><kbd class="block">sudo apachectl graceful</kbd></p>

<p>You should be good to go!</p>

<p>Please let me know your thoughts and corrections in the comments.</p>

<ins>

<h2>Update – 28 Oct, 2008</h2>

<p>As Brian Toth mentioned in the comments, it&#8217;s probably also necessary to add 127.0.0.1 in your DNS settings in the Network System Pref pane.</p>

</ins>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/a-smarter-mamp/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>Wheels Keep on Spinning ‘Round</title>
		<link>http://postpostmodern.com/instructional/wheels-keep-on-spinning-round/</link>
		<comments>http://postpostmodern.com/instructional/wheels-keep-on-spinning-round/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 02:37:52 +0000</pubDate>
		<dc:creator>Jason Johnson</dc:creator>
				<category><![CDATA[Instructional]]></category>
		<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Geometry]]></category>
		<category><![CDATA[Math]]></category>

		<guid isPermaLink="false">http://postpostmodern.com/?p=133</guid>
		<description><![CDATA[Spinning wheels means fun with geometry and ActionScript.]]></description>
			<content:encoded><![CDATA[<p>Yesterday, I was working on a Flash animation for a client. Part of the animation involved an automobile driving over the client&#8217;s product as a display of structural integrity. That meant spinning wheels. That meant a little fun with geometry and ActionScript.</p>

<p>I threw together some ActionScript 2 to rotate the wheels based on the movement of the vehicle. Not sure if it&#8217;s perfect, but it seemed to work okay.</p>

<p>The ActionScript to calculate the rotation of each wheel depends on two formulae:</p>

<div style="margin: 20px 0;">
<p style="text-align: center;"><a href="/wp-content/media/pythagorean_theorem.png" class="img"><img src="/wp-content/media/pythagorean_theorem.png" alt="Pythagorean Theorem" title="Pythagorean Theorem" width="133" height="23" class="size-full wp-image-152" /></a></p>
<p style="text-align: center;"> -and- </p>
<p style="text-align: center;"><a href="http://en.wikipedia.org/wiki/Circumference" class="img"><img src="/wp-content/media/circumference.png" alt="Circumference" title="Circumference" width="133" height="23" class="size-full wp-image-154" /></a></p>
</div>

<p><em>Thanks, Pythagoras and Pi.</em> <strong><em>Thorasandpi.</em></strong></p>

<p>Here is the resulting ActionScript (attached to the wheel movie clip):</p>

<pre><code lang="javascript">
onEnterFrame = function() {

    // _parent is the vehicle clip. It's what's moving.
    // Figure out its x and y coordinates relative to last time.
    dx = _parent._x - this.lastx;
    dy = _parent._y - this.lasty;

    // The sum of the square of the two sides (horiz. and vert. change)
    sum = Math.pow(dx, 2) + Math.pow(dy, 2)

    // The hypotenuse
    dist = Math.sqrt(Math.abs(sum));

    // The direction is determined by whether dx is positive or negative
    dist = dx &lt; 0 ? -1 * dist : dist;

    _rotation = _rotation + ( (360 / (_width * Math.PI) ) * dist );

    // Store the vehicle's x and y coordinates for next time.
    this.lastx = _parent._x;
    this.lasty = _parent._y;

}
</code></pre>

<p>And here is an example:</p>

<div id="wheel" style="border: solid 2px #CECCC7; width: 490px; margin: 10px auto;">This Flash animation requires Javascript and Flash 9.</div>

<script type="text/javascript" charset="utf-8">
  var so_wheel = new SWFObject("/wp-content/media/wheeltest.swf", "flash-wheel", "490", "250",  "9", "#EFEDE6");
  so_wheel.write('wheel');
</script>

<p>I&#8217;m sure this is basic stuff for most ActionScript people, but I don&#8217;t work with it that often. Sometimes I wish I did. I&#8217;ve always loved geometry, and I know there are all kinds of fun puzzles like this when you combine animation with math. Ah well&#8230; just not enough hours in the day.</p>
]]></content:encoded>
			<wfw:commentRss>http://postpostmodern.com/instructional/wheels-keep-on-spinning-round/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
