<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Jason Leveille]]></title>
  <link href="http://jasonleveille.com/atom.xml" rel="self"/>
  <link href="http://jasonleveille.com/"/>
  <updated>2014-12-19T09:11:44-05:00</updated>
  <id>http://jasonleveille.com/</id>
  <author>
    <name><![CDATA[Jason Leveille]]></name>
    <email><![CDATA[i@leve.us]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Stop The War: Don't Hurt Each Other]]></title>
    <link href="http://jasonleveille.com/blog/2014/12/stop-the-war/"/>
    <updated>2014-12-19T08:51:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2014/12/stop-the-war</id>
    <content type="html"><![CDATA[<p>I love this bit of arts and crafts from my oldest daughter.  This&rsquo;ll bring a smile to my face for years to come. Thanks Cameron.</p>

<p><img src="http://jasonleveille.com/images/posts/war.jpg" title="Stop the War" alt="Stop the War"></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Civic Hacking with #HFCWesternMA, #hackforchange]]></title>
    <link href="http://jasonleveille.com/blog/2013/06/civic-hacking-with-hfcwesternma-hackforchange/"/>
    <updated>2013-06-03T10:07:00-04:00</updated>
    <id>http://jasonleveille.com/blog/2013/06/civic-hacking-with-hfcwesternma-hackforchange</id>
    <content type="html"><![CDATA[<p><a href="http://www.flickr.com/photos/molly_ampersand/8914863543/" title="Hanging the National Day of Civic Hacking banner by Molly Ampersand, on Flickr"><img src="http://farm4.staticflickr.com/3686/8914863543_eff66535e4_c.jpg" style="width: 100%" alt="Hanging the National Day of Civic Hacking banner"></a></p>

<p><em>Photo Courtesy of <a href="http://mollymcleod.com/">Molly McLeod</a></em></p>

<p>This past weekend ~100 hackers from all over Massachussetts (and Eliot, ME :) generously donated their time and expertise for the <a href="http://hackforchange.org/">National Day of Civic Hacking</a> event for <a href="http://hackforwesternmass.org/">Western Mass</a>.  This inspiring event was one of 95 held across the country.</p>

<blockquote><p>The event will bring together citizens, software developers, and entrepreneurs from all over the nation to collaboratively create, build, and invent new solutions using publicly-released data, code and technology to solve challenges relevant to our neighborhoods, our cities, our states and our country.</p><footer><strong>@hackforchange</strong> <cite><a href='http://hackforchange.org/page/about'>About National Day of Civic Hacking</a></cite></footer></blockquote>




<!--more-->


<h2>The Projects</h2>

<p>There were some <a href="http://hackforwesternmass.org/challenges">outstanding projects</a> at the event.  Turnout was great (~100 hackers), so each project seemed to be adequately represented.  A strong indicator of success were the presentations on Sunday.  The quality of the <a href="https://github.com/hackforwesternmass">work produced</a> was impressive.  I&rsquo;ve continued to see activity on GitHub since Sunday afternoon.  It&rsquo;s clear that the folks involved with each project care about its success, and that they&rsquo;re willing to see it through to completion.</p>

<h3>Visualizing Federal Data</h3>

<p>NPP has a great tool for <a href="http://data.nationalpriorities.org/">mapping federal data</a>.  Unfortunately, the <a href="http://data.nationalpriorities.org/mashups/l61x9apge9ovggvi/">map for the data is generated in Flash</a>.</p>

<p><img src="http://jasonleveille.com/images/posts/flash-map.jpg" title="Flash Map" alt="Flash Map"></p>

<p><em>Flash Map: Percentage of youth under age 18 estimated to be <a href="http://data.nationalpriorities.org/mashups/l61x9apge9ovggvi/">living in poverty during 2011</a>. Darker colors indicate higher percentages.</em></p>

<p>Part of our goal for 2013 is to make the main <a href="http://nationalpriorities.org">NPP site</a> more accessible and responsive to varying devices.  I&rsquo;ve been tackling bits and pieces of that goal over the past few months, and figured this event would be a great time to start getting away from flash.  With the help of <a href="http://www.gismatters.com/">Chris Duncan</a> I made some good progress toward that goal.</p>

<p><img src="http://jasonleveille.com/images/posts/d3-map-states.jpg" title="D3 States Map" alt="D3 States Map"></p>

<p><em>D3/JavaScript Map: Percentage of youth under age 18 estimated to be <a href="http://data.nationalpriorities.org/mashups/l61x9apge9ovggvi/">living in poverty during 2011</a>. Darker colors indicate higher percentages.</em></p>

<p>We allow folks to drill into a state to view data at the County level.  However, we feel that painting a picture of budget data showing all counties in the US at once may tell a more compelling story.  I have much more work to do here, however I did make some progress on that front (See: JavaScript/D3 County Map)</p>

<p><img src="http://jasonleveille.com/images/posts/d3-map-counties.jpg" title="D3 Counties Map" alt="D3 Counties Map"></p>

<p><em>D3/JavaScript County Map: Colors on this map mean nothing. They merely helped with the proof of concept.</em></p>

<p>In general, I&rsquo;m happy with what Chris and I were able to accomplish in a few days.  I had never worked with <a href="http://d3js.org">D3</a> before, which was a fun experience. I have a lot of work left to do, however this past weekend was a big push in the right direction.  Soon the NPP/Data site will be free of flash maps.</p>

<h2>An Awesome Event</h2>

<p>The event organizers deserve a big pat on the back.  The food was great (SUSHI!!!) and there were plenty of healthy choices for sustained energy.  <a href="http://www.umass.edu/">The location</a> couldn&rsquo;t have been more comfortable, and the energy throughout the weekend was really &hellip; energizing.  This was the first time I&rsquo;d attended a civic hacking event (I attended a Facebook event a few years ago) and I&rsquo;d definitely attend again.  I&rsquo;ll be eagerly anticipating this event next year.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The 10 Commandments of Logging]]></title>
    <link href="http://jasonleveille.com/blog/2013/03/the-10-commandments-of-logging/"/>
    <updated>2013-03-01T08:56:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2013/03/the-10-commandments-of-logging</id>
    <content type="html"><![CDATA[<p>Some great and practical tips for logging.</p>

<blockquote><p>When a developer writes a log message, it is in the context of the code in which the log directive is to be inserted. In those conditions we tend to write messages the infer on the current context. Unfortunately when reading the log itself this context is absent, and those messages might not be understandable.</p><footer><strong>Brice Figureau @_masterzen_</strong> <cite><a href='http://www.masterzen.fr/2013/01/13/the-10-commandments-of-logging/'>The 10 Commandments of Logging</a></cite></footer></blockquote>


<p><strong>Original Article</strong>: <a href="http://www.masterzen.fr/2013/01/13/the-10-commandments-of-logging/">The 10 Commandments of Logging</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Debian & Ubuntu: Adding a StartUp Script]]></title>
    <link href="http://jasonleveille.com/blog/2013/01/debian-ubuntu-adding-a-startup-script/"/>
    <updated>2013-01-15T07:39:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2013/01/debian-ubuntu-adding-a-startup-script</id>
    <content type="html"><![CDATA[<p>I recently had the need to run some code with each server restart.  <a href="http://manpages.ubuntu.com/manpages/precise/en/man8/update-rc.d.8.html">update-rc.d</a> provides a great and easy way execute your own code on server startup (in my case, Ubuntu 12.04).</p>

<!--more-->


<p>As root, create your script:</p>

<figure class='code'><figcaption><span>spaghetti.sh</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c">#!/bin/sh</span>
</span><span class='line'>mkdir /tmp/spaghetti <span class="o">&amp;&amp;</span> touch /tmp/spaghetti/meatballs.txt
</span></code></pre></td></tr></table></div></figure>


<p>Make the script executable:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>root@cameron ~ % chmod +x spaghetti.sh
</span></code></pre></td></tr></table></div></figure>


<p>Add your script to <code>/etc/init.d</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>root@cameron ~ % mv spaghetti.sh /etc/init.d
</span></code></pre></td></tr></table></div></figure>


<p>Run <code>update-rc.d</code> on the new script:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>root@cameron ~ % update-rc.d spaghetti.sh defaults
</span></code></pre></td></tr></table></div></figure>


<p>So, what is the <code>defaults</code> argument?</p>

<blockquote><p>If  defaults  is  used  then  update-rc.d  will make links to start the service in runlevels 2345 and to stop the service in runlevels 016.</p><footer><strong>Ubuntu Manuals, Installing Init Script Links,</strong> <cite><a href='http://manpages.ubuntu.com/manpages/precise/en/man8/update-rc.d.8.html'>manpages.ubuntu.com/manpages/en/&hellip;</a></cite></footer></blockquote>


<p>Here&rsquo;s a great article describing runlevels in exhausting detail:</p>

<blockquote><p>And what is a runlevel? You might assume that this refers to different levels that the system goes through during a boot up. Instead, think of the runlevel as the point at which the system is entered. Runlevel 1 is the most basic configuration (simple single user access using an text interface), while runlevel 5 is the most advanced (multi-user, networking, and a GUI front end). Runlevels 0 and 6 are used for halting and rebooting the system.</p><footer><strong>linux.com, An introduction to services, runlevels, and rc.d scripts,</strong> <cite><a href='https://www.linux.com/news/enterprise/systems-management/8116'>www.linux.com/news/enterprise/&hellip;</a></cite></footer></blockquote>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Linux: Extending a Logical Volume]]></title>
    <link href="http://jasonleveille.com/blog/2013/01/linux-extending-logical-volume/"/>
    <updated>2013-01-14T12:07:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2013/01/linux-extending-logical-volume</id>
    <content type="html"><![CDATA[<p>One of the servers I&rsquo;m working with started running out of disk space recently.  The machine is running on a Ubuntu VM in Windows, about 200 miles from my desk.  I have remote access to the VM, but I don&rsquo;t have access to the virtualization software.  After requesting a disk resize through the IT company that manages our Windows network, here&rsquo;s what I saw:</p>

<!--more-->




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>root@outlays:~# df -h
</span><span class='line'>Filesystem                Size  Used Avail Use% Mounted on
</span><span class='line'>/dev/mapper/outlays-root   14G   14G    0G 100% /
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<p>The request I made was to increase the disk space from 14G to ~40G.  That additional space doesn&rsquo;t show up, as it&rsquo;s free space on the disk (it hasn&rsquo;t yet been assigned to a volume).  Running the <code>vgdisplay</code> will show the additional space (<strong>Free  PE / Size</strong>):</p>

<figure class='code'><figcaption><span>http://linux.die.net/man/8/vgdisplay</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>root@outlays:~# vgdisplay
</span><span class='line'>  --- Volume group ---
</span><span class='line'>  VG Name               outlays
</span><span class='line'>  ...
</span><span class='line'>  VG Size               39.76 GiB
</span><span class='line'>  Free  PE / Size       6412 / 25.05 GiB
</span></code></pre></td></tr></table></div></figure>


<p>So, the disk was expanded, however I needed to assign that free space to /dev/mapper/outlays-root &hellip; I wasn&rsquo;t sure how.  A bit of Googling brought me to this article: <a href="http://www.dbvisit.com/forums/showthread.php?t=343">Extending LVM disks in Linux using VMWare virtual disks</a>.  The solution seemed to be to extend the /dev/mapper/outlays-root by the amount of freespace available in the volume group.  First, I wanted to check out the /dev/mapper/outlays-root disk:</p>

<figure class='code'><figcaption><span>http://linux.die.net/man/8/parted</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>root@outlays:~# parted
</span><span class='line'><span class="o">(</span>parted<span class="o">)</span> print all
</span><span class='line'>...
</span><span class='line'>Model: Linux device-mapper <span class="o">(</span>linear<span class="o">)</span> <span class="o">(</span>dm<span class="o">)</span>
</span><span class='line'>Disk /dev/mapper/outlays-root: 14GB
</span><span class='line'>Sector size <span class="o">(</span>logical/physical<span class="o">)</span>: 512B/512B
</span><span class='line'>Partition Table: loop
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<p>And running the <code>lvdisplay</code> command shows the following:</p>

<figure class='code'><figcaption><span>http://linux.die.net/man/8/lvdisplay</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>root@outlays:~# lvdisplay
</span><span class='line'>  --- Logical volume ---
</span><span class='line'>  LV Name                /dev/outlays/root
</span><span class='line'>  VG Name                outlays
</span><span class='line'>  ...
</span><span class='line'>  LV Size                14 GiB
</span></code></pre></td></tr></table></div></figure>


<p>So, the assumption I made here was the /dev/mapper/outlays-root maps to /dev/outlays/root.  Alright, I needed to expand /dev/outlays/root.  Expanding the disk was as simple as running the following commands:</p>

<figure class='code'><figcaption><span>http://linux.die.net/man/8/lvextend</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>lvextend -L+25G /dev/outlays/root
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span>http://linux.die.net/man/8/resize2fs</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>resize2fs /dev/outlays/root
</span></code></pre></td></tr></table></div></figure>


<p>Now, here&rsquo;s the amount of disk space I have:</p>

<figure class='code'><figcaption><span>http://linux.die.net/man/8/resize2fs</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>root@outlays:~# df -h
</span><span class='line'>Filesystem                Size  Used Avail Use% Mounted on
</span><span class='line'>/dev/mapper/outlays-root   39G  8.7G   28G  24% /
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<p>Much better.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Django TwitterCard Released]]></title>
    <link href="http://jasonleveille.com/blog/2013/01/django-twittercard-released/"/>
    <updated>2013-01-14T08:42:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2013/01/django-twittercard-released</id>
    <content type="html"><![CDATA[<p>I recently pushed a <a href="http://jasonleveille.com/django-twittercard/">Django TwitterCard</a> to GitHub.  The project simplifies the process of working with <a href="https://dev.twitter.com/docs/cards">Twitter cards</a> in Django.</p>

<blockquote><p>Twitter cards make it possible for you to attach media experiences to Tweets that link to your content. Simply add a few lines of HTML to your webpages, and users who Tweet links to your content will have a &#8220;card&#8221; added to the Tweet that’s visible to all of their followers.</p><footer><strong>@twitterapi</strong> <cite><a href='https://dev.twitter.com/docs/cards'>dev.twitter.com/docs/cards/&hellip;</a></cite></footer></blockquote>




<!--more-->


<h2>Demonstration</h2>

<p>With a small bit of configuration, Django TwitterCard can handle the creation of the necessary meta-tags related to your card.  Here&rsquo;s a quick example:</p>

<figure class='code'><figcaption><span>settings.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">TWITTERCARD_CONFIG</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>    <span class="s">&#39;SITE&#39;</span><span class="p">:</span> <span class="s">&#39;@jleveille&#39;</span><span class="p">,</span>
</span><span class='line'>    <span class="s">&#39;CREATOR&#39;</span><span class="p">:</span> <span class="s">&#39;@jleveille&#39;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>




<div><script src='https://gist.github.com/4530272.js'></script>
<noscript><pre><code>{% load twittercard %}
&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;title&gt;Django TwitterCard Example&lt;/title&gt;
        {% twittercard_summary title=&quot;Django TwitterCard Example&quot; description=&quot;Django TwitterCard simplifies the process of working with Twitter cards in ... Django&quot; %}
    &lt;/head&gt;
    &lt;body&gt;&lt;/body&gt;
&lt;/html&gt;</code></pre></noscript></div>


<p>The resulting meta-tags follow:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;twitter:card&quot;</span> <span class="na">content=</span><span class="s">&quot;summary&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;twitter:site&quot;</span> <span class="na">content=</span><span class="s">&quot;@jleveille&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;twitter:creator&quot;</span> <span class="na">content=</span><span class="s">&quot;@jleveille&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;twitter:url&quot;</span> <span class="na">content=</span><span class="s">&quot;http://url.tld/sub/&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;twitter:title&quot;</span> <span class="na">content=</span><span class="s">&quot;Django TwitterCard Example&quot;</span><span class="nt">/&gt;</span>
</span><span class='line'><span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">&quot;twitter:description&quot;</span> <span class="na">content=</span><span class="s">&quot;Django TwitterCard simplifies the process of working with Twitter cards in ... Django&quot;</span><span class="nt">&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Download / Documentation</h2>

<ul>
<li><a href="https://github.com/leveille/django-twittercard">https://github.com/leveille/django-twittercard</a></li>
<li><a href="http://jasonleveille.com/django-twittercard/">http://jasonleveille.com/django-twittercard/</a></li>
<li><a href="http://davidwalsh.name/twitter-cards">http://davidwalsh.name/twitter-cards</a></li>
</ul>


<h2>Twitter Cards and the Open Graph</h2>

<p>It&rsquo;s important to note the relationship between Twitter cards and the Open Graph:</p>

<blockquote><p>If you&#8217;re already using OpenGraph to describe data on your page, it’s easy to generate a Twitter card without duplicating your tags and data. When the Twitter card processor looks for tags on your page, it first checks for the Twitter property, and if not present, falls back to the supported Open Graph property</p><footer><strong>@twitterapi</strong> <cite><a href='https://dev.twitter.com/docs/cards#open-graph'>dev.twitter.com/docs/&hellip;</a></cite></footer></blockquote>


<p>If you&rsquo;re already using the following tags in the Open Graph, they won&rsquo;t be necessary in your Twitter card tags:</p>

<ol>
<li><code>og:url</code></li>
<li><code>og:description</code></li>
<li><code>og:title</code></li>
<li><code>og:image</code></li>
<li><code>og:image:width</code></li>
<li><code>og:image:height</code></li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Giving Your Images an Extra Squeeze]]></title>
    <link href="http://jasonleveille.com/blog/2013/01/giving-your-images-an-extra-squeeze/"/>
    <updated>2013-01-04T16:45:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2013/01/giving-your-images-an-extra-squeeze</id>
    <content type="html"><![CDATA[<p>Images are the main contender when it comes to page weight.</p>

<blockquote><p>According to the latest HTTP archive stats, the average Web page weighs 1286KB, and 60% of that is image data.<br/>&#8230;<br/>Yet, when we look at the actual numbers “in the wild”, we see that few developers actually compress their images, and even for those that do, the results are not always ideal.</p><footer><strong>Yoav Weiss @yoavweiss</strong> <cite><a href='http://calendar.perfplanet.com/2012/giving-your-images-an-extra-squeeze/'>Perf Planet: Giving Your Images an Extra Squeeze</a></cite></footer></blockquote>


<p>This articles provides a range of options for optimizing any image type.  There wasn&rsquo;t much new here for me.  Perhaps most importantly, this serves as a reminder that we should all be thinking about image compression during any sort of build process.</p>

<p><strong>Original Article</strong>: <a href="http://calendar.perfplanet.com/2012/giving-your-images-an-extra-squeeze/">Giving Your Images An Extra Squeeze</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[2012 Recap, 2013 Goals]]></title>
    <link href="http://jasonleveille.com/blog/2013/01/2012-recap-2013-goals/"/>
    <updated>2013-01-02T07:30:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2013/01/2012-recap-2013-goals</id>
    <content type="html"><![CDATA[<h2>2012 Recap</h2>

<p><a href="http://www.flickr.com/photos/dhgatsby/"><img class="left" src="http://jasonleveille.com/images/posts/8333312959_9444dd2051_n.jpg" width="280" height="280" title="Photo by dhgatsby" alt="Happy New Year"></a> Of all the highlights of 2012 (there are a lot, only a fraction of which will be here), my family has been the best part of my year.  My wife is a rock and helped me through some personal struggles.  My girls (6 and 3) never fail to make me laugh.  They&rsquo;re both at such fun ages.  We spent more time this summer upta camp which was a nice change from 2011.  I&rsquo;m already looking forward to opening up camp this Spring.</p>

<!--more-->


<p>In July I biked 200 miles from Seattle, WA to Portland, OR over 2 days.  I spent the first part of the year getting ready for that ride and I really enjoyed the exercise.  I had multiple weeks where my bicycle mile count was over 100, and a few weeks where I was scratching at 200 miles.  The <a href="https://shop.cascade.org/content/events/stp-details">STP ride</a> was challenging and fun.  Most important, I got to spend a lot of time with my younger brother (though he was mostly at my back wheel).  With all of that said &hellip; I spent the last part of 2012 getting fat and sitting on my ass.  That certainly has to change in 2013.</p>

<p>I read ~10 books this year (not including technical books).  My favorite book in 2012 was <a href="http://www.amazon.com/Unbroken-World-Survival-Resilience-Redemption/dp/1400064163/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1357156649&amp;sr=1-1&amp;keywords=unbroken">Unbroken</a> by Laura Hillenbrand.  The story of Louis Zamperini is incredible.  My second favorite read was <a href="http://www.amazon.com/John-Dies-End-David-Wong/dp/1250035953/ref=sr_1_1?ie=UTF8&amp;qid=1357156544&amp;sr=8-1&amp;keywords=david+wong+john+dies+at+the+end">John Dies at the End</a> by David Wong.</p>

<h3>Professionally</h3>

<p>For the past 3 years I&rsquo;ve enjoyed working from home, especially now that I get out of the house 2-3 times a week and find different spots to flex my terminal.  Speaking of work, I worked for <a href="http://sprucemedia.com/">Spruce Media</a> until the end of September.  The ~19 months I worked for Spruce were awesome &hellip; the talent level there is crazy and the people were great.  Leaving Spruce was a difficult decision, but it was the right one for me.  The guy who looks like he&rsquo;s <a href="http://sprucemedia.com/about">all head and one shoulder</a> in this pic (Chad) has been a great friend of mine (like a brother) for a long time.  Getting to work with him was incroyable.</p>

<p>In October I started working for the <a href="http://nationalpriorities.org/">National Priorities Project</a> (NPP) and I&rsquo;m really enjoying the work.  Not only am I learning a lot about the budget process, but I&rsquo;m once again working with some great people (really high on the pre-req list for anyplace I work).  I&rsquo;m still a web developer (just in case you thought I was now an economist or something).  I spend most of my time in a terminal window wrangling servers and writing code.  I&rsquo;ve always had the desire to do work that provides greater value to society.  NPP is helping me achieve that goal.</p>

<p>This year I completed more contract work than ever before.  Most notably, I built an e-commerce and reporting solution for <a href="https://secure.winterkids.org/">WinterKids</a>.  WinterKids is a great Maine non-profit which helps children develop healthy lifelong habits through fun, outdoor winter activity.  The work itself was rewarding (it was my first time working with <a href="http://stripe.com/">Stripe</a>), however the real reward is helping the children &hellip; &lsquo;cause I believe the children are our future.</p>

<h2>2013 Goals</h2>

<p>In no particular order:</p>

<ul>
<li>Do a much better job of unplugging at night</li>
<li>Write one blog article per month</li>
<li>More Twitter</li>
<li>Get down to 180 and maintain that weight</li>
<li>Read more blog articles (and actually leave comments and take part in the discussion)</li>
<li>Start to contribute to an open source project (even if that means answering questions and getting back on IRC)</li>
<li>Create something with Node.js (maybe I&rsquo;ll actually read this book I have)</li>
<li>Exercise</li>
<li>Learn at least one new language</li>
<li>Learn to fly my remote control helicopter from the basement of my house to the attic (challenge accepted) &hellip; BTW, thanks <a href="http://newrelic.com">New Relic</a> for the free chopper!</li>
<li>Learn VIM (even though I&rsquo;ve been passively using VIM for ~5 years)</li>
<li>More TMUX</li>
<li>Read more zombie books</li>
<li>Learn more about the wine I&rsquo;m drinking</li>
</ul>


<p>SIDE NOTE: Did I ever mention that in 2010 my resolution was to go the entire year w/out eating dessert?  I made it to October 18th, when I had myself a fat ice cream with my oldest daughter.  I figured I deserved it.  If I can do that, I should be able to meet these goals.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Pairing Django and Titanium in a Desktop App]]></title>
    <link href="http://jasonleveille.com/blog/2010/02/pairing-django-and-titanium-in-a-desktop-app/"/>
    <updated>2010-02-17T21:07:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2010/02/pairing-django-and-titanium-in-a-desktop-app</id>
    <content type="html"><![CDATA[<p>Over the past four months I have been doing a lot of work in Python and Django. Naturally, while recently playing around with <a href="http://www.appcelerator.com/products/titanium-desktop-application-development/">Appcelerator Titanium Desktop</a> (which seems to have good Python support), I wanted to see how Django and Titanium would pair.</p>

<!--more-->


<h2>Assumptions</h2>

<ol>
<li><a href="http://www.appcelerator.com/products/download/">Titanium installed</a></li>
<li><a href="http://docs.djangoproject.com/en/dev/topics/install/">Django installed</a></li>
</ol>


<h2>What Worked</h2>

<p>Over the course of a few hours, I was able to accomplish the following:</p>

<ul>
<li>Django Template integration</li>
<li>Django ORM interaction</li>
<li>Titanium Database communication with the Django DB (SQLite) defined in settings.py</li>
</ul>


<h2>Links</h2>

<ul>
<li><a href="http://jasonleveille.com/assets/leveille-django-titanium-7da2c38.tar.gz">Source Files</a></li>
</ul>


<h2>Directory Layout</h2>

<p><img src="https://www.evernote.com/shard/s33/sh/06d56a74-d35e-419e-840f-13cc9ab3dc22/9e3f959c495e5f348d463c6882dd7f75/res/8d23c11d-590c-404f-a1e7-d5b3dd480110.jpg?resizeSmall&width=832"></p>

<h2>Creating the Project</h2>

<p>When a Titanium Desktop application (with Python support) is running, the Resources directory for the application is placed in the system Python path. Therefore, my first step was to place the main django directory in Resources. From there, I navigated to Resources and executed the startproject command:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ django-admin.py startproject test_project</span></code></pre></td></tr></table></div></figure>


<p>Next, I updated settings.py with information about my test database:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">os</span>
</span><span class='line'><span class="n">DATABASES</span> <span class="o">=</span><span class="p">{</span>
</span><span class='line'>    <span class="s">&#39;default&#39;</span><span class="p">:{</span>
</span><span class='line'>        <span class="s">&#39;ENGINE&#39;</span><span class="p">:</span><span class="s">&#39;django.db.backends.sqlite3&#39;</span><span class="p">,</span>
</span><span class='line'>        <span class="s">&#39;NAME&#39;</span><span class="p">:</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">)),</span><span class="s">&#39;test_project.db&#39;</span><span class="p">),</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>I made sure to include the full path to my test_project.db database, knowing that I would eventually need to refer to this path for Titanium Database support. Finally, I executed my syncdb command from within my test_project directory:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="err">$</span> <span class="o">./</span><span class="n">manage</span><span class="o">.</span><span class="n">py</span> <span class="n">syncdb</span>
</span></code></pre></td></tr></table></div></figure>


<p>When prompted, I added a superuser account for myself.</p>

<h2>Django Template Integration</h2>

<p>Template integration was pretty smooth. What follows is a scaled down version of my index.html resource, and its associated files:</p>

<p>Resources >> <strong>index.html</strong></p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">//Yes,this is all I have inmy main index.html resource</span>
</span><span class='line'><span class="o">&lt;</span><span class="nx">script</span> <span class="nx">type</span><span class="o">=</span><span class="s2">&quot;text/python&quot;</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="nx">from</span> <span class="nx">test_project</span><span class="p">.</span><span class="nx">contrib</span><span class="p">.</span><span class="nx">template</span> <span class="kr">import</span> <span class="nx">index</span>
</span><span class='line'>    <span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">index</span><span class="p">())</span>
</span><span class='line'><span class="o">&lt;</span><span class="err">/script&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Resources >> test_project >> contrib >> <strong>template.py</strong></p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
</span><span class='line'>    <span class="n">kwargs</span> <span class="o">=</span><span class="p">{</span><span class="s">&#39;foo&#39;</span><span class="p">:</span><span class="s">&#39;bar&#39;</span><span class="p">}</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">_render_template</span><span class="p">(</span><span class="s">&#39;index&#39;</span><span class="p">,</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">_render_template</span><span class="p">(</span><span class="n">template_name</span><span class="p">,</span><span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span class='line'>    <span class="kn">from</span> <span class="nn">django.templateimport</span> <span class="nn">loader</span><span class="p">,</span><span class="n">Context</span>
</span><span class='line'>    <span class="n">t</span> <span class="o">=</span> <span class="n">loader</span><span class="o">.</span><span class="n">get_template</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s">.html&#39;</span><span class="o">%</span> <span class="n">template_name</span><span class="p">)</span>
</span><span class='line'>    <span class="n">c</span> <span class="o">=</span><span class="n">Context</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">t</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Resources >> test_project >> templates >> <strong>base.html</strong>, <strong>index.html</strong></p>

<div><script src='https://gist.github.com/4440297.js'></script>
<noscript><pre><code>{% block py_imports %}{% endblock %}
&lt;!DOCTYPE html&gt;
&lt;html dir=&quot;ltr&quot; lang=&quot;en-US&quot;&gt;
    &lt;head&gt;
        &lt;title&gt;{% block title %}{% endblock %}|TitaniumTesting&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot; src=&quot;jquery-1.3.2.js&quot;&gt;&lt;/script&gt;
        {% block js %}{% endblock %}
    &lt;/head&gt;
    &lt;body&gt;
        {% block content %}{% endblock %}
    &lt;/body&gt;
&lt;/html&gt;</code></pre></noscript></div>




<div><script src='https://gist.github.com/4440303.js'></script>
<noscript><pre><code># index.html
{%extends&quot;base.html&quot;%}
{% block title %}TemplateCommunication{{ block.super}}{% endblock %}
{% block content %}
    &lt;strong&gt;Foo&lt;/strong&gt;:{{ foo }}&lt;!--Prints bar --&gt;
{% endblock %}</code></pre></noscript></div>


<h2>Database Communication</h2>

<p>Database communication also went fairly smooth (though I did get tripped up trying to find a method to use an existing SQLite db for Titanium &hellip; ultimately the following worked for me:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">Titanium</span><span class="o">.</span><span class="n">Database</span><span class="o">.</span><span class="n">openFile</span><span class="p">(</span><span class="s">&#39;/path/to/db&#39;</span><span class="p">))</span>
</span></code></pre></td></tr></table></div></figure>


<p>What follows are the code snippets which represent successful communication with the DB via Django, and via the Titanium Database API:</p>

<p>Resources >> test_project >> contrib >> <strong>db.py</strong>, <strong>user.py</strong></p>

<div><script src='https://gist.github.com/4440318.js'></script>
<noscript><pre><code># db.py
def py_get_db():
    from test_project import settings
    return settings.DATABASES['default']['NAME']
</code></pre></noscript></div>




<div><script src='https://gist.github.com/4440319.js'></script>
<noscript><pre><code># user.py
def py_update_name(username, first_name, last_name):
    from django.contrib.auth.models importUser
    user =User.objects.get(username=username)
    user.first_name = first_name
    user.last_name = last_name
    user.save()

def py_get_full_name(username):
    from django.contrib.auth.models importUser
    user =User.objects.get(username=username)
    return user.get_full_name()</code></pre></noscript></div>


<p>Resources >> test_project >> templates >> <strong>index.html</strong> (full version)</p>

<div><script src='https://gist.github.com/4440328.js'></script>
<noscript><pre><code>{%extends&quot;base.html&quot;%}

{% block title %}DatabaseCommunication{{ block.super}}{% endblock %}

{% block py_imports %}
&lt;script type=&quot;text/python&quot;&gt;             
from test_project.contrib.user import py_update_name, py_get_full_name
from test_project.contrib.db import py_get_db
&lt;/script&gt;
{% endblock %}

{% block js %}
    &lt;script&gt;
        var username = 'leveille';
        var first_name = 'Jason'
        var last_name = 'Leveille'
        
        /**
         *TellDjango to update user first/last name
         */
        py_update_name(username, first_name, last_name);
        
        $(document).ready(function(){
            /**
             *UseDjango to query the auth database
             *andreturn the user fullname
             */
            var $test_1 = $('#test_1');
            $('button', $test_1).bind('click', function(){
               $('.result', $test_1).text(py_get_full_name(username)); 
            });
            
            var $test_2 = $('#test_2');
            $('button', $test_2).bind('click', function(){
                var val = 'Empty result set';
                try {
                    var db = Titanium.Database.openFile(py_get_db());
                    var rs = db.execute(
                        &quot;SELECT first_name, last_name FROM auth_user &quot; 
                        + &quot;WHERE username = '&quot; 
                        + username 
                        + &quot;'&quot;
                    );
                    if(rs.isValidRow()){
                        val = rs.field(0) + ' ' + rs.field(1);
                    }
                } catch (err) {
                    val = err;
                } finally {
                    rs.close();
                    db.close();
                    $('.result', $test_2).text(val);
                }
            });
        });            
    &lt;/script&gt;
{% endblock %}

{% block content %}
    &lt;div id=&quot;test_1&quot;&gt;
        &lt;h1&gt;Test1&lt;/h1&gt;
        &lt;p&gt;
            &lt;button&gt;Django Query for my Full Name&lt;/button&gt;
        &lt;/p&gt;
        &lt;p&gt;
            &lt;strong&gt;Result&lt;/strong&gt;: 
        &lt;/p&gt;
    &lt;/div&gt;
    &lt;div id=&quot;test_2&quot;&gt;
        &lt;h1&gt;Test2&lt;/h1&gt;
        &lt;p&gt;
            &lt;button&gt;Titanium Query for my Full Name&lt;/button&gt;
        &lt;/p&gt;
        &lt;p&gt;
            &lt;strong&gt;Result&lt;/strong&gt;: 
        &lt;/p&gt;
    &lt;/div&gt;
    &lt;div id=&quot;test_3&quot;&gt;
        &lt;h1&gt;Test3&lt;/h1&gt;
        &lt;p&gt;
            Passing Template Variables
        &lt;/p&gt;
        &lt;p&gt;
            &lt;strong&gt;Foo&lt;/strong&gt;: {{ foo }}
        &lt;/p&gt;
    &lt;/div&gt;
{% endblock %}</code></pre></noscript></div>


<h2>The Result</h2>

<p><img src="https://www.evernote.com/shard/s33/sh/06d56a74-d35e-419e-840f-13cc9ab3dc22/9e3f959c495e5f348d463c6882dd7f75/res/bba35d6b-fa73-45f5-873b-e278c340cda5.jpg?resizeSmall&width=832"></p>

<p>If you have experience playing around with these two playfellows, feel free to share them here.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CakePHP vs Django vs Rails vs Who Cares - Make a Decision]]></title>
    <link href="http://jasonleveille.com/blog/2009/02/cakephp-vs-django-vs-rails-vs-who-cares-make-a-decision/"/>
    <updated>2009-02-11T20:54:00-05:00</updated>
    <id>http://jasonleveille.com/blog/2009/02/cakephp-vs-django-vs-rails-vs-who-cares-make-a-decision</id>
    <content type="html"><![CDATA[<p>As someone who:</p>

<ol>
<li>has made a framework choice, and developed numerous projects on that framework (<a href="http://cakephp.org/">CakePHP</a>) and,</li>
<li>is always <a href="http://www.djangoproject.com/">poking</a> <a href="http://pylonshq.com/">around</a> <a href="http://rubyonrails.org/">with</a> <a href="http://framework.zend.com/">other</a> <a href="http://codeigniter.com/">frameworks</a></li>
</ol>


<p>I am often asked about the tough choice of picking among all the great framework choices (both in and out of the PHP world).  My advice is always the same.</p>

<!--more-->


<h2>Who Cares &ndash; Make a Decision</h2>

<p>Getting stuck in <a href="http://www.google.com/search?hl=en&amp;q=which+framework+should+I+choose&amp;btnG=Google+Search&amp;aq=f&amp;oq=which+framework+should+I+choos">choice limbo</a> is bad for many reasons.  Perhaps the biggest one of all has to do with inaction.  If you are unsure which framework to choose from, chances are pretty good you’re not writing code or being as productive as you could be.  If you’re not writing code than you’re not starting the process of getting over one or more learning curves (every framework will carry a learning curve &hellip; if you choose a framework outside of a language you are familiar with, than you’ll have many learning curves to get over).</p>

<h2>Go Easy on Yourself</h2>

<p>I would recommend selecting a framework in a language that you are already familiar with.  If you are a PHP person, choose a <a href="http://www.google.com/search?hl=en&amp;q=php+frameworks&amp;btnG=Search">PHP framework</a>.  If you are a Python person, choose a <a href="http://www.google.com/search?hl=en&amp;q=python+frameworks&amp;btnG=Search">Python framework</a>.  If you are a Ruby person, choose a <a href="http://www.google.com/search?hl=en&amp;q=ruby+frameworks&amp;btnG=Search">Ruby framework</a>.  Just pick one and go with it, but don’t make the task any more difficult than it needs to be.</p>

<h2>Life After a Few Applications</h2>

<p>You won’t get anywhere with your choice unless you write a few applications with your chosen framework.  You’ll find (and this is the good part), that after you gain the confidence you can only gain by getting your hands dirty, you’ll more easily be able to transition into another framework.  Once you gain a firm grasp on the concepts of <a href="http://en.wikipedia.org/wiki/Model-view-controller">MVC</a>, it’s amazing how familiar other MVC frameworks will look.  If after a few projects you feel as though you’ve made a poor choice, choose something else.  Your new found confidence and experience should make the transition much less painful.</p>

<h2>Should you Choose a Framework</h2>

<p>If you look for them, you’ll find more <a href="http://www.google.com/search?hl=en&amp;q=frameworks+suck&amp;btnG=Search">opinions</a> <a href="http://www.sitepoint.com/blogs/2008/08/29/rasmus-lerdorf-php-frameworks-think-again/">regarding</a> frameworks than you could possibly care to read.  My personal feeling is that:</p>

<ol>
<li>unless you are writing an application that can’t afford the performance penalty that is likely to come along with any framework (perhaps &lt; .005% of applications on the Internet are in this category, and congratulations if you are working on one), <strong>or</strong></li>
<li>you are working on an application that doesn’t need a framework to begin with, <strong>or</strong></li>
<li>you shouldn’t be writing a custom application (when perhaps the best thing you can do for your client is choose a proven CMS &hellip; one that eases content management/maintenance/etc) <strong>than</strong></li>
</ol>


<p>Yes, you should choose a framework.  A good framework will help you stay organized, will remove a lot of mundane (but won’t remove the need for you to be responsible!), and will come packaged with proven, maintained, debuged, tested, cared for, etc, code.</p>

<h2>You’re Also Choosing a Community</h2>

<p>It’s not all about the code.  Though a framework won’t do your job for you, it can help you be better at your job.  Part of getting better is learning, and choosing a framework with a good community will help you learn.  Whatever you choose, either be involved or observe the community.  Admittedly, I am not very involved in the <a href="http://groups.google.com/group/cake-php">CakePHP</a> community (for many reasons &hellip; including the fact that I develop in .Net, Classic ASP, and Python).  But I am constantly observing the community.  I receive a daily digest of Google Group postings, I occasionally follow conversations on IRC, and I read ~20 blogs having something to do with CakePHP.  I follow the community even though it’s been more than 2 months since I’ve developed in CakePHP.  I’ve made a commitment to this framework and I would be doing myself a disservice by not maintaining some sort of connection to the community.</p>

<h2>Last Thoughts</h2>

<p>In case I haven’t been clear about this: JUST MAKE A CHOICE and don’t worry about it.  Just make a choice and develop a few real applications with your choice.  If you’re worried about making the wrong choice, don’t be.  If you’re asking if you should choose framework X or framework Y, than you’re wasting time.  Making a choice is liberating.  Liberate yourself and start coding.</p>

<p>Even though you are choosing a framework, never stop learning/reading the language in which the framework is written.  I sometimes code with CakePHP, however I read PHP books/blogs/magazines that have nothing to do with CakePHP.  I read programming books/blogs/magazines so that I can be a better developer.  Try to remember that you are a programmer first; you are a PHP/Python/PERL/Ruby/etc programmer second; and you are a CakePHP/Django/Rails/etc developer third.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[JavaScript Lazy Loading]]></title>
    <link href="http://jasonleveille.com/blog/2008/05/javascript-lazy-loading/"/>
    <updated>2008-05-07T20:40:00-04:00</updated>
    <id>http://jasonleveille.com/blog/2008/05/javascript-lazy-loading</id>
    <content type="html"><![CDATA[<p>I just finished a great <a href="http://www.digital-web.com/">Digital Web Magazine</a> article about improving page load times with <a href="http://www.digital-web.com/articles/improve_page_performance_with_lazy_loading/">lazy loading techniques</a>. The article (by <a href="http://www.digital-web.com/about/contributors/jakob_heuser">Jakob Heuser</a>) was very well written and described <a href="http://www.digital-web.com/extras/lazy_loading/yui_3types.html">proximity, timeout, and event</a> based lazy loading. If you continue to read you will see how I was able to reduce page load by 300+kb by implementing lazy loading.</p>

<!--more-->


<h2>What is Lazy Loading</h2>

<p>Lazy loading, <a href="http://www.martinfowler.com/eaaCatalog/lazyLoad.html">described by Martin Fowler</a> in “<a href="http://www.martinfowler.com/books.html#eaa">Patterns of Enterprise Application Architecture</a>”, is the process by which an object isn’t loaded with data until it is needed. Of course “needed” is subjective to the needs of your application (for example needed in proximity or based on an event). In the context of this article, Jakob Heuser was really talking about lazy loading JavaScript files when they are needed, as opposed to loading them on page load. The loading of the files happens via <a href="http://en.wikipedia.org/wiki/XMLHttpRequest">XHR</a> (therefore the request is subject to the browser <a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy</a>). He provides examples of <a href="http://www.gaiaonline.com/">Gaia Online</a> and <a href="http://www.zimbra.com/">Zimbra</a> who both reduced their page load by 200k+ after implementing lazy loading techniques.</p>

<h2>Lazy Loading and Me</h2>

<p>I have had a few instances over the last month or so where projects I have worked on required some form of lazy loading (<a href="http://www.martinfowler.com/eaaCatalog/lazyLoad.html">Fowler describes 4 flavors</a>).</p>

<h3>Lazy Initialization</h3>

<blockquote><p>uses a special marker value (usually null) to indicate a field isn’t loaded. Every access to the field checks the field for the marker value and if unloaded, loads it.</p><footer><strong>Martin Fowler</strong> <cite><a href='http://www.martinfowler.com/eaaCatalog/lazyLoad.html'>Lazy Load</a></cite></footer></blockquote>


<p>In my first example (original blog post &ndash; no longer accessible), I had the need to display <a href="http://www.timeanddate.com/library/abbreviations/timezones/na/est.html">EST</a>/<a href="http://www.timeanddate.com/library/abbreviations/timezones/na/edt.html">EDT</a> time via JavaScript, regardless of the location of the client. The solution of course is to pull in a timestamp from the server (whose time is in EST/EDT), and feed that to the JavaScript Date constructor. From there, all that is needed is a <a href="http://developer.mozilla.org/en/docs/DOM:window.setInterval">setInterval</a>, called every 1 second, and an increment of the timestamp variable by 1 second.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">TIME</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">milliseconds</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">return</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>        <span class="nx">construct</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>            <span class="c1">//lazy load milliseconds</span>
</span><span class='line'>            <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">milliseconds</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>                <span class="nx">$</span><span class="p">.</span><span class="nx">getJSON</span><span class="p">(</span><span class="s2">&quot;time.php&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">r</span><span class="p">){</span>
</span><span class='line'>
</span><span class='line'>                    <span class="c1">//ensure that we are getting the proper data</span>
</span><span class='line'>                    <span class="k">if</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">zone</span> <span class="o">&amp;&amp;</span> <span class="nx">r</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">timestamp</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>                       <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#time .zone&quot;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="nx">r</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">zone</span><span class="p">);</span>
</span><span class='line'>                       <span class="nx">milliseconds</span> <span class="o">=</span> <span class="nx">r</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">timestamp</span><span class="p">;</span>
</span><span class='line'>                       <span class="nx">TIME</span><span class="p">.</span><span class="nx">update</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">milliseconds</span><span class="p">));</span>
</span><span class='line'>                       <span class="nb">window</span><span class="p">.</span><span class="nx">setInterval</span><span class="p">(</span><span class="s2">&quot;TIME.construct()&quot;</span><span class="p">,</span> <span class="mi">1000</span><span class="p">);</span>
</span><span class='line'>                    <span class="p">}</span>
</span><span class='line'>                    <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                       <span class="k">return</span><span class="p">;</span>
</span><span class='line'>                    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>                <span class="p">});</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>            <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>                <span class="nx">TIME</span><span class="p">.</span><span class="nx">update</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">milliseconds</span><span class="p">));</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>        <span class="nx">update</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">time</span><span class="p">){</span>
</span><span class='line'>            <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#time .time&quot;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">toLocaleTimeString</span><span class="p">());</span>
</span><span class='line'>            <span class="nx">milliseconds</span> <span class="o">+=</span> <span class="mi">1000</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">};</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>


<p>In the case of the code above, milliseconds starts at null. In the construct method a check is performed to see if milliseconds is null or not. If it is, an XHR request is made to time.php to pull in a timestamp (measured in milliseconds). The first call to construct updates the time display, assigns a value to milliseconds, and sets up the setInterval for TIME.construct(), at a frequency of 1000 milliseconds (1 second). With the second call to TIME.construct(), because the milliseconds variable is already loaded, another XHR request is not necessary. Instead, all that is needed is a call to TIME.update(), and the construction of a new Date object. Piece of cake. So, in this instance, lazy initialization enhanced the application because it provided a means for checking whether or not an XHR request should be made to obtain a timestamp, or if a timestamp already existed.</p>

<h3>ghost</h3>

<blockquote><p>A ghost is the real object without any data. The first time you call a method the ghost loads the full data into its fields.</p><footer><strong>Martin Fowler</strong> <cite><a href='http://www.martinfowler.com/eaaCatalog/lazyLoad.html'>Lazy Load</a></cite></footer></blockquote>


<p>This second example is more along the lines of those provided in the Digital Web article, however it is even more simplified. In this case, what I actually have is a combination of ghost and lazy initialization (leaning more in the direction of lazy initialization). The application in which I implemented this bit of code required most of the UI to be constructed through JavaScript. Part of the application requires the implementation of <a href="http://get.live.com/messenger/overview">Windows Live Messanger</a> for tech support purposes. This portion of the application is not visible on page load, and is only available on request. Initially I was loading the JavaScript/CSS/Image files on page load, and the application was suffering a significant performance hit as a result. I don’t have exact numbers, but Windows Live Messanger has in excess of 300+k of JavaScript/CSS/Image files, and I was loading them (via requests for the resources through an iframe) on page load. As you can imagine, the rest of the application was suffering. It was sluggish and unresponsive for seconds at a time.</p>

<blockquote><p>Through the implementation of lazy loading (tied to a click event), I was able to do away with this initial 300+k load, and garner significant page responsiveness.</p></blockquote>


<p>The goodies:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">msnPayLoad</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="p">...</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">setupLiveMessangerChat</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">if</span><span class="p">(</span><span class="nx">config</span><span class="p">.</span><span class="nx">playerMode</span><span class="p">.</span><span class="nx">isLive</span><span class="p">)</span>
</span><span class='line'>   <span class="p">{</span>
</span><span class='line'>      <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;a#activate-chat&#39;</span><span class="p">).</span><span class="nx">toggle</span><span class="p">(</span>
</span><span class='line'>         <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>            <span class="c1">//lazy load msn javascript</span>
</span><span class='line'>            <span class="c1">//this payload is only needed if the user actually clicks on the live support link</span>
</span><span class='line'>            <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">msnPayLoad</span><span class="p">)</span>
</span><span class='line'>            <span class="p">{</span>
</span><span class='line'>               <span class="nx">msnPayLoad</span> <span class="o">=</span> <span class="nx">activateMsnJavascript</span><span class="p">;</span>
</span><span class='line'>               <span class="nx">msnPayLoad</span><span class="p">();</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>            <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#support&#39;</span><span class="p">).</span><span class="nx">show</span><span class="p">();</span>
</span><span class='line'>            <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#activate-chat&#39;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="s1">&#39;Close Live Support&#39;</span><span class="p">);</span>
</span><span class='line'>         <span class="p">},</span>
</span><span class='line'>         <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'>            <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#support&#39;</span><span class="p">).</span><span class="nx">hide</span><span class="p">();</span>
</span><span class='line'>            <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#activate-chat&#39;</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="s1">&#39;Open Live Support&#39;</span><span class="p">);</span>
</span><span class='line'>         <span class="p">}</span>
</span><span class='line'>      <span class="p">);</span>
</span><span class='line'>   <span class="p">}</span>
</span><span class='line'>   <span class="k">else</span>
</span><span class='line'>   <span class="p">{</span>
</span><span class='line'>      <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;#support&#39;</span><span class="p">).</span><span class="nx">hide</span><span class="p">();</span>
</span><span class='line'>   <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="p">...</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">activateMsnJavascript</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>   <span class="c1">//Grab the necessary scripts for live chat</span>
</span><span class='line'>   <span class="nx">$</span><span class="p">.</span><span class="nx">getScript</span><span class="p">(</span><span class="s2">&quot;http://settings.messenger.live.com/controls/1.0/PresenceButton.js&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>      <span class="nx">$</span><span class="p">.</span><span class="nx">getScript</span><span class="p">(</span><span class="s2">&quot;http://messenger.services.live.com/users/etc&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>         <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#support div.support&quot;</span><span class="p">).</span><span class="nx">load</span><span class="p">(</span><span class="s2">&quot;core/section-includes/live-messanger-chat.inc.htm?stamp=&quot;</span> <span class="o">+</span> <span class="nx">getStamp</span><span class="p">());</span>
</span><span class='line'>      <span class="p">})</span>
</span><span class='line'>   <span class="p">});</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>In the case of the above example, I have a null payload variable, which is loaded when the activate chat link is clicked the first time. During this time a call is also made to activateMsnJavascript(), and 300kb+ of files join the party.</p>

<h2>I’m so loaded man</h2>

<p>So, I hope if you’ve gotten anything from this article it is that employing lazy loading techniques doesn’t have to be hard. What it might bring to your application table is well worth the time it will take to investigate this very interesting topic.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Avectra Member Management API]]></title>
    <link href="http://jasonleveille.com/blog/2008/04/avectra-member-management-api/"/>
    <updated>2008-04-18T20:25:00-04:00</updated>
    <id>http://jasonleveille.com/blog/2008/04/avectra-member-management-api</id>
    <content type="html"><![CDATA[<p>Recently I worked on a project where all member data was being managed through a third party member management service, provided by a company named <a href="http://www.avectra.com/eweb/StartPage.aspx?site=Avectra07">Avectra</a>. The product does more than manage member data from the looks of things, but all I cared about was interaction with the member management API.</p>

<!--more-->


<p>I had to authenticate against an external data source, as well as query the data source for member information when needed. Avectra does have a web service API which it has named xWeb. Here is a quote from <a href="http://wiki.avectra.com/index.php?title=NetFORUM">their Wiki</a>:</p>

<blockquote><p>xWeb is netFORUM’s XML web services application. netFORUM is an enterprise level Association Management System (AMS) developed by Avectra that allows associations to manage their customers and related activities. netFORUM is used by association staff, members, and the public at large.</p><footer><strong>Avectra</strong> <cite><a href='http://wiki.avectra.com/index.php?title=NetFORUM'>Avectra Wiki</a></cite></footer></blockquote>


<h2>Interacting with the API</h2>

<p>After a successful authentication with Avectra, the authenticated user is presented with a token that they pass along with API requests. Pretty standard stuff. The Wiki does an ok job of explaining authentication and login (two different things), therefore I’ll jump right to the good stuff. If you’re stuck on authentication/weblogin please let me know.</p>

<p>For interacting with the API I created a class file to abstract, at least to a small degree, some of the details of consuming the service. Here it is:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'>  <span class="cm">/*</span>
</span><span class='line'><span class="cm">  * @author: Jason Leveille</span>
</span><span class='line'><span class="cm">  * Provides access to avectra web services</span>
</span><span class='line'><span class="cm">  */</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">class</span> <span class="nc">Avectra</span>
</span><span class='line'>  <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>     <span class="c1">//Avectra organization api username and password (not member username/password) to access web services</span>
</span><span class='line'>     <span class="k">private</span> <span class="nv">$user</span> <span class="o">=</span> <span class="s1">&#39;user&#39;</span><span class="p">;</span>
</span><span class='line'>     <span class="k">private</span> <span class="nv">$pass</span> <span class="o">=</span> <span class="s1">&#39;password&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>     <span class="c1">//Avectra paths to xweb and eweb.  This is handy so that you can easily switch back and fourth between dev and production</span>
</span><span class='line'>     <span class="k">private</span> <span class="nv">$xweb</span> <span class="o">=</span> <span class="s1">&#39;www.mencnet.org/xweb/&#39;</span><span class="p">;</span>
</span><span class='line'>     <span class="k">private</span> <span class="nv">$eweb</span> <span class="o">=</span> <span class="s1">&#39;https://www.mencnet.org/netforummenctest/eweb/&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>     <span class="sd">/**</span>
</span><span class='line'><span class="sd">    * Grabs data associated with a member based on customer key / token</span>
</span><span class='line'><span class="sd">    * @param $cst_key Customer Key to search on</span>
</span><span class='line'><span class="sd">    */</span>
</span><span class='line'>     <span class="k">public</span> <span class="k">function</span> <span class="nf">getMemberDataByKey</span><span class="p">(</span><span class="nv">$cst_key</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span><span class="k">empty</span><span class="p">(</span><span class="nv">$cst_key</span><span class="p">))</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>           <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$memberData</span> <span class="o">=</span> <span class="nb">sprintf</span><span class="p">(</span><span class="s1">&#39;https://%s:%s@%snetFORUMXML.asmx/GetIndividualInformation?IndividualKey=%s&#39;</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">user</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">pass</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">xweb</span><span class="p">,</span> <span class="nv">$cst_key</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">//The simplest solution is to call simplexml_load_file directly, however this was causing issues on Solaris 10, php 5.2.  Didn&#39;t have time to investigate, so I went with load_string</span>
</span><span class='line'>        <span class="c1">//return simplexml_load_file($memberData);</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$data</span> <span class="o">=</span> <span class="nb">simplexml_load_string</span><span class="p">(</span><span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$memberData</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">//make sure that the returned xml file actually contains data</span>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span><span class="k">empty</span><span class="p">(</span><span class="nv">$data</span><span class="o">-&gt;</span><span class="na">IndividualObject</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">-&gt;</span><span class="na">eml_address</span><span class="p">))</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>           <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$data</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>     <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>     <span class="sd">/**</span>
</span><span class='line'><span class="sd">    * Grabs data associated with a member based on member email</span>
</span><span class='line'><span class="sd">    * @param $email Member email to search on</span>
</span><span class='line'><span class="sd">    */</span>
</span><span class='line'>     <span class="k">public</span> <span class="k">function</span> <span class="nf">getMemberDataByEmail</span><span class="p">(</span><span class="nv">$email</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">if</span><span class="p">(</span><span class="k">empty</span><span class="p">(</span><span class="nv">$email</span><span class="p">))</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>           <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$memberData</span> <span class="o">=</span> <span class="nb">sprintf</span><span class="p">(</span><span class="s1">&#39;https://%s:%s@%snetFORUMXML.asmx/GetQuery?szObjectName=%s&amp;szColumnList=%s&amp;szWhereClause=%s&amp;szOrderBy=%s&#39;</span><span class="p">,</span>
</span><span class='line'>           <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">user</span><span class="p">,</span>
</span><span class='line'>           <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">pass</span><span class="p">,</span>
</span><span class='line'>           <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">xweb</span><span class="p">,</span>
</span><span class='line'>           <span class="s1">&#39;Individual&#39;</span><span class="p">,</span>
</span><span class='line'>           <span class="s1">&#39;ind_first_name, ind_last_name, cst_org_name_dn, adr_city, adr_state, eml_address&#39;</span><span class="p">,</span>
</span><span class='line'>           <span class="nb">sprintf</span><span class="p">(</span><span class="s2">&quot;eml_address = &#39;%s&#39;&quot;</span><span class="p">,</span> <span class="nv">$email</span><span class="p">),</span>
</span><span class='line'>           <span class="s2">&quot;ind_last_name&quot;</span>
</span><span class='line'>        <span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">return</span> <span class="nb">simplexml_load_file</span><span class="p">(</span><span class="nv">$memberData</span><span class="p">);</span>
</span><span class='line'>     <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>     <span class="sd">/**</span>
</span><span class='line'><span class="sd">    * Grabs the url of the avectra eweb application</span>
</span><span class='line'><span class="sd">    */</span>
</span><span class='line'>     <span class="k">public</span> <span class="k">function</span> <span class="nf">getEwebUrl</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">eweb</span><span class="p">;</span>
</span><span class='line'>     <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="cp">?&gt;</span><span class="x"></span>
</span></code></pre></td></tr></table></div></figure>


<p>So, for example, to retrieve data about a specific member, and to store that data in session variables for later use, your code might look similar to the following:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="cp">&lt;?php</span>
</span><span class='line'>  <span class="k">function</span> <span class="nf">login_success</span><span class="p">(</span><span class="nv">$cst_key</span> <span class="o">=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>     <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nv">$cst_key</span><span class="p">)</span>
</span><span class='line'>     <span class="p">{</span>
</span><span class='line'>        <span class="c1">//set error message and redirect</span>
</span><span class='line'>     <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>     <span class="c1">//ensure clean referer data</span>
</span><span class='line'>     <span class="nv">$original_referer</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clean</span><span class="o">-&gt;</span><span class="na">stripScripts</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">params</span><span class="p">[</span><span class="s1">&#39;url&#39;</span><span class="p">][</span><span class="s1">&#39;ref&#39;</span><span class="p">]);</span>
</span><span class='line'>
</span><span class='line'>     <span class="c1">//Avectra object</span>
</span><span class='line'>     <span class="c1">//include avectra class file, for example, in CakePHP</span>
</span><span class='line'>     <span class="nx">App</span><span class="o">::</span><span class="na">import</span><span class="p">(</span><span class="s1">&#39;Vendor&#39;</span><span class="p">,</span> <span class="s1">&#39;Avectra&#39;</span><span class="p">);</span>
</span><span class='line'>     <span class="nv">$avectra</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Avectra</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>     <span class="c1">//ensure a clean customer key</span>
</span><span class='line'>     <span class="nv">$cst_key</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clean</span><span class="o">-&gt;</span><span class="na">stripScripts</span><span class="p">(</span><span class="nv">$cst_key</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>     <span class="c1">//if we successfully load the associated user data</span>
</span><span class='line'>     <span class="k">if</span><span class="p">(</span><span class="nv">$data</span> <span class="o">=</span> <span class="nv">$avectra</span><span class="o">-&gt;</span><span class="na">getMemberDataByKey</span><span class="p">(</span><span class="nv">$cst_key</span><span class="p">))</span>
</span><span class='line'>     <span class="p">{</span>
</span><span class='line'>        <span class="nv">$data</span> <span class="o">=</span> <span class="nv">$data</span><span class="o">-&gt;</span><span class="na">IndividualObject</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">Session</span><span class="o">-&gt;</span><span class="na">write</span><span class="p">(</span><span class="s2">&quot;Member.memberId&quot;</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clean</span><span class="o">-&gt;</span><span class="na">stripScripts</span><span class="p">(</span><span class="nv">$data</span><span class="o">-&gt;</span><span class="na">eml_address</span><span class="p">));</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">Session</span><span class="o">-&gt;</span><span class="na">write</span><span class="p">(</span><span class="s2">&quot;Member.firstName&quot;</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clean</span><span class="o">-&gt;</span><span class="na">stripScripts</span><span class="p">(</span><span class="nv">$data</span><span class="o">-&gt;</span><span class="na">ind_first_name</span><span class="p">));</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">Session</span><span class="o">-&gt;</span><span class="na">write</span><span class="p">(</span><span class="s2">&quot;Member.lastName&quot;</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clean</span><span class="o">-&gt;</span><span class="na">stripScripts</span><span class="p">(</span><span class="nv">$data</span><span class="o">-&gt;</span><span class="na">ind_last_name</span><span class="p">));</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">Session</span><span class="o">-&gt;</span><span class="na">write</span><span class="p">(</span><span class="s2">&quot;Member.email&quot;</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clean</span><span class="o">-&gt;</span><span class="na">stripScripts</span><span class="p">(</span><span class="nv">$data</span><span class="o">-&gt;</span><span class="na">eml_address</span><span class="p">));</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">Session</span><span class="o">-&gt;</span><span class="na">write</span><span class="p">(</span><span class="s2">&quot;Member.location&quot;</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">clean</span><span class="o">-&gt;</span><span class="na">stripScripts</span><span class="p">(</span><span class="nv">$data</span><span class="o">-&gt;</span><span class="na">adr_city</span> <span class="o">.</span> <span class="s1">&#39;, &#39;</span> <span class="o">.</span> <span class="nv">$data</span><span class="o">-&gt;</span><span class="na">adr_state</span><span class="p">));</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">Session</span><span class="o">-&gt;</span><span class="na">write</span><span class="p">(</span><span class="s2">&quot;Member.loggedIn&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">Session</span><span class="o">-&gt;</span><span class="na">write</span><span class="p">(</span><span class="s2">&quot;Member.customerKey&quot;</span><span class="p">,</span> <span class="nv">$cst_key</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="c1">//indicate successful login and redirect to original referrer</span>
</span><span class='line'>
</span><span class='line'>     <span class="p">}</span>
</span><span class='line'>     <span class="k">else</span>
</span><span class='line'>     <span class="p">{</span>
</span><span class='line'>        <span class="c1">//set error message and redirect</span>
</span><span class='line'>     <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="cp">?&gt;</span><span class="x"></span>
</span></code></pre></td></tr></table></div></figure>


<h2>The SOAP Alternative</h2>

<p>The <a href="http://wiki.avectra.com/index.php?title=XWeb:PHP">Avectra Wiki examples</a> are slanted heavily in the direction of <a href="http://en.wikipedia.org/wiki/SOAP">SOAP</a>, however in this instance I just thought it was overkill. I figured the response was going to come back in XML, so I would just use <a href="simplexml_load_file">simplexml_load_file</a> and pass in the URI. The application lives with Solaris 10 and PHP 5.2. For some reason simplexml_load_file was failing under certain boundary cases that I couldn’t quite pin down. This was an easy fix as I just used <a href="http://us3.php.net/manual/en/function.simplexml-load-string.php">simplexml_load_string</a> and <a href="http://us3.php.net/manual/en/function.file-get-contents.php">file_get_contents</a> to retrieve the xml response. An extra step, but it seemed to solve whatever the issue was that I was having. So, all I needed to do was make sure that I had the properly constructed URI, and that I could authenticate. Authentication is simply handled by sending in the username:password combination as part of the request.</p>
]]></content>
  </entry>
  
</feed>
