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

<channel>
	<title>The Wojo Group &#187; Programming</title>
	<atom:link href="http://www.thewojogroup.com/tag/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thewojogroup.com</link>
	<description>The musings of a small creative media company.</description>
	<lastBuildDate>Tue, 11 May 2010 00:10:34 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Simulating HTML5 Local Storage Support</title>
		<link>http://www.thewojogroup.com/2010/01/simulating-html5-local-storage/</link>
		<comments>http://www.thewojogroup.com/2010/01/simulating-html5-local-storage/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 06:07:07 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[localStorage]]></category>
		<category><![CDATA[Persistent Local Storage]]></category>
		<category><![CDATA[Storage]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=580</guid>
		<description><![CDATA[I have been wanting to use HTML5's local storage for a while, but I haven't had a project where I can just ignore the older browsers.  So I put together a little ( <1Kb gzipped ) script that checks for HTML5's local storage API, and simulates the method for browsers that do not support it.  For those browsers, the script implements a nearly identical interface to localStorage for persistent storage of name/value pairs, except it uses cookies. ]]></description>
			<content:encoded><![CDATA[<p>I have been wanting to use <a href="http://www.w3.org/TR/2009/WD-webstorage-20091222/" target="_blank">HTML5&#8217;s local storage</a> for a while, but I haven&#8217;t had a project where I can just ignore the older browsers.  So I put together a little ( &lt;1Kb gzipped ) script that checks for HTML5&#8217;s local storage API, and simulates the method for browsers that do not support it. For those browsers, the script implements a nearly identical interface to localStorage for persistent storage of name/value pairs, except it uses cookies.  For the impatient types, you can see the repo at <a href="http://github.com/thewojogroup/local-storage-js" target="_blank">github</a> or <a href="http://cloud.github.com/downloads/thewojogroup/local-storage-js/local-storage-js-1.zip">download the script</a>. Below is a description of usage:</p>
<pre name="code" class="javascript">

localStorage.setItem( key , value );
// saves a new name/value pair if the key doesn&#039;t exist, otherwise
// updates the value

localStorage.getItem( key );
// returns the value associated with the given key, if it exists
// returns null if the key doesn&#039;t exist

localStorage.length;
// the number of unique keys stored

localStorage.removeItem( key );
// deletes the name/value pair with the given key, if it exists
// if it does not exist, exits

localStorage.clear();
// delete all name/value pairs currently stored

localStorage.key( n );
// returns the name of the nth key in the list, will return null if n is
// greater than or equal to localStorage.length
</pre>
<p>If the localStorage object is available, the setup script exits and allows the method to work normally.  Otherwise, it will use the same interface to create a string of name/value pairs to store in cookies.  You can use all the methods described above, but it does not support direct access to data, such as &#8216;localStorage.name = &#8220;bob&#8221; ;&#8217;.  One issue is that the older browsers with slow performance will experience another setback when storing large amounts of data, because the cookies will be included in headers.</p>
<p>There are two types of storage methods in the new Web Storage Specification: localStorage and sessionStorage.  The sessionStorage data will only persist for the life of the browser window, whereas localStorage will last indefinitely, depending on the browser.  This script uses the localStorage, but can be switched to sessionStorage pretty easily.  There are a few resources out there already where you can learn a <a href="http://hacks.mozilla.org/2009/06/localstorage/">little</a> <a href="http://24ways.org/2009/breaking-out-the-edges-of-the-browser">bit</a> <a href="http://www.w3.org/TR/2009/WD-webstorage-20091222/">more</a>.  Currently, the specification is supported by IE8, Firefox3.5, Safari4, and Chrome (localStorage only).</p>
<p><a class="btnDownload" href="http://cloud.github.com/downloads/thewojogroup/local-storage-js/local-storage-js-1.zip">Download</a> or Check out the <a href="http://github.com/thewojogroup/local-storage-js">repo on github</a>.</p>
<p>[<strong>Note</strong>: I've done some brief testing on most browsers, but if you run into a problem, let me know]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2010/01/simulating-html5-local-storage/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Simple Pagination with Rails</title>
		<link>http://www.thewojogroup.com/2009/05/simple-pagination-with-rails/</link>
		<comments>http://www.thewojogroup.com/2009/05/simple-pagination-with-rails/#comments</comments>
		<pubDate>Tue, 05 May 2009 14:07:17 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Motionspire]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[content]]></category>
		<category><![CDATA[pages]]></category>
		<category><![CDATA[pagination]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=510</guid>
		<description><![CDATA[While I was developing Motionspire, I needed to implement a pagination system for the video content.  I looked through the existing plugins, but found that I really desired something extremely simple and custom to work within my search controller.  With only a few lines of code, I created a very basic system for managing pagination [...]]]></description>
			<content:encoded><![CDATA[<p>While I was developing <a href="http://www.motionspire.com">Motionspire</a>, I needed to implement a pagination system for the video content.  I looked through the existing plugins, but found that I really desired something extremely simple and custom to work within my search controller.  With only a few lines of code, I created a very basic system for managing pagination that can be ported to other sites with ease.</p>
<h4>The Search Controller</h4>
<p>The Motionspire search controller uses one function and view for returning any content, whether it&#8217;s filtered or not, so the pagination only required one copy of the code to be implemented.  I keep a session variable for maintaining the user&#8217;s preference for items per page, and if that parameter has been sent to the search function I set the session variable :</p>
<pre name="code" class="ruby">

if params[:itemsPerPage] then session[:itemsPerPage] = params[:itemsPerPage] end
</pre>
<p>When I run though the search function, I see if a page parameter has been passed:</p>
<pre name="code" class="ruby">

if params[:page] then @page = params[:page].to_i else @page = 1 end
</pre>
<p>After I retrieve the articles pertaining to the search parameters (in this case the results are stored into an array called @videos), I check the :itemsPerPage preference and find the last possible page:</p>
<pre name="code" class="ruby">

if session[:itemsPerPage] then @per = session[:itemsPerPage].to_i else @per = 24 end

@lastpage = @videos.length/(@per) + 1

if @videos.length%(@per) == 0

    @lastpage = @lastpage - 1

end
</pre>
<p>I have a default itemsPerPage value of 24 hardcoded, and you can change this for your search.</p>
<p>From here, we simply return the search results for that page, using the current page and the items per page preference:</p>
<pre name="code" class="ruby">

@videos = @videos[((@page-1)*@per),@per]
</pre>
<p><em>For search queries within a large data set, I would recommend using these parameters with the sql query with the &#8216;ORDER BY&#8217; and &#8216;LIMIT&#8217; in order to avoid returning extremely large results unnecessarily.</em></p>
<h4>The Helper</h4>
<p>First, I created a short helper function that finds the min and max pages, ensuring we don&#8217;t show a negative page or a page that doesn&#8217;t exist:</p>
<pre name="code" class="ruby">

def minmaxpage(current,total,option)
    min = current - 2
    if min &lt; 1
        min = 1
        max = 1 + 4
        if max &gt; total then max = total end
    end
    max = min + 4
    if max &gt; total
        max = total
        min = max - 4
        while min &lt; 1
            min = min + 1
        end
    end
    if option == &#039;min&#039; then return min else return max end
end
</pre>
<h4>The View</h4>
<p>For the content from the view, we use the @videos array to present the content for the page.  The only custom coding necessary is in the links for the pages.  For this site, I provide a first and last page link, along with 2 pages on either side of the current page.  You can manipulate this code how you want, but the basic idea will remain the same.</p>
<p>First we grab the min and max page from the helper:</p>
<pre name="code" class="ruby">

&lt;% min = minmaxpage(@page, @lastpage, &#039;min&#039;) %&gt;

&lt;% max = minmaxpage(@page, @lastpage, &#039;max&#039;) %&gt;
</pre>
<p>For the code for the page links, we simply check to see if the min page is within two of the current:</p>
<pre name="code" class="ruby">

&lt;% if min &lt; @page %&gt;

    &lt;%= link_to( &quot;Prev&quot;,

        :action =&gt; &quot;search&quot;,

        :page =&gt; (@page - 1) ) %&gt;

&lt;% end %&gt;

&lt;% if min &gt; 1 %&gt;

    &lt;%= link_to( &quot;1&quot;,

        :action =&gt; &quot;search&quot;,

        :page =&gt; 1 ) %&gt;

&lt;% end %&gt;

&lt;% x = min %&gt;
</pre>
<p>Then we loop through the remaining pages, ensuring we don&#8217;t go over the max, and make the current page simple text instead of a link:</p>
<pre name="code" class="ruby">

&lt;% while x &lt;= max %&gt;

    &lt;% if x.to_i == @page.to_i %&gt;

        &lt;span class=&quot;current&quot;&gt;&lt;%= x %&gt;&lt;/span&gt;

    &lt;% else %&gt;

        &lt;%= link_to( x.to_s,

            :action =&gt; &quot;search&quot;,

            :page =&gt; x ) %&gt;

    &lt;% end %&gt;

    &lt;% x = x+1 %&gt;

&lt;% end %&gt;

&lt;% if max &lt; @lastpage %&gt;

    &lt;%= link_to( @lastpage.to_s,

        :action =&gt; &quot;search&quot;,

        :page =&gt; @lastpage ) %&gt;

&lt;% end %&gt;

&lt;% if max &gt; @page %&gt;

    &lt;%= link_to( &quot;Next&quot;,

        :action =&gt; &quot;search&quot;,

        :page =&gt; (@page + 1) ) %&gt;

&lt;% end %&gt;
</pre>
<p>The code may look a little long, but the implementation took very little time.  I know exactly what the code is doing and it is very easy to expand this for different situations and code.</p>
<p>There are a lot of solutions for pagination of content, but I found that this simple implementation helped me avoid using plugins and save time.  Let me know if you guys have any questions or comparable solutions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2009/05/simple-pagination-with-rails/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Twetris: twitter + tetris</title>
		<link>http://www.thewojogroup.com/2009/04/twetris-twitter-tetris/</link>
		<comments>http://www.thewojogroup.com/2009/04/twetris-twitter-tetris/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 17:44:23 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[javscript]]></category>
		<category><![CDATA[tetris]]></category>
		<category><![CDATA[twetris]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=460</guid>
		<description><![CDATA[We developed a little creation called <a href="http://brett.wejrowski.com/twetris/" alt="Twetris">Twetris</a> that uses the twitter timeline to create blocks for a tetris game.  It's a simple javascript/html/css creation thats great for wasting time. <a href="http://brett.wejrowski.com/twetris/" alt="Twetris">Check it out!</a>
]]></description>
			<content:encoded><![CDATA[<p>We developed a little creation called <a href="http://brett.wejrowski.com/twetris/" target="_blank">Twetris</a> that uses the twitter timeline to create blocks for a tetris game. The high score list is published automatically to <a href="http://twitter.com/twetris">@twetris</a> and you can even retweet your high scores right from the game. It&#8217;s a simple javascript/html/css creation thats great for wasting time.<br />
<a style="text-decoration: none;" href="http://brett.wejrowski.com/twetris/" target="_blank">Check it out!</a></p>
<p><a href="http://brett.wejrowski.com/twetris"><img class="alignnone size-full wp-image-474" title="twetris3" src="http://www.thewojogroup.com/wp-content/uploads/2009/04/twetris3.png" alt="" width="500" height="433" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2009/04/twetris-twitter-tetris/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>April Fools &#8216;flip text&#8217; Script</title>
		<link>http://www.thewojogroup.com/2009/04/april-fools-flip-text-script/</link>
		<comments>http://www.thewojogroup.com/2009/04/april-fools-flip-text-script/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 13:45:38 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[april fools]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[joke]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[text flip]]></category>
		<category><![CDATA[tricks]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=453</guid>
		<description><![CDATA[Over breakfast this morning, I put together a little JS script that will flip all the text on a page.  Just put this link AT THE BOTTOM of your page, and it should provide a little April Fools joke for some visitors. ]]></description>
			<content:encoded><![CDATA[<p>Over breakfast this morning, I put together a little JS script that will flip all the text on a page.  Just put this link <strong>AT THE BOTTOM</strong> of your page, and it should provide a little April Fools joke for some visitors:</p>
<pre name="code" class="html">

&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.thewojogroup.com/flipEm.js&quot; &gt;&lt;/script&gt;
</pre>
<p>**Make sure to test this on your site, some flash objects or other plugins may not work properly</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2009/04/april-fools-flip-text-script/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Developing vs Programming</title>
		<link>http://www.thewojogroup.com/2009/03/developing-vs-programming/</link>
		<comments>http://www.thewojogroup.com/2009/03/developing-vs-programming/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 15:34:51 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[application development]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Coding Style]]></category>
		<category><![CDATA[developing]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=442</guid>
		<description><![CDATA[I'm a mediocre programmer, at best.

When I'm programming, I need 8 different tabs open with every reference site I can get for a particular language.  I google function names constantly, most of my debugging time is spent with dumb syntax errors, and I'm never going to be able to use Regular Expressions off the top of my head.

So what can mediocre programmers like myself do? Develop. I'm going to go over a few tips for good application development, and how to use development methods that can improve your programming.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a mediocre programmer, at best.</p>
<p>When I&#8217;m programming, I need 8 different tabs open with every reference site I can get for a particular language.  I google function names constantly, most of my debugging time is spent with dumb syntax errors, and I&#8217;m never going to be able to use Regular Expressions off the top of my head.</p>
<p>So what can mediocre programmers like myself do? Develop. I&#8217;m going to go over a few tips for good application development, and how to use development methods that can improve your programming, even if you lack superstar skills.</p>
<h3>Project Management</h3>
<p>There are too many different project management philosophies to mention here, and many of them are developed by very experienced and knowledgeable professionals in the industry.  However, <em>project management and planning remain to be the biggest downfall for most programmers</em>.  Many of these methods are made to apply to development teams, but you can abstract a lot of the ideas to individual projects.  Try to check out a few papers or books on the topic during your free time.</p>
<h3>1/3 Rule</h3>
<p>For most projects, I try to stick with the <strong>1/3 rule</strong>:  spend (approximately) 1/3 of your time on planning, 1/3 on coding, and 1/3 on testing.  Many programmers expect to spend the majority of the project timeline writing code, and believe that good code will drive the project.  However, I have found that most worthwhile final products are created from development timelines that have actual coding as a minority.  This 1/3 flow can often take iterations for different portions of a project, where you plan, code, and test small portions and move on to the next section.  But you will often find dedicating time to plan properly will cut down on actual coding, and proper testing will save you time in the long run.</p>
<h3>Start with Your User</h3>
<p>I am a big fan of top-down development.  There are a lot of different theories about development strategies and methods, but I have found that for real world applications, the single most important aspect of any program is the interface.</p>
<p>With that in mind, I start my planning with laying out the interface.  Implementation of this idea can vary depending on the project.  For example, you may start with wireframes and a user flow for a web application.  For something like <a href="http://www.thewojogroup.com/2008/10/simplecartjs-paypal-e-commerce-in-minutes/">simpleCart(js)</a>, I started by listing every way in which the user would interact with the code, including function calls, div classes, and html layout for cart items.  When you start your project by building out the interface first, you are ensuring that your program will adhere to the end-user functionality of the project.</p>
<h3>Compartmentalize Functionality</h3>
<p>It doesn&#8217;t matter whether you are a big believer in MVC (I am) or like procedural or object-oriented (I&#8217;m a OOP guy); you will find yourself improving your code by creating structure first, and then implementing code.  It is often beneficial to create functions (or objects) that relate to real-world goals or problems.  If you say to yourself, &#8220;I am going to need to store the current user preferences in a cookie,&#8221; you might want to create a function for exactly that.</p>
<p>By focusing on individual problems, it becomes much easier to create efficient code for that particular purpose.  In turn, you often write better code.  It also becomes much easier to debug; if you are having a problem storing to a cookie, you simply look at your &#8217;store to cookie&#8217; function.  Documentation also becomes extremely easy, as the purpose of your code becomes evident simply by looking at the function name.  I know this may be second nature to many developers, but it can&#8217;t hurt to mention it.</p>
<h3>Abstract Data Storage</h3>
<p>I&#8217;ve found that many projects outlast hardware, hosting, or storage implementations.  You may move your code to another server, decide to implement a different database system, or find that you outgrow your storage and need to keep data in more than one place.  In any of these cases, abstracting data storage and retrieval functions from the rest of your code will benefit you immensely.  Data storage is often the last part I consider for my project.  I often do most of my developing with two empty functions: load() and store(). They are usually the last thing I implement, as, in most situations, they are the least important to the functionality of your end-user.  It also becomes extremely easy to maintain consistency of your core functionality when switching to a new data implementation by simply altering these functions.</p>
<h3>Conclusion</h3>
<p>These are all very high level concepts, and it may or may not be clear how to actually implement some of them in your projects.  The overriding theme that I hope you can take away from this article is that every program looks the same from 10,000 feet.  Most great applications are built with the end-user in mind, and great development isn&#8217;t necessarily dependent on great code.  Please let me know if you guys have any other tips.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2009/03/developing-vs-programming/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>simpleCart(js) + PayPal = E-commerce in minutes</title>
		<link>http://www.thewojogroup.com/2008/10/simplecartjs-paypal-e-commerce-in-minutes/</link>
		<comments>http://www.thewojogroup.com/2008/10/simplecartjs-paypal-e-commerce-in-minutes/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 18:23:57 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cart]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[e-commerce]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=178</guid>
		<description><![CDATA[Over the past few years, our company has had several clients who have needed a smaller shopping cart, usually to only sell a couple items.  Because we expected sporadic traffic, we were tentative to go with a packaged shopping cart and merchant service.  That just seemed like a lot of overhead.  Thus, I have developed a few different ajax carts using paypal.  I realized it would be nice to package this up, and create a lightweight, easy-to-use, flexible shopping cart.

So we made simpleCart(js).  The cart is a 10.5kb javascript file that uses cookies to keep track of the items in the cart.  Thus, simpleCart(js) doesn't require any databases or programming.  You simply need to know some basic HTML and have the ability to copy and paste.  However, it can easily be expanded to use databases or contain more advanced options. ]]></description>
			<content:encoded><![CDATA[<p>****UPDATE: Version 2 is now available, this post is outdated.  Please go to <a href="http://simplecartjs.com">simplecartjs.com</a> to find out more*****</p>
<p>**update: v1.2: fixed rounding error in price formatting<br />
**update: v1.1: back button works, no trailing comma for options</p>
<p>(if you want to skip right to the example and downloads, check it out <a href="http://thewojogroup.com/simpleCart/" target="_blank">here</a>)</p>
<p>Over the past few years, our company has had several clients who have needed a smaller shopping cart, usually to sell just a couple of items.  We generally built these small carts using paypal.  I realized it would be nice to package this up, and create a lightweight, easy-to-use, flexible shopping cart.</p>
<p>So we made simpleCart(js).  The cart is a 10.5kb javascript file that uses cookies to keep track of the items in the cart.  SimpleCart(js) doesn&#8217;t require any databases or programming knowledge.  You simply need to know some basic HTML and have the ability to copy and paste.  However, it can easily be expanded to use databases or contain more advanced options.</p>
<h3>Setup Paypal</h3>
<p>The first thing you will need to do, if you don&#8217;t already have one, is set up a free merchant account with <a href="http://paypal.com">Paypal.</a></p>
<h3>Add simpleCart(js) to your pages</h3>
<p>Once you have the files downloaded, simply add this snippet to the top of any page you wish to have the cart running on:</p>
<pre name="code" class="html">

&lt;script src=&quot;simpleCart.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
simpleCart = new cart(&quot;you@yours.com&quot;);
// --&gt;&lt;/script&gt;
</pre>
<p>You will need to replace you@yours.com with the email address you used to sign up to Paypal.</p>
<h3>Adding items to the cart</h3>
<p>Any page you have the simpleCart(js) running, you can add an item by simply using a link like this:</p>
<pre name="code" class="html">

&lt;a onclick=&quot;simpleCart.add(&#039;name=[name]&#039;,&#039;price=[price]&#039;);return false;&quot; href=&quot;#&quot;&gt; link to add item &lt;/a&gt;
</pre>
<p>You are required to at least have a name and price when adding an item to the cart.  However, you can add other fields also.  If you want an image to be linked to the item, you can add it like this:</p>
<pre name="code" class="javascript">

simpleCart.add(&#039;name=Shirt&#039;,&#039;price=6.00&#039;,&#039;image=images/myImage.png&#039;);
</pre>
<h3>Viewing the cart</h3>
<p>You may have the cart on any page, and it will update automatically using ajax. To show the cart items on a particular page, you simply need to have an element with the class of &#8220;simpleCart_items&#8221; on the page. This element will automatically be filled with all of the items in the cart, and will show each field.</p>
<pre name="code" class="javascript">

&lt;div class=&quot;simpleCart_items&quot;&gt;&lt;/div&gt;
</pre>
<p>You can use any element (div,a,span,p,etc.) and the values will be put in the innerHTML of that element.</p>
<h3>Showing the totals on a page</h3>
<p>You can show the total quantity or price on any page by simply having an element with a class &#8220;simpleCart_quantity&#8221; or &#8220;simpleCart_total&#8221;:</p>
<pre name="code" class="html">

&lt;div class=&quot;simpleCart_total&quot;&gt;&lt;/div&gt; &lt;span class=&quot;simpleCart_quantity&quot;&gt;&lt;/span&gt; items
</pre>
<h3>Checkout and Empty Cart links</h3>
<p>You can have a checkout or empty cart link anywhere on any page where the simpleCart(js) is active. You do this by simply setting the class of an element to &#8220;simpleCart_checkout&#8221; or &#8220;simpleCart_empty&#8221;:</p>
<pre name="code" class="html">

&lt;a class=&quot;simpleCart_checkout&quot; href=&quot;#&quot;&gt;checkout&lt;/a&gt;

&lt;a class=&quot;simpleCart_empty&quot; href=&quot;#&quot;&gt;empty cart&lt;/a&gt;
</pre>
<p>You can use any type of element for these, and you can put anything inside of the element. Anything wrapped in a tag with those classes will link appropriately.</p>
<h3>Other Options</h3>
<p><strong>Adding other product options to items.</strong></p>
<pre name="code" class="javascript">

simpleCart.add(&#039;name=Shirt&#039;,&#039;price=6.00&#039;,&#039;image=images/myImage.png&#039;,&#039;size=XL&#039;,&#039;color=Blue&#039;);
</pre>
<p><strong>You can also change the quantity that will be added to the cart:</strong></p>
<pre name="code" class="javascript">

simpleCart.add(&#039;name=Shirt&#039;,&#039;price=6.00&#039;,&#039;image=images/myImage.png&#039;,&#039;quantity=5&#039;,&#039;size=XL&#039;,&#039;color=Blue&#039;);
</pre>
<p><em>The order of the arguments doesn&#8217;t matter, and you can add as many options as you would like.</em></p>
<p><strong>Styling the cart.</strong></p>
<p>You can style this cart to fit the look of your page.  The contents of the cart will start with a header row:</p>
<pre name="code" class="html">

&lt;div class=&quot;cartHeaders&quot;&gt;
&lt;div class=&quot;itemImage&quot;&gt;Image&lt;/div&gt;
&lt;div class=&quot;itemName&quot;&gt;Name&lt;/div&gt;
&lt;div class=&quot;itemPrice&quot;&gt;Price&lt;/div&gt;
&lt;div class=&quot;itemOptions&quot;&gt;Options&lt;/div&gt;
&lt;div class=&quot;itemQuantity&quot;&gt;Quantity&lt;/div&gt;
&lt;div class=&quot;itemTotal&quot;&gt;Total&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>Each item in the cart will have the following form:</p>
<pre name="code" class="html">

&lt;div class=&quot;itemContainer&quot;&gt;
&lt;div class=&quot;itemImage&quot;&gt;[myImage]&lt;/div&gt;
&lt;div class=&quot;itemName&quot;&gt;Shirt&lt;/div&gt;
&lt;div class=&quot;itemPrice&quot;&gt;$6.00&lt;/div&gt;
&lt;div class=&quot;itemOptions&quot;&gt;size: XL; color: Blue&lt;/div&gt;
&lt;div class=&quot;itemQuantity&quot;&gt;&lt;input type=&quot;text&quot; /&gt;&lt;/div&gt;
&lt;div class=&quot;itemTotal&quot;&gt;$30.00&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>And there will also be a totals row:</p>
<pre name="code" class="html">

&lt;div class=&quot;totalRow&quot;&gt;
&lt;div class=&quot;totalItems&quot;&gt;6&lt;/div&gt;
&lt;div class=&quot;totalPrice&quot;&gt;$30.00&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>You can choose to omit part of the cart in your stylesheet:</p>
<pre name="code" class="css">

.itemOptions,itemImage{
display:none;
}
</pre>
<p>Or you can hide the header or totals rows:</p>
<pre name="code" class="css">

.totalRow{
display:none;
}

.cartHeaders{
display:none;
}
</pre>
<p><strong>Change the order of the cart columns.</strong></p>
<p>If you would like to change the order of columns or remove the columns from ever being shown, simply add a line to the top of your page:</p>
<pre name="code" class="html">

&lt;script type=&quot;text/javascript&quot; src=&quot;simpleCart.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
simpleCart = new cart(&quot;you@yours.com&quot;);

//Add the following line to reorder and remove item columns
simpleCart.ItemColumns = [&#039;Image&#039;,&#039;Price&#039;,&#039;Name&#039;,&#039;Quantity&#039;,&#039;Total&#039;];

&lt;/script&gt;
</pre>
<p><strong>Download and Demo</strong></p>
<p>Below are links to download simpleCart(js) and to view a working Demo. One great thing about the cart being stored in cookies is that you can have your items be added on one page and the cart be on another if you wish. The demo reflects this. The main page of the sample store is <a href="http://thewojogroup.com/simpleCart">here</a> and the View Your Cart page is <a href="http://thewojogroup.com/simpleCart/myCart.html">here.</a></p>
<p>********* Please go to <a href="http://simplecartjs.com">simplecartjs.com</a> for the updated downloads and demo************</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2008/10/simplecartjs-paypal-e-commerce-in-minutes/feed/</wfw:commentRss>
		<slash:comments>398</slash:comments>
		</item>
		<item>
		<title>Writing your own code vs. Plugins</title>
		<link>http://www.thewojogroup.com/2008/09/writing-your-own-code-vs-plugins/</link>
		<comments>http://www.thewojogroup.com/2008/09/writing-your-own-code-vs-plugins/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 14:06:16 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Coding Style]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[RoR]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=160</guid>
		<description><![CDATA[Recently I have been discussing with some fellow coders the benefits of plugins, and when you should write your own code.  I basically wanted to throw out a couple of ideas and hope for some discussion on the topic.  Let me know what you guys think and I'll do a follow up soon.]]></description>
			<content:encoded><![CDATA[<p>Recently I have been discussing with some fellow coders the benefits of plugins, and when you should write your own code.  I basically wanted to throw out a couple of ideas and hope for some discussion on the topic.  Let me know what you guys think and I&#8217;ll do a follow up soon.</p>
<h3>Some Background</h3>
<p>I, like many of you out there, started programming back in the day by messing around with computers, writing little calculator programs, making websites, etc.  But I really didn&#8217;t get into it much more until I started college, where I immediately started programming with C++.  </p>
<p>Most of my classes started out with projects where we had to write everything (no STL!), and all of my code was from scratch.  Once I started doing more of the &#8220;development&#8221; in &#8220;web design and development&#8221;, I still practiced the idea that the only code I know is good is the code I write.</p>
<h3>But now I can see&#8230;</h3>
<p>Then one day, the skies parted, trumpets sounded, and my designer Steve said &#8220;Hey, have you heard of Ruby on Rails?&#8221;  </p>
<p>I immediately started developing with nearly pure Rails, using the built-in-just-about-everything and loving the fact that anything I couldn&#8217;t code (or didn&#8217;t want to) was usually readily available in plugins ( I love file_column!).  </p>
<p>I will say this, RoR is good code.  And it&#8217;s constantly being improved.  For the most part, the plugins are also good code.  And many times, a plugin works perfectly into your project to save you time and add functionality.  </p>
<h3>Good Programming</h3>
<p>Ask any real programmer, and the efficiency of code is not only about how it performs, but how long it takes you to create.  So obviously there is a trade-off between using plugins and writing your own code.  </p>
<p>That being said, if you are a web designer who is using rails to help you out, or just trying something new, use the plugins: they are great and it will save you days of coding and headaches.  </p>
<p>If you consider yourself a developer (or hope to), you should still use plugins.  If you code everything, you&#8217;re going to waste time. However, don&#8217;t completely rely on them.  If you want to be a programmer, you need to know how things work, because some day there won&#8217;t be a plugin for you, and you&#8217;re going to need to know what to do.  </p>
<p>Also, plugins are meant to be helpful for a range of situations.  Therefore, there is going to be some overhead.  If you are concerned with performance, and a plugin isn&#8217;t &#8220;perfect&#8221; for what you&#8217;re trying to do; you might need to code from scratch (or at least be prepared to customize the plugin code).</p>
<h3>Here&#8217;s the thing&#8230;</h3>
<p>All things considered, I will say that my natural tendency is to code most everything myself.  I like to know where everything is, and <strong>exactly </strong>what the code is doing.  I also appreciate when the code is only doing exactly what I want it to do.  If it&#8217;s impractical to write something, by all means I will ( and do ) use plugins.  </p>
<p>If you want some good coding experience, and have the time, try writing something yourself that you wouldn&#8217;t normally do.  Even if you don&#8217;t end up using it, you&#8217;ll learn a bit more about RoR (or any other language) and you may just have some good code you can use again.</p>
<p>Agree? Disagree? Don&#8217;t care?</p>
<p>I&#8217;m just one guy.  Let me know what you guys think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2008/09/writing-your-own-code-vs-plugins/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Remember Me&#8217;s with Rails</title>
		<link>http://www.thewojogroup.com/2008/09/remember-mes-with-rails/</link>
		<comments>http://www.thewojogroup.com/2008/09/remember-mes-with-rails/#comments</comments>
		<pubDate>Fri, 26 Sep 2008 18:51:13 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[expiration]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[remember me]]></category>
		<category><![CDATA[RoR]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[session]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=150</guid>
		<description><![CDATA[I recently had a need for a login system that needed a 'remember me' function.  After hours of looking through countless blogs, I came to the conclusion that either (1) people don't use a remember me function with Rails logins, or (2) they don't write about it.  In this article, I outline a simple remember me system using the cookie variable in Rails that will tack on to most custom authentication systems.  ]]></description>
			<content:encoded><![CDATA[<p>I recently had a need for a login system that <em>needed </em>a &#8216;remember me&#8217; function.  After hours of looking through countless blogs, I came to the conclusion that either (1) people don&#8217;t use a remember me function with custom authentication systems for Rails, or (2) they don&#8217;t talk about it.  In this article, I outline a simple remember me system using the <span style="color: #008000;">cookie</span> variable in Rails that will tack on to most custom authentication systems.</p>
<p>Using the <span style="color: #008000;">cookie</span> functions in Rails is pretty <a href="http:/http://api.rubyonrails.org/classes/ActionController/Cookies.html" target="_blank">straightforward.</a> It&#8217;s used with the ActionController and is quite simple to use.  Most people use <span style="color: #008000;">sessions </span>for authentication, which is a good idea.  <span style="color: #008000;">Sessions</span>, unlike cookies, automatically save your content as encrypted strings using the browsers cookies. ActionController#<span style="color: #008000;">cookie</span> provides a method for saving information in the browser, but you need to hash the content yourself if need be.</p>
<p>However, if a user selects the remember me option when logging in, we would like to have the <span style="color: #008000;">session</span> expiration set to be a longer period, like 30 days.  Unfortunately, this is quite difficult to do if you don&#8217;t want to change the expiration of ALL sessions.</p>
<p>My site already uses <span style="color: #008000;">sessions</span> for authentication, and I&#8217;m going to leave that be.  In fact, I&#8217;m not going to change anything about the <span style="color: #008000;">session</span> variable <em>at all. </em>This way, I can add this remember function to almost any authentication system I use in the future very easily.</p>
<p>When a user is authenticated and has selected the &#8220;remember me&#8221; option, I do two things:</p>
<p>- create a cookie that stores (<strong>plain text</strong>) the user&#8217;s <span style="color: #ff0000;">id</span><span style="color: #ff0000;"> </span>(you can use name, email, etc. but I prefer the id because it says nothing about the user to anyone trying to get information)</p>
<p>- create a second cookie with an <strong>hashed string</strong> of some other information about the user( name, email, address )</p>
<pre name="code" class="ruby">
if params[:rememberMe]
userId = (@user.id).to_s
cookies[:remember_me_id] = { :value =&gt; userId, :expires =&gt; 30.days.from_now }
userCode = Digest::SHA1.hexdigest( @user.email )[4,18]
cookies[:remember_me_code] = { :value =&gt; userCode, :expires =&gt; 30.days.from_now }
end
</pre>
<p>For the hashing of the second piece of information, use a hash such as SHA1 or MD5.  We can use these two cookies to authenticate a user when they return after a session has expired.</p>
<pre name="code" class="ruby">
if ( cookies[:remember_me] and cookies[:remember_me] and User.find( cookies[:remember_me]) and Digest::SHA1.hexdigest( User.find( cookies[:remember_me] ).email )[4,18] == cookies[:remember_me_code]  )
@u = User.find( cookies[:remember_me_id] )
session[&#039;user&#039;] = @u.id
end
</pre>
<p>Just work that into your <span style="color: #ff9900;">:before_filter</span> for your authentication system, and you&#8217;re all set.  Make sure you delete the variables when someone logs out:</p>
<pre name="code" class="ruby">
if cookies[:remember_me_id] then cookies.delete :remember_me_id end
if cookies[:remember_me_code] then cookies.delete :remember_me_code end
</pre>
<p>****Edit: make sure to have &#8220;require &#8216;digest/sha1&#8242;&#8221; at the top of any page where you are using the SHA1 hash.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2008/09/remember-mes-with-rails/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Simple login with Rails</title>
		<link>http://www.thewojogroup.com/2008/09/super-simple-login-with-rails/</link>
		<comments>http://www.thewojogroup.com/2008/09/super-simple-login-with-rails/#comments</comments>
		<pubDate>Thu, 11 Sep 2008 15:47:39 +0000</pubDate>
		<dc:creator>Brett Wejrowski</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[Motionspire]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[RoR]]></category>
		<category><![CDATA[user]]></category>

		<guid isPermaLink="false">http://www.thewojogroup.com/?p=121</guid>
		<description><![CDATA[We recently beta launched a new site, motionspire.com.  Our main goal for the launch was to get statistics from user testing, mainly from a targeted audience.  In order to keep a limited user base, we wanted to make visitors create a beta account, and use a login system in order to view the site.

I wanted to create a quick and simple login system that was, most importantly, temporary.  The authentication didn't require a lot of security because no user information was stored in our db other than an email and password.  I also wanted to contain all the code for the system (as much as possible at least) in a few different directories, so I can easily remove the system for the main launch.]]></description>
			<content:encoded><![CDATA[<p>We recently beta launched a new site, motionspire.com.  Our main goal for the launch was to get statistics from user testing, mainly from a targeted audience.  In order to keep a limited user base, we wanted to make visitors create a beta account, and use a login system in order to view the site.</p>
<p>I wanted to create a quick and simple login system that was, most importantly, temporary.  The authentication didn&#8217;t require a lot of security because no user information was stored in our db other than an email and password.  I also wanted to contain all the code for the system (as much as possible at least) in a few different directories, so I can easily remove the system for the main launch.</p>
<p>Here is the process I wanted to create:</p>
<ol>
<li>1. user comes to the site, and inputs an email address requesting a beta account</li>
<li>2. the user gets an email with (1) a link to create their password and (2) a code for authentication</li>
<li>3. the user inputs the code and creates their password</li>
<li>4. the user can now view the site, and login at a later time</li>
</ol>
<p>So that&#8217;s the process.  My designer created two pages: (1) a page with a form requesting an account and another form to login and (2) a page to create a password with the code.  I created a new controller, beta, and started with these two functions:</p>
<pre name="code" class="ruby">
&lt;span style=&quot;color: #333399;&quot;&gt;&gt; ruby script/generate controller beta index create_password&lt;/span&gt;
</pre>
<p>And I created a model, betauser:</p>
<pre name="code" class="ruby">
&lt;span style=&quot;color: #333399;&quot;&gt;&gt; ruby script/generate model betauser&lt;/span&gt;
</pre>
<p>The model had three fields: email, password, and a boolean &#8216;active&#8217; to keep track of whether the user had activated the account. I usually use the timestamps for every model just as good practice.  Here is the migration:</p>
<pre name="code" class="ruby">
&lt;span style=&quot;color: #333399;&quot;&gt;class AddBetaUsers &lt; ActiveRecord::Migration
def self.up
create_table :betausers do |t|
t.boolean :active
t.string :email, :password
t.timestamps
end
end&lt;/span&gt;
</pre>
<pre name="code" class="ruby">
&lt;span style=&quot;color: #333399;&quot;&gt; def self.down
drop_table :betausers
end
end&lt;/span&gt;
</pre>
<p>Next was the function for requesting a beta account.  The form&#8217;s only input was their email:</p>
<pre name="code" class="ruby">
&lt;span style=&quot;color: #333399;&quot;&gt;def create_beta_invite
email = params[:email]
beta = Betauser.new
&lt;/span&gt; &lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt; //set the account to inactive
&lt;/span&gt; &lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt; beta.active = false
beta.email = email
if beta.save
&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// create a code based on the users email
// its not the most secure way to do things,
// but its simple and doesnt require another
// field in the database&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;
code = Digest::SHA1.hexdigest(email)[3,12]
&lt;/span&gt; &lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;
// create an email with my ActiveMailer model &#039;Notifier&#039;
&lt;/span&gt; &lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt; email = Notifier.create_beta(email,code)
email.set_content_type(&quot;text/html&quot;)
Notifier.deliver(email)
&lt;/span&gt; &lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt; //redirect to the password creation page
&lt;/span&gt; &lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt; redirect_to :action =&gt; &quot;create_password&quot;,
:email =&gt; email
[sourcecode language=&quot;ruby&quot;]&lt;span style=&quot;color: #333399;&quot;&gt; else
redirect_to :action =&gt; &quot;index&quot;
end
end&lt;/span&gt;
</pre>
<p></span>[/sourcecode]</p>
<pre name="code" class="ruby">
After the user gets their email with their activation code, they go to the create_password page.  I send the email as a param in the link, so the activation page will only work if they use the link in the email (or directly edit the address if they are real crafty). The create password page has 3 inputs: code, password, and passRepeat (to verify the password).  Here is the action for this form:
</pre>
<pre name="code" class="ruby">
[sourcecode language=&quot;ruby&quot;]&lt;span style=&quot;color: #333399;&quot;&gt;def make_account
@beta = Betauser.find_by_email(params[:email])
if !@beta
redirect_to :action =&gt; &quot;index&quot;
&lt;/span&gt; &lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt; //check that password fields match
&lt;/span&gt; &lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt; elsif params[:password] == params[:passRepeat] &lt;/span&gt; &lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt; &lt;/span&gt;&lt;/em&gt;
</pre>
<p>[/sourcecode]</p>
<pre name="code" class="ruby">
[sourcecode language=&quot;ruby&quot;]&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt; // check that the code matches our formula from before
&lt;/span&gt; &lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt; if params[:code] != Digest::SHA1.hexdigest(@beta.email)[3,12]
flash[:alert] = &quot;Incorrect Code!&quot;
redirect_to :action =&gt; &quot;create_password&quot;,
:email =&gt; @beta.email
else
&lt;/span&gt; &lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt; //save the password
&lt;/span&gt; &lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt; @beta.password = Digest::SHA1.hexdigest(params[:password])
&lt;/span&gt; &lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt; //set the account to active
&lt;/span&gt; &lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt; @beta.active = true
@beta.save
&lt;span style=&quot;color: #999999;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;//use the session cookies to log the user in,
// then redirect to the site&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;
&lt;/span&gt; session[&#039;betauser&#039;] = @beta.id
redirect_to :controller =&gt; &quot;main&quot;,
:action =&gt; &quot;index&quot;
end
else
flash[:alert] = &quot;Passwords do not match!&quot;
redirect_to :action =&gt; &quot;create_password&quot;,
:email =&gt; @beta.email
end
end
&lt;/span&gt;
</pre>
<p>So now we have a user logged in.  But we have to have a &#8216;gatekeeper&#8217; function to allow logged in users to view the site, and send everyone else to the login page.  We will put this in the application.rb controller:[/sourcecode]</p>
<pre name="code" class="ruby">
[sourcecode language=&quot;ruby&quot;]&lt;span style=&quot;color: #999999;&quot;&gt; &lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// run the function before every action in our app&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;
&lt;/span&gt; before_filter :check_beta
....
protected
....&lt;/span&gt;
</pre>
<p>[/sourcecode]</p>
<pre name="code" class="ruby">
&lt;span style=&quot;color: #333399;&quot;&gt;def checkbeta
&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// don&#039;t check when user is in the beta pages
// that will cause an infinite redirect loop&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;
if controller_name != &#039;beta&#039;
&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// if betauser session variable is there
// and the beta user exists, set a
// global @betauser to represent the user&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;
if (session[&#039;betauser&#039;] and Betauser.find(session[&#039;betauser&#039;]) )
@betauser = Betauser.find(session[&#039;betauser&#039;])
&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// if the account has not been activated,
// send the user to the create password page&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;
if @betauser.active == false
session[:original_uri] = request.request_uri
redirect_to :controller =&gt; &quot;beta&quot;,
:action =&gt; &quot;create_password&quot;,
:email =&gt; @betauser.email
end
else
&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// if a user is not logged in,
// store the requested call
// and send the user to the
// account request and login page&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;
session[:original_uri] = request.request_uri
redirect_to :controller =&gt; &quot;beta&quot;,
:action =&gt; &quot;index&quot;
end
end
end&lt;/span&gt;
</pre>
<p>Notice that if the user is logged in and the account is active, there is no redirect, and the user goes to the requested page.</p>
<p>The only thing left is to create a login and logout function in our beta controller:</p>
<pre name="code" class="ruby">
&lt;span style=&quot;color: #333399;&quot;&gt;def login
password = params[:password]
email = params[:email]
user = Betauser.find_by_email(email)
&lt;span style=&quot;color: #999999;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// make sure the user exists&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;
&lt;/span&gt; if !user
flash[:alert] = &quot;No user with that email address.&quot;
redirect_to :action =&gt; &quot;index&quot;
&lt;span style=&quot;color: #999999;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// make sure the account is active&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;
&lt;/span&gt; elsif user.active == 0
flash[:alert] = &quot;You must activate your beta account.&quot;
redirect_to :action =&gt; &quot;create_password&quot;,
:email =&gt; user.email
&lt;span style=&quot;color: #999999;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// verify the password&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;
&lt;/span&gt; elsif Digest::SHA1.hexdigest(password) != user.password
flash[:alert] = &quot;Incorrect Password.&quot;
redirect_to :action =&gt; &quot;index&quot;
else
&lt;span style=&quot;color: #999999;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// set the session variable to log the user in&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;&lt;span style=&quot;color: #999999;&quot;&gt;
&lt;/span&gt; session[&#039;betauser&#039;] = user.id
&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// send to the original request, if exists
// otherwise, send to the homepage&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;
if session[:original_uri]
redirect_to session[:original_uri]
else
redirect_to :controller =&gt; &quot;main&quot;,
:action =&gt; &quot;index&quot;
end
end
end&lt;/span&gt;
</pre>
<pre name="code" class="ruby">
&lt;span style=&quot;color: #333399;&quot;&gt;def logout
&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;color: #333399;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;// set the session variable to nil
// and redirect to the login page&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: #333399;&quot;&gt;
session[&#039;betauser&#039;] = nil
redirect_to :controller =&gt; &quot;beta&quot;,
:action =&gt; &quot;index&quot;
end&lt;/span&gt;
</pre>
<p>That&#8217;s about it.  There are definitely things I could have done better, but I wanted something quick, dirty, and temporary.  It works, and is not something I would want to use long term.  However, if you have a need for a low-security, simple login, this gets it done.  Overall, it only took me about an hour and 15 minutes to code, and will be very simple to remove.</p>
<p>**I will follow up with a very simple removal of the system, and post the files in their entirety at a later time.  Check it out at <a href="http://motionspire.com">Motionspire.com!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.thewojogroup.com/2008/09/super-simple-login-with-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
