<?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>EssentialCode</title>
	<atom:link href="http://www.essentialcode.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.essentialcode.com</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Sun, 29 Jan 2012 15:22:28 +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>Automated Versioned Deployments For Flask (Or Any Python) Webapps</title>
		<link>http://www.essentialcode.com/2012/01/24/automated-versioned-deployments-for-flask-or-any-python-webapps/</link>
		<comments>http://www.essentialcode.com/2012/01/24/automated-versioned-deployments-for-flask-or-any-python-webapps/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 04:37:05 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[fabric]]></category>
		<category><![CDATA[flask]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.essentialcode.com/?p=388</guid>
		<description><![CDATA[Working at VendAsta during the day, all of the development I do is for Google App Engine. For my personal projects, however, I have been ]]></description>
			<content:encoded><![CDATA[<p>Working at VendAsta during the day, all of the development I do is for <a title="Google App Engine" href="http://appengine.google.com" target="_blank">Google App Engine</a>. For my personal projects, however, I have been developing with the <a title="Flask" href="http://flask.pocoo.org/" target="_blank">Flask</a> framework lately. Discussing the pros and cons of App Engine could fill a whole blog unto itself but the one feature I definitely miss when developing non-App Engine apps is the ease of deployment. With an App Engine app you increment a version number in your app.yaml file, call the update script and your application&#8217;s new version is uploaded to Google&#8217;s infrastructure. After that, you make the new version the default one to serve and you&#8217;re done. Even data schema changes are handled for you (though you still might need a Map-Reduce job to migrate data values). All of this can easily be rolled into a Continuous Integration system like TeamCity or Jenkins and that is exactly what we&#8217;ve done at VendAsta (with TeamCity).</p>
<p>In the non-App Engine world, things are a lot trickier and frankly, less fun. In this post I will detail how I have pulled together something almost as fun and easy as App Engine deployments for Flask apps. The secret sauce is <a title="Fabric" href="http://docs.fabfile.org/en/1.3.3/index.html" target="_blank">Fabric</a>, a python library/command-line tool for deployments and systems administration. Essentially, Fabric acts as a wrapper around the shell and, more importantly, ssh. I started out using it just for the deployment portion of my pet projects but have since used it to completely replace the ANT scripts I had been using previously. It is simpler, more powerful and doesn&#8217;t require you to use anything besides python to manage your targets. While I am using this with Flask apps specifically, there is nothing in this example which couldn&#8217;t apply to any other framework you happen to prefer using.</p>
<p>Let&#8217;s jump right into things with the actual deployment. Listing 1 contains two functions, one to pack up the files of your app (pack) and one to upload the files to the server (upload). Have a look at it and then I will step through the various pieces.</p>
<h6>Listing 1: Pack and upload methods complete.</h6>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># python imports</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> with_statement
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># fabric imports</span>
<span style="color: #ff7700;font-weight:bold;">from</span> fabric.<span style="color: black;">api</span> <span style="color: #ff7700;font-weight:bold;">import</span> local, run, <span style="color: #dc143c;">cd</span>, put, env
&nbsp;
env.<span style="color: black;">host_string</span> = <span style="color: #483d8b;">&quot;user@someserver.org&quot;</span>
env.<span style="color: black;">password</span> = <span style="color: #483d8b;">'s3kr3tz'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> pack<span style="color: black;">&#40;</span>target, version, revision, release_dir, tmp_dir=<span style="color: #483d8b;">'/tmp'</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Method to package a release for deployment
    &quot;&quot;&quot;</span>
    archive_name = <span style="color: #483d8b;">'.'</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>target, version, revision, <span style="color: #483d8b;">'tgz'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    full_archive_path = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>tmp_dir, archive_name<span style="color: black;">&#41;</span>
    local<span style="color: black;">&#40;</span><span style="color: #483d8b;">'tar czf %s -C %s .'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>full_archive_path, release_dir<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> archive_name
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> upload<span style="color: black;">&#40;</span>target, version, revision, release_dir<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Method to upload the released code to a server
    &quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># package the release for deployment</span>
    tmp_dir = <span style="color: #483d8b;">'/tmp'</span>
    archive_name = pack<span style="color: black;">&#40;</span>target, version, revision, release_dir, tmp_dir<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">cd</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'public_html'</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">dir</span> = run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ls'</span><span style="color: black;">&#41;</span>
        dir_contents = <span style="color: black;">&#91;</span>d.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> d <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\s</span>*&quot;</span>,<span style="color: #008000;">dir</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> d.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> target <span style="color: #ff7700;font-weight:bold;">in</span> dir_contents:
            run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir %s'</span> <span style="color: #66cc66;">%</span> target<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">cd</span><span style="color: black;">&#40;</span>target<span style="color: black;">&#41;</span>:
            <span style="color: #008000;">dir</span> = run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ls'</span><span style="color: black;">&#41;</span>
            dir_contents = <span style="color: black;">&#91;</span>d.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> d <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\s</span>*&quot;</span>,<span style="color: #008000;">dir</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> d.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> version <span style="color: #ff7700;font-weight:bold;">in</span> dir_contents:
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir %s'</span> <span style="color: #66cc66;">%</span> version<span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">cd</span><span style="color: black;">&#40;</span>version<span style="color: black;">&#41;</span>:
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'rm -rf *'</span><span style="color: black;">&#41;</span>
                put<span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>tmp_dir, archive_name<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'.'</span><span style="color: black;">&#41;</span>
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'tar xzf %s'</span> <span style="color: #66cc66;">%</span> archive_name<span style="color: black;">&#41;</span>
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'rm -f %s'</span> <span style="color: #66cc66;">%</span> archive_name<span style="color: black;">&#41;</span>
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mv fcgi.htaccess .htaccess'</span><span style="color: black;">&#41;</span>
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'chmod 755 index.fcgi'</span><span style="color: black;">&#41;</span>
&nbsp;
            run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'rm -f current'</span><span style="color: black;">&#41;</span>
            run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ln -s %s current'</span> <span style="color: #66cc66;">%</span> version<span style="color: black;">&#41;</span></pre>
</td>
</tr>
</table>
</div>
<p>First, let&#8217;s look at the <code>pack(target, version, revision, release_dir, tmp_dir='/tmp')</code> method, since it is relatively straight-forward. The arguments themselves are really a matter of personal preference here. I have chosen to build the archive name of the code I am releasing from the <em>target</em> I am deploying to (typically this would be &#8216;test&#8217;, &#8216;demo&#8217; or &#8216;prod&#8217; as needed), the <em>version</em> I am deploying (for test deployments I usually deploy to a version of &#8216;daily&#8217; which gets overwritten with each subsequent release and for demo and prod I use a loose interpretation of <a href="http://semver.org/">Semantic Versioning</a> with a &lt;major&gt;.&lt;minor&gt;.&lt;patch&gt; scheme) and the <em>revision</em> of the latest commit in the release. The <em>release_dir</em> argument specifies where the code to be packaged up resides and <em>tmp_dir</em> is simply the location of a temporary directory. Lines 15 and 16 of Listing 1 show the first three arguments being assembled, with the temp directory, into an archive filename. There are more sophisticated ways to package things up for distribution (such as <a href='http://pypi.python.org/pypi/distribute'>Distribute</a> which is given some attention on the <a href='http://flask.pocoo.org/docs/patterns/distribute/#distribute-deployment' title="Deploying with Distribute">Flask site</a>) but I just prefer the simplicity of gzipping everything up and then sshing the file onto the server.</p>
<p>Line 17 of listing one utilizes the Fabric method <code>local()</code> which makes it easy to run shell commands from within your python code. Here, I am simply calling tar to archive the specified release directory into an archive with the filename I just put together. Finally, the <code>pack</code> method returns the filename of the newly created archive.</p>
<p>The <code>pack</code> method is all well and good, but all it has really done is saved you from having to write a little ANT code. There is nothing in there that couldn&#8217;t have been done very easily from a traditional build script. The upload method is where the real power of Fabric starts to shine. The arguments to this method are identical to those of <code>pack</code> with the exception of the temp directory which is defined in this method. More properly, this should be defined in a properties file (the subject of another post for another day) but for this example it is fine here. Secondly, upload just calls <code>pack</code> to package up the deliverables and return the name of the archive. Listing 2 shows the first piece of <code>upload</code> that is actually interesting.</p>
<h6>Listing 2: Preparing the <em>target</em> directory</h6>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;">    <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">cd</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'public_html'</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">dir</span> = run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ls'</span><span style="color: black;">&#41;</span>
        dir_contents = <span style="color: black;">&#91;</span>d.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> d <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\s</span>*&quot;</span>,<span style="color: #008000;">dir</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> d.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> target <span style="color: #ff7700;font-weight:bold;">in</span> dir_contents:
            run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir %s'</span> <span style="color: #66cc66;">%</span> target<span style="color: black;">&#41;</span></pre>
</td>
</tr>
</table>
</div>
<p>Line 1 of Listing 2 introduces the Fabric method <code>cd</code> which does exactly what its counterpart in your shell does. This version, however, does the change directory over an ssh connection. Two important lines in Listing 1 are repeated here in Listing 3:</p>
<h6>Listing 3: SSH authentication</h6>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;">env.<span style="color: black;">host_string</span> = <span style="color: #483d8b;">&quot;user@someserver.org&quot;</span>
env.<span style="color: black;">password</span> = <span style="color: #483d8b;">'s3kr3tz'</span></pre>
</td>
</tr>
</table>
</div>
<p>These two lines specify the user and server to make an SSH connection to and the password to use for that user&#8217;s login. For a production environment using key-based authentication is recommended if not required in order to keep everything properly secured. These lines set values in Fabric&#8217;s environment that it then uses to connect to the remote server for the remainder of the operations we have ahead.</p>
<p>Jumping back to Listing 2, we can see that the script changes into the directory <em>public_html</em>. This will be the root of your deployments, whatever that path might be. This is another value that should more properly be placed in a properties file. Utilizing the python <code>with</code> statement, lines 2, 3, 4 and 5 will all execute within the context of the <em>public_html</em> directory. Line 2 performs an ls in the <em>public_html</em> directory and line 3 parses the result into a list of names. Line 4 then checks if we have a directory in <em>public_html</em> which matches the name of the target we are deploying and if not, line 5 creates it. As an example, if this was our first time deploying a demo build, this would create a <em>demo</em> directory within <em>public_html</em>.</p>
<p>Listing 4 shows the next block, which does a similar operation only this time within the target directory, checking for and creating a version subdirectory.</p>
<h6>Listing 4: Creating a directory for the version being deployed</h6>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;">        <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">cd</span><span style="color: black;">&#40;</span>target<span style="color: black;">&#41;</span>:
            <span style="color: #008000;">dir</span> = run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ls'</span><span style="color: black;">&#41;</span>
            dir_contents = <span style="color: black;">&#91;</span>d.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> d <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\s</span>*&quot;</span>,<span style="color: #008000;">dir</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> d.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> version <span style="color: #ff7700;font-weight:bold;">in</span> dir_contents:
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mkdir %s'</span> <span style="color: #66cc66;">%</span> version<span style="color: black;">&#41;</span></pre>
</td>
</tr>
</table>
</div>
<p>So, to continue our example, if we are deploying version 1.0.1 to demo, then we would now have the path <em>public_html/demo/1.0.1/</em> created. Finally, listing 5 contains the actual deployment of code to the server!</p>
<h6>Listing 5: Deploying the new version of the code</h6>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;">            <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">cd</span><span style="color: black;">&#40;</span>version<span style="color: black;">&#41;</span>:
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'rm -rf *'</span><span style="color: black;">&#41;</span>
                put<span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>tmp_dir, archive_name<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'.'</span><span style="color: black;">&#41;</span>
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'tar xzf %s'</span> <span style="color: #66cc66;">%</span> archive_name<span style="color: black;">&#41;</span>
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'rm -f %s'</span> <span style="color: #66cc66;">%</span> archive_name<span style="color: black;">&#41;</span>
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'mv fcgi.htaccess .htaccess'</span><span style="color: black;">&#41;</span>
                run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'chmod 755 index.fcgi'</span><span style="color: black;">&#41;</span></pre>
</td>
</tr>
</table>
</div>
<p>Line 1 of Listing 5 should be familiar now, it is a <code>with</code> statement to perform the following operations within our version directory. Line 2 removes any files and directories that might already exist there. This allows for deploying the same version over and over for daily builds from a Continuous Integration platform. Line 3 does the actual transfer of files utilizing the Fabric <code>put()</code> method to send our archive file to the server. Line 4 extracts the files from the archive and line 5 removes the archive afterwards. Lines 6 and 7 are needed for my webhost (HostGator) with 6 renaming the deployed .htaccess file needed to have FastCGI function properly and 7 sets the permissions as needed for the .fcgi entry script.</p>
<p>Last but not least we have the two simple lines shown in Listing 6.</p>
<h6>Listing 6: Serving up the correct version</h6>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;">            run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'rm -f current'</span><span style="color: black;">&#41;</span>
            run<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ln -s %s current'</span> <span style="color: #66cc66;">%</span> version<span style="color: black;">&#41;</span></pre>
</td>
</tr>
</table>
</div>
<p>Now that the script is ready, you can deploy your code to the server using the <code>fab</code> shell command. For a real project you&#8217;d likely have a <code>deploy</code> method which does all of your prep work and then calls the <code>upload</code> method above. For now, however, you could call upload directly, adding the <em>target</em>, <em>version</em>, <em>revision</em> and <em>release_dir</em> arguments. Arguments to fab can be done just like calling the python methods themselves, either with position arguments, named arguments or a combination. Listing 7 shows some example calls to deploy your code.</p>
<h6>Listing 7: Deploying with fab</h6>
<div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
</pre>
</td>
<td class="code">
<pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Positional arguments</span>
fab upload:demo,1.0.1,0264103894,<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>jread<span style="color: #000000; font-weight: bold;">/</span>project
&nbsp;
<span style="color: #666666; font-style: italic;"># Named arguments</span>
fab upload:<span style="color: #007800;">target</span>=demo,<span style="color: #007800;">version</span>=1.0.1,<span style="color: #007800;">revision</span>=0264103894,<span style="color: #007800;">release_dir</span>=<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>jread<span style="color: #000000; font-weight: bold;">/</span>project
&nbsp;
<span style="color: #666666; font-style: italic;"># combination</span>
fab upload:demo,1.0.1,<span style="color: #007800;">revision</span>=0264103894,<span style="color: #007800;">release_dir</span>=<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>jread<span style="color: #000000; font-weight: bold;">/</span>project</pre>
</td>
</tr>
</table>
</div>
<p>It is all well and good that we now have the new version of our code deployed to the server, but it still needs to be available via your webserver. You can&#8217;t very well have your users change all of their URLs to point to the new version subdirectory, so you need to add a little magic. In this case, I have pointed my webserver to use <em>public_html/demo/current</em> as the webroot for the demo version of my app. The two lines in Listing 6 remove an existing <em>current</em> and then create a new one which is a symlink to the newly deployed version directory. No server configurations need to be changed and certainly no DNS needs changing. If you discover a nasty bug in a new deployment, you can simply shell to your server and remake the symlink to the previous version&#8217;s directory and you have an instant rollback of the release.</p>
<p>The possibilities of this technique are actually quite limitless. Deployments could be kicked off from certain commits to your source repo. It would be fairly trivial to implement a small dashboard which gives you manual control over the symlink <em>current</em> allowing for a web interface to set the currently active version, just like in the Google App Engine admin.</p>
<p>It is worth noting that the entire script as presented in Listing 1 is only a small fraction of the full deployment script that I am using for my real projects. In fact, I have everything split into several different files for easier organization. I will be adding future posts on this subject covering things like automated versioning, resource versioning, compilation of Coffeescript or LESS files, preparing files for release and the far more complicated problem of data schema deployment.</p>
<p><strong>Update</strong> 2012-01-29: Added example of actually calling Fabric to deploy code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2012/01/24/automated-versioned-deployments-for-flask-or-any-python-webapps/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>&#8220;The last packet sent&#8221; MySQL Error Installing Jira</title>
		<link>http://www.essentialcode.com/2010/11/10/the-last-packet-sent-mysql-error-installing-jira/</link>
		<comments>http://www.essentialcode.com/2010/11/10/the-last-packet-sent-mysql-error-installing-jira/#comments</comments>
		<pubDate>Thu, 11 Nov 2010 04:31:06 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Errors]]></category>
		<category><![CDATA[Jira]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.essentialcode.com/?p=375</guid>
		<description><![CDATA[For tracking issues and bugs in my side work for Pinch Software, I use Jira by Atlassian. They offer a wonderful set of Starter Licenses ]]></description>
			<content:encoded><![CDATA[<p>For tracking issues and bugs in my side work for <a href='http://www.pinchsoft.com'>Pinch Software</a>, I use <a href='http://www.atlassian.com/software/jira/'>Jira</a> by <a href='http://www.atlassian.com/'>Atlassian</a>. They offer a wonderful set of <a href='http://www.atlassian.com/starter/'>Starter Licenses</a> which provide everything a small startup or freelancer would need to manage Agile software development.</p>
<p>Tonight I was planning on upgrading to the latest Jira release when I realized that I had never hooked the existing install up to MySQL. In light of that I decided to just do a fresh installation. During the course of this installation I ran into an error I had yet to encounter before:</p>
<blockquote><p>The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.</p></blockquote>
<p>After a good deal of poking around and Googling, I found and fixed the problem. You see, the default setup for MySQL and Jira is (if you follow Atlassian&#8217;s excellent how-tos) to connect to the MySQL server running on localhost. This works great most of the time. However, if you are like me and want your MySQL to be remote manageable from another machine on your network, you may have configured MySQL to listen on an IP (e.g. 192.168.0.40) instead of just localhost. The solution is actually quite simple.</p>
<p>Where the Atlassian docs say to put<br />
<blockquote>url=&#8221;jdbc:mysql://localhost/jiradb?useUnicode=true&amp;characterEncoding=UTF8&#8243;</p></blockquote>
<p> into your server.xml file, you&#8217;ll actually want to specify the IP address you have MySQL listening on. So, if MySQL is listening on 192.168.0.40, you&#8217;d put<br />
<blockquote>url=&#8221;jdbc:mysql://192.168.0.40/jiradb?useUnicode=true&amp;characterEncoding=UTF8&#8243;</p></blockquote>
<p> into the server.xml file.</p>
<p>Hopefully this will help anyone out there who comes across this error. As an aside, if you are interested in trying out Jira (and the rest of Atlassian&#8217;s excellent tools), I highly recommend taking on their <a href='http://confluence.atlassian.com/display/ATLAS/Here+Be+Dragons'>Dragon Quest</a>. You&#8217;ll get a tonne of excellent experience setting up their suite of tools, a working setup of said tools, and if you send them a screenshot when done, you&#8217;ll also get a free T-shirt!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2010/11/10/the-last-packet-sent-mysql-error-installing-jira/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running JSLint in Automated Build Scripts</title>
		<link>http://www.essentialcode.com/2009/05/05/running-jslint-in-automated-build-scripts/</link>
		<comments>http://www.essentialcode.com/2009/05/05/running-jslint-in-automated-build-scripts/#comments</comments>
		<pubDate>Tue, 05 May 2009 18:29:14 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[build scripts]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=224</guid>
		<description><![CDATA[At VendAsta we use automated build scripts and a TeamCity server for continuous integration. Whenever someone commits code to a project, a whole suite of ]]></description>
			<content:encoded><![CDATA[<p>At <a href="http://www.vendasta.com">VendAsta</a> we use automated build scripts and a <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> server for continuous integration. Whenever someone commits code to a project, a whole suite of automated build targets are run against the code base to check things like unit tests, python syntax (via pylint) and code coverage. One thing that was missing from the mix was the automated running of jslint to check the syntax of our ever-increasing corpus of JavaScript code. As it turns out, adding this to our ANT targets wasn&#8217;t all that difficult.</p>
<p>The only real difficulty you are likely to encounter in creating a JSLint target for your build scripts is that JSLint is, itself, written in JavaScript. Other helpful libraries such as JSMin or the YUICompressor from Yahoo are distributed as jar files and can be executed easily with an <code>exec</code> block with the executable set to java. With JSLint, however, you are going to need a JavaScript engine which you can execute from the command line in order to run the JSLint script to validate your JavaScript code. THis actually sounds harder than it is.</p>
<p>For our implementation, I chose to use the <a href="http://www.mozilla.org/rhino/">Rhino</a> engine since there is documented support for JSLint on it, and even a handy helper file to include in your system: <a href="http://www.JSLint.com/rhino/rhino.js">rhino.js</a>. Grab a copy of Rhino (the actual file you&#8217;ll want to include is js.jar), the Rhino helper script I just mentioned and <a href="http://www.JSLint.com/fulljslint.js">JSLint itself</a>. Place them all together into some sort of tools directory in your project. Ours is located in /tools/ant.</p>
<p>Now comes the fun part, writing the actual target in ANT. For our purposes, we want to process all .js files contained in a particular location, as defined in a build property called <code>jsdir</code>. We also want to ignore any files that are contained in a vendor subdirectory of <code>jsdir</code>, as we should not need to worry about third-party scripts that don&#8217;t pass JSLint. Let&#8217;s get things started with our basic, empty target:</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
</pre>
</td>
<td class="code">
<pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!--</span>
<span style="color: #808080; font-style: italic;">jslint - Runs lint checks on js files</span>
<span style="color: #808080; font-style: italic;">--&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jslint&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre>
</td>
</tr>
</table>
</div>
<h5>Listing 1: The basic, empty jslint target</h5>
</p>
<p>Within the target there are two things we are going to need. First a way to reference all of the files we want to operate over and second, the actual call to run JSLint on those files. For the first requirement we&#8217;ll use a <code>pathconvert</code> tag with a nested <code>fileset</code>. The <code>pathconvert</code> will allow us to generate a space-separated list of files and stuff that into a property which we&#8217;ll call <code>jsfiles</code>. The <code>fileset</code> block will do the actual work of finding the files in question. It will operate over <code>${jsdir}</code> including all .js files and excluding all .js files in the vendor subdirectory. Listing 2 shows the <code>pathconvert</code> block added to our empty target.</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
</pre>
</td>
<td class="code">
<pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!--</span>
<span style="color: #808080; font-style: italic;">jslint - Runs lint checks on js files</span>
<span style="color: #808080; font-style: italic;">--&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jslint&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pathconvert</span> <span style="color: #000066;">pathsep</span>=<span style="color: #ff0000;">&quot; &quot;</span> <span style="color: #000066;">property</span>=<span style="color: #ff0000;">&quot;jsfiles&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${jsdir}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;**/*.js&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclude</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;vendor/**/*.js&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fileset<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pathconvert<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre>
</td>
</tr>
</table>
</div>
<h5>Listing 2: The <code>pathconvert</code> block added to our target.</h5>
</p>
<p>Finally, it is time to add the actual call to JSLint. To allow our build scripts to work for multiple projects, we have pushed as much information into properties that get defined in project-specific files as possible. The location of the Rhino jar (js.jar) is placed into the property <code>js.jar</code> and the location of the JSLint script (jslint.js) is placed into the property <code>jslint.js</code>. With those properties suitably defined elsewhere, we have the final piece of our puzzle: the <code>exec</code> block. We have the executable set to java and failonerror set to true, so that our target will appropriately fail when JSLint fails to give our code a passing grade. The final target, including the <code>exec</code> block can be seen in listing 3.</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre>
</td>
<td class="code">
<pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!--</span>
<span style="color: #808080; font-style: italic;">jslint - Runs lint checks on js files</span>
<span style="color: #808080; font-style: italic;">--&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jslint&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pathconvert</span> <span style="color: #000066;">pathsep</span>=<span style="color: #ff0000;">&quot; &quot;</span> <span style="color: #000066;">property</span>=<span style="color: #ff0000;">&quot;jsfiles&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fileset</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${jsdir}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;**/*.js&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exclude</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;vendor/**/*.js&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fileset<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pathconvert<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;exec</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${jsdir}&quot;</span> <span style="color: #000066;">executable</span>=<span style="color: #ff0000;">&quot;java&quot;</span> <span style="color: #000066;">failonerror</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;arg</span> <span style="color: #000066;">line</span>=<span style="color: #ff0000;">&quot;-jar ${js.jar} ${jslint.js} ${jsfiles}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/exec<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre>
</td>
</tr>
</table>
</div>
<h5>Listing 3: The final target.</h5>
</p>
<p>Put all together, the <code>pathconvert</code> block stuffs the list of files to work on into the property <code>${jsfiles}</code> which is then passed as an argument to the jslint.js file. The jslint.js file is itself the first argument passed to the Rhino JavaScript engine (js.jar) which is run directly by java. Running your <code>ant jslint</code> target should give you some nice feedback on the syntax of your JavaScript code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2009/05/05/running-jslint-in-automated-build-scripts/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Splitting Django Models Into Separate Files</title>
		<link>http://www.essentialcode.com/2009/01/26/splitting-django-models-into-separate-files/</link>
		<comments>http://www.essentialcode.com/2009/01/26/splitting-django-models-into-separate-files/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 04:16:38 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=182</guid>
		<description><![CDATA[A little while ago I wrote a post about getting Django unittests to work on DreamHost. The particular problem with the DreamHost setup is that ]]></description>
			<content:encoded><![CDATA[<p>A little while ago I wrote a post about <a href="http://www.essentialcode.com/2008/12/27/django-unittesting-on-dreamhost/">getting Django unittests to work on DreamHost</a>. The particular problem with the DreamHost setup is that they don&#8217;t allow you to programmatically create and drop databases and the default Django unittest behaviour is to do just that: create a brand new test db, use it and then drop it. Since I wrote that post I have begun migrating all of my domains away from DreamHost but I have still found that technique to be useful with new projects.</p>
<p>I first started using Django when I started at VendAsta and this issue didn&#8217;t creep up there because we are use Google App Engine and its DataStore on the backend instead of a traditional database. With no database there was no issue with creating/dropping anything. It was only when I started using Django on my own that I came across that problem. There was one more issue with Django that I came across only when I started doing things outside of work: Django expects all of your models to be in a single file called models.py. I hate that. A lot.</p>
<p>I did some googling about the problem and found that there were a bunch of other people who didn&#8217;t like it much either. There were a few solutions but they all involved manually mucking about with the __all__ attribute in the __init__.py file of your models directory. Sure, it works, but I don&#8217;t like having to define a model in two places to use it. Oddly enough it was in some test code at work that I found the answer.</p>
<p>For our project at VendAsta we are using the Django App Engine Helper to provide a nice easy interface to the DataStore on the backend. A part of this is a small __init__.py file which allows you to spread your tests out in multiple files. Django likes its tests to be in a single tests.py file just like it likes its models to be in models.py. The wee bit of Google code is shown in Listing 1.</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python2.4</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Copyright 2008 Google Inc.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span>
<span style="color: #808080; font-style: italic;"># you may not use this file except in compliance with the License.</span>
<span style="color: #808080; font-style: italic;"># You may obtain a copy of the License at</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;">#     http://www.apache.org/licenses/LICENSE-2.0</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Unless required by applicable law or agreed to in writing, software</span>
<span style="color: #808080; font-style: italic;"># distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span>
<span style="color: #808080; font-style: italic;"># WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span>
<span style="color: #808080; font-style: italic;"># See the License for the specific language governing permissions and</span>
<span style="color: #808080; font-style: italic;"># limitations under the License.</span>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Loads all the _test.py files into the top level of the package.
&nbsp;
This file is a hack around the fact that Django expects the tests &quot;module&quot; to
be a single tests.py file and cannot handle a tests package inside an
application.
&nbsp;
All _test.py files inside this package are imported and any classes derived
from unittest.TestCase are then referenced from this file itself so that they
appear at the top level of the tests &quot;module&quot; that Django will import.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">types</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
PACKAGE = <span style="color: #483d8b;">'appname.tests'</span>
TEST_RE = r<span style="color: #483d8b;">&quot;^.*_test.py$&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Search through every file inside this package.</span>
test_names = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
test_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span> __file__<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>test_dir<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>TEST_RE, filename<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">continue</span>
  <span style="color: #808080; font-style: italic;"># Import the test file and find all TestClass clases inside it.</span>
  test_module = <span style="color: #008000;">__import__</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s.%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>PACKAGE, filename<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>,
                           <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>,
                           filename<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>test_module<span style="color: black;">&#41;</span>:
    item = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>test_module, name<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: black;">&#40;</span><span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>item, <span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, <span style="color: #dc143c;">types</span>.<span style="color: black;">ClassType</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span>
            <span style="color: #008000;">issubclass</span><span style="color: black;">&#40;</span>item, <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
      <span style="color: #ff7700;font-weight:bold;">continue</span>
    <span style="color: #808080; font-style: italic;"># Found a test, bring into the module namespace.</span>
    <span style="color: #ff7700;font-weight:bold;">exec</span> <span style="color: #483d8b;">&quot;%s = item&quot;</span> <span style="color: #66cc66;">%</span> name
    test_names.<span style="color: black;">append</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Hide everything other than the test cases from other modules.</span>
__all__ = test_names</pre>
</td>
</tr>
</table>
</div>
<h5>Listing 1: __init__.py file from Google for a tests module</h5>
</p>
<p>Essentially what this file does is loop through all files in the same directory and for each on that matches the pattern listed on line 40 (in this case, files that end in &#8216;_test.py&#8217;) and import all of the Classes from those files that are subclasses of the TestCase class. Finally, the code on line 62 does the magic with __all__ that I wanted to avoid doing manually for my models. It was this line that caught my attention and started me wondering if this code could be used for spreading models across multiple files.</p>
<p>In order for this to work for models there are a few things that need to be changed. First of all, on line 40, the pattern should be changed to match on *.py to grab all of the python files in the directory. Then, on line 46, add<br />
<blockquote> or filename == &#8220;__init__.py&#8221;</p></blockquote>
<p> to ensure that we don&#8217;t try to import the file we are in. Finally, remove the subclass requirement from line 55, as we are just concerned with importing classes here not what they inherit from. Putting it all together results in Listing 2. Place that in the __init__.py of a directory called models and you&#8217;ll not have to manually manage the __all__ list for your models in separate files.</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python2.4</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">types</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
PACKAGE = <span style="color: #483d8b;">'my_app.models'</span>
MODEL_RE = r<span style="color: #483d8b;">&quot;^.*.py$&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Search through every file inside this package.</span>
model_names = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
model_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span> __file__<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>model_dir<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>MODEL_RE, filename<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> filename == <span style="color: #483d8b;">&quot;__init__.py&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">continue</span>
  <span style="color: #808080; font-style: italic;"># Import the model file and find all clases inside it.</span>
  model_module = <span style="color: #008000;">__import__</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s.%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>PACKAGE, filename<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>,
                           <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>,
                           filename<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>model_module<span style="color: black;">&#41;</span>:
    item = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>model_module, name<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>item, <span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, <span style="color: #dc143c;">types</span>.<span style="color: black;">ClassType</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
      <span style="color: #ff7700;font-weight:bold;">continue</span>
    <span style="color: #808080; font-style: italic;"># Found a model, bring into the module namespace.</span>
    <span style="color: #ff7700;font-weight:bold;">exec</span> <span style="color: #483d8b;">&quot;%s = item&quot;</span> <span style="color: #66cc66;">%</span> name
    model_names.<span style="color: black;">append</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Hide everything other than the classes from other modules.</span>
__all__ = model_names</pre>
</td>
</tr>
</table>
</div>
<h5>Listing 2: __init__.py file modified for a models module</h5>
</p>
<p>Now, there is one last thing that you are going to need to do in order for everything to run properly in Django. It is a very simple addition to the end of each of your classes. I have seem some people complaining about the need to do this in various forums, but honestly, if you are using any form of modern text editing application, it should only take you about 2 minutes to create a new template for a model that has the little piece of code shown in Listing 3 at the bottom of the class (replace your_app_name with your actual app name).</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        <span style="color: #483d8b;">&quot;&quot;&quot;Meta Class for your model.&quot;&quot;&quot;</span>
        app_label = <span style="color: #483d8b;">'your_app_name'</span></pre>
</td>
</tr>
</table>
</div>
<h5>Listing 3: Meta class required at the end of each model for proper functioning.</h5></p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2009/01/26/splitting-django-models-into-separate-files/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Django Unittesting on Dreamhost</title>
		<link>http://www.essentialcode.com/2008/12/27/django-unittesting-on-dreamhost/</link>
		<comments>http://www.essentialcode.com/2008/12/27/django-unittesting-on-dreamhost/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 04:56:08 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[dreamhost]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/?p=150</guid>
		<description><![CDATA[The default test behaviour for a Django site creates and then destroys a whole test database on each test run. Normally this is not a problem, but the way Dreamhost has their MySQL setup running, the commands to create and drop databases are not available outside of their administration panel. What follows is the solution I have come up with and am currently using to run Django unittests with my Dreamhost MySQL databases]]></description>
			<content:encoded><![CDATA[<p>Unit testing. It&#8217;s important. We all know that, even if we don&#8217;t practice what we preach. There was zero policy on unit testing at my last job, but now that I have started working at VendAsta, there is plenty of support for proper testing at the highest levels. Now that I am getting back into the habit of writing unit tests for my code at work I have been starting to focus on proper testing for my code at home. Combining Django and hosting with Dreamhost has proven to be a bit of a challenge.
<p>The first hurdle is actually getting a Django site running on Dreamhost. Luckily, there is this <a href="http://www.soasi.com/2008/09/django-10-on-dreamhost-with-passenger-mod_rails/">blog post</a> which details exactly how to get your site up and running on Dreamhost. I have used this method a couple of times (once modified to get a Satchmo install running) and have met with success each time.</p>
<p>Once the site is running, setting up tests poses another problem. The default test behaviour for a Django site creates and then destroys a whole test database on each test run. Normally this is not a problem, but the way Dreamhost has their MySQL setup running, the commands to create and drop databases are not available outside of their administration panel. What follows is the solution I have come up with and am currently using to run Django unittests with my Dreamhost MySQL databases.</p>
<p>First of all, it is important to understand a little about the default testing setup that Django uses. When you run the command <code>python manage.py test</code>, Django looks at the TEST_RUNNER setting to determine what to do. By default this setting points to django.test.simple.run_tests. A quick look and we can see that this is the functionality we want to alter. Specifically, lines 2 and 4 shown in listing #1 are what we need to replace.</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection
connection.<span style="color: black;">creation</span>.<span style="color: black;">create_test_db</span><span style="color: black;">&#40;</span>verbosity, autoclobber=<span style="color: #ff7700;font-weight:bold;">not</span> interactive<span style="color: black;">&#41;</span>
result = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TextTestRunner</span><span style="color: black;">&#40;</span>verbosity=verbosity<span style="color: black;">&#41;</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span>suite<span style="color: black;">&#41;</span>
connection.<span style="color: black;">creation</span>.<span style="color: black;">destroy_test_db</span><span style="color: black;">&#40;</span>old_name, verbosity<span style="color: black;">&#41;</span></pre>
</td>
</tr>
</table>
</div>
<h5>Listing 1: Excerpt from django.test.simple.run_tests</h5>
</p>
<p>It is these lines which make the calls to create and then drop the test database. The functionality needed, however, in order to work with Dreamhost&#8217;s setup, is to &#8220;flush&#8221; and existing test database both before and after the test run is complete. I have accomplished this through the creation of a method called <code>flush_test_db</code>, shown in Listing #2.</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> flush_test_db<span style="color: black;">&#40;</span>test_db<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Method to flush out the test database, removing tables, before
    and after test runs&quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection
    cursor = connection.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    current_tables =  connection.<span style="color: black;">introspection</span>.<span style="color: black;">table_names</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> table <span style="color: #ff7700;font-weight:bold;">in</span> current_tables:
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;use %s&quot;</span> <span style="color: #66cc66;">%</span> test_db<span style="color: black;">&#41;</span>
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;drop table %s&quot;</span> <span style="color: #66cc66;">%</span> table<span style="color: black;">&#41;</span></pre>
</td>
</tr>
</table>
</div>
<h5>Listing 2: New method to remove all tables from the test db</h5>
</p>
<p>With this method, we can drop all of the tables in the test db both before and after a test run. It is necessary to do both just in case something goes horribly awry during a test run and we end up with leftover data from a previous test run. With this new method, we can then create a new version of the run_tests method and place both methods into a new file. I called my file test_runner.py and placed it in a tests directory within my app. The complete test_runner.py is shown in Listing 3.</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;Override of the simple tests module from django in order to skip
database creation and use an existing db&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> get_app, get_apps
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">backends</span>.<span style="color: black;">creation</span> <span style="color: #ff7700;font-weight:bold;">import</span> TEST_DATABASE_PREFIX
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: #dc143c;">test</span> <span style="color: #ff7700;font-weight:bold;">import</span> simple
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: #dc143c;">test</span>.<span style="color: black;">utils</span> <span style="color: #ff7700;font-weight:bold;">import</span> setup_test_environment, teardown_test_environment
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span> <span style="color: #ff7700;font-weight:bold;">import</span> management
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> flush_test_db<span style="color: black;">&#40;</span>test_db<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Method to flush out the test database, removing tables, before
    and after test runs&quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> connection
    cursor = connection.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    current_tables =  connection.<span style="color: black;">introspection</span>.<span style="color: black;">table_names</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> table <span style="color: #ff7700;font-weight:bold;">in</span> current_tables:
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;use %s&quot;</span> <span style="color: #66cc66;">%</span> test_db<span style="color: black;">&#41;</span>
        cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;drop table %s&quot;</span> <span style="color: #66cc66;">%</span> table<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> run_tests<span style="color: black;">&#40;</span>test_labels, verbosity=<span style="color: #ff4500;">1</span>, interactive=<span style="color: #008000;">True</span>, extra_tests=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Replacement for the run_tests in Django.
    &quot;&quot;&quot;</span>
    setup_test_environment<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    settings.<span style="color: black;">DEBUG</span> = <span style="color: #008000;">False</span>
    suite = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestSuite</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> test_labels:
        <span style="color: #ff7700;font-weight:bold;">for</span> label <span style="color: #ff7700;font-weight:bold;">in</span> test_labels:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'.'</span> <span style="color: #ff7700;font-weight:bold;">in</span> label:
                suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_test</span><span style="color: black;">&#40;</span>label<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                app = get_app<span style="color: black;">&#40;</span>label<span style="color: black;">&#41;</span>
                suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_suite</span><span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> app <span style="color: #ff7700;font-weight:bold;">in</span> get_apps<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span>simple.<span style="color: black;">build_suite</span><span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">test</span> <span style="color: #ff7700;font-weight:bold;">in</span> extra_tests:
        suite.<span style="color: black;">addTest</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">test</span><span style="color: black;">&#41;</span>
&nbsp;
    old_name = settings.<span style="color: black;">DATABASE_NAME</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> settings.<span style="color: black;">TEST_DATABASE_NAME</span>:
        test_database_name = settings.<span style="color: black;">TEST_DATABASE_NAME</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        test_database_name = TEST_DATABASE_PREFIX + settings.<span style="color: black;">DATABASE_NAME</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#replace the normal DATABASE_NAME with the name of the test db</span>
    settings.<span style="color: black;">DATABASE_NAME</span> = test_database_name
&nbsp;
    <span style="color: #808080; font-style: italic;">#flush the test db</span>
    flush_test_db<span style="color: black;">&#40;</span>test_database_name<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;">#load the test db with models</span>
    management.<span style="color: black;">call_command</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'syncdb'</span><span style="color: black;">&#41;</span>
&nbsp;
    result = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TextTestRunner</span><span style="color: black;">&#40;</span>verbosity=verbosity<span style="color: black;">&#41;</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span>suite<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#flush the test db again</span>
    flush_test_db<span style="color: black;">&#40;</span>test_database_name<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#reset the value of DATABASE_NAME in settings</span>
    settings.<span style="color: black;">DATABASE_NAME</span> = old_name
    teardown_test_environment<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result.<span style="color: black;">failures</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result.<span style="color: black;">errors</span><span style="color: black;">&#41;</span></pre>
</td>
</tr>
</table>
</div>
<h5>Listing 3: The complete test_runner.py</h5>
</p>
<p>The final step is to point the test framework to your new test runner by placing a new line in your settings.py. The exact value will vary based on where in your project you have placed the new test runner. In this example I have placed the test_runner.py file, containing the run_tests method in the tests directory of an app called &#8216;your_app&#8217;. This is shown in listing 4.</p>
<p><div class="wp_syntax">
<table>
<tr>
<td class="line_numbers">
<pre>1
</pre>
</td>
<td class="code">
<pre class="python" style="font-family:monospace;">TEST_RUNNER = <span style="color: #483d8b;">'your_app.tests.test_runner.run_tests'</span></pre>
</td>
</tr>
</table>
</div>
<h5>Listing 4: Settings.py setting pointing the test framework towards your new test_runner</h5>
</p>
<p>Finally a few words of caveat. I have omitted any comments I am using to tell pylint to ignore certain things and I have done little in this sample code to properly handle Exceptions that might arise. Nevertheless, this should get you a good start on running unit tests in Django if you host your site with Dreamhost.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2008/12/27/django-unittesting-on-dreamhost/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Giving Back</title>
		<link>http://www.essentialcode.com/2008/11/24/giving-back/</link>
		<comments>http://www.essentialcode.com/2008/11/24/giving-back/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 14:32:56 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/2008/11/24/giving-back/</guid>
		<description><![CDATA[I have been a long time fan of open source software. Over the years I have utilized countless open source projects to accomplish large tasks ]]></description>
			<content:encoded><![CDATA[<p>I have been a long time fan of open source software. Over the years I have utilized countless open source projects to accomplish large tasks with ease for both my day job and my consulting work. Using these projects has always saved me a lot of reinventing the wheel and has made work on projects much easier.</p>
<p>For the past three and a half years, I have been working in a very heavy Microsoft shop. As a result, it was always difficult to get acceptance for open source projects at Cover-All. The more work I started doing on web projects the easier it became to bring some open source into the fold but there certainly wasn&#8217;t any interest in giving anything back to those projects we benefited from and, even if there was interest, there wouldn&#8217;t have been time to do so anyway.</p>
<p>At VendAsta, things are a lot different. Here is a company that not only embraces the use of open source projects but actually encourages everyone to give back to those projects if they make any improvements / changes to them. I absolutely love that! This has given me the opportunity to give back to my first open source project!</p>
<p>I have been doing some work on developing Facebook applications over the past few weeks. Specifically, I have been using the awesome <a href='http://code.google.com/p/pyfacebook/'>pyFacebook</a> library. This is a Python library which gives the same functionality as the Facebook-supplied PHP client library, except with the goodness of Python. A total bonus for us is the fact that the library includes functionality to work with <a href='http://code.google.com/appengine/'>Google App Engine</a>, another new technology we are using. There was a small gap in this functionality and that is where I found my opportunity. While everything was setup to work with retrieving information from Facebook in GAE (Google has disabled socket access in the version of Python available through GAE, so you need to use their urlfetch method instead of calls to httplib), the Photos.upload() method was not setup in the same manner. I needed to upload files to Facebook, so I modified the library to work the way I needed.</p>
<p>Once my mods were complete I sent them to the maintainer of the pyFacebook project and, after a few helpful suggestions from him, I had a version that he was willing to commit to the project&#8217;s svn repository: <a href='http://code.google.com/p/pyfacebook/source/detail?r=166'>http://code.google.com/p/pyfacebook/source/detail?r=166</a>. After that I was able to track down and fix an actual bug involving some infinite redirects: <a href='http://code.google.com/p/pyfacebook/source/detail?r=168'>http://code.google.com/p/pyfacebook/source/detail?r=168</a>.</p>
<p>Two very small contributions to a single project, but I am hopeful that this is only the beginning!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2008/11/24/giving-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How I Got Started in Software Development</title>
		<link>http://www.essentialcode.com/2008/09/08/how-i-got-started-in-software-development/</link>
		<comments>http://www.essentialcode.com/2008/09/08/how-i-got-started-in-software-development/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 00:14:29 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/2008/09/08/how-i-got-started-in-software-development/</guid>
		<description><![CDATA[It&#8217;s been a while since I have posted anything here, but I am always willing to step up in the face of a challenge from ]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I have posted anything here, but I am always willing to step up in the face of a challenge from across the pond! <a href='http://blog.philipstears.net/'>Philip</a> as <a href='http://blog.philipstears.net/2008/08/how-i-got-start.html'>has posted</a> to his blog a series of questions regarding how he got started in Software Development and he has challenged me, among others, to do the same. So, here goes&#8230;</p>
<ol>
<li><strong>How old were you when you started programming?</strong>
<p>Honestly, I think I got a later start at programming than a lot of the programmers I know. I guess technically, the first time I made a computer bend to my will would have been in grade 10 with some HyperCard scripting. Honestly, I don&#8217;t really consider that programming though, so I&#8217;ll have to say I first started programming in grade 11 when I was 16.</p>
</li>
<li><strong>How did you get started in programming?</strong>
<p>I got started by taking a class in high school. Not very exciting at all. I was already heavily into computers at that time, having been a huge computer gaming fan since my first computer &#8211; an 8086 with two double-density floppy drives and no hard drive at all. It was a great computer for playing Sierra adventure games and got me my first taste of the Wing Commander (even if I had to send away the high-density floppies for twice as many double-density ones and had to get used to swapping disks during dogfights). It was the games that got me interested in the computers and it was that interest that got me to take the classes in high school.</p>
<p>I&#8217;m sort of ashamed to admit that, aside from some web stuff (the only portion thereof that could remotely qualify as &#8220;programming&#8221; was a JavaScript routine to display a random &#8220;fun thing to do with monkies&#8221; on a Geocities page), within six months of finishing the last programming class in high school I didn&#8217;t do any more programming until my thrid year of University. It was then that I took a 100-level CompSci class as an elective. I was introduced to Java. I went to maybe half of the classes. It was all very easy for me and I ended up with a 94% in the class for almost zero effort. It happened at just the right time too: my Bio classes were all boring me because I had taken more advanced versions of a lot of them in BioChem. So, I made the leap, changed my major to CompSci and haven&#8217;t looked back.</p>
</li>
<li><strong>What was your first language?</strong>
<p>Ignoring the aforementioned HyperCard experience, my first real language was Pascal. Think Pascal on the Macs at school and Turbo Pascal on my computer at home.</p>
</li>
<li><strong>What was the first real program that you wrote?</strong>
<p>Well, I won&#8217;t include the first &#8220;real&#8221; program I wrote specifically for a class (a D&#038;D character sheet generator). Instead, I&#8217;ll say that the first real program I wrote was a bowling league / tournament management application, in Turbo Pascal. My parents were playing in a league at the time and one of their friends wanted a program that could track teams&#8217; progress.</p>
<p>I was even ambitious enough to make it such that you could run one season / tournament for free but if you wanted to start over it would show you a message saying that you needed to buy the program.</p>
</li>
<li><strong>What languages have you used since you started programming?</strong>
<p>Let&#8217;s see. I started with Pascal in high school and then learned Java at University. I also had to deal with C,C++,Eiffel, TCL/Tk, Prolog and Lisp before finishing my degree. I&#8217;ve worked with Perl, Python, PHP, VB6, VB.NET, and C# professionally since then. Plus a whole schwack of web technologies such as JavaScript, Flex/Actionscript and the many markups that make up the web. Oh, and a bunch of scripting languages on *nix.</p>
</li>
<li><strong>What was your first programming gig?</strong>
<p>My first real job that involved a significant amount of programming wasn&#8217;t a programming position at all. I was working for a web hosting company, doing all of the duties of a Systems/Network Administrator with little more than an intern&#8217;s pay. When my boss realized that I was actually more of a programmer than a systems guy, he got me working on rebuilding their online ordering system which had been shutdown for the better part of a year when they changed their domain name. The remainder of my time there was spent wrestling to learn Perl and re-implement the ordering system and online payment processing systems &#8211; interfacing with their domain provider&#8217;s horrible Perl API and Moneris&#8217; horrible payment processing Perl API.</p>
</li>
<li><strong>If you knew then what you know now, would you have started programming?</strong>
<p>Definitely. Hell, if I knew then what I know now I could have avoided 3 years of Biology classes and I&#8217;d have two more years&#8217; experience under my belt.</p>
</li>
<li><strong>If there is one thing you learned along the way that you would tell new developers, what would it be?</strong>
<p>Trust yourself, and your code. One of the more annoying things I have seen lately with newer developers is the tendency to ask more experienced coders to look at their code / query and tell them if it will work the way they think it will. I honestly don&#8217;t remember ever being like this, as I&#8217;ve always been the type to just try things out &#8211; but it is possible I was one of those guys. Seriously, if you don&#8217;t have the confidence in your abilities to try running code without someone looking it over first, this might not be the career for you.</p>
</li>
</ol>
<p>Taking Philip&#8217;s word for it that this is a meme (but Milhouse still is not), I&#8217;ll tag a few others I&#8217;d like to see answer these questions as well: <a href='http://manylittlethings.org/blog/'>Ralph Marchildon</a>,<a href='http://blog.sapara.com/'>James Sapara</a>, <a href='http://cst06.dyndns.org/phpBB3/'>Dustin Wasyliw</a>. I&#8217;d add Andrew Munro to the list but he thinks he&#8217;s too good for blogging.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2008/09/08/how-i-got-started-in-software-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Vista File Copy Woes</title>
		<link>http://www.essentialcode.com/2007/07/14/windows-vista-file-copy-woes/</link>
		<comments>http://www.essentialcode.com/2007/07/14/windows-vista-file-copy-woes/#comments</comments>
		<pubDate>Sun, 15 Jul 2007 03:53:01 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.ifisgeek.com/2007/07/14/windows-vista-file-copy-woes/</guid>
		<description><![CDATA[Now, I don&#8217;t know if you have come across this, but Windows Vista has an upper limit on the number of files that its Explorer ]]></description>
			<content:encoded><![CDATA[<p>Now, I don&#8217;t know if you have come across this, but Windows Vista has an upper limit on the number of files that its Explorer can copy in a single operation. I am in the process of moving a bunch of files off of one of my Linux servers &#8211; in preparation for some reload-y goodness &#8211; to my newish 500GB drive housed in my primary Windows box. A quick Google of the problem reveals several posts about Vista having a limit of 16,384 file copies in a single operation. The strange thing is, these posts all mention receiving an out-of-memory error message. In my case, all that happens is the copy dialog closes itself. That&#8217;s it. Nothing else.</p>
<p>I can&#8217;t help but wonder about this. With drive sizes ever-increasing and drive prices ever-plummeting, why would a so-called modern OS have such a low limit? Is it something that slipped through the cracks with the decision to not include WinFS in the initial release of Vista? I am also not sure about the number 16,384. I have been copying a <em>lot</em> of files today and I swear that one of those operations involved either 19K or 20K files&#8230;it is only when I try for 23K+ that it seems to misbehave. Very odd.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2007/07/14/windows-vista-file-copy-woes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Secure Logins with Challenge-Response</title>
		<link>http://www.essentialcode.com/2007/01/14/secure_logins_with_challenge_response/</link>
		<comments>http://www.essentialcode.com/2007/01/14/secure_logins_with_challenge_response/#comments</comments>
		<pubDate>Mon, 15 Jan 2007 02:12:52 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.testbed.ifisgeek.com/tutorials/secure-logins-with-challenge-response/</guid>
		<description><![CDATA[Background No matter how securely you code your site, someone with a valid password can access that which you mean to keep private. The best ]]></description>
			<content:encoded><![CDATA[<h3>Background</h3>
<p>No matter how securely you code your site, someone with a valid password can access that which you mean to keep private. The best solution is, of course, to keep any and all pages that require the input of a password protected using an SSL certificate. In reality, not all sites can afford the luxury of their own SSL certificate. Another, entirely free, method of keeping passwords from being transmitted across the web in clear text is to use a challenge-response system for logins.</p>
<p>The basic idea behind a challenge-response system is that the page requesting a password will have some extra information embedded in it &#8211; information that is unique to that particular login attempt &#8211; which is used to encode the password before it is sent across the network. In this tutorial, we&#8217;ll see how to generate this extra information, called the <em>salt</em> and how to incorporate it into a secure hash using SHA1</p>
<h3>The work upfront</h3>
<p>First of all, we&#8217;ll take a look at things on the client end of things. We will need a javascript implementation of the SHA1 algorithm. I found one as done by a guy named Chris Vaness. I am not sure where I found it, but I did maintain his copyright as requested. Grab it for your own use here: <a href="http://www.ifisgeek.com/js/sha1.js">sha1.js</a>. For CakePHP, place this file in the app/webroot/js directory. All you really need to know about this file is that it defines a function <em>sha1Hash</em> that takes one argument &#8211; the string to hash &#8211; and returns the hashed value.</p>
</p>
<p>Now we need a form for logging in to a site. The html code for a simple login is shown in snippet #1.</p>
<h4>Snippet #1: HTML code for our simplified login.</h4>
<div class="wp_syntax">
<div class="code">
<pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;error_message&quot;</span>&gt;</span>The login credentials you supplied could not be recognized. Please try again.<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span>
&nbsp;
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/admin/login&quot;</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;label&quot;</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;username&quot;</span>&gt;</span>Username:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span>
    <span style="color: #009900;">&lt;?php input<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'User/username'</span>, array<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'size'</span> <span style="color: #66cc66;">=</span>&gt;</span> 20, 'class' =&gt; 'TextField', 'id'=&gt;'username')); ?&gt;
    <span style="color: #009900;">&lt;?php tagErrorMsg<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'User/username'</span>, <span style="color: #ff0000;">'Username is required.'</span><span style="color: #66cc66;">&#41;</span>?&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;label&quot;</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;password&quot;</span>&gt;</span>Password:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span>
    <span style="color: #009900;">&lt;?php password<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'User/password'</span>, array<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'size'</span> <span style="color: #66cc66;">=</span>&gt;</span> 20, 'class' =&gt; 'TextField', 'id'=&gt;'password')); ?&gt;
    <span style="color: #009900;">&lt;?php tagErrorMsg<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'User/password'</span>, <span style="color: #ff0000;">'Password is required.'</span><span style="color: #66cc66;">&#41;</span>?&gt;</span>
    <span style="color: #009900;">&lt;?php submit<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Login'</span>, array<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'class'</span><span style="color: #66cc66;">=</span>&gt;</span>'Button'));?&gt;
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></pre>
</div>
</div>
<p>Of course, the code in Snippet #1 is just the login bits of the page, you&#8217;ll want to embed that in a full page (and hopefully pretty it up with some CSS) for production use. In our controller, we&#8217;ll need to generate the salt to embed in the page. Code for doing this is shown in Snippet #2.</p>
<h4>Snippet #2: Adding the salt in the controller.</h4>
<div class="wp_syntax">
<div class="code">
<pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> login<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
         <span style="color: #666666; font-style: italic;">//handle the login - we'll get to this later</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">//create the salt by creating an MD5 Hash of the current time</span>
        <span style="color: #000088;">$salt</span> <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//make the salt available to the view</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'special_sauce'</span><span style="color: #339933;">,</span><span style="color: #000088;">$salt</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//store the salt in the session</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">write</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'salt'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$salt</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre>
</div>
</div>
<p>As you can see, generating the salt and making it available in a variable which we can access in the view is really a trivial matter. A couple of points bear explanation. First of all, why am I using MD5 here when using SHA1 for the hashing itself? Well, this particular use of a hash is simply to generate a random assortment of characters to use as salt, therefore we can use the less secure MD5 algorithm which will run a little faster than SHA1. It really makes no difference, and is more a matter of preference than anything else. For the actual hashes, however, you should use SHA1 as it is more secure. Secondly, you may wonder why I am saving the salt in the session when I have made it available to the view (yes, I am going to be placing it in a hidden form element). The reason for this is to ensure that we use the salt generated here when we do our comparisons later on. If we were to place it in the form element and use that return to check the stored password, an attacker could simply supply the salt he wanted to use in that form element and he could bypass our security. This way, we are protected against clever people like that.</p>
<p>With our form defined and our salt available we need to write some javascript to process the user input before sending it to the server. Specifically, we are going to take the entered password, run the SHA1 algorithm on it, concatenate the resulting hash with the salt and run the algorithm on it again. Following that process we write our new password value into the password field and let the form submit. Javascript to accomplish this is shown in Snippet #3.</p>
<h4>Snippet #3: Javascript transform_login function</h4>
<div class="wp_syntax">
<div class="code">
<pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> transform_login<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> password <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'password'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">value</span><span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> salt <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'special_sauce'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">value</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> hashed_pass <span style="color: #339933;">=</span> sha1Hash<span style="color: #009900;">&#40;</span>password<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> hashed_and_salted_pass <span style="color: #339933;">=</span> hashed_pass <span style="color: #339933;">+</span> salt<span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> salted_hash_pass_hash <span style="color: #339933;">=</span> sha1Hash<span style="color: #009900;">&#40;</span>hashed_and_salted_pass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'password'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">value</span> <span style="color: #339933;">=</span> salted_hash_pass_hash<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre>
</div>
</div>
<p>This new javascript function requires that we make some changes to our login code, as shown in Snippet #4.</p>
<h4>Snippet #4: Modfied login form.</h4>
<div class="wp_syntax">
<div class="code">
<pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/sha1.js&quot;</span> <span style="color: #000066;">language</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/login.js&quot;</span> <span style="color: #000066;">language</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span>
<span style="color: #009900;">&lt;?php if <span style="color: #66cc66;">&#40;</span>$error<span style="color: #66cc66;">&#41;</span>: ?&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;error_message&quot;</span>&gt;</span>The login credentials you supplied could not be recognized. Please try again.<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span>
<span style="color: #009900;">&lt;?php endif; ?&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/admin/login&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span><span style="color: #66cc66;">&#41;</span>&gt;</span>
        <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;username&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;label&quot;</span>&gt;</span>Username:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span>
        <span style="color: #009900;">&lt;?php echo $html-&gt;</span>input('User/username', array('size' =&gt; 20, 'class' =&gt; 'TextField', 'id'=&gt;'username')); ?&gt;
        <span style="color: #009900;">&lt;?php echo $html-&gt;</span>tagErrorMsg('User/username', 'Username is required.')?&gt;
        <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;password&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;label&quot;</span>&gt;</span>Password:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span>
        <span style="color: #009900;">&lt;?php echo $html-&gt;</span>password('User/password', array('size' =&gt; 20, 'class' =&gt; 'TextField', 'id'=&gt;&quot;password&quot;)); ?&gt;
        <span style="color: #009900;">&lt;?php echo $html-&gt;</span>tagErrorMsg('User/password', 'Password is required.')?&gt;
        <span style="color: #009900;">&lt;?php echo $html-&gt;</span>submit(&quot;Login&quot;, array('class'=&gt;'Button', 'onclick'=&gt;&quot;Javascript:return transform_login();&quot;)); ?&gt;
        <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hidden&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;special_sauce&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;special_sauce&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">'&lt;?php echo $special_sauce; ?&gt;</span></span>'&gt;
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span>
<span style="color: #009900;">&lt;?php if <span style="color: #66cc66;">&#40;</span>$error<span style="color: #66cc66;">&#41;</span>: ?&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">language</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;javascript&quot;</span>&gt;</span>
        document.getElementById('password').value = &quot;&quot;;
        document.getElementById('username').value = &quot;&quot;;
    <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span>
<span style="color: #009900;">&lt;?php endif; ?&gt;</span></pre>
</div>
</div>
<p>As you can see, we have added code to include the sha1.js and login.js files which contain our sha1 functions and login function transform_login. We have also inserted our hidden value with the salt in it, called <em>special_sauce</em> here. Finally, we have added an <em>onclick</em> to the submit button to call the javascript function and transform our password. This should be everything we need on the client end of things.</p>
<h3>The login process in the controller</h3>
<p>Earlier, in Snippet #2, we passed over the code in the controller that actually handles the processing of the login. Now it is time to revisit the controller and finish off our secure login. The goal here is to replicate the actions taken in the javascript function <em>transform_login</em> and compare the results of the server-side transform and that done on the client end.</p>
<p>Since we embedded the salt in the login form using a hidden form value, that value will be available to us here in the controller. We never want to use that value, however, because we can never be sure of the source of any information coming to us from a web form. It is very easy to construct a duplicate form which submits faulty information in an attempt to gain access to a secured system. What we will do is take the password from the user&#8217;s database record and the salt stored in the session and put that information through the same transformations as we did on the client side. If the values match then we know the user entered the right password and can be granted access. Snippet #5 contains the full code of the final controller method.</p>
<h4>Snippet #5: Completed controller login code.</h4>
<div class="wp_syntax">
<div class="code">
<pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> login<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
     <span style="color: #666666; font-style: italic;">// If a has submitted form data:</span>
     <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
     <span style="color: #009900;">&#123;</span>
         <span style="color: #000088;">$someone</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">User</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">findByUsername</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'data'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'User'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'username'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
         <span style="color: #666666; font-style: italic;">//the password from the database</span>
         <span style="color: #000088;">$password</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$someone</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'User'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
         <span style="color: #666666; font-style: italic;">//the salt value from the session</span>
         <span style="color: #000088;">$salt</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">read</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'salt'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #666666; font-style: italic;">//hash the password</span>
         <span style="color: #000088;">$hashed_password</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$password</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #666666; font-style: italic;">//add the salt to the hashed password</span>
         <span style="color: #000088;">$salted_and_hashed_password</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$hashed_password</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$salt</span><span style="color: #339933;">;</span>
         <span style="color: #666666; font-style: italic;">//salt the salted and hashed password</span>
         <span style="color: #000088;">$salted_hash_pass_hash</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$salted_and_hashed_password</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
         <span style="color: #666666; font-style: italic;">//do our comparison</span>
         <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$salted_hash_pass_hash</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'data'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'User'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
         <span style="color: #009900;">&#123;</span>
              <span style="color: #666666; font-style: italic;">// This means they were the same. We can now build some basic</span>
              <span style="color: #666666; font-style: italic;">// session information to remember this user as 'logged-in'.</span>
              <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">write</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'User'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$someone</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'User'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
              <span style="color: #666666; font-style: italic;">// Now that we have them stored in a session, forward them on</span>
              <span style="color: #666666; font-style: italic;">// to a landing page for the application.</span>
              <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/logged_in/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #009900;">&#125;</span>
         <span style="color: #666666; font-style: italic;">// Else, they supplied incorrect data:</span>
         <span style="color: #b1b100;">else</span>
         <span style="color: #009900;">&#123;</span>
             <span style="color: #666666; font-style: italic;">//Remember the $error var in the view? Let's set that to true:</span>
             <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'error'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #009900;">&#125;</span>
     <span style="color: #009900;">&#125;</span>
     <span style="color: #b1b100;">else</span>
     <span style="color: #009900;">&#123;</span>
         <span style="color: #000088;">$salt</span> <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'special_sauce'</span><span style="color: #339933;">,</span><span style="color: #000088;">$salt</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">write</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'salt'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$salt</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre>
</div>
</div>
<h3>Summary and Caveats</h3>
<p>That&#8217;s really all there is to securing your logins with a challenge-response system. Of course, if you have an SSL certificate available to you, using it would be in your best interests. There is, however, nothing stopping you from using both at the same time. You can never have too much security.</p>
<p>A few words of warning, however. This is not intended to be a complete solution for your login needs. There are several aspects of a login system that have been overlooked in the name of brevity. Not the least of these are validating required fields and protecting all input fields from SQL Injection vulnerablilities. This only provides you with the means of obscuring password data in transit over public networks. I recommend that you do your research up front on a complete solution to prevent getting burned by something simple you may have overlooked.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2007/01/14/secure_logins_with_challenge_response/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing Single Table Inheritance in CakePHP</title>
		<link>http://www.essentialcode.com/2007/01/14/implementing_single_table_inheritance_in_cakephp/</link>
		<comments>http://www.essentialcode.com/2007/01/14/implementing_single_table_inheritance_in_cakephp/#comments</comments>
		<pubDate>Mon, 15 Jan 2007 02:05:05 +0000</pubDate>
		<dc:creator>Jeffery Read</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[cakePHP]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://www.testbed.ifisgeek.com/implementing-single-table-inheritance-in-cakephp/</guid>
		<description><![CDATA[Single Table Inheritance is one of the coolest features of Ruby on Rails. Unfortunately, it is one feature that has not made its way into ]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.essentialcode.com/2006/08/19/the_joys_of_single_table_inheritance/">Single Table Inheritance</a> is one of the coolest features of Ruby on Rails. Unfortunately, it is one feature that has not made its way into CakePHP. With a little bit of work, however, you can implement it for yourself. It should be noted, however, that this is by  no means a complete solution. What follows works for me in my applications but does not cover all possible scenarios. This tutorial is in the same table as my blog entries so you are seeing the methods below in action but your mileage may vary. </p>
<h4>An Example Scenario</h4>
<p>To best illustrate this method we will need an example scenario to work with. As I mentioned in my blog entry on <a href="http://www.essentialcode.com/2006/08/19/the_joys_of_single_table_inheritance/">Single Table Inheritance</a>, it is particularly helpful when creating a site like Digg. For our example, let&#8217;s consider building a site called Excavate. Our requirements are rather simple: a site for people to input links with descriptions. Once a link has been entered it will be considered an &quot;upcoming&quot; entry. Once enough members (only people who have signed up can view and excavate upcoming items) excavate an item it gets green-lighted and becomes a &quot;current&quot; entry. We will store both types of entry in one database table.</p>
<h4>The Database Bits</h4>
<p>The basic information we need for both kinds of entry is the same: a title, a description, a url, an author name, an author email address, and a created date. A current posting will also require the date which it was green-lighted to order the postings chronologically. To these required fields we will be adding a type field which will hold a reference to which object the record references, upcoming or current. Snippet 1 shows the SQL code for creating our table in MySQL.</p>
<h4>Snippet #1: SQL Code for our entries table.</h4>
<div class="wp_syntax">
<div class="code">
<pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`entries`</span> <span style="color: #66cc66;">&#40;</span>
    <span style="color: #ff0000;">`id`</span> <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">`title`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">`description`</span> text <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">`url`</span> var <span style="color: #993333; font-weight: bold;">CHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">`author_name`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">`author_email`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">`created`</span> datetime <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">`greenlit`</span> datetime <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff0000;">`type`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'BlogEntry'</span><span style="color: #66cc66;">,</span>
    <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&#41;</span>
    ENGINE<span style="color: #66cc66;">=</span>MyISAM <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>latin1;</pre>
</div>
</div>
<p>There are a few things to check with your database code to ensure that everything will function smoothly. First of all, ensure that your `created` field is called created. CakePHP will automagically handle setting this value for you when you are saving your model. Secondly, ensure that you do not set any model-specific fields to NOT NULL. If, for example, we had set the `greenlit` field to be NOT NULL we would run into troubles when saving an upcoming object, as that object has not been greenlit yet.</p>
<h4>The Models</h4>
<p>Now that we have the database table in place to hold our data it is time to write the Model classes for our two objects. We will need to add several variable to the models and override several methods from the parent class AppModel. Let&#8217;s start by looking at the Current model.</p>
<h4>Snippet #2: Class definition and variables<br />
for the Current Model.</h4>
<div class="wp_syntax">
<div class="code">
<pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> <span style="color: #990000;">Current</span> <span style="color: #000000; font-weight: bold;">extends</span> AppModel
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Current'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//single table inheritance vars</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__table</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'entries'</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__fields</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Current.id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Current.title'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Current.description'</span><span style="color: #339933;">,</span>
<span style="color: #0000ff;">'Current.author_name'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Current.author_email'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Current.created'</span><span style="color: #339933;">,</span>
<span style="color: #0000ff;">'Current.greenlit'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__type_field</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'type'</span><span style="color: #339933;">;</span></pre>
</div>
</div>
<p>The first variable we need to define is $name. This is required in CakePHP if you are using PHP4 but not in PHP5. Nevertheless, we will be using it as it will make many things we are going to do much easier. Ensure that the value of this variable matches exactly the name of your class. The next variable $__table contains the name of the database table in which we are storing our objects. $__fields is an array containing a list of the fields that belong to this model. Note that each field is prefixed with the name of the class it belongs to &#8211; even though the name of the table is not Current this will work because the queries created by CakePHP will have FROM `entries` AS `Current` to make everything play nicely. Also of note is the fact that we are not specifying that the type field is a part of the model &#8211; this is because it is not. The type field determines which model a record is but we will be handling that automatically and so do not need to manipulate the field directly. Finally, we place the name of the field in which we are storing our type into the variable $__type_field.</p>
<div class="right_cutout">
<h4>Associations?</h4>
<p>What about using associations in our models? Using associations with Single Table Inheritance works the same way as it would in ordinary circumstances. Other models would reference the Current and Upcoming models as if they were regular models. For example, we might have two other models in play: Comment and Author. In Author we would have Current and Upcoming listed in the $hasMany array and in Comment we would have Current and Upcoming listed in the $belongsTo array. Within Current and Upcoming we would reference other models in the same way. The only thing to watch out for is that you specify the model name in the $__fields array. So, if we had a table of authors our Current $__fields array would contain &#8216;Author.name&#8217; if we wanted to pull in the author&#8217;s name.</p></div>
<p>With the above variables in place, we can turn our attention to the methods we need to override. Any methods which involve reading or writing records need to be modified to take our changes into account. For my particular needs, I have found that I needed to override <em>__construct, findAll, findCount, findAllThreaded</em> and <em>save</em>. <em>__construct</em> is modified to supply the tablename to the <em>__construct</em> method of AppModel and, as such, is the simplest modification we will be making. The modifications to the <em>save</em> method are a little more significant by equally easy to accomplish. All that needs doing is to add a reference to the type field and its value to the $data variable before passing it to the parent.</p>
<p>The data retrieval methods <em>findAll, findCount</em> and <em>findAllThreaded</em> require a little more work than the fields detailed above. There are two things that need to be done here: modify the conditions to include a reference to the value of the type field and check for the fields being queried. The latter requires a little more explanation. Since we are storing the information for both objects in one table there are certain fields which belong to one model but not to the other. We need to make sure that we are only grabbing the fields that belong to the model in question. In our example, we need to check that we are not querying the greenlit field if we are querying for an Upcoming model. If the fields are not being queried specifically and $fields is null, then we will substitute our $__fields array for $fields to only return that which belongs to this model. Snippet #3 contains the completed code for our Current model.</p>
<h4>Snippet #3: Complete definition for the Current Model.</h4>
<div class="wp_syntax">
<div class="code">
<pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> <span style="color: #990000;">Current</span> <span style="color: #000000; font-weight: bold;">extends</span> AppModel
<span style="color: #009900;">&#123;</span>
     <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Current'</span><span style="color: #339933;">;</span>
&nbsp;
     <span style="color: #666666; font-style: italic;">//single table inheritance vars</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__table</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'entries'</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__fields</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Current.id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Current.title'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Current.description'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Current.author_name'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Current.author_email'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Current.created'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Current.greenlit'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__type_field</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'type'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><span style="color: #000088;">$ignore_table</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ds</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$table</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__table<span style="color: #339933;">;</span>
        parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #339933;">,</span><span style="color: #000088;">$table</span><span style="color: #339933;">,</span><span style="color: #000088;">$ds</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> findAll<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$order</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$limit</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #000088;">$recursive</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$conditions</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; AND &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__fields<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #b1b100;">AS</span> <span style="color: #000088;">$field</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__fields<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Field &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$field</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; does not exist in Model &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
         <span style="color: #009900;">&#125;</span>
&nbsp;
         <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">findAll</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fields</span><span style="color: #339933;">,</span> <span style="color: #000088;">$order</span><span style="color: #339933;">,</span> <span style="color: #000088;">$limit</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #339933;">,</span> <span style="color: #000088;">$recursive</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> findCount<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$recursive</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$conditions</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; AND &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">findCount</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$recursive</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> findAllThreaded<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sort</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__table <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$conditions</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; AND &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__fields<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #b1b100;">AS</span> <span style="color: #000088;">$field</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__fields<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Field &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$field</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; does not exist in Model &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">findAllThreaded</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fields</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sort</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> save<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$validate</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fieldList</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #000088;">$validate</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fieldList</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre>
</div>
</div>
<p>Snippet #4 contains the complete code for our Upcoming Model. Notice that it does not reference the greenlit field whereas the Current Model did.</p>
<h4>Snippet #4: Complete definition for the Upcoming Model.</h4>
<div class="wp_syntax">
<div class="code">
<pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Upcoming <span style="color: #000000; font-weight: bold;">extends</span> AppModel
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Upcoming'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//single table inheritance vars</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__table</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'entries'</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__fields</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Upcoming.id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Upcoming.title'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Upcoming.description'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Upcoming.author_name'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Upcoming.author_email'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Upcoming.created'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$__type_field</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'type'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span><span style="color: #000088;">$ignore_table</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span><span style="color: #000088;">$ds</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$table</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__table<span style="color: #339933;">;</span>
        parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #339933;">,</span><span style="color: #000088;">$table</span><span style="color: #339933;">,</span><span style="color: #000088;">$ds</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> findAll<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$order</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$limit</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #000088;">$recursive</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$conditions</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; AND &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__fields<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #b1b100;">AS</span> <span style="color: #000088;">$field</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__fields<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Field &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$field</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; does not exist in Model &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">findAll</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fields</span><span style="color: #339933;">,</span> <span style="color: #000088;">$order</span><span style="color: #339933;">,</span> <span style="color: #000088;">$limit</span><span style="color: #339933;">,</span> <span style="color: #000088;">$page</span><span style="color: #339933;">,</span> <span style="color: #000088;">$recursive</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> findCount<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$recursive</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$conditions</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; AND &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">findCount</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$recursive</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> findAllThreaded<span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sort</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__table <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$conditions</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$conditions</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; AND &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;.&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; = '&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;'&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #339933;">==</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__fields<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fields</span> <span style="color: #b1b100;">AS</span> <span style="color: #000088;">$field</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">array_search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__fields<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Field &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$field</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; does not exist in Model &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">findAllThreaded</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conditions</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fields</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sort</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> save<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$validate</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fieldList</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>__type_field<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #000088;">$validate</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fieldList</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre>
</div>
</div>
<p>As you can see, aside from the values of the variables at the top, these two models are nearly identical for our simple example. In a real system you would likely add other methods to your models to handle more than just the simplest of situations. An example here would be for the green-lighting process. A method in the Upcoming model which sets the value of the greenlit field and changes the type field to &#8216;Current&#8217; would effectively change the model of the record and have it show up where needed. I&#8217;ll leave that code as an exercise.</p>
<p>Given the fact that the modified methods are the same in both models, this method lends itself to scaffolding quite easily. One of these days I am going to look into modifying / extending the CakePHP script bake.php to allow for scaffolding Single Table Inheritance models. If someone has a chance to do this before I do, please drop me a line!</p>
<h4>Controllers and Views</h4>
<p>With the database table and Model classes taken care of it is time to look at the Controllers and Views. What needs to be done specially to handle the Single Table Inheritance? Nothing! This is the realy beauty of a setup like this, you make your changes at the Database and Model levels but your controllers and views are handled like they are for any other models. As far as you are concerned when writing the controllers and views, there are two database tables &#8211; one for Upcoming and one for Current &#8211; and you can handle them as you would normally.</p>
<h4>Caveats</h4>
<p>As I mentioned at the beginning of this, not every scenario will be covered by this method. Depending on your needs you may need to override more or less methods from AppModel. I am currently using this on two projects in addition to on this site. If anyone else manages to get some use out of it or if you have any questions/comments/error reports, please feel free to leave a comment below.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.essentialcode.com/2007/01/14/implementing_single_table_inheritance_in_cakephp/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

